Search code examples
gtkvala

Why GtkWindow does not fire "draw" event?


I am trying to get a transparent window with GTK+ 3.x. AFAIK the following code should work, but my window never fires the "draw" signal. What could be the reason?

My code:

using Gtk;

public class WallpaperWindow : Object {
  private Window  window;

  public static int main (string[] args) {
    Gtk.init (ref args);

    new WallpaperWindow();

    Gtk.main();

    return 0;
  }

  public WallpaperWindow() {
    // Initialize window
    this.window = new Window();
    this.window.resize(200, 200);

    this.window.set_decorated(false);
    this.window.set_border_width(8);


    // Enable transparency

    var screen = this.window.get_screen();
    var visual = screen.get_rgba_visual();

    if(visual != null && screen.is_composited()) {
      message("Composition is enabled, enabling transparency");
      this.window.set_visual(visual);
    } else {
      warning("Composition is not enabled, cannot enable transparency");
    }

    this.window.draw.connect(on_window_draw);

    // Run!
    this.window.show_all();

  }

  // NEVER CALLED
  private bool on_window_draw(Cairo.Context cr) {
    warning("on_window_draw");
    cr.set_source_rgba(0.0, 0.0, 0.0, 0.0);
    cr.set_operator(Cairo.Operator.SOURCE);
    cr.paint();
    cr.set_operator(Cairo.Operator.OVER);

    return true;
  }
}

Solution

  • You don't assign the newly created WallpaperWindow instance to a variable. Vala isn't garbage collected... when an object goes out of scope it is immediately unrefed, and if you don't assign it to a variable it goes out of scope at the end of the constructor call. The generated C from your example looks like this:

    _tmp0_ = wallpaper_window_new ();
    _tmp1_ = _tmp0_;
    _g_object_unref0 (_tmp1_);
    gtk_main ();
    

    As you can see, your new WallpaperWindow gets unrefed before gtk_main is called. If you assign it to a variable (so it lasts past gtk_main) your example works as you expect.