When pressing Alt-Tab for example, the application receives the KeyPress event for Alt key before losing focus, but when focusing it back it never receives the corresponding KeyRelease event and this can lead to incorrect key state for applications listening on WM_SYSKEYUP/DOWN messages, or for applications that use dinput keyboard device which is implemented with the corresponding low-level keyboard hooks messages.
When focus is gained back the application receives a KeymapNotify to indicate the full keyboard state, and this can be used to make up for the missing KeyRelease events.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winex11.drv/keyboard.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 131c5f5442f..166b5446aab 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1209,14 +1209,20 @@ BOOL X11DRV_KeymapNotify( HWND hwnd, XEvent *event ) int i, j; BYTE keystate[256]; WORD vkey; + WORD scan; + DWORD flags; BOOL changed = FALSE; struct { WORD vkey; + WORD scan; WORD pressed; } keys[256];
if (!get_async_key_state( keystate )) return FALSE;
+ /* from KeymapNotify documentation this should always be true */ + if (!hwnd) hwnd = GetForegroundWindow(); + memset(keys, 0, sizeof(keys));
EnterCriticalSection( &kbd_section ); @@ -1229,11 +1235,13 @@ BOOL X11DRV_KeymapNotify( HWND hwnd, XEvent *event ) for (j = 0; j < 8; j++) { vkey = keyc2vkey[(i * 8) + j]; + scan = keyc2scan[(i * 8) + j] & 0xff;
/* If multiple keys map to the same vkey, we want to report it as * pressed iff any of them are pressed. */ if (!keys[vkey & 0xff].vkey) keys[vkey & 0xff].vkey = vkey; if (event->xkeymap.key_vector[i] & (1<<j)) keys[vkey & 0xff].pressed = TRUE; + keys[vkey & 0xff].scan = scan; } }
@@ -1244,6 +1252,14 @@ BOOL X11DRV_KeymapNotify( HWND hwnd, XEvent *event ) TRACE( "Adjusting state for vkey %#.2x. State before %#.2x\n", keys[vkey].vkey, keystate[vkey]);
+ flags = 0; + if (!keys[vkey].pressed) + flags |= KEYEVENTF_KEYUP; + if (keys[vkey].vkey & 0x100) + flags |= KEYEVENTF_EXTENDEDKEY; + + X11DRV_send_keyboard_input( hwnd, vkey, keys[vkey].scan, flags, GetTickCount() ); + update_key_state( keystate, vkey, keys[vkey].pressed ); changed = TRUE; }