How to make Gtk+ window background transparent?

Viewed 32082

I'd like to make the background of a Gtk+ window transparent so that only the widgets in the window are visible. I found a few tutorials:

http://mikehearn.wordpress.com/2006/03/26/gtk-windows-with-alpha-channels/

http://macslow.thepimp.net/?p=26

But they both appear to listen to the "expose" event, and then delegate to Cairo to do the rendering. This means that other widgets added to the window are not rendered (for example, I've tried adding a button to the window as well).

I see that there's a method modify-bg on GtkWidget: http://library.gnome.org/devel/gtk/stable/GtkWidget.html#gtk-widget-modify-bg

However, GdkColor does not appear to accept a parameter for transparency: http://library.gnome.org/devel/gdk/stable/gdk-Colormaps-and-Colors.html

I've tried the GtkWindow.set_opacity method as well, but this sets the opacity for the window contents as well, which is not what I want.

I'd appreciate any guidance anyone can provide in this.

4 Answers

For those using golang, here's one using gotk3 ( https://github.com/gotk3/gotk3 ) :

package main

import (
    "github.com/gotk3/gotk3/cairo"
    "github.com/gotk3/gotk3/gdk"
    "github.com/gotk3/gotk3/gtk"
    "log"
)

var alphaSupported = false

func main() {
    gtk.Init(nil)

    win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
    if err != nil {
        log.Fatal("Unable to create window:", err)
    }
    win.SetTitle("Simple Example")
    win.Connect("destroy", func() {
        gtk.MainQuit()
    })

    // Needed for transparency
    win.SetAppPaintable(true)

    win.Connect("screen-changed", func (widget *gtk.Widget, oldScreen *gdk.Screen, userData ...interface{}) {
        screenChanged(widget)
    })
    win.Connect("draw", func (window *gtk.Window, context *cairo.Context) {
        exposeDraw(window, context)
    })

    l, err := gtk.LabelNew("I'm transparent !")
    if err != nil {
        log.Fatal("Unable to create label:", err)
    }

    win.Add(l)
    win.SetDefaultSize(800, 600)

    screenChanged(&win.Widget)

    win.ShowAll()
    gtk.Main()
}

func screenChanged(widget *gtk.Widget) {
    screen, _ := widget.GetScreen()
    visual, _ := screen.GetRGBAVisual()

    if visual != nil {
        alphaSupported = true
    } else {
        println("Alpha not supported")
        alphaSupported = false
    }

    widget.SetVisual(visual)
}

func exposeDraw(w *gtk.Window, ctx *cairo.Context) {
    if alphaSupported {
        ctx.SetSourceRGBA(0.0, 0.0, 0.0, 0.25)
    } else {
        ctx.SetSourceRGB(0.0, 0.0, 0.0)
    }

    ctx.SetOperator(cairo.OPERATOR_SOURCE)
    ctx.Paint()
}
Related