mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
ui/gtk: handle console hotplug/unplug events
Register a console notifier so the GTK display dynamically creates and destroys VirtualConsole tabs when graphic consoles are added or removed at runtime (e.g. vfio-pci with display=on hotplug). Add skips consoles that already have a VC binding, remove skips unknown 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-30-4656aec3398d@redhat.com>
This commit is contained in:
@@ -141,6 +141,7 @@ struct GtkDisplayState {
|
||||
GdkCursor *null_cursor;
|
||||
Notifier mouse_mode_notifier;
|
||||
VMChangeStateEntry *vmse;
|
||||
Notifier console_notifier;
|
||||
gboolean free_scale;
|
||||
gboolean keep_aspect_ratio;
|
||||
|
||||
|
||||
75
ui/gtk.c
75
ui/gtk.c
@@ -2332,7 +2332,8 @@ static bool gd_scale_valid(double scale)
|
||||
return scale >= VC_SCALE_MIN && scale <= VC_SCALE_MAX;
|
||||
}
|
||||
|
||||
static void add_gfx_console(GtkDisplayState *s, QemuConsole *con)
|
||||
static VirtualConsole *
|
||||
add_gfx_console(GtkDisplayState *s, QemuConsole *con)
|
||||
{
|
||||
VirtualConsole *vc = g_new0(VirtualConsole, 1);
|
||||
const DisplayChangeListenerOps *ops = &dcl_ops;
|
||||
@@ -2414,6 +2415,74 @@ static void add_gfx_console(GtkDisplayState *s, QemuConsole *con)
|
||||
qemu_console_register_listener(con, &vc->gfx.dcl, ops);
|
||||
|
||||
gd_connect_vc_gfx_signals(vc);
|
||||
return vc;
|
||||
}
|
||||
|
||||
static void gd_vc_add_gfx(GtkDisplayState *s, QemuConsole *con)
|
||||
{
|
||||
VirtualConsole *vc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int)s->vcs->len; i++) {
|
||||
VirtualConsole *v = g_ptr_array_index(s->vcs, i);
|
||||
if (v->type == GD_VC_GFX && v->gfx.dcl.con == con) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
vc = add_gfx_console(s, con);
|
||||
gtk_widget_show_all(vc->tab_item);
|
||||
gtk_widget_realize(vc->gfx.drawing_area);
|
||||
|
||||
if (s->free_scale) {
|
||||
gd_update_windowsize(vc);
|
||||
}
|
||||
|
||||
gd_update_caption(s);
|
||||
gd_rebuild_vc_menu(s);
|
||||
}
|
||||
|
||||
static void gd_vc_remove_gfx(GtkDisplayState *s, QemuConsole *con)
|
||||
{
|
||||
VirtualConsole *vc = NULL;
|
||||
guint idx;
|
||||
|
||||
for (idx = 0; idx < s->vcs->len; idx++) {
|
||||
VirtualConsole *v = g_ptr_array_index(s->vcs, idx);
|
||||
if (v->type == GD_VC_GFX && v->gfx.dcl.con == con) {
|
||||
vc = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!vc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->kbd_owner == vc) {
|
||||
gd_ungrab_keyboard(s);
|
||||
}
|
||||
if (s->ptr_owner == vc) {
|
||||
gd_ungrab_pointer(s);
|
||||
}
|
||||
|
||||
g_ptr_array_remove_index(s->vcs, idx);
|
||||
gd_rebuild_vc_menu(s);
|
||||
gd_update_caption(s);
|
||||
}
|
||||
|
||||
static void gd_console_notify(Notifier *n, void *data)
|
||||
{
|
||||
GtkDisplayState *s = container_of(n, GtkDisplayState, console_notifier);
|
||||
QemuConsoleEvent *event = data;
|
||||
|
||||
switch (event->type) {
|
||||
case QEMU_CONSOLE_ADDED:
|
||||
gd_vc_add_gfx(s, event->con);
|
||||
break;
|
||||
case QEMU_CONSOLE_REMOVED:
|
||||
gd_vc_remove_gfx(s, event->con);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void gd_create_menu_view(GtkDisplayState *s, DisplayOptions *opts)
|
||||
@@ -2694,6 +2763,9 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
|
||||
|
||||
gd_create_menus(s, opts);
|
||||
|
||||
s->console_notifier.notify = gd_console_notify;
|
||||
qemu_console_add_notifier(&s->console_notifier);
|
||||
|
||||
gd_connect_signals(s);
|
||||
|
||||
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), FALSE);
|
||||
@@ -2814,6 +2886,7 @@ static void gtk_display_cleanup(void)
|
||||
return;
|
||||
}
|
||||
qemu_del_vm_change_state_handler(s->vmse);
|
||||
qemu_console_remove_notifier(&s->console_notifier);
|
||||
qemu_remove_mouse_mode_change_notifier(&s->mouse_mode_notifier);
|
||||
gd_clipboard_cleanup(s);
|
||||
g_signal_handlers_disconnect_by_func(s->notebook,
|
||||
|
||||
Reference in New Issue
Block a user