From 6ae1faa3de228624a60f8a2d0b3d8dd2485fd677 Mon Sep 17 00:00:00 2001 From: "Pierre-Loup A. Griffais" Date: Thu, 11 Sep 2014 19:24:42 -0700 Subject: [PATCH] [X11] Reconcile logical keyboard state with physical state on FocusIn since the window system doesn't do it for us like other platforms. This prevents sticky keys and missed keys when going in and out of focus, for example Alt would appear to stick if switching away from an SDL app with Alt-Tab and had to be pressed again. CR: Sam --- src/video/x11/SDL_x11events.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index c67fc38e3..b4b33d76a 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -507,6 +507,27 @@ ProcessHitTest(_THIS, const SDL_WindowData *data, const XEvent *xev) return ret; } +static void +ReconcileKeyboardState(_THIS, const SDL_WindowData *data) +{ + SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata; + SDL_Window* window = data->window; + Display *display = viddata->display; + char keys[32]; + int keycode = 0; + + X11_XQueryKeymap( display, keys ); + + while ( keycode < 256 ) { + if ( keys[keycode / 8] & (1 << (keycode % 8)) ) { + SDL_SendKeyboardKey(SDL_PRESSED, viddata->key_layout[keycode]); + } else { + SDL_SendKeyboardKey(SDL_RELEASED, viddata->key_layout[keycode]); + } + keycode++; + } +} + static void X11_DispatchEvent(_THIS) { @@ -655,16 +676,7 @@ X11_DispatchEvent(_THIS) #endif if (data->pending_focus == PENDING_FOCUS_OUT && data->window == SDL_GetKeyboardFocus()) { - /* We want to reset the keyboard here, because we may have - missed keyboard messages after our previous FocusOut. - */ - /* Actually, if we do this we clear the ALT key on Unity - because it briefly takes focus for their dashboard. - - I think it's better to think the ALT key is held down - when it's not, then always lose the ALT modifier on Unity. - */ - /* SDL_ResetKeyboard(); */ + ReconcileKeyboardState(_this, data); } data->pending_focus = PENDING_FOCUS_IN; data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_IN_TIME;