The Wayland specification states about the keyboard leave event:
After this event client must assume that all keys, including modifiers, are lifted and also it must stop key repeating if there's some going on.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56001
---
To replicate a manifestation of the problem: 1. Open notepad 2. Hold down a key, wait for repetition to begin 3. While keeping key pressed, change focus to some other window (e.g. click away) 4. Key keeps repeating in notepad forever (lifting the key has no effect now, since the keyboard focus has been lost)
From: Alexandros Frantzis alexandros.frantzis@collabora.com
The Wayland specification states about the keyboard leave event:
After this event client must assume that all keys, including modifiers, are lifted and also it must stop key repeating if there's some going on.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56001 --- dlls/winewayland.drv/wayland_keyboard.c | 44 +++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/dlls/winewayland.drv/wayland_keyboard.c b/dlls/winewayland.drv/wayland_keyboard.c index ba6a66995a6..2ff7646f6a6 100644 --- a/dlls/winewayland.drv/wayland_keyboard.c +++ b/dlls/winewayland.drv/wayland_keyboard.c @@ -33,6 +33,7 @@
#include "waylanddrv.h" #include "wine/debug.h" +#include "wine/server.h"
WINE_DEFAULT_DEBUG_CHANNEL(keyboard); WINE_DECLARE_DEBUG_CHANNEL(key); @@ -602,6 +603,45 @@ static BOOL find_xkb_layout_variant(const char *name, const char **layout, const return FALSE; }
+static BOOL get_async_key_state(BYTE state[256]) +{ + BOOL ret; + + SERVER_START_REQ(get_key_state) + { + req->async = 1; + req->key = -1; + wine_server_set_reply(req, state, 256); + ret = !wine_server_call(req); + } + SERVER_END_REQ; + + return ret; +} + +static void release_all_keys(HWND hwnd) +{ + BYTE state[256]; + int vkey; + INPUT input = {.type = INPUT_KEYBOARD}; + + get_async_key_state(state); + + for (vkey = 0; vkey < 256; vkey++) + { + if (state[vkey] & 0x80) + { + UINT scan = NtUserMapVirtualKeyEx(vkey, MAPVK_VK_TO_VSC_EX, + keyboard_hkl); + input.ki.wVk = vkey; + input.ki.wScan = scan & 0xff; + input.ki.dwFlags = KEYEVENTF_KEYUP; + if (scan & ~0xff) input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; + __wine_send_input(hwnd, &input, NULL); + } + } +} + /********************************************************************** * Keyboard handling */ @@ -740,6 +780,10 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, keyboard->focused_hwnd = NULL; pthread_mutex_unlock(&keyboard->mutex);
+ /* The spec for the leave event tells us to treat all keys as released, + * and for any key repetition to stop. */ + release_all_keys(hwnd); + /* FIXME: update foreground window as well */ }