On Wed, Sep 9, 2026 at 11:27 AM <[email protected]> wrote: > > From: Dongwon Kim <[email protected]> > > When all virtual console tabs are detached (untabified) from the main > window, the notebook contains no active pages, causing > gtk_notebook_get_current_page() to return -1. > > Because gtk_notebook_page_num() also returns -1 for any detached VC, > gd_vc_find_by_page(s, -1) mistakenly matches the first detached > console. As a result, gd_vc_find_current() incorrectly returns > a detached VC instead of NULL. Menu actions executed on the empty main > window then unintentionally operate on that detached VC. > > Fix this by having gd_vc_find_current() explicitly check for page < 0 > and return NULL when the notebook has no active page. In addition, add > NULL checks for the current VC across relevant UI menu callbacks so > actions are properly bypassed or reset when no console tab is focused > in the main window. > > Cc: Daniel P. Berrangé <[email protected]> > Cc: Marc-André Lureau <[email protected]> > Signed-off-by: Dongwon Kim <[email protected]>
Reviewed-by: Marc-André Lureau <[email protected]> > --- > ui/gtk.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------ > 1 file changed, 50 insertions(+), 6 deletions(-) > > diff --git a/ui/gtk.c b/ui/gtk.c > index 7078d89d67..0b5139ef31 100644 > --- a/ui/gtk.c > +++ b/ui/gtk.c > @@ -184,6 +184,11 @@ static VirtualConsole > *gd_vc_find_current(GtkDisplayState *s) > gint page; > > page = gtk_notebook_get_current_page(GTK_NOTEBOOK(s->notebook)); > + > + if (page < 0) { > + return NULL; > + } > + > return gd_vc_find_by_page(s, page); > } > > @@ -1462,7 +1467,10 @@ static void gd_menu_show_tabs(GtkMenuItem *item, void > *opaque) > } else { > gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), FALSE); > } > - gd_update_windowsize(vc); > + > + if (vc) { > + gd_update_windowsize(vc); > + } > } > > static int gd_vc_notebook_pos(GtkDisplayState *s, VirtualConsole *target) > @@ -1535,6 +1543,10 @@ static void gd_menu_untabify(GtkMenuItem *item, void > *opaque) > GtkDisplayState *s = opaque; > VirtualConsole *vc = gd_vc_find_current(s); > > + if (!vc) { > + return; > + } > + > if (vc->type == GD_VC_GFX && > qemu_console_is_graphic(vc->gfx.dcl.con)) { > gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), > @@ -1588,7 +1600,10 @@ static void gd_menu_show_menubar(GtkMenuItem *item, > void *opaque) > } else { > gtk_widget_hide(s->menu_bar); > } > - gd_update_windowsize(vc); > + > + if (vc) { > + gd_update_windowsize(vc); > + } > } > > static void gd_accel_show_menubar(void *opaque) > @@ -1605,7 +1620,7 @@ static void gd_menu_full_screen(GtkMenuItem *item, void > *opaque) > if (!s->full_screen) { > gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), FALSE); > gtk_widget_hide(s->menu_bar); > - if (vc->type == GD_VC_GFX) { > + if (vc && vc->type == GD_VC_GFX) { > gtk_widget_set_size_request(vc->gfx.drawing_area, -1, -1); > } > gtk_window_fullscreen(GTK_WINDOW(s->window)); > @@ -1618,14 +1633,16 @@ static void gd_menu_full_screen(GtkMenuItem *item, > void *opaque) > gtk_widget_show(s->menu_bar); > } > s->full_screen = FALSE; > - if (vc->type == GD_VC_GFX) { > + if (vc && vc->type == GD_VC_GFX) { > vc->gfx.scale_x = vc->gfx.preferred_scale; > vc->gfx.scale_y = vc->gfx.preferred_scale; > gd_update_windowsize(vc); > } > } > > - gd_update_cursor(vc); > + if (vc) { > + gd_update_cursor(vc); > + } > } > > static void gd_accel_full_screen(void *opaque) > @@ -1639,6 +1656,10 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void > *opaque) > GtkDisplayState *s = opaque; > VirtualConsole *vc = gd_vc_find_current(s); > > + if (!vc) { > + return; > + } > + > gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item), > FALSE); > > @@ -1659,6 +1680,10 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void > *opaque) > GtkDisplayState *s = opaque; > VirtualConsole *vc = gd_vc_find_current(s); > > + if (!vc) { > + return; > + } > + > gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item), > FALSE); > > @@ -1676,6 +1701,10 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, void > *opaque) > GtkDisplayState *s = opaque; > VirtualConsole *vc = gd_vc_find_current(s); > > + if (!vc) { > + return; > + } > + > vc->gfx.scale_x = vc->gfx.preferred_scale; > vc->gfx.scale_y = vc->gfx.preferred_scale; > > @@ -1687,6 +1716,10 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void > *opaque) > GtkDisplayState *s = opaque; > VirtualConsole *vc = gd_vc_find_current(s); > > + if (!vc) { > + return; > + } > + > if > (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item))) { > s->free_scale = TRUE; > } else { > @@ -1800,6 +1833,11 @@ static void gd_menu_grab_input(GtkMenuItem *item, void > *opaque) > VirtualConsole *vc = gd_vc_find_current(s); > > if (gd_is_grab_active(s)) { > + if (!vc) { > + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), > + FALSE); > + return; > + } > gd_grab_keyboard(vc, "user-request-main-window"); > gd_grab_pointer(vc, "user-request-main-window"); > } else { > @@ -1807,7 +1845,9 @@ static void gd_menu_grab_input(GtkMenuItem *item, void > *opaque) > gd_ungrab_pointer(s); > } > > - gd_update_cursor(vc); > + if (vc) { > + gd_update_cursor(vc); > + } > } > > static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2, > @@ -1983,6 +2023,10 @@ static void gd_menu_copy(GtkMenuItem *item, void > *opaque) > GtkDisplayState *s = opaque; > VirtualConsole *vc = gd_vc_find_current(s); > > + if (!vc) { > + return; > + } > + > #if VTE_CHECK_VERSION(0, 50, 0) > vte_terminal_copy_clipboard_format(VTE_TERMINAL(vc->vte.terminal), > VTE_FORMAT_TEXT); > -- > 2.43.0 > > -- Marc-André Lureau
