From fca4774a96843ba9d32a5d5d1c3826e1478facae Mon Sep 17 00:00:00 2001 From: linzhecheng Date: Mon, 25 Dec 2017 10:37:30 +0800 Subject: [PATCH 1/9] input: fix memory leak If kbd_queue is not empty and queue_count >= queue_limit, we should free evt. Change-Id: Ieeacf90d5e7e370a40452ec79031912d8b864d83 Signed-off-by: linzhecheng Message-id: 20171225023730.5512-1-linzhecheng@huawei.com Signed-off-by: Gerd Hoffmann --- ui/input.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/input.c b/ui/input.c index 3e2d324278..e5b78aae9e 100644 --- a/ui/input.c +++ b/ui/input.c @@ -421,6 +421,8 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down) } else if (queue_count < queue_limit) { qemu_input_queue_event(&kbd_queue, src, evt); qemu_input_queue_sync(&kbd_queue); + } else { + qapi_free_InputEvent(evt); } } From b7715af2b31f47060cc5b4be930d16c13be93fa9 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 12 Dec 2017 11:34:40 +0000 Subject: [PATCH 2/9] ui: deprecate use of GTK 2.x in favour of 3.x series The GTK 3.0 release was made in Feb, 2011: https://blog.gtk.org/2011/02/10/gtk-3-0-released/ That will soon be 7 years ago, which is enough time to consider the 3.x series widely supported. Thus we deprecate the GTK 2.x support, which will allow us to delete it in the last release of 2018. By this time, GTK 3.x will be almost 8 years old. Signed-off-by: Daniel P. Berrange Message-id: 20171212113440.16483-1-berrange@redhat.com Signed-off-by: Gerd Hoffmann --- configure | 6 ++++++ qemu-doc.texi | 9 +++++++++ ui/gtk.c | 5 +++++ 3 files changed, 20 insertions(+) diff --git a/configure b/configure index 89bd662a6a..b272a0336b 100755 --- a/configure +++ b/configure @@ -5629,6 +5629,12 @@ if test "$sdl_too_old" = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" fi +if test "$gtkabi" = "2.0"; then + echo + echo "WARNING: Use of GTK 2.0 is deprecated and will be removed in" + echo "WARNING: future releases. Please switch to using GTK 3.0" +fi + if test "$supported_cpu" = "no"; then echo echo "WARNING: SUPPORT FOR THIS HOST CPU WILL GO AWAY IN FUTURE RELEASES!" diff --git a/qemu-doc.texi b/qemu-doc.texi index a3d2054c90..3e9eb819a6 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2587,6 +2587,15 @@ they were first deprecated in the 2.10.0 release. What follows is a list of all features currently marked as deprecated. +@section Build options + +@subsection GTK 2.x + +Previously QEMU has supported building against both GTK 2.x +and 3.x series APIs. Support for the GTK 2.x builds will be +discontinued, so maintainers should switch to using GTK 3.x, +which is the default. + @section System emulator command line arguments @subsection -tdf (since 1.3.0) diff --git a/ui/gtk.c b/ui/gtk.c index 342e96fbe9..f3b7567984 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -2248,6 +2248,11 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover) exit(1); } +#if !GTK_CHECK_VERSION(3, 0, 0) + g_printerr("Running QEMU with GTK 2.x is deprecated, and will be removed\n" + "in a future release. Please switch to GTK 3.x instead\n"); +#endif + s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); #if GTK_CHECK_VERSION(3, 2, 0) s->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); From 9fedfa49092c55628a96fd2783060d58ccec9db0 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Wed, 22 Nov 2017 13:56:22 +0000 Subject: [PATCH 3/9] spice: remove QXLWorker interface field This fields points to an old interface that is no more used in the current code. Signed-off-by: Frediano Ziglio Message-id: 20171122135625.16625-1-fziglio@redhat.com Signed-off-by: Gerd Hoffmann --- hw/display/qxl.c | 1 - include/ui/spice-display.h | 1 - ui/spice-display.c | 2 -- 3 files changed, 4 deletions(-) diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 99365c3e8f..b9fa067f6e 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -518,7 +518,6 @@ static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker) PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); trace_qxl_interface_attach_worker(qxl->id); - qxl->ssd.worker = qxl_worker; } static void interface_set_compression_level(QXLInstance *sin, int level) diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index aaf2019889..6b5c73b21c 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -86,7 +86,6 @@ struct SimpleSpiceDisplay { DisplayChangeListener dcl; void *buf; int bufsize; - QXLWorker *worker; QXLInstance qxl; uint32_t unique; pixman_image_t *surface; diff --git a/ui/spice-display.c b/ui/spice-display.c index ad1ceafb3f..85a72fe76a 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -519,7 +519,6 @@ static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker) SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl); dprint(1, "%s/%d:\n", __func__, ssd->qxl.id); - ssd->worker = qxl_worker; } static void interface_set_compression_level(QXLInstance *sin, int level) @@ -1028,7 +1027,6 @@ static void qemu_spice_display_init_one(QemuConsole *con) ssd->qxl.base.sif = &dpy_interface.base; qemu_spice_add_display_interface(&ssd->qxl, con); - assert(ssd->worker); qemu_spice_create_host_memslot(ssd); register_displaychangelistener(&ssd->dcl); From 44e8f22986a010d6078e5cd868098283b875a515 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Wed, 22 Nov 2017 13:56:23 +0000 Subject: [PATCH 4/9] spice: remove unused watch list Signed-off-by: Frediano Ziglio Message-id: 20171122135625.16625-2-fziglio@redhat.com Signed-off-by: Gerd Hoffmann --- ui/spice-core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ui/spice-core.c b/ui/spice-core.c index ea04dc69b5..85b9ea2127 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -92,9 +92,7 @@ struct SpiceWatch { int event_mask; SpiceWatchFunc func; void *opaque; - QTAILQ_ENTRY(SpiceWatch) next; }; -static QTAILQ_HEAD(, SpiceWatch) watches = QTAILQ_HEAD_INITIALIZER(watches); static void watch_read(void *opaque) { @@ -131,7 +129,6 @@ static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void * watch->fd = fd; watch->func = func; watch->opaque = opaque; - QTAILQ_INSERT_TAIL(&watches, watch, next); watch_update_mask(watch, event_mask); return watch; @@ -140,7 +137,6 @@ static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void * static void watch_remove(SpiceWatch *watch) { qemu_set_fd_handler(watch->fd, NULL, NULL, NULL); - QTAILQ_REMOVE(&watches, watch, next); g_free(watch); } From 58a5d33aa8da8b0f55c97232f74bdf987885df17 Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Wed, 22 Nov 2017 13:56:24 +0000 Subject: [PATCH 5/9] spice: remove only written event_mask field Signed-off-by: Frediano Ziglio Message-id: 20171122135625.16625-3-fziglio@redhat.com Signed-off-by: Gerd Hoffmann --- ui/spice-core.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ui/spice-core.c b/ui/spice-core.c index 85b9ea2127..6d579faaae 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -89,7 +89,6 @@ static void timer_remove(SpiceTimer *timer) struct SpiceWatch { int fd; - int event_mask; SpiceWatchFunc func; void *opaque; }; @@ -111,11 +110,10 @@ static void watch_update_mask(SpiceWatch *watch, int event_mask) IOHandler *on_read = NULL; IOHandler *on_write = NULL; - watch->event_mask = event_mask; - if (watch->event_mask & SPICE_WATCH_EVENT_READ) { + if (event_mask & SPICE_WATCH_EVENT_READ) { on_read = watch_read; } - if (watch->event_mask & SPICE_WATCH_EVENT_WRITE) { + if (event_mask & SPICE_WATCH_EVENT_WRITE) { on_write = watch_write; } qemu_set_fd_handler(watch->fd, on_read, on_write, watch); From abda4766815af3db3c3c43fa96a45d935e2b217a Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Wed, 22 Nov 2017 13:56:25 +0000 Subject: [PATCH 6/9] spice: remove unused timer list Signed-off-by: Frediano Ziglio Message-id: 20171122135625.16625-4-fziglio@redhat.com Signed-off-by: Gerd Hoffmann --- ui/spice-core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ui/spice-core.c b/ui/spice-core.c index 6d579faaae..2baf0c7120 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -55,9 +55,7 @@ static QemuThread me; struct SpiceTimer { QEMUTimer *timer; - QTAILQ_ENTRY(SpiceTimer) next; }; -static QTAILQ_HEAD(, SpiceTimer) timers = QTAILQ_HEAD_INITIALIZER(timers); static SpiceTimer *timer_add(SpiceTimerFunc func, void *opaque) { @@ -65,7 +63,6 @@ static SpiceTimer *timer_add(SpiceTimerFunc func, void *opaque) timer = g_malloc0(sizeof(*timer)); timer->timer = timer_new_ms(QEMU_CLOCK_REALTIME, func, opaque); - QTAILQ_INSERT_TAIL(&timers, timer, next); return timer; } @@ -83,7 +80,6 @@ static void timer_remove(SpiceTimer *timer) { timer_del(timer->timer); timer_free(timer->timer); - QTAILQ_REMOVE(&timers, timer, next); g_free(timer); } From 2821671629531184d9fa2f8fcc3cea1bd605b872 Mon Sep 17 00:00:00 2001 From: Jindrich Makovicka Date: Fri, 17 Nov 2017 12:22:56 +0100 Subject: [PATCH 7/9] sdl2: Do not hide the cursor on auxilliary windows Signed-off-by: Jindrich Makovicka Message-Id: <20171117112258.5888-2-makovick@gmail.com> Signed-off-by: Gerd Hoffmann --- ui/sdl2.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ui/sdl2.c b/ui/sdl2.c index 8718cf36b5..62a75318dd 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -466,6 +466,10 @@ static void handle_mousemotion(SDL_Event *ev) int max_x, max_y; struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + if (!qemu_console_is_graphic(scon->dcl.con)) { + return; + } + if (qemu_input_is_absolute() || absolute_enabled) { int scr_w, scr_h; SDL_GetWindowSize(scon->real_window, &scr_w, &scr_h); @@ -494,6 +498,10 @@ static void handle_mousebutton(SDL_Event *ev) SDL_MouseButtonEvent *bev; struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + if (!qemu_console_is_graphic(scon->dcl.con)) { + return; + } + bev = &ev->button; if (!gui_grab && !qemu_input_is_absolute()) { if (ev->type == SDL_MOUSEBUTTONUP && bev->button == SDL_BUTTON_LEFT) { @@ -516,6 +524,10 @@ static void handle_mousewheel(SDL_Event *ev) SDL_MouseWheelEvent *wev = &ev->wheel; InputButton btn; + if (!qemu_console_is_graphic(scon->dcl.con)) { + return; + } + if (wev->y > 0) { btn = INPUT_BUTTON_WHEEL_UP; } else if (wev->y < 0) { @@ -657,6 +669,11 @@ static void sdl_mouse_warp(DisplayChangeListener *dcl, int x, int y, int on) { struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + + if (!qemu_console_is_graphic(scon->dcl.con)) { + return; + } + if (on) { if (!guest_cursor) { sdl_show_cursor(); From d9f0626280fb5224071415e6fd82cc0c2e9d6590 Mon Sep 17 00:00:00 2001 From: Jindrich Makovicka Date: Fri, 17 Nov 2017 12:22:57 +0100 Subject: [PATCH 8/9] sdl2 uses surface relative coordinates This patch fixes mouse positioning with -device usb-tablet and fullscreen or resized window. Fixes: 46522a82236ea0cf9011b89896d2d8f8ddaf2443 Signed-off-by: Jindrich Makovicka Message-Id: <20171117112258.5888-3-makovick@gmail.com> Signed-off-by: Gerd Hoffmann --- ui/sdl2.c | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/ui/sdl2.c b/ui/sdl2.c index 62a75318dd..8a0bd9149b 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -276,32 +276,10 @@ static void sdl_send_mouse_event(struct sdl2_console *scon, int dx, int dy, } if (qemu_input_is_absolute()) { - int scr_w, scr_h; - int max_w = 0, max_h = 0; - int off_x = 0, off_y = 0; - int cur_off_x = 0, cur_off_y = 0; - int i; - - for (i = 0; i < sdl2_num_outputs; i++) { - struct sdl2_console *thiscon = &sdl2_console[i]; - if (thiscon->real_window && thiscon->surface) { - SDL_GetWindowSize(thiscon->real_window, &scr_w, &scr_h); - cur_off_x = thiscon->x; - cur_off_y = thiscon->y; - if (scr_w + cur_off_x > max_w) { - max_w = scr_w + cur_off_x; - } - if (scr_h + cur_off_y > max_h) { - max_h = scr_h + cur_off_y; - } - if (i == scon->idx) { - off_x = cur_off_x; - off_y = cur_off_y; - } - } - } - qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_X, off_x + x, 0, max_w); - qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_Y, off_y + y, 0, max_h); + qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_X, + x, 0, surface_width(scon->surface)); + qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_Y, + y, 0, surface_height(scon->surface)); } else { if (guest_cursor) { x -= guest_x; From 849bbe60356caf3d320202d45f1ddffeefae06c7 Mon Sep 17 00:00:00 2001 From: Jindrich Makovicka Date: Fri, 17 Nov 2017 12:22:58 +0100 Subject: [PATCH 9/9] sdl2: Ignore UI hotkeys after a focus change when GUI modifier is held When SDL2 windows change focus while a key is held, the window that receives the focus also receives a new KeyDown event, without an autorepeat flag. This means that if a WM places the qemu console over the main window after Ctrl-Alt-2, the console closes immediately after opening. Then, the main window receives the KeyDown event again and the whole process repeats. This patch makes the SDL2 UI ignore the KeyDown events on a window that just received the focus, if the GUI modifier was held. The ignore flag is reset on a first KeyUp event. This effectively works around the issue above. Signed-off-by: Jindrich Makovicka Message-Id: <20171117112258.5888-4-makovick@gmail.com> Signed-off-by: Gerd Hoffmann --- include/ui/sdl2.h | 1 + ui/sdl2.c | 32 ++++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h index b29cf803c9..51084e6320 100644 --- a/include/ui/sdl2.h +++ b/include/ui/sdl2.h @@ -24,6 +24,7 @@ struct sdl2_console { int opengl; int updates; int idle_counter; + int ignore_hotkeys; SDL_GLContext winctx; #ifdef CONFIG_OPENGL QemuGLShader *gls; diff --git a/ui/sdl2.c b/ui/sdl2.c index 8a0bd9149b..89c6a2633c 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -312,22 +312,28 @@ static void toggle_full_screen(struct sdl2_console *scon) sdl2_redraw(scon); } -static void handle_keydown(SDL_Event *ev) +static int get_mod_state(void) { - int mod_state, win; - struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + SDL_Keymod mod = SDL_GetModState(); if (alt_grab) { - mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) == + return (mod & (gui_grab_code | KMOD_LSHIFT)) == (gui_grab_code | KMOD_LSHIFT); } else if (ctrl_grab) { - mod_state = (SDL_GetModState() & KMOD_RCTRL) == KMOD_RCTRL; + return (mod & KMOD_RCTRL) == KMOD_RCTRL; } else { - mod_state = (SDL_GetModState() & gui_grab_code) == gui_grab_code; + return (mod & gui_grab_code) == gui_grab_code; } - gui_key_modifier_pressed = mod_state; +} - if (gui_key_modifier_pressed) { +static void handle_keydown(SDL_Event *ev) +{ + int win; + struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + + gui_key_modifier_pressed = get_mod_state(); + + if (!scon->ignore_hotkeys && gui_key_modifier_pressed && !ev->key.repeat) { switch (ev->key.keysym.scancode) { case SDL_SCANCODE_2: case SDL_SCANCODE_3: @@ -401,6 +407,8 @@ static void handle_keyup(SDL_Event *ev) int mod_state; struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + scon->ignore_hotkeys = false; + if (!alt_grab) { mod_state = (ev->key.keysym.mod & gui_grab_code); } else { @@ -547,6 +555,14 @@ static void handle_windowevent(SDL_Event *ev) if (!gui_grab && (qemu_input_is_absolute() || absolute_enabled)) { absolute_mouse_grab(scon); } + /* If a new console window opened using a hotkey receives the + * focus, SDL sends another KEYDOWN event to the new window, + * closing the console window immediately after. + * + * Work around this by ignoring further hotkey events until a + * key is released. + */ + scon->ignore_hotkeys = get_mod_state(); break; case SDL_WINDOWEVENT_FOCUS_LOST: if (gui_grab && !gui_fullscreen) {