From c8489a3710fdf9ee3c5f09df0b3a3c439513a952 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
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 246f565e3000a..4372132d4c1f2 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 f056abb2dfe38..8eb0487b00ed3 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 7f5c0c682d5ea..7c4da2cb35e1f 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 a80f4361bbcaf..e9ebc89f7dd90 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)