From c8489a3710fdf9ee3c5f09df0b3a3c439513a952 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Mar 2024 08:50:47 -0700 Subject: [PATCH] Disable XInput2 keyboard events It turns out they're only delivered to the window with mouse focus, not keyboard focus. Fixes https://github.com/libsdl-org/SDL/issues/9374 --- src/video/x11/SDL_x11events.c | 8 ++++---- src/video/x11/SDL_x11window.c | 9 +++++++-- src/video/x11/SDL_x11window.h | 3 ++- src/video/x11/SDL_x11xinput2.c | 21 ++++++++++++++++----- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 246f565e3..4372132d4 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1528,7 +1528,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) case KeyPress: case KeyRelease: { - if (data->using_xinput2) { + if (data->xinput2_keyboard_enabled) { // This input is being handled by XInput2 break; } @@ -1538,7 +1538,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) case MotionNotify: { - if (data->using_xinput2) { + if (data->xinput2_mouse_enabled) { // This input is being handled by XInput2 break; } @@ -1556,7 +1556,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) case ButtonPress: { - if (data->using_xinput2) { + if (data->xinput2_mouse_enabled) { // This input is being handled by XInput2 break; } @@ -1567,7 +1567,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) case ButtonRelease: { - if (data->using_xinput2) { + if (data->xinput2_mouse_enabled) { // This input is being handled by XInput2 break; } diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index f056abb2d..8eb0487b0 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -796,9 +796,14 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesI { unsigned int x11_keyboard_events = KeyPressMask | KeyReleaseMask; unsigned int x11_pointer_events = ButtonPressMask | ButtonReleaseMask | PointerMotionMask; - if (X11_Xinput2SelectMouseAndKeyboard(_this, window)) { - /* If XInput2 can handle pointer and keyboard events, we don't track them here */ + + X11_Xinput2SelectMouseAndKeyboard(_this, window); + + /* If XInput2 can handle pointer and keyboard events, we don't track them here */ + if (windowdata->xinput2_keyboard_enabled) { x11_keyboard_events = 0; + } + if (windowdata->xinput2_mouse_enabled) { x11_pointer_events = 0; } diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 7f5c0c682..7c4da2cb3 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -59,7 +59,8 @@ struct SDL_WindowData int border_right; int border_top; int border_bottom; - SDL_bool using_xinput2; + SDL_bool xinput2_mouse_enabled; + SDL_bool xinput2_keyboard_enabled; SDL_bool mouse_grabbed; Uint64 last_focus_event_time; PendingFocusEnum pending_focus; diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c index a80f4361b..e9ebc89f7 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -607,27 +607,38 @@ SDL_bool X11_Xinput2SelectMouseAndKeyboard(SDL_VideoDevice *_this, SDL_Window *w eventmask.mask = mask; eventmask.deviceid = XIAllDevices; +/* This is not enabled by default because these events are only delivered to the window with mouse focus, not keyboard focus */ +#ifdef USE_XINPUT2_KEYBOARD XISetMask(mask, XI_KeyPress); XISetMask(mask, XI_KeyRelease); + windowdata->xinput2_keyboard_enabled = SDL_TRUE; +#endif + XISetMask(mask, XI_ButtonPress); XISetMask(mask, XI_ButtonRelease); XISetMask(mask, XI_Motion); + windowdata->xinput2_mouse_enabled = SDL_TRUE; + XISetMask(mask, XI_Enter); XISetMask(mask, XI_Leave); + /* Hotplugging: */ XISetMask(mask, XI_DeviceChanged); XISetMask(mask, XI_HierarchyChanged); XISetMask(mask, XI_PropertyEvent); /* E.g., when swapping tablet pens */ - if (X11_XISelectEvents(data->display, windowdata->xwindow, &eventmask, 1) == Success) { - windowdata->using_xinput2 = SDL_TRUE; - } else { + if (X11_XISelectEvents(data->display, windowdata->xwindow, &eventmask, 1) != Success) { SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "Could not enable XInput2 event handling\n"); - windowdata->using_xinput2 = SDL_FALSE; + windowdata->xinput2_keyboard_enabled = SDL_FALSE; + windowdata->xinput2_mouse_enabled = SDL_FALSE; } } #endif - return windowdata->using_xinput2; + + if (windowdata->xinput2_keyboard_enabled || windowdata->xinput2_mouse_enabled) { + return SDL_TRUE; + } + return SDL_FALSE; } int X11_Xinput2IsMultitouchSupported(void)