ui/gtk: implement display cleanup

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.

Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260623-b4-ui-v4-22-4656aec3398d@redhat.com>
This commit is contained in:
Marc-André Lureau
2026-06-23 11:44:37 +04:00
parent 7d949d9621
commit b09e45f77a
3 changed files with 36 additions and 1 deletions

View File

@@ -140,6 +140,7 @@ struct GtkDisplayState {
GdkCursor *null_cursor;
Notifier mouse_mode_notifier;
VMChangeStateEntry *vmse;
gboolean free_scale;
gboolean keep_aspect_ratio;
@@ -225,6 +226,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);

View File

@@ -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;
}

View File

@@ -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();
@@ -2560,7 +2562,7 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
s->mouse_mode_notifier.notify = gd_mouse_mode_change;
qemu_add_mouse_mode_change_notifier(&s->mouse_mode_notifier);
qemu_add_vm_change_state_handler(gd_change_runstate, s);
s->vmse = qemu_add_vm_change_state_handler(gd_change_runstate, s);
gtk_window_set_icon_name(GTK_WINDOW(s->window), "qemu");
@@ -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_del_vm_change_state_handler(s->vmse);
qemu_remove_mouse_mode_change_notifier(&s->mouse_mode_notifier);
gd_clipboard_cleanup(s);
g_clear_pointer(&s->window, gtk_widget_destroy);
g_clear_object(&s->null_cursor);
g_clear_pointer(&gtk_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",
};