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) {