On 2026/06/08 16:16, Marc-André Lureau wrote:
Add gtk_display_cleanup() to properly tear down GTK display state:
remove console and mouse notifiers, unregister clipboard peer,
destroy the main window and virtual consoles.
Signed-off-by: Marc-André Lureau <[email protected]>
---
include/ui/gtk.h | 1 +
ui/gtk-clipboard.c | 15 +++++++++++++++
ui/gtk.c | 18 ++++++++++++++++++
3 files changed, 34 insertions(+)
diff --git a/include/ui/gtk.h b/include/ui/gtk.h
index 3e6ce3cb48c..5156a049509 100644
--- a/include/ui/gtk.h
+++ b/include/ui/gtk.h
@@ -225,6 +225,7 @@ int gd_gl_area_make_current(DisplayGLCtx *dgc,
/* gtk-clipboard.c */
void gd_clipboard_init(GtkDisplayState *gd);
+void gd_clipboard_cleanup(GtkDisplayState *gd);
void gd_update_scale(VirtualConsole *vc, int ww, int wh, int fbw, int fbh);
diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c
index ea9444be70f..476e6b8303c 100644
--- a/ui/gtk-clipboard.c
+++ b/ui/gtk-clipboard.c
@@ -235,3 +235,18 @@ void gd_clipboard_init(GtkDisplayState *gd)
g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_SECONDARY],
"owner-change", G_CALLBACK(gd_owner_change), gd);
}
+
+void gd_clipboard_cleanup(GtkDisplayState *gd)
+{
+ if (!gd->cbpeer.name) {
+ return;
+ }
+ qemu_clipboard_peer_unregister(&gd->cbpeer);
+ g_signal_handlers_disconnect_by_data(
+ gd->gtkcb[QEMU_CLIPBOARD_SELECTION_CLIPBOARD], gd);
+ g_signal_handlers_disconnect_by_data(
+ gd->gtkcb[QEMU_CLIPBOARD_SELECTION_PRIMARY], gd);
+ g_signal_handlers_disconnect_by_data(
+ gd->gtkcb[QEMU_CLIPBOARD_SELECTION_SECONDARY], gd);
+ gd->cbpeer.name = NULL;
+}
diff --git a/ui/gtk.c b/ui/gtk.c
index 2ee826b56fb..c26dc83ac3e 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -2505,6 +2505,7 @@ static void gd_create_menus(GtkDisplayState *s,
DisplayOptions *opts)
}
+static GtkDisplayState *gtk_display_state;
static gboolean gtkinit;
static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
@@ -2523,6 +2524,7 @@ static void gtk_display_init(DisplayState *ds,
DisplayOptions *opts)
}
assert(opts->type == DISPLAY_TYPE_GTK);
s = g_malloc0(sizeof(*s));
+ gtk_display_state = s;
s->opts = opts;
theme = gtk_icon_theme_get_default();
@@ -2681,10 +2683,26 @@ static void early_gtk_display_init(DisplayOptions *opts)
#endif
}
+static void gtk_display_cleanup(void)
+{
+ GtkDisplayState *s = gtk_display_state;
+
+ if (!s) {
+ return;
+ }
+
+ qemu_remove_mouse_mode_change_notifier(&s->mouse_mode_notifier);
qemu_del_vm_change_state_handler() should be called too.
Regards,
Akihiko Odaki
+ gd_clipboard_cleanup(s);
+ g_clear_pointer(&s->window, gtk_widget_destroy);
+ g_clear_object(&s->null_cursor);
+ g_clear_pointer(>k_display_state, g_free);
+}
+
static QemuDisplay qemu_display_gtk = {
.type = DISPLAY_TYPE_GTK,
.early_init = early_gtk_display_init,
.init = gtk_display_init,
+ .cleanup = gtk_display_cleanup,
.vc = "vc",
};