Gtk4: Widget snapshot

Hello,
I’m not sure why the following code don’t work!
This output an empty window.

int main (string[] args) {
    // Create a new application
    var app = new Gtk.Application ("com.example.GtkApplication", GLib.ApplicationFlags.FLAGS_NONE);

    app.activate.connect (() => {
        // Create a new window
        var window = new Gtk.ApplicationWindow (app);

        var custom = new Custom ();

        var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 10);
        box.append (custom);

        window.set_child (box);
        window.present ();
    });

    return app.run (args);
}

public class Custom : Gtk.Widget {
    construct {
    }

    public Custom () {
    }

    public override void snapshot (Gtk.Snapshot snapshot) {
        snapshot.save ();
        print ("start drawing\n");
        Gdk.RGBA red = {}, green = {}, blue = {}, yellow = {};
        red.parse ("red");
        green.parse ("green");
        blue.parse ("blue");
        yellow.parse ("yellow");

        var w = get_width () / 2;
        var h = get_height () / 2;

        snapshot.append_color (red, { { 0, 0 }, { w, h } });
        snapshot.append_color (green, { { w, 0 }, { w, h } });
        snapshot.append_color (yellow, { { 0, h }, { w, h } });
        snapshot.append_color (blue, { { w, h }, { w, h } });

        snapshot.restore ();
    }
}

Your Custom widget has no size. You either need to implement a LayoutManager and assign it to the widget, or you need to implement the measure() and size_allocate() virtual functions. Alternatively, you must set your widget to expand so that it fills the whole allocated area of the window.

You should read the blog post about drawing in GTK4.

Thank you. I’ve already read the post. It mentions that

If your drawing needs a certain size, you should implement the measure() function too

this implies that overriding this function is not a requirement for custom drawing to work, or so was my understanding.
Thank you for your help. :+1:

It’s not necessary unless your widget’s size is driven by something else; unless:

  • you use the expand flags
  • the parent container automatically expands its children
  • you provide a measure() implementation
  • you have a CSS fragment that provides a minimum with and height

then the minimum and natural sizes of your widget are going to be 0×0—just like in GTK3.

2 posts were split to a new topic: GTK4: Widget measurement

Thank you for taking the time to answer our questions.

I’ve another one. In vala an object implementing the Gdk.Paintable interface must implement the method
void snapshot (Gdk.Snapshot snapshot, double width, double height)
but all the drawing functions present only in the Gtk.Snapshot namespace. My question is it safe to cast the Gdk.Snapshot to Gtk.Snapshot?

for example

public void snapshot (Gdk.Snapshot snapshot, double width, double height) {
        (snapshot as Gtk.Snapshot).append_color (this.color, { { 0, 0 }, { (float) width, (float) height } });
}

Yes; GdkSnapshot is just a type alias needed to be able to have GdkPaintable inside GDK. The actual implementation is all inside GTK.

1 Like