X11: handle XI device hotplugging

Fixes #9370
This commit is contained in:
copilot-swe-agent[bot]
2026-01-10 03:11:05 +00:00
committed by Kovid Goyal
parent 813c560e29
commit bfc21fc7a4
3 changed files with 30 additions and 2 deletions

15
glfw/x11_init.c vendored
View File

@@ -148,7 +148,7 @@ static void detectEWMH(void)
XFree(supportedAtoms);
}
static void
void
read_xi_scroll_devices(void) {
#define xi _glfw.x11.xi
xi.num_scroll_devices = 0;
@@ -512,6 +512,19 @@ static bool initExtensions(void)
_glfw.x11.xi.LIBINPUT_SCROLL_METHOD_ENABLED = XInternAtom(_glfw.x11.display, "libinput Scroll Method Enabled", False);
read_xi_scroll_devices();
// Select XI_HierarchyChanged events to detect device add/remove
if (_glfw.x11.xi.available) {
XIEventMask em;
unsigned char mask[XIMaskLen(XI_HierarchyChanged)] = { 0 };
em.deviceid = XIAllDevices;
em.mask_len = sizeof(mask);
em.mask = mask;
XISetMask(mask, XI_HierarchyChanged);
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
}
// The compositing manager selection name contains the screen number
{
char name[32];

2
glfw/x11_platform.h vendored
View File

@@ -498,3 +498,5 @@ void _glfwInputErrorX11(int error, const char* message);
void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, bool bypass_cache);
void _glfwPushSelectionToManagerX11(void);
void read_xi_scroll_devices(void);

15
glfw/x11_window.c vendored
View File

@@ -58,7 +58,6 @@
#define _GLFW_XDND_VERSION 5
// Wait for data to arrive using poll
// This avoids blocking other threads via the per-display Xlib lock that also
// covers GLX functions
@@ -1388,6 +1387,20 @@ static void processEvent(XEvent *event)
}
}
}
// Handle XI_HierarchyChanged for device hotplug
else if (event->xcookie.evtype == XI_HierarchyChanged)
{
XIHierarchyEvent* he = (XIHierarchyEvent*)event->xcookie.data;
// Check if any devices were added or removed
for (int i = 0; i < he->num_info; i++) {
if (he->info[i].flags & (XISlaveAdded | XISlaveRemoved |
XIMasterAdded | XIMasterRemoved)) {
// Re-read scroll devices when devices are added or removed
read_xi_scroll_devices();
break;
}
}
}
XFreeEventData(_glfw.x11.display, &event->xcookie);
}
}