The ownership of top level windows (GtkWindow, GtkDialog, etc) is transferred from GtkBuilder to GTK itself:
A GtkBuilder holds a reference to all objects that it has constructed and drops these references when it is finalized. This finalization can cause the destruction of non-widget objects or widgets which are not contained in a toplevel window. For toplevel windows constructed by a builder, it is the responsibility of the user to call gtk_widget_destroy() to get rid of them and all the widgets they contain.
Any GtkWindow instance (and its derived types, like GtkDialog) will call gtk_widget_destroy() as the default behaviour for the action of closing a window using the “close” button on the window decoration. If you want to avoid that, you have two options:
for GtkDialog instances, you should connect to the GtkDialog::respose and handle the GTK_RESPONSE_DELETE_EVENT response
I also recommend you don’t use gtk_dialog_run(). Always connect to the “response” signal, instead. If you want to prevent user interaction with the rest of the application, you can make the dialog modal using GTK_DIALOG_MODAL.
This shouldn’t matter, because GtkBuilder does not get finalized in my code - if I’m not mistaken on the meaning of finalize.
How would I have to handle GTK_RESPONSE_DELETE_EVENT to prevent its effect?
I would expect the callback to return TRUE/FALSE depending on, if gtk should go on cleaning up, but the callback is void
Even doing this, will not prevent the window from closing:
You missed the rest of the quote, regarding the top level windows.
You can stop the signal emission by using g_signal_stop_emission_by_name(dialog, "response") from within the signal handler—but I’d like to point out that you’re really doing something wrong, here. Dialogs should not be kept around and recycled; if you find yourself doing this, then you should really use a GtkWindow and use the delete-event signal instead.
Alternatively, you could create your own GtkDialog subclass, and use a composite widget template to load the UI from an XML definition. Once you do that, you can then just create a new instance of your subclass every time you need it.
The immediate solution for me will be using the delete-event as you suggested. Thank you!
Fundamental handling of GtkBuilder
Something might be fundamentally wrong with my code. So I’d like to add a follow-up question.
If I don’t do that, I would have to gtk_builder_new_from_xxx everytime the dialog opens. I.e. GtkBuilder would everytime have to parse the string/file/resource. Is it supposed to be like that? This feels like a lot of parsing overhead for the same object again and again…
In my (real) case (not the example), there are several dialogs inside one UI definition file. Could it be, that usually only one window goes into one definition file?
The cost of using GtkBuilder is not in the parsing, but in the object instantiation—and you still need to pay that when building objects by hand. The XML parser is really fast, unless you have a multi megabytes UI definition file, in which case you should split it out into multiple files anyway, or it’s going to be unmaintainable.
GtkBuilder is not a factory, it will create every object only once.
Maybe subclassing a widget and use composite widget template might be like a factory (unfinished investigation).
Objects from GtkBuilder are not meant to be reused/recycled. You should destroy closed windows and create a new GtkBuilder for everytime the window should be opened again.
Don’t use gtk_dialog_run for making dialogs modal. They are only modal until a (any) response happened… and the function is removed in GTK4.
Signal emission can generally be stopped with g_signal_stop_emission_by_name.
That post makes less sense for me now. Apparently GtkBuilder instantiates all objects it parses. That means it doesn’t matter if parsing or instantiation is slow, because both is happening on gtk_builder_new.
If I don’t recycle dialogs and instead create a new GtkBuilder each time the dialog is opened, I have to pay the cost of instantiation of dialogs that I don’t need. I feel there’s a lot of unnecessary work going on, then.
Shouldn’t then be the suggested way to have only one dialog per file/ string / resource?
You have to pay the cost of instantiating an object regardless of whether you do it through GtkBuilder or the object constructor; my point is that the XML parsing cost is minimal compared to the actual instantiation.
Yes: you should break up your UI definition file to one top level per file, so you only parse the UI definition for the dialog only when you need to create it. That will lead you towards using templates and composite widgets with your own dialog subclass, so you automatically parse the UI definition when instantiating that class.