GtkApplicationWindow子类destroy信号触发两次问题的原因与修复
save_some_state() being called twice? Great question—let's break down what's happening here and how to fix it.
The double invocation of save_some_state() comes down to two separate triggers for your destroy virtual function:
- First call: When you close the window manually,
gtk_widget_destroy()is invoked, which calls your overriddendestroymethod. You save the state here, then pass control to the parent class'sdestroyimplementation. - Second call:
GtkApplicationWindowautomatically links the window'sdestroysignal tog_application_quit(). After your firstdestroycall, this signal handler kicks off the application shutdown process. During shutdown,GtkApplicationreleases its reference to the window. If the window's reference count drops to zero at this point,g_object_run_dispose()fires, which calls thedestroyvirtual function again.
On top of that, overriding the destroy virtual function isn't the ideal approach for state saving. The destroy method is intended for internal widget cleanup (like freeing allocated resources), not for application-level tasks like saving user state. Signals are GTK's designed way to hook into these events.
Recommended Fix: Use the destroy signal instead of overriding the virtual function
This aligns with GTK's best practices and avoids the double-invocation issue entirely:
// Signal handler for the destroy event static void on_app_window_destroy (GtkWidget* widget) { ExampleAppWindow* win = EXAMPLE_APP_WINDOW(widget); save_some_state(win); } // Instance initialization (add this if you don't have it) static void example_app_window_init (ExampleAppWindow *win) { // Connect the destroy signal to our handler when the window is created g_signal_connect(win, "destroy", G_CALLBACK(on_app_window_destroy), NULL); } static void example_app_window_class_init (ExampleAppWindowClass *klass) { // Remove the line that overrides widget_class->destroy // We don't need it anymore—we're using the signal instead }
Alternative Fix: Add a guard check in the virtual function
If you need to keep the virtual function override for some reason, add a check to ensure state is only saved once:
static void on_app_window_destroy (GtkWidget* widget) { // Check if the widget is already marked as destroyed if (gtk_widget_is_destroyed(widget)) { // Skip state saving and just call the parent's destroy method GTK_WIDGET_CLASS(example_app_window_parent_class)->destroy(widget); return; } ExampleAppWindow* win = EXAMPLE_APP_WINDOW(widget); save_some_state(win); GTK_WIDGET_CLASS(example_app_window_parent_class)->destroy(widget); }
Why the signal approach is better
Using signals keeps your application logic (state saving) separate from the widget's internal cleanup code. It also ensures your handler runs exactly once when the destroy signal is emitted, even if the underlying virtual function is called multiple times during the application shutdown process.
内容的提问来源于stack exchange,提问作者Somebody

