I want to implement a widget with custom drawing, either an instance of an already existing basic widget like GtkWidget or GtkFixed, or by defining a custom widget. But I want to do it from a non-C language, with access to GObject Introspection.
In previous Gtk versions I could just connect to the draw signal and this is widely supported in language bindings and GObject Introspection. According to this post the recommended way for Gtk4 is to change the widget snapshot vfunction.
The post does not say how to do that but I found two ways: either by creating a new custom widget, or by calling GTK_WIDGET_GET_CLASS on the instance.
GTK_WIDGET_GET_CLASS is a macro, not available via GObject Introspection. Creating a custom widget also relies on many macros not available via introspection.
Is there a simple way to either override the snapshop function of the widget or create a custom widget class via GObject Introspection? Or do I have to implement GObject subclassing in my language from scratch to have a way to do it?
Your language bindings to GTK should have a way to create a derived type. If they don’t, then you can’t achieve what you want—and it has nothing to do with macros: pre-processor macros are just C convenience that set up data structures and call public functions. The main issue is that interfacing with the type system is mechanically complicated, and cannot really be done just at run time by calling functions through FFI trampolines; it requires integrating with a programming language’s own representation of types.
Thanks. I mentioned the macros because they make subclassing more convenient in C, and I hoped there could be similar functionality from libgirepository.
As for the other question: is the only way to change the snapshot function of an existing widget using the GTK_WIDGET_GET_CLASS to change the value, or is there another way?
You must never do this. The class structure is shared across all instances of a type, which means you cannot change the virtual function of a single instance. It’s also a perfect way to break everything.
If you want to override a virtual function, you must create a new derived type.