I just wanted to ask if, in gjs, it is intended for types to be lazy loaded after importing a library. A minimal sample code to understand what I mean is the following one:
#!/usr/bin/gjs -m
import GObject from 'gi://GObject'
import Gtk from 'gi://Gtk?version=4.0'
console.log(GObject.type_from_name('GtkApplication'))
After executing it, we can see that GtkApplication has not been registered from only Gtk having been imported. Of course, accessing Gtk.Application or Gtk.Window before looking for it makes the previous log no longer logging null; however, accessing Gtk.Widget is not enough.
This behaviour can be replicated in other libraries. A noticable example is libgtkhex, where accessing Hex.Widget is needed for Gtk.Builder to recognize it from a ui file.
Is this behaviour the same in other language bindings?
Yes, this is how GObject type loading works in general; the types are lazily registered when they are first accessed. As you’re noticing, if you try to look up a type by name before it gets loaded, you’ll simply get a null.
It’s also written in the GtkBuilder documentation: types must be registered before using them. Typically, this happens with internal types, but it’s also the case for libraries that expose types without an initialisation function—like gtk_init() or adw_init()—that explicitly registers all public types.
To work around this, you need to call g_type_ensure(), or the equivalent function exposed by the language bindings you’re using; in the case of GJS, it’s GObject.type_ensure.
Yes, I understood that; because GtkBuilder only receives strings at the end of the day. I just didn’t know that loading a library didn’t register all public types.
Typically, this happens with internal types, but it’s also the case for libraries that expose types without an initialisation function—like gtk_init() or adw_init()—that explicitly registers all public types.
I just realized that part of the job of such functions were to ensure its public types were registered.
To work around this, you need to call g_type_ensure(), or the equivalent function exposed by the language bindings you’re using; in the case of GJS, it’s GObject.type_ensure.
Oh, so if I understand correctly, in general, accessing a public type is not enought, right? I should make sure to call GObject.type_ensure on those GTypes; for instance, in the case I mentioned of libgtkhex, instead of just accessing Hex.Widget, I should really call GObject.type_ensure(Hex.Widget.$gtype), right?
If you’re referring to the type inside a UI definition file of a template widget, you should call GObject.type_ensure() before the template is initialised, so that GtkBuilder can create an instance for it.