From f88e5c5744c7969ba0ccb7f9a3b85cdcac3aacf1 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 15 May 2018 07:45:01 +0200 Subject: [PATCH 01/10] sdl2: move opts assignment into loop So the opts pointer is set for all sdl2_consoles. Fixes: 844fd50dbbcfc9e401895274bf4fb8da8e8d3f64 Signed-off-by: Gerd Hoffmann --- ui/sdl2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/sdl2.c b/ui/sdl2.c index da037248c2..a0f9b16bc1 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -804,7 +804,6 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) return; } sdl2_console = g_new0(struct sdl2_console, sdl2_num_outputs); - sdl2_console->opts = o; for (i = 0; i < sdl2_num_outputs; i++) { QemuConsole *con = qemu_console_lookup_by_index(i); assert(con != NULL); @@ -812,6 +811,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) sdl2_console[i].hidden = true; } sdl2_console[i].idx = i; + sdl2_console[i].opts = o; #ifdef CONFIG_OPENGL sdl2_console[i].opengl = display_opengl; sdl2_console[i].dcl.ops = display_opengl ? &dcl_gl_ops : &dcl_2d_ops; From 1d18774579759a8b5046119266626e9fdf9f7c0b Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Fri, 11 May 2018 01:07:38 +0200 Subject: [PATCH 02/10] gtk: make it possible to hide the menu bar Saves some space and disables the F10 button as side-effect. Fixes: https://bugs.launchpad.net/qemu/+bug/1726910 Signed-off-by: Peter Wu Message-Id: <20180510230739.28459-1-peter@lekensteyn.nl> Signed-off-by: Gerd Hoffmann --- ui/gtk.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/ui/gtk.c b/ui/gtk.c index bb3214cffb..9e5390f2c2 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -145,6 +145,7 @@ #define GDK_KEY_2 GDK_2 #define GDK_KEY_f GDK_f #define GDK_KEY_g GDK_g +#define GDK_KEY_m GDK_m #define GDK_KEY_q GDK_q #define GDK_KEY_plus GDK_plus #define GDK_KEY_equal GDK_equal @@ -208,6 +209,7 @@ struct GtkDisplayState { GtkWidget *show_tabs_item; GtkWidget *untabify_item; + GtkWidget *show_menubar_item; GtkWidget *vbox; GtkWidget *notebook; @@ -1387,6 +1389,30 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) } } +static void gd_menu_show_menubar(GtkMenuItem *item, void *opaque) +{ + GtkDisplayState *s = opaque; + VirtualConsole *vc = gd_vc_find_current(s); + + if (s->full_screen) { + return; + } + + if (gtk_check_menu_item_get_active( + GTK_CHECK_MENU_ITEM(s->show_menubar_item))) { + gtk_widget_show(s->menu_bar); + } else { + gtk_widget_hide(s->menu_bar); + } + gd_update_windowsize(vc); +} + +static void gd_accel_show_menubar(void *opaque) +{ + GtkDisplayState *s = opaque; + gtk_menu_item_activate(GTK_MENU_ITEM(s->show_menubar_item)); +} + static void gd_menu_full_screen(GtkMenuItem *item, void *opaque) { GtkDisplayState *s = opaque; @@ -1403,7 +1429,10 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque) } else { gtk_window_unfullscreen(GTK_WINDOW(s->window)); gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s); - gtk_widget_show(s->menu_bar); + if (gtk_check_menu_item_get_active( + GTK_CHECK_MENU_ITEM(s->show_menubar_item))) { + gtk_widget_show(s->menu_bar); + } s->full_screen = FALSE; if (vc->type == GD_VC_GFX) { vc->gfx.scale_x = 1.0; @@ -2036,6 +2065,8 @@ static void gd_connect_signals(GtkDisplayState *s) G_CALLBACK(gd_menu_show_tabs), s); g_signal_connect(s->untabify_item, "activate", G_CALLBACK(gd_menu_untabify), s); + g_signal_connect(s->show_menubar_item, "activate", + G_CALLBACK(gd_menu_show_menubar), s); g_signal_connect(s->window, "delete-event", G_CALLBACK(gd_window_close), s); @@ -2272,6 +2303,19 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s) s->untabify_item = gtk_menu_item_new_with_mnemonic(_("Detach Tab")); gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->untabify_item); + s->show_menubar_item = gtk_check_menu_item_new_with_mnemonic( + _("Show Menubar")); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->show_menubar_item), + TRUE); + gtk_accel_group_connect(s->accel_group, GDK_KEY_m, HOTKEY_MODIFIERS, 0, + g_cclosure_new_swap(G_CALLBACK(gd_accel_show_menubar), s, NULL)); +#if GTK_CHECK_VERSION(3, 8, 0) + gtk_accel_label_set_accel( + GTK_ACCEL_LABEL(gtk_bin_get_child(GTK_BIN(s->show_menubar_item))), + GDK_KEY_m, HOTKEY_MODIFIERS); +#endif + gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->show_menubar_item); + return view_menu; } From 4f4cb8282df82d43ba6b3c9045a3ac6fc4c4ef09 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Mon, 7 May 2018 15:42:37 +0200 Subject: [PATCH 03/10] ui/gtk: Only try to initialize EGL/X11 if GtkGlArea failed The commit referenced below changed the logic by causing the gtk-egl backend to be initialized regardless of whether GtkGlArea initialization succeeded. This causes eglInitialize to crash in Wayland systems without XWayland. This patch restores the previous logic. Fixes: 4c70280592f5 ("ui/gtk: use GtkGlArea on wayland only") Signed-off-by: Tomeu Vizoso Message-id: 20180507134237.14996-1-tomeu.vizoso@collabora.com Signed-off-by: Gerd Hoffmann --- ui/gtk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/gtk.c b/ui/gtk.c index 9e5390f2c2..568c9563ce 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -2484,7 +2484,7 @@ static void early_gtk_display_init(DisplayOptions *opts) if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) { gtk_use_gl_area = true; gtk_gl_area_init(); - } + } else #endif { gtk_egl_init(); From f31f9c1080d8907c95f1501c6abab038eceb5490 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 7 May 2018 12:22:54 +0200 Subject: [PATCH 04/10] vnc: add magic cookie to VncState Set magic cookie on initialization. Clear on cleanup. Sprinkle a bunch of assert()s checking the cookie, to verify the pointer is valid. Signed-off-by: Gerd Hoffmann Message-id: 20180507102254.12107-1-kraxel@redhat.com --- ui/vnc-jobs.c | 4 ++++ ui/vnc.c | 10 +++++++++- ui/vnc.h | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 868dddef4b..b0b15d42a8 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -82,6 +82,7 @@ VncJob *vnc_job_new(VncState *vs) { VncJob *job = g_new0(VncJob, 1); + assert(vs->magic == VNC_MAGIC); job->vs = vs; vnc_lock_queue(queue); QLIST_INIT(&job->rectangles); @@ -214,6 +215,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) /* Here job can only be NULL if queue->exit is true */ job = QTAILQ_FIRST(&queue->jobs); vnc_unlock_queue(queue); + assert(job->vs->magic == VNC_MAGIC); if (queue->exit) { return -1; @@ -236,6 +238,7 @@ static int vnc_worker_thread_loop(VncJobQueue *queue) /* Make a local copy of vs and switch output buffers */ vnc_async_encoding_start(job->vs, &vs); + vs.magic = VNC_MAGIC; /* Start sending rectangles */ n_rectangles = 0; @@ -289,6 +292,7 @@ disconnected: vnc_unlock_queue(queue); qemu_cond_broadcast(&queue->cond); g_free(job); + vs.magic = 0; return 0; } diff --git a/ui/vnc.c b/ui/vnc.c index 5526e54f48..359693238b 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1138,6 +1138,7 @@ static void audio_capture_notify(void *opaque, audcnotification_e cmd) { VncState *vs = opaque; + assert(vs->magic == VNC_MAGIC); switch (cmd) { case AUD_CNOTIFY_DISABLE: vnc_lock_output(vs); @@ -1167,6 +1168,7 @@ static void audio_capture(void *opaque, void *buf, int size) { VncState *vs = opaque; + assert(vs->magic == VNC_MAGIC); vnc_lock_output(vs); if (vs->output.offset < vs->throttle_output_offset) { vnc_write_u8(vs, VNC_MSG_SERVER_QEMU); @@ -1275,6 +1277,7 @@ void vnc_disconnect_finish(VncState *vs) vs->ioc = NULL; object_unref(OBJECT(vs->sioc)); vs->sioc = NULL; + vs->magic = 0; g_free(vs); } @@ -1414,7 +1417,7 @@ static void vnc_client_write_locked(VncState *vs) static void vnc_client_write(VncState *vs) { - + assert(vs->magic == VNC_MAGIC); vnc_lock_output(vs); if (vs->output.offset) { vnc_client_write_locked(vs); @@ -1487,6 +1490,7 @@ static void vnc_jobs_bh(void *opaque) { VncState *vs = opaque; + assert(vs->magic == VNC_MAGIC); vnc_jobs_consume_buffer(vs); } @@ -1537,6 +1541,8 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED, GIOCondition condition, void *opaque) { VncState *vs = opaque; + + assert(vs->magic == VNC_MAGIC); if (condition & G_IO_IN) { if (vnc_client_read(vs) < 0) { /* vs is free()ed here */ @@ -1568,6 +1574,7 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED, void vnc_write(VncState *vs, const void *data, size_t len) { + assert(vs->magic == VNC_MAGIC); if (vs->disconnecting) { return; } @@ -3064,6 +3071,7 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc, int i; trace_vnc_client_connect(vs, sioc); + vs->magic = VNC_MAGIC; vs->sioc = sioc; object_ref(OBJECT(vs->sioc)); vs->ioc = QIO_CHANNEL(sioc); diff --git a/ui/vnc.h b/ui/vnc.h index 7b29def77d..762632929b 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -255,8 +255,11 @@ typedef enum { VNC_STATE_UPDATE_FORCE, } VncStateUpdate; +#define VNC_MAGIC ((uint64_t)0x05b3f069b3d204bb) + struct VncState { + uint64_t magic; QIOChannelSocket *sioc; /* The underlying socket */ QIOChannel *ioc; /* The channel currently used for I/O */ guint ioc_tag; From 776d1344bd0566f412d5bc063e753a6b98530bcf Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 7 May 2018 11:55:36 +0200 Subject: [PATCH 05/10] ui: add qapi parser for -display Add parse_display_qapi() function which parses the -display command line using a qapi visitor for DisplayOptions. Wire up as default catch in parse_display(). Improves the error message for unknown display types. Also enables json as -display argument, i.e. -display "{ 'type': 'gtk' }" Signed-off-by: Gerd Hoffmann Reviewed-by: Eric Blake Message-id: 20180507095539.19584-2-kraxel@redhat.com --- vl.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/vl.c b/vl.c index b9f6b42779..c56f7f8046 100644 --- a/vl.c +++ b/vl.c @@ -120,12 +120,14 @@ int main(int argc, char **argv) #include "ui/qemu-spice.h" #include "qapi/string-input-visitor.h" #include "qapi/opts-visitor.h" +#include "qapi/clone-visitor.h" #include "qom/object_interfaces.h" #include "exec/semihost.h" #include "crypto/init.h" #include "sysemu/replay.h" #include "qapi/qapi-events-run-state.h" #include "qapi/qapi-visit-block-core.h" +#include "qapi/qapi-visit-ui.h" #include "qapi/qapi-commands-block-core.h" #include "qapi/qapi-commands-misc.h" #include "qapi/qapi-commands-run-state.h" @@ -2088,6 +2090,25 @@ static void select_vgahw(const char *p) } } +static void parse_display_qapi(const char *optarg) +{ + Error *err = NULL; + DisplayOptions *opts; + Visitor *v; + + v = qobject_input_visitor_new_str(optarg, "type", &err); + if (!v) { + error_report_err(err); + exit(1); + } + + visit_type_DisplayOptions(v, NULL, &opts, &error_fatal); + QAPI_CLONE_MEMBERS(DisplayOptions, &dpy, opts); + + qapi_free_DisplayOptions(opts); + visit_free(v); +} + static void parse_display(const char *p) { const char *opts; @@ -2203,8 +2224,7 @@ static void parse_display(const char *p) } else if (strstart(p, "none", &opts)) { dpy.type = DISPLAY_TYPE_NONE; } else { - error_report("unknown display type"); - exit(1); + parse_display_qapi(p); } } From 2c9498c3e44cd5574df3baaebfb9d5a095252205 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 7 May 2018 11:55:37 +0200 Subject: [PATCH 06/10] ui: switch trivial displays to qapi parser Drop the option-less display types (egl-headless, curses, none) from parse_display(), so they'll be handled by parse_display_qapi(). Signed-off-by: Gerd Hoffmann Reviewed-by: Eric Blake Message-id: 20180507095539.19584-3-kraxel@redhat.com --- vl.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/vl.c b/vl.c index c56f7f8046..6b8f946d58 100644 --- a/vl.c +++ b/vl.c @@ -2185,10 +2185,6 @@ static void parse_display(const char *p) error_report("VNC requires a display argument vnc="); exit(1); } - } else if (strstart(p, "egl-headless", &opts)) { - dpy.type = DISPLAY_TYPE_EGL_HEADLESS; - } else if (strstart(p, "curses", &opts)) { - dpy.type = DISPLAY_TYPE_CURSES; } else if (strstart(p, "gtk", &opts)) { dpy.type = DISPLAY_TYPE_GTK; while (*opts) { @@ -2221,8 +2217,6 @@ static void parse_display(const char *p) } opts = nextopt; } - } else if (strstart(p, "none", &opts)) { - dpy.type = DISPLAY_TYPE_NONE; } else { parse_display_qapi(p); } From 002b2902f39fd9c2b01881e1ca07db80266dc5bf Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 7 May 2018 11:55:38 +0200 Subject: [PATCH 07/10] ui: switch gtk display to qapi parser Drop the gtk option parser from parse_display(), so parse_display_qapi() will handle it instead. With this change the parser will accept gl=core and gl=es too, gtk must catch the unsupported gles variant now. Signed-off-by: Gerd Hoffmann Message-id: 20180507095539.19584-4-kraxel@redhat.com --- ui/gtk.c | 6 +++++- vl.c | 32 -------------------------------- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index 568c9563ce..ef6ca7179e 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -2478,7 +2478,11 @@ static void early_gtk_display_init(DisplayOptions *opts) } assert(opts->type == DISPLAY_TYPE_GTK); - if (opts->has_gl && opts->gl) { + if (opts->has_gl && opts->gl != DISPLAYGL_MODE_OFF) { + if (opts->gl == DISPLAYGL_MODE_ES) { + error_report("gtk: opengl es not supported"); + return; + } #if defined(CONFIG_OPENGL) #if defined(CONFIG_GTK_GL) && defined(GDK_WINDOWING_WAYLAND) if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) { diff --git a/vl.c b/vl.c index 6b8f946d58..5f1734d851 100644 --- a/vl.c +++ b/vl.c @@ -2185,38 +2185,6 @@ static void parse_display(const char *p) error_report("VNC requires a display argument vnc="); exit(1); } - } else if (strstart(p, "gtk", &opts)) { - dpy.type = DISPLAY_TYPE_GTK; - while (*opts) { - const char *nextopt; - - if (strstart(opts, ",grab_on_hover=", &nextopt)) { - opts = nextopt; - dpy.u.gtk.has_grab_on_hover = true; - if (strstart(opts, "on", &nextopt)) { - dpy.u.gtk.grab_on_hover = true; - } else if (strstart(opts, "off", &nextopt)) { - dpy.u.gtk.grab_on_hover = false; - } else { - goto invalid_gtk_args; - } - } else if (strstart(opts, ",gl=", &nextopt)) { - opts = nextopt; - dpy.has_gl = true; - if (strstart(opts, "on", &nextopt)) { - dpy.gl = DISPLAYGL_MODE_ON; - } else if (strstart(opts, "off", &nextopt)) { - dpy.gl = DISPLAYGL_MODE_OFF; - } else { - goto invalid_gtk_args; - } - } else { - invalid_gtk_args: - error_report("invalid GTK option string"); - exit(1); - } - opts = nextopt; - } } else { parse_display_qapi(p); } From 7a61f4385991a7b47d71c8d657dea1e34a792baf Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 7 May 2018 11:55:39 +0200 Subject: [PATCH 08/10] ui: document non-qapi parser cases. Add comments to the cases not (yet) switched over to parse_display_qapi(). Signed-off-by: Gerd Hoffmann Message-id: 20180507095539.19584-5-kraxel@redhat.com --- vl.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/vl.c b/vl.c index 5f1734d851..3b39bbd7a8 100644 --- a/vl.c +++ b/vl.c @@ -2114,6 +2114,16 @@ static void parse_display(const char *p) const char *opts; if (strstart(p, "sdl", &opts)) { + /* + * sdl DisplayType needs hand-crafted parser instead of + * parse_display_qapi() due to some options not in + * DisplayOptions, specifically: + * - frame + * Already deprecated. + * - ctrl_grab + alt_grab + * Not clear yet what happens to them long-term. Should + * replaced by something better or deprecated and dropped. + */ dpy.type = DISPLAY_TYPE_SDL; while (*opts) { const char *nextopt; @@ -2179,6 +2189,10 @@ static void parse_display(const char *p) opts = nextopt; } } else if (strstart(p, "vnc", &opts)) { + /* + * vnc isn't a (local) DisplayType but a protocol for remote + * display access. + */ if (*opts == '=') { vnc_parse(opts + 1, &error_fatal); } else { From cd6cd8fa0da7839b11ca7e5d7d45b73810394395 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 7 May 2018 11:54:24 +0200 Subject: [PATCH 09/10] console: use linked list for QemuConsoles Signed-off-by: Gerd Hoffmann Message-id: 20180507095424.16220-1-kraxel@redhat.com --- ui/console.c | 105 ++++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 47 deletions(-) diff --git a/ui/console.c b/ui/console.c index b02510cdca..945f05d728 100644 --- a/ui/console.c +++ b/ui/console.c @@ -165,6 +165,8 @@ struct QemuConsole { QEMUFIFO out_fifo; uint8_t out_fifo_buf[16]; QEMUTimer *kbd_timer; + + QTAILQ_ENTRY(QemuConsole) next; }; struct DisplayState { @@ -180,8 +182,8 @@ struct DisplayState { static DisplayState *display_state; static QemuConsole *active_console; -static QemuConsole **consoles; -static int nb_consoles = 0; +static QTAILQ_HEAD(consoles_head, QemuConsole) consoles = + QTAILQ_HEAD_INITIALIZER(consoles); static bool cursor_visible_phase; static QEMUTimer *cursor_timer; @@ -197,7 +199,7 @@ static void gui_update(void *opaque) uint64_t dcl_interval; DisplayState *ds = opaque; DisplayChangeListener *dcl; - int i; + QemuConsole *con; ds->refreshing = true; dpy_refresh(ds); @@ -212,9 +214,9 @@ static void gui_update(void *opaque) } if (ds->update_interval != interval) { ds->update_interval = interval; - for (i = 0; i < nb_consoles; i++) { - if (consoles[i]->hw_ops->update_interval) { - consoles[i]->hw_ops->update_interval(consoles[i]->hw, interval); + QTAILQ_FOREACH(con, &consoles, next) { + if (con->hw_ops->update_interval) { + con->hw_ops->update_interval(con->hw, interval); } } trace_console_refresh(interval); @@ -1292,10 +1294,13 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, s->ds = ds; s->console_type = console_type; - consoles = g_realloc(consoles, sizeof(*consoles) * (nb_consoles+1)); - if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) { - s->index = nb_consoles; - consoles[nb_consoles++] = s; + if (QTAILQ_EMPTY(&consoles)) { + s->index = 0; + QTAILQ_INSERT_TAIL(&consoles, s, next); + } else if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) { + QemuConsole *last = QTAILQ_LAST(&consoles, consoles_head); + s->index = last->index + 1; + QTAILQ_INSERT_TAIL(&consoles, s, next); } else { /* * HACK: Put graphical consoles before text consoles. @@ -1303,15 +1308,24 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, * Only do that for coldplugged devices. After initial device * initialization we will not renumber the consoles any more. */ - for (i = nb_consoles; i > 0; i--) { - if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE) - break; - consoles[i] = consoles[i - 1]; - consoles[i]->index = i; + QemuConsole *c = QTAILQ_FIRST(&consoles); + + while (QTAILQ_NEXT(c, next) != NULL && + c->console_type == GRAPHIC_CONSOLE) { + c = QTAILQ_NEXT(c, next); + } + if (c->console_type == GRAPHIC_CONSOLE) { + /* have no text consoles */ + s->index = c->index + 1; + QTAILQ_INSERT_AFTER(&consoles, c, s, next); + } else { + s->index = c->index; + QTAILQ_INSERT_BEFORE(c, s, next); + /* renumber text consoles */ + for (i = s->index + 1; c != NULL; c = QTAILQ_NEXT(c, next), i++) { + c->index = i; + } } - s->index = i; - consoles[i] = s; - nb_consoles++; } return s; } @@ -1861,21 +1875,21 @@ static DisplayState *get_alloc_displaystate(void) DisplayState *init_displaystate(void) { gchar *name; - int i; + QemuConsole *con; get_alloc_displaystate(); - for (i = 0; i < nb_consoles; i++) { - if (consoles[i]->console_type != GRAPHIC_CONSOLE && - consoles[i]->ds == NULL) { - text_console_do_init(consoles[i]->chr, display_state); + QTAILQ_FOREACH(con, &consoles, next) { + if (con->console_type != GRAPHIC_CONSOLE && + con->ds == NULL) { + text_console_do_init(con->chr, display_state); } /* Hook up into the qom tree here (not in new_console()), once * all QemuConsoles are created and the order / numbering * doesn't change any more */ - name = g_strdup_printf("console[%d]", i); + name = g_strdup_printf("console[%d]", con->index); object_property_add_child(container_get(object_get_root(), "/backend"), - name, OBJECT(consoles[i]), &error_abort); + name, OBJECT(con), &error_abort); g_free(name); } @@ -1957,33 +1971,34 @@ void graphic_console_close(QemuConsole *con) QemuConsole *qemu_console_lookup_by_index(unsigned int index) { - if (index >= nb_consoles) { - return NULL; + QemuConsole *con; + + QTAILQ_FOREACH(con, &consoles, next) { + if (con->index == index) { + return con; + } } - return consoles[index]; + return NULL; } QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head) { + QemuConsole *con; Object *obj; uint32_t h; - int i; - for (i = 0; i < nb_consoles; i++) { - if (!consoles[i]) { - continue; - } - obj = object_property_get_link(OBJECT(consoles[i]), + QTAILQ_FOREACH(con, &consoles, next) { + obj = object_property_get_link(OBJECT(con), "device", &error_abort); if (DEVICE(obj) != dev) { continue; } - h = object_property_get_uint(OBJECT(consoles[i]), + h = object_property_get_uint(OBJECT(con), "head", &error_abort); if (h != head) { continue; } - return consoles[i]; + return con; } return NULL; } @@ -2013,22 +2028,19 @@ QemuConsole *qemu_console_lookup_by_device_name(const char *device_id, QemuConsole *qemu_console_lookup_unused(void) { + QemuConsole *con; Object *obj; - int i; - for (i = 0; i < nb_consoles; i++) { - if (!consoles[i]) { + QTAILQ_FOREACH(con, &consoles, next) { + if (con->hw_ops != &unused_ops) { continue; } - if (consoles[i]->hw_ops != &unused_ops) { - continue; - } - obj = object_property_get_link(OBJECT(consoles[i]), + obj = object_property_get_link(OBJECT(con), "device", &error_abort); if (obj != NULL) { continue; } - return consoles[i]; + return con; } return NULL; } @@ -2130,12 +2142,11 @@ static void text_console_update_cursor_timer(void) static void text_console_update_cursor(void *opaque) { QemuConsole *s; - int i, count = 0; + int count = 0; cursor_visible_phase = !cursor_visible_phase; - for (i = 0; i < nb_consoles; i++) { - s = consoles[i]; + QTAILQ_FOREACH(s, &consoles, next) { if (qemu_console_is_graphic(s) || !qemu_console_is_visible(s)) { continue; From 677b490501823c1cb6946d8bb9e7907c12cd0c71 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Fri, 11 May 2018 01:07:39 +0200 Subject: [PATCH 10/10] gtk: disable the F10 menubar key The F10 key is used in various applications, disable it unconditionally (do not limit it to grab mode). Note that this property is deprecated and might be removed in the future (GTK+ commit b082fb598d). Fixes: https://bugs.launchpad.net/qemu/+bug/1726910 Signed-off-by: Peter Wu Message-id: 20180510230739.28459-2-peter@lekensteyn.nl Signed-off-by: Gerd Hoffmann --- ui/gtk.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui/gtk.c b/ui/gtk.c index ef6ca7179e..dbce970dc4 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -2321,6 +2321,8 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s) static void gd_create_menus(GtkDisplayState *s) { + GtkSettings *settings; + s->accel_group = gtk_accel_group_new(); s->machine_menu = gd_create_menu_machine(s); s->view_menu = gd_create_menu_view(s); @@ -2336,6 +2338,10 @@ static void gd_create_menus(GtkDisplayState *s) g_object_set_data(G_OBJECT(s->window), "accel_group", s->accel_group); gtk_window_add_accel_group(GTK_WINDOW(s->window), s->accel_group); + + /* Disable the default "F10" menu shortcut. */ + settings = gtk_widget_get_settings(s->window); + g_object_set(G_OBJECT(settings), "gtk-menu-bar-accel", "", NULL); }