You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GtkApplicationWindow子类destroy信号触发两次问题的原因与修复

Why is 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:

  1. First call: When you close the window manually, gtk_widget_destroy() is invoked, which calls your overridden destroy method. You save the state here, then pass control to the parent class's destroy implementation.
  2. Second call: GtkApplicationWindow automatically links the window's destroy signal to g_application_quit(). After your first destroy call, this signal handler kicks off the application shutdown process. During shutdown, GtkApplication releases its reference to the window. If the window's reference count drops to zero at this point, g_object_run_dispose() fires, which calls the destroy virtual 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.


Fixes to resolve the double call

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:38:30