From f58946e3baf65f5de2c081cd2c4416b3a2bc0f59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Thu, 9 Nov 2023 23:28:27 +0100 Subject: [PATCH] winewayland.drv: Basic handling of Wayland keyboard events. Handle Wayland keyboard events and translate them to Windows events, currently using a hardcoded US key mapping. --- configure | 91 +++++++- configure.ac | 5 +- dlls/winewayland.drv/Makefile.in | 5 +- dlls/winewayland.drv/wayland.c | 6 + dlls/winewayland.drv/wayland_keyboard.c | 274 ++++++++++++++++++++++++ dlls/winewayland.drv/wayland_surface.c | 5 + dlls/winewayland.drv/waylanddrv.h | 17 ++ include/config.h.in | 3 + 8 files changed, 402 insertions(+), 4 deletions(-) create mode 100644 dlls/winewayland.drv/wayland_keyboard.c diff --git a/configure b/configure index ce5019f76a9..e14a35b5266 100755 --- a/configure +++ b/configure @@ -702,6 +702,8 @@ INOTIFY_LIBS INOTIFY_CFLAGS PCSCLITE_LIBS PCAP_LIBS +XKBCOMMON_LIBS +XKBCOMMON_CFLAGS WAYLAND_SCANNER WAYLAND_CLIENT_LIBS WAYLAND_CLIENT_CFLAGS @@ -1793,6 +1795,8 @@ XMKMF CPP WAYLAND_CLIENT_CFLAGS WAYLAND_CLIENT_LIBS +XKBCOMMON_CFLAGS +XKBCOMMON_LIBS INOTIFY_CFLAGS INOTIFY_LIBS DBUS_CFLAGS @@ -2612,6 +2616,10 @@ Some influential environment variables: C compiler flags for wayland-client, overriding pkg-config WAYLAND_CLIENT_LIBS Linker flags for wayland-client, overriding pkg-config + XKBCOMMON_CFLAGS + C compiler flags for xkbcommon, overriding pkg-config + XKBCOMMON_LIBS + Linker flags for xkbcommon, overriding pkg-config INOTIFY_CFLAGS C compiler flags for libinotify, overriding pkg-config INOTIFY_LIBS @@ -11078,6 +11086,7 @@ CFLAGS="$CFLAGS -nostdlib -nodefaultlibs -Wmicrosoft-enum-forward-reference" ac_exeext=".exe" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +void *__os_arm64x_dispatch_ret = 0; int __cdecl mainCRTStartup(void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" @@ -15825,8 +15834,86 @@ fi CPPFLAGS=$ac_save_CPPFLAGS + rm -f conftest.err +if ${XKBCOMMON_CFLAGS:+false} : +then : + if test ${PKG_CONFIG+y} +then : + XKBCOMMON_CFLAGS=`$PKG_CONFIG --cflags xkbcommon 2>conftest.err` fi -if test -z "$WAYLAND_CLIENT_LIBS" -o -z "$WAYLAND_SCANNER" -o "$ac_cv_header_linux_input_h" = "no" +fi + +if ${XKBCOMMON_LIBS:+false} : +then : + if test ${PKG_CONFIG+y} +then : + XKBCOMMON_LIBS=`$PKG_CONFIG --libs xkbcommon 2>/dev/null` +fi +fi + + +printf "%s\n" "$as_me:${as_lineno-$LINENO}: xkbcommon cflags: $XKBCOMMON_CFLAGS" >&5 +printf "%s\n" "$as_me:${as_lineno-$LINENO}: xkbcommon libs: $XKBCOMMON_LIBS" >&5 +if test -s conftest.err; then + printf %s "$as_me:${as_lineno-$LINENO}: xkbcommon errors: " >&5 + cat conftest.err >&5 +fi +rm -f conftest.err +ac_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $XKBCOMMON_CFLAGS" +ac_fn_c_check_header_compile "$LINENO" "xkbcommon/xkbcommon.h" "ac_cv_header_xkbcommon_xkbcommon_h" "$ac_includes_default" +if test "x$ac_cv_header_xkbcommon_xkbcommon_h" = xyes +then : + printf "%s\n" "#define HAVE_XKBCOMMON_XKBCOMMON_H 1" >>confdefs.h + +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for xkb_context_new in -lxkbcommon" >&5 +printf %s "checking for xkb_context_new in -lxkbcommon... " >&6; } +if test ${ac_cv_lib_xkbcommon_xkb_context_new+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lxkbcommon $XKBCOMMON_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char xkb_context_new (); +int +main (void) +{ +return xkb_context_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_xkbcommon_xkb_context_new=yes +else $as_nop + ac_cv_lib_xkbcommon_xkb_context_new=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xkbcommon_xkb_context_new" >&5 +printf "%s\n" "$ac_cv_lib_xkbcommon_xkb_context_new" >&6; } +if test "x$ac_cv_lib_xkbcommon_xkb_context_new" = xyes +then : + : +else $as_nop + XKBCOMMON_LIBS="" +fi + +CPPFLAGS=$ac_save_CPPFLAGS + +fi +if test -z "$WAYLAND_CLIENT_LIBS" -o -z "$WAYLAND_SCANNER" -o -z "$XKBCOMMON_LIBS" -o "$ac_cv_header_linux_input_h" = "no" then : case "x$with_wayland" in x) as_fn_append wine_notices "|Wayland ${notice_platform}development files not found, the Wayland driver won't be supported." ;; @@ -23410,6 +23497,8 @@ X_EXTRA_LIBS = $X_EXTRA_LIBS WAYLAND_CLIENT_CFLAGS = $WAYLAND_CLIENT_CFLAGS WAYLAND_CLIENT_LIBS = $WAYLAND_CLIENT_LIBS WAYLAND_SCANNER = $WAYLAND_SCANNER +XKBCOMMON_CFLAGS = $XKBCOMMON_CFLAGS +XKBCOMMON_LIBS = $XKBCOMMON_LIBS PCAP_LIBS = $PCAP_LIBS PCSCLITE_LIBS = $PCSCLITE_LIBS INOTIFY_CFLAGS = $INOTIFY_CFLAGS diff --git a/configure.ac b/configure.ac index 1167ff765f7..154e0ee06aa 100644 --- a/configure.ac +++ b/configure.ac @@ -1368,8 +1368,11 @@ then [AC_PATH_PROG(WAYLAND_SCANNER,wayland-scanner, [`test -n "$PKG_CONFIG" && $PKG_CONFIG --variable=wayland_scanner wayland-scanner 2>/dev/null`])], [WAYLAND_CLIENT_LIBS=""],[$WAYLAND_CLIENT_LIBS])])]) + WINE_PACKAGE_FLAGS(XKBCOMMON,[xkbcommon],,,, + [AC_CHECK_HEADERS([xkbcommon/xkbcommon.h]) + AC_CHECK_LIB(xkbcommon,xkb_context_new,[:],[XKBCOMMON_LIBS=""],[$XKBCOMMON_LIBS])]) fi -WINE_NOTICE_WITH(wayland, [test -z "$WAYLAND_CLIENT_LIBS" -o -z "$WAYLAND_SCANNER" -o "$ac_cv_header_linux_input_h" = "no"], +WINE_NOTICE_WITH(wayland, [test -z "$WAYLAND_CLIENT_LIBS" -o -z "$WAYLAND_SCANNER" -o -z "$XKBCOMMON_LIBS" -o "$ac_cv_header_linux_input_h" = "no"], [Wayland ${notice_platform}development files not found, the Wayland driver won't be supported.], [enable_winewayland_drv]) diff --git a/dlls/winewayland.drv/Makefile.in b/dlls/winewayland.drv/Makefile.in index e1019ad8348..4fbc516266e 100644 --- a/dlls/winewayland.drv/Makefile.in +++ b/dlls/winewayland.drv/Makefile.in @@ -1,13 +1,14 @@ MODULE = winewayland.drv UNIXLIB = winewayland.so -UNIX_CFLAGS = $(WAYLAND_CLIENT_CFLAGS) -UNIX_LIBS = -lwin32u $(WAYLAND_CLIENT_LIBS) $(PTHREAD_LIBS) -lm +UNIX_CFLAGS = $(WAYLAND_CLIENT_CFLAGS) $(XKBCOMMON_CFLAGS) +UNIX_LIBS = -lwin32u $(WAYLAND_CLIENT_LIBS) $(XKBCOMMON_LIBS) $(PTHREAD_LIBS) -lm SOURCES = \ display.c \ dllmain.c \ version.rc \ wayland.c \ + wayland_keyboard.c \ wayland_output.c \ wayland_pointer.c \ wayland_surface.c \ diff --git a/dlls/winewayland.drv/wayland.c b/dlls/winewayland.drv/wayland.c index b8c69a105cb..7c7a217d310 100644 --- a/dlls/winewayland.drv/wayland.c +++ b/dlls/winewayland.drv/wayland.c @@ -35,6 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv); struct wayland process_wayland = { .seat.mutex = PTHREAD_MUTEX_INITIALIZER, + .keyboard.mutex = PTHREAD_MUTEX_INITIALIZER, .pointer.mutex = PTHREAD_MUTEX_INITIALIZER, .output_list = {&process_wayland.output_list, &process_wayland.output_list}, .output_mutex = PTHREAD_MUTEX_INITIALIZER @@ -66,6 +67,11 @@ static void wl_seat_handle_capabilities(void *data, struct wl_seat *seat, wayland_pointer_init(wl_seat_get_pointer(seat)); else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && process_wayland.pointer.wl_pointer) wayland_pointer_deinit(); + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !process_wayland.keyboard.wl_keyboard) + wayland_keyboard_init(wl_seat_get_keyboard(seat)); + else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && process_wayland.keyboard.wl_keyboard) + wayland_keyboard_deinit(); } static void wl_seat_handle_name(void *data, struct wl_seat *seat, const char *name) diff --git a/dlls/winewayland.drv/wayland_keyboard.c b/dlls/winewayland.drv/wayland_keyboard.c new file mode 100644 index 00000000000..741dbfe1157 --- /dev/null +++ b/dlls/winewayland.drv/wayland_keyboard.c @@ -0,0 +1,274 @@ +/* + * Keyboard related functions + * + * Copyright 2020 Alexandros Frantzis for Collabora Ltd. + * Copyright 2023 RĂ©mi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" + +#include +#undef SW_MAX /* Also defined in winuser.rh */ +#include + +#include "waylanddrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(keyboard); +WINE_DECLARE_DEBUG_CHANNEL(key); + +static WORD key2scan(UINT key) +{ + /* base keys can be mapped directly */ + if (key <= KEY_KPDOT) return key; + + /* map keys found in KBDTABLES definitions (Txx Xxx Yxx macros) */ + switch (key) + { + case 84 /* ISO_Level3_Shift */: return 0x005a; /* T5A / VK_OEM_WSCTRL */ + case KEY_SYSRQ: return 0x0054; /* T54 / VK_SNAPSHOT */ + case KEY_102ND: return 0x0056; /* T56 / VK_OEM_102 */ + case KEY_F11: return 0x0057; /* T57 / VK_F11 */ + case KEY_F12: return 0x0058; /* T58 / VK_F12 */ + case KEY_LINEFEED: return 0x0059; /* T59 / VK_CLEAR */ + case KEY_EXIT: return 0x005b; /* T5B / VK_OEM_FINISH */ + case KEY_OPEN: return 0x005c; /* T5C / VK_OEM_JUMP */ + /* FIXME: map a KEY to T5D / VK_EREOF */ + /* FIXME: map a KEY to T5E / VK_OEM_BACKTAB */ + case KEY_COMPOSE: return 0x005f; /* T5F / VK_OEM_AUTO */ + case KEY_SCALE: return 0x0062; /* T62 / VK_ZOOM */ + case KEY_HELP: return 0x0063; /* T63 / VK_HELP */ + case KEY_F13: return 0x0064; /* T64 / VK_F13 */ + case KEY_F14: return 0x0065; /* T65 / VK_F14 */ + case KEY_F15: return 0x0066; /* T66 / VK_F15 */ + case KEY_F16: return 0x0067; /* T67 / VK_F16 */ + case KEY_F17: return 0x0068; /* T68 / VK_F17 */ + case KEY_F18: return 0x0069; /* T69 / VK_F18 */ + case KEY_F19: return 0x006a; /* T6A / VK_F19 */ + case KEY_F20: return 0x006b; /* T6B / VK_F20 */ + case KEY_F21: return 0x006c; /* T6C / VK_F21 */ + case KEY_F22: return 0x006d; /* T6D / VK_F22 */ + case KEY_F23: return 0x006e; /* T6E / VK_F23 */ + /* FIXME: map a KEY to T6F / VK_OEM_PA3 */ + case KEY_COMPUTER: return 0x0071; /* T71 / VK_OEM_RESET */ + /* FIXME: map a KEY to T73 / VK_ABNT_C1 */ + case KEY_F24: return 0x0076; /* T76 / VK_F24 */ + case KEY_KPPLUSMINUS: return 0x007b; /* T7B / VK_OEM_PA1 */ + /* FIXME: map a KEY to T7C / VK_TAB */ + /* FIXME: map a KEY to T7E / VK_ABNT_C2 */ + /* FIXME: map a KEY to T7F / VK_OEM_PA2 */ + case KEY_PREVIOUSSONG: return 0x0110; /* X10 / VK_MEDIA_PREV_TRACK */ + case KEY_NEXTSONG: return 0x0119; /* X19 / VK_MEDIA_NEXT_TRACK */ + case KEY_KPENTER: return 0x011c; /* X1C / VK_RETURN */ + case KEY_RIGHTCTRL: return 0x011d; /* X1D / VK_RCONTROL */ + case KEY_MUTE: return 0x0120; /* X20 / VK_VOLUME_MUTE */ + case KEY_PROG2: return 0x0121; /* X21 / VK_LAUNCH_APP2 */ + case KEY_PLAYPAUSE: return 0x0122; /* X22 / VK_MEDIA_PLAY_PAUSE */ + case KEY_STOPCD: return 0x0124; /* X24 / VK_MEDIA_STOP */ + case KEY_VOLUMEDOWN: return 0x012e; /* X2E / VK_VOLUME_DOWN */ + case KEY_VOLUMEUP: return 0x0130; /* X30 / VK_VOLUME_UP */ + case KEY_HOMEPAGE: return 0x0132; /* X32 / VK_BROWSER_HOME */ + case KEY_KPSLASH: return 0x0135; /* X35 / VK_DIVIDE */ + case KEY_PRINT: return 0x0137; /* X37 / VK_SNAPSHOT */ + case KEY_RIGHTALT: return 0x0138; /* X38 / VK_RMENU */ + case KEY_CANCEL: return 0x0146; /* X46 / VK_CANCEL */ + case KEY_HOME: return 0x0147; /* X47 / VK_HOME */ + case KEY_UP: return 0x0148; /* X48 / VK_UP */ + case KEY_PAGEUP: return 0x0149; /* X49 / VK_PRIOR */ + case KEY_LEFT: return 0x014b; /* X4B / VK_LEFT */ + case KEY_RIGHT: return 0x014d; /* X4D / VK_RIGHT */ + case KEY_END: return 0x014f; /* X4F / VK_END */ + case KEY_DOWN: return 0x0150; /* X50 / VK_DOWN */ + case KEY_PAGEDOWN: return 0x0151; /* X51 / VK_NEXT */ + case KEY_INSERT: return 0x0152; /* X52 / VK_INSERT */ + case KEY_DELETE: return 0x0153; /* X53 / VK_DELETE */ + case KEY_LEFTMETA: return 0x015b; /* X5B / VK_LWIN */ + case KEY_RIGHTMETA: return 0x015c; /* X5C / VK_RWIN */ + case KEY_MENU: return 0x015d; /* X5D / VK_APPS */ + case KEY_POWER: return 0x015e; /* X5E / VK_POWER */ + case KEY_SLEEP: return 0x015f; /* X5F / VK_SLEEP */ + case KEY_FIND: return 0x0165; /* X65 / VK_BROWSER_SEARCH */ + case KEY_BOOKMARKS: return 0x0166; /* X66 / VK_BROWSER_FAVORITES */ + case KEY_REFRESH: return 0x0167; /* X67 / VK_BROWSER_REFRESH */ + case KEY_STOP: return 0x0168; /* X68 / VK_BROWSER_STOP */ + case KEY_FORWARD: return 0x0169; /* X69 / VK_BROWSER_FORWARD */ + case KEY_BACK: return 0x016a; /* X6A / VK_BROWSER_BACK */ + case KEY_PROG1: return 0x016b; /* X6B / VK_LAUNCH_APP1 */ + case KEY_MAIL: return 0x016c; /* X6C / VK_LAUNCH_MAIL */ + case KEY_MEDIA: return 0x016d; /* X6D / VK_LAUNCH_MEDIA_SELECT */ + case KEY_PAUSE: return 0x021d; /* Y1D / VK_PAUSE */ + } + + /* otherwise just make up some extended scancode */ + return 0x200 | (key & 0x7f); +} + +/********************************************************************** + * Keyboard handling + */ + +static HWND wayland_keyboard_get_focused_hwnd(void) +{ + struct wayland_keyboard *keyboard = &process_wayland.keyboard; + HWND hwnd; + + pthread_mutex_lock(&keyboard->mutex); + hwnd = keyboard->focused_hwnd; + pthread_mutex_unlock(&keyboard->mutex); + + return hwnd; +} + +static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, + uint32_t format, int fd, uint32_t size) +{ + FIXME("stub!\n"); + close(fd); +} + +static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, struct wl_surface *wl_surface, + struct wl_array *keys) +{ + struct wayland_keyboard *keyboard = &process_wayland.keyboard; + HWND hwnd; + + if (!wl_surface) return; + + /* The wl_surface user data remains valid and immutable for the whole + * lifetime of the object, so it's safe to access without locking. */ + hwnd = wl_surface_get_user_data(wl_surface); + TRACE("serial=%u hwnd=%p\n", serial, hwnd); + + pthread_mutex_lock(&keyboard->mutex); + keyboard->focused_hwnd = hwnd; + pthread_mutex_unlock(&keyboard->mutex); + + /* FIXME: update foreground window as well */ +} + +static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, struct wl_surface *wl_surface) +{ + struct wayland_keyboard *keyboard = &process_wayland.keyboard; + HWND hwnd; + + if (!wl_surface) return; + + /* The wl_surface user data remains valid and immutable for the whole + * lifetime of the object, so it's safe to access without locking. */ + hwnd = wl_surface_get_user_data(wl_surface); + TRACE("serial=%u hwnd=%p\n", serial, hwnd); + + pthread_mutex_lock(&keyboard->mutex); + if (keyboard->focused_hwnd == hwnd) + keyboard->focused_hwnd = NULL; + pthread_mutex_unlock(&keyboard->mutex); + + /* FIXME: update foreground window as well */ +} + +static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, uint32_t time, uint32_t key, + uint32_t state) +{ + UINT scan = key2scan(key); + INPUT input = {0}; + HWND hwnd; + + if (!(hwnd = wayland_keyboard_get_focused_hwnd())) return; + + TRACE_(key)("serial=%u hwnd=%p key=%d scan=%#x state=%#x\n", serial, hwnd, key, scan, state); + + input.type = INPUT_KEYBOARD; + input.ki.wScan = scan & 0xff; + input.ki.wVk = NtUserMapVirtualKeyEx(scan, MAPVK_VSC_TO_VK_EX, NtUserGetKeyboardLayout(0)); + if (scan & ~0xff) input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; + + if (state == WL_KEYBOARD_KEY_STATE_RELEASED) input.ki.dwFlags |= KEYEVENTF_KEYUP; + __wine_send_input(hwnd, &input, NULL); +} + +static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard, + uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, + uint32_t xkb_group) +{ + FIXME("serial=%u mods_depressed=%#x mods_latched=%#x mods_locked=%#x xkb_group=%d stub!\n", + serial, mods_depressed, mods_latched, mods_locked, xkb_group); +} + +static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keyboard, + int rate, int delay) +{ + FIXME("rate=%d delay=%d stub!\n", rate, delay); +} + +static const struct wl_keyboard_listener keyboard_listener = { + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, + keyboard_handle_repeat_info, +}; + +/*********************************************************************** + * wayland_keyboard_init + */ +void wayland_keyboard_init(struct wl_keyboard *wl_keyboard) +{ + struct wayland_keyboard *keyboard = &process_wayland.keyboard; + struct xkb_context *xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + if (!xkb_context) + { + ERR("Failed to create XKB context\n"); + return; + } + + pthread_mutex_lock(&keyboard->mutex); + keyboard->wl_keyboard = wl_keyboard; + keyboard->xkb_context = xkb_context; + pthread_mutex_unlock(&keyboard->mutex); + wl_keyboard_add_listener(keyboard->wl_keyboard, &keyboard_listener, NULL); +} + +/*********************************************************************** + * wayland_keyboard_deinit + */ +void wayland_keyboard_deinit(void) +{ + struct wayland_keyboard *keyboard = &process_wayland.keyboard; + + pthread_mutex_lock(&keyboard->mutex); + if (keyboard->wl_keyboard) + { + wl_keyboard_destroy(keyboard->wl_keyboard); + keyboard->wl_keyboard = NULL; + } + if (keyboard->xkb_context) + { + xkb_context_unref(keyboard->xkb_context); + keyboard->xkb_context = NULL; + } + pthread_mutex_unlock(&keyboard->mutex); +} diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index ae4812ebb08..8bda2a5420b 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -181,6 +181,11 @@ void wayland_surface_destroy(struct wayland_surface *surface) } pthread_mutex_unlock(&process_wayland.pointer.mutex); + pthread_mutex_lock(&process_wayland.keyboard.mutex); + if (process_wayland.keyboard.focused_hwnd == surface->hwnd) + process_wayland.keyboard.focused_hwnd = NULL; + pthread_mutex_unlock(&process_wayland.keyboard.mutex); + pthread_mutex_lock(&surface->mutex); if (surface->xdg_toplevel) diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 4bcd9e6706e..78ed68d3881 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -27,6 +27,7 @@ #include #include +#include #include "xdg-output-unstable-v1-client-protocol.h" #include "xdg-shell-client-protocol.h" @@ -65,6 +66,14 @@ enum wayland_surface_config_state WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN = (1 << 3) }; +struct wayland_keyboard +{ + struct wl_keyboard *wl_keyboard; + struct xkb_context *xkb_context; + HWND focused_hwnd; + pthread_mutex_t mutex; +}; + struct wayland_cursor { struct wayland_shm_buffer *shm_buffer; @@ -100,6 +109,7 @@ struct wayland struct xdg_wm_base *xdg_wm_base; struct wl_shm *wl_shm; struct wayland_seat seat; + struct wayland_keyboard keyboard; struct wayland_pointer pointer; struct wl_list output_list; /* Protects the output_list and the wayland_output.current states. */ @@ -223,6 +233,13 @@ void wayland_window_surface_update_wayland_surface(struct window_surface *surfac struct wayland_surface *wayland_surface) DECLSPEC_HIDDEN; void wayland_window_flush(HWND hwnd) DECLSPEC_HIDDEN; +/********************************************************************** + * Wayland Keyboard + */ + +void wayland_keyboard_init(struct wl_keyboard *wl_keyboard) DECLSPEC_HIDDEN; +void wayland_keyboard_deinit(void) DECLSPEC_HIDDEN; + /********************************************************************** * Wayland pointer */ diff --git a/include/config.h.in b/include/config.h.in index 157bf572df5..ca13952d1ea 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -672,6 +672,9 @@ /* Define to 1 if `callback' is a member of `XICCallback'. */ #undef HAVE_XICCALLBACK_CALLBACK +/* Define to 1 if you have the header file. */ +#undef HAVE_XKBCOMMON_XKBCOMMON_H + /* Define if Xrender has the XRenderCreateLinearGradient function */ #undef HAVE_XRENDERCREATELINEARGRADIENT