@samitouri / QOSamiQemu / commits / 50cff68a63

ui/gtk: convert VirtualConsole storage from fixed array to GPtrArray

Replace the fixed-size vc[MAX_VCS] with GPtrArray. This is a preparatory refactoring for console hotplug support, which needs to add/remove VCs dynamically. 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-26-4656aec3398d@redhat.com>

Marc-André Lureau committed Jun 23, 2026 at 11:44 UTC 50cff68a63815e6ce62efb7fff7adce0b24cee98
2 files changed +87 -24
include/ui/gtk.h
+1 -2
@@ -118,8 +118,7 @@ struct GtkDisplayState {
118 GtkWidget *grab_item;
119 GtkWidget *grab_on_hover_item;
120
121 - int nb_vcs;
122 - VirtualConsole vc[MAX_VCS];
121 + GPtrArray *vcs;
122
123 GtkWidget *show_tabs_item;
124 GtkWidget *untabify_item;
ui/gtk.c
+86 -22
@@ -150,8 +150,8 @@ static VirtualConsole *gd_vc_find_by_menu(GtkDisplayState *s)
150 VirtualConsole *vc;
151 gint i;
152
153 - for (i = 0; i < s->nb_vcs; i++) {
154 - vc = &s->vc[i];
153 + for (i = 0; i < s->vcs->len; i++) {
154 + vc = g_ptr_array_index(s->vcs, i);
155 if (gtk_check_menu_item_get_active
156 (GTK_CHECK_MENU_ITEM(vc->menu_item))) {
157 return vc;
@@ -165,8 +165,11 @@ static VirtualConsole *gd_vc_find_by_page(GtkDisplayState *s, gint page)
165 VirtualConsole *vc;
166 gint i, p;
167
168 - for (i = 0; i < s->nb_vcs; i++) {
169 - vc = &s->vc[i];
168 + if (!s->vcs) {
169 + return NULL;
170 + }
171 + for (i = 0; i < s->vcs->len; i++) {
172 + vc = g_ptr_array_index(s->vcs, i);
173 p = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook), vc->tab_item);
174 if (p == page) {
175 return vc;
@@ -247,8 +250,8 @@ static void gd_update_caption(GtkDisplayState *s)
250 gtk_window_set_title(GTK_WINDOW(s->window), title);
251 g_free(title);
252
250 - for (i = 0; i < s->nb_vcs; i++) {
251 - VirtualConsole *vc = &s->vc[i];
253 + for (i = 0; i < s->vcs->len; i++) {
254 + VirtualConsole *vc = g_ptr_array_index(s->vcs, i);
255
256 if (!vc->window) {
257 continue;
@@ -357,7 +360,7 @@ static void gtk_release_modifiers(GtkDisplayState *s)
360 {
361 VirtualConsole *vc = gd_vc_find_current(s);
362
360 - if (vc->type != GD_VC_GFX ||
363 + if (!vc || vc->type != GD_VC_GFX ||
364 !qemu_console_is_graphic(vc->gfx.dcl.con)) {
365 return;
366 }
@@ -702,8 +705,8 @@ static void gd_mouse_mode_change(Notifier *notify, void *data)
705 gd_ungrab_pointer(s);
706 }
707 }
705 - for (i = 0; i < s->nb_vcs; i++) {
706 - VirtualConsole *vc = &s->vc[i];
708 + for (i = 0; i < s->vcs->len; i++) {
709 + VirtualConsole *vc = g_ptr_array_index(s->vcs, i);
710 gd_update_cursor(vc);
711 }
712 }
@@ -2114,9 +2117,10 @@ static void gd_vcs_init(GtkDisplayState *s, GSList *group,
2117 int i;
2118
2119 for (i = 0; i < nb_vcs; i++) {
2117 - VirtualConsole *vc = &s->vc[s->nb_vcs];
2118 - group = gd_vc_vte_init(s, vc, vcs[i], s->nb_vcs, group, view_menu);
2119 - s->nb_vcs++;
2120 + VirtualConsole *vc = g_new0(VirtualConsole, 1);
2121 + g_ptr_array_add(s->vcs, vc);
2122 + group = gd_vc_vte_init(s, vc, vcs[i], s->vcs->len - 1,
2123 + group, view_menu);
2124 }
2125 }
2126 #endif /* CONFIG_VTE */
@@ -2441,13 +2445,14 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, DisplayOptions *opts)
2445
2446 /* gfx */
2447 for (vc = 0;; vc++) {
2448 + VirtualConsole *v;
2449 con = qemu_console_lookup_by_index(vc);
2450 if (!con) {
2451 break;
2452 }
2448 - group = gd_vc_gfx_init(s, &s->vc[vc], con,
2449 - vc, group, view_menu);
2450 - s->nb_vcs++;
2453 + v = g_new0(VirtualConsole, 1);
2454 + g_ptr_array_add(s->vcs, v);
2455 + group = gd_vc_gfx_init(s, v, con, vc, group, view_menu);
2456 }
2457
2458 #if defined(CONFIG_VTE)
@@ -2505,6 +2510,64 @@ static void gd_create_menus(GtkDisplayState *s, DisplayOptions *opts)
2510 }
2511
2512
2513 +static void gd_vc_free(void *p)
2514 +{
2515 + VirtualConsole *vc = p;
2516 +
2517 + switch (vc->type) {
2518 + case GD_VC_GFX:
2519 + qemu_console_unregister_listener(&vc->gfx.dcl);
2520 +#if defined(CONFIG_OPENGL)
2521 + if (display_opengl) {
2522 + qemu_console_set_display_gl_ctx(vc->gfx.dcl.con, NULL);
2523 + }
2524 + if (vc->gfx.ectx) {
2525 + eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
2526 + vc->gfx.esurface, vc->gfx.ectx);
2527 + } else if (gtk_use_gl_area) {
2528 + gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area));
2529 + }
2530 + if (vc->gfx.gls) {
2531 + surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds);
2532 + qemu_gl_fini_shader(vc->gfx.gls);
2533 + }
2534 + egl_fb_destroy(&vc->gfx.guest_fb);
2535 + egl_fb_destroy(&vc->gfx.win_fb);
2536 + egl_fb_destroy(&vc->gfx.cursor_fb);
2537 + if (vc->gfx.esurface) {
2538 + eglDestroySurface(qemu_egl_display, vc->gfx.esurface);
2539 + }
2540 + if (vc->gfx.ectx) {
2541 + eglDestroyContext(qemu_egl_display, vc->gfx.ectx);
2542 + }
2543 +#endif
2544 + qkbd_state_free(vc->gfx.kbd);
2545 + if (vc->gfx.surface) {
2546 + cairo_surface_destroy(vc->gfx.surface);
2547 + }
2548 + if (vc->gfx.convert) {
2549 + pixman_image_unref(vc->gfx.convert);
2550 + }
2551 + break;
2552 + case GD_VC_VTE:
2553 +#ifdef CONFIG_VTE
2554 + fifo8_destroy(&vc->vte.out_fifo);
2555 +#endif
2556 + break;
2557 + }
2558 +
2559 + if (vc->window) {
2560 + gtk_widget_destroy(vc->window);
2561 + } else if (vc->tab_item) {
2562 + gtk_widget_destroy(vc->tab_item);
2563 + }
2564 + if (vc->menu_item) {
2565 + gtk_widget_destroy(vc->menu_item);
2566 + }
2567 + g_free(vc->label);
2568 + g_free(vc);
2569 +}
2570 +
2571 static GtkDisplayState *gtk_display_state;
2572 static gboolean gtkinit;
2573
@@ -2525,6 +2588,7 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
2588 assert(opts->type == DISPLAY_TYPE_GTK);
2589 s = g_malloc0(sizeof(*s));
2590 gtk_display_state = s;
2591 + s->vcs = g_ptr_array_new_with_free_func(gd_vc_free);
2592 s->opts = opts;
2593
2594 theme = gtk_icon_theme_get_default();
@@ -2582,13 +2646,10 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
2646
2647 gtk_widget_show_all(s->window);
2648
2585 - for (idx = 0;; idx++) {
2586 - QemuConsole *con = qemu_console_lookup_by_index(idx);
2587 - if (!con) {
2588 - break;
2589 - }
2590 - if (s->vc[idx].type == GD_VC_GFX) {
2591 - gtk_widget_realize(s->vc[idx].gfx.drawing_area);
2649 + for (idx = 0; idx < s->vcs->len; idx++) {
2650 + VirtualConsole *v = g_ptr_array_index(s->vcs, idx);
2651 + if (v->type == GD_VC_GFX) {
2652 + gtk_widget_realize(v->gfx.drawing_area);
2653 }
2654 }
2655
@@ -2693,6 +2754,9 @@ static void gtk_display_cleanup(void)
2754 qemu_del_vm_change_state_handler(s->vmse);
2755 qemu_remove_mouse_mode_change_notifier(&s->mouse_mode_notifier);
2756 gd_clipboard_cleanup(s);
2757 + g_signal_handlers_disconnect_by_func(s->notebook,
2758 + G_CALLBACK(gd_change_page), s);
2759 + g_clear_pointer(&s->vcs, g_ptr_array_unref);
2760 g_clear_pointer(&s->window, gtk_widget_destroy);
2761 g_clear_object(&s->null_cursor);
2762 g_clear_pointer(&gtk_display_state, g_free);