Skip to content

Commit

Permalink
sdl2: Ignore UI hotkeys after a focus change when GUI modifier is held
Browse files Browse the repository at this point in the history
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 <[email protected]>
Message-Id: <[email protected]>
Signed-off-by: Gerd Hoffmann <[email protected]>
  • Loading branch information
jmakovicka authored and kraxel committed Jan 12, 2018
1 parent d9f0626 commit 849bbe6
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
1 change: 1 addition & 0 deletions include/ui/sdl2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
32 changes: 24 additions & 8 deletions ui/sdl2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 849bbe6

Please sign in to comment.