Search code examples
gtkgtk3subclassinggtkbuilder

Custom Gtk Widget with template UI


I've created a custom Gtk Widget with a template, and I want to use it on other Gtk Builder file.

What I've done:

  • Wrote a .ui file with <template class="G3JAMinScenes" parent="GtkBox">
  • Wrote widget source code (.c/.h)

when I create it with g3jamin_scenes_new the widget works as expected, the problem is that I want to add it as child of a window using Gtk Builder, so I wrote:

...
<child>
    <object class="G3JAMinScenes" parent="GtkBox" id="scnes">
    </object>
</child>
...

but it throws an error when I try to run:

Gtk-CRITICAL **: Error building template class 'G3JAMinAppWindow' for an instance of type 'G3JAMinAppWindow': Invalid object type `G3JAMinScenes'

Solution

  • I haven't been able to find any official answer to this in any documentation. I went digging through the GTK+ source and found a few things though.

    When GtkBuilder sees a type it doesn't know about yet, it tries to obtain a function that returns the relevantGType. It will try a couple of heuristics to determine what function to call. If you are using one of the G_DEFINE_TYPE family of macros, it will generate the necessary mywidget_get_type style function that is needed. If you are doing something weird, you can also specify the function in the type-func attribute for the object in your ui file.

    But, for simple programs that probably isn't going to work (at least on Linux) because the compiler probably isn't going to export the function in the dynamic symbol table, and so GtkBuilder won't be able to find it. So you are left with a few options.

    1. Call mywidget_get_type() somewhere early in your application. This will register the type in the GObject type system and GtkBuilder will be able to find it. I am using a subclass of GtkApplication, so I'm calling it in my myapp_class_init. This feels a little bit like a hack, but I settled on this solution because it seems like it should be portable to every situation.
    2. If you are using GCC, link the final executable with -rdynamic. This will put all symbols in the dynamic symbol table so the magic described above will allow GtkBuilder to find it.
    3. Build your widget in a shared library. I haven't tried this one, but I believe it should work for the same reason that -rdynamic works.