Use the real device IDs for the X11 master keyboard and pointer

These always exist so they don't really help detect whether a keyboard/mouse is attached. Looking at the slave devices isn't that helpful either, as they're very permissive in what they might send.

For example, on my system with a single mouse and keyboard attached, xinput -list shows:
 Virtual core pointer                    	id=2	[master pointer  (3)]
   - Virtual core XTEST pointer              	id=4	[slave  pointer  (2)]
   - Generic USB Mouse                       	id=10	[slave  pointer  (2)]
   - Generic USB Consumer Control            	id=11	[slave  pointer  (2)]
   - KINESIS CORPORATION KB800HM Kinesis Freestyle2 for Mac	id=18	[slave  pointer  (2)]
   - Logitech Gaming Mouse G502 Consumer Control	id=15	[slave  pointer  (2)]
   - Logitech Gaming Mouse G502              	id=17	[slave  pointer  (2)]
 Virtual core keyboard                   	id=3	[master keyboard (2)]
   - Virtual core XTEST keyboard             	id=5	[slave  keyboard (3)]
   - Power Button                            	id=6	[slave  keyboard (3)]
   - Power Button                            	id=7	[slave  keyboard (3)]
   - Sleep Button                            	id=8	[slave  keyboard (3)]
   - Generic USB                             	id=9	[slave  keyboard (3)]
   - Generic USB System Control              	id=12	[slave  keyboard (3)]
   - Generic USB Consumer Control            	id=19	[slave  keyboard (3)]
   - KINESIS CORPORATION KB800HM Kinesis Freestyle2 for Mac	id=20	[slave  keyboard (3)]
   - KINESIS CORPORATION KB800HM Kinesis Freestyle2 for Mac	id=21	[slave  keyboard (3)]
   - Logitech Gaming Mouse G502 Keyboard     	id=13	[slave  keyboard (3)]
   - Logitech Gaming Mouse G502 System Control	id=14	[slave  keyboard (3)]
   - Logitech Gaming Mouse G502 Consumer Control	id=16	[slave  keyboard (3)]
main
Sam Lantinga 2024-03-21 11:53:10 -07:00
parent d1eb4adb16
commit 476245564c
3 changed files with 72 additions and 47 deletions

View File

@ -25,6 +25,8 @@
#include <unistd.h> /* For getpid() and readlink() */
#include "../../core/linux/SDL_system_theme.h"
#include "../../events/SDL_keyboard_c.h"
#include "../../events/SDL_mouse_c.h"
#include "../SDL_pixels_c.h"
#include "../SDL_sysvideo.h"
@ -415,7 +417,13 @@ int X11_VideoInit(SDL_VideoDevice *_this)
return -1;
}
X11_InitXinput2(_this);
if (!X11_InitXinput2(_this)) {
/* Assume a mouse and keyboard are attached */
data->keyboardID = SDL_GetNextObjectID();
SDL_AddKeyboard(data->keyboardID, SDL_FALSE);
data->mouseID = SDL_GetNextObjectID();
SDL_AddMouse(data->mouseID, SDL_FALSE);
}
#ifdef SDL_VIDEO_DRIVER_X11_XFIXES
X11_InitXfixes(_this);

View File

@ -95,6 +95,55 @@ static SDL_Window *xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window
return windowdata ? windowdata->window : NULL;
}
static void xinput2_init_device_list(SDL_VideoData *videodata)
{
XIDeviceInfo *info;
int ndevices;
info = X11_XIQueryDevice(videodata->display, XIAllDevices, &ndevices);
for (int i = 0; i < ndevices; i++) {
XIDeviceInfo *dev = &info[i];
switch (dev->use) {
case XIMasterKeyboard:
videodata->keyboardID = (SDL_KeyboardID)dev->deviceid;
SDL_AddKeyboard(videodata->keyboardID, SDL_FALSE);
break;
case XIMasterPointer:
videodata->mouseID = (SDL_MouseID)dev->deviceid;
SDL_AddMouse(videodata->mouseID, SDL_FALSE);
break;
default:
break;
}
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
for (int j = 0; j < dev->num_classes; j++) {
SDL_TouchID touchId;
SDL_TouchDeviceType touchType;
XIAnyClassInfo *class = dev->classes[j];
XITouchClassInfo *t = (XITouchClassInfo *)class;
/* Only touch devices */
if (class->type != XITouchClass) {
continue;
}
if (t->mode == XIDependentTouch) {
touchType = SDL_TOUCH_DEVICE_INDIRECT_RELATIVE;
} else { /* XIDirectTouch */
touchType = SDL_TOUCH_DEVICE_DIRECT;
}
touchId = t->sourceid;
SDL_AddTouch(touchId, touchType, dev->name);
}
#endif // SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
}
X11_XIFreeDeviceInfo(info);
}
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
static void xinput2_normalize_touch_coordinates(SDL_Window *window, double in_x, double in_y, float *out_x, float *out_y)
{
@ -119,7 +168,7 @@ static void xinput2_normalize_touch_coordinates(SDL_Window *window, double in_x,
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
void X11_InitXinput2(SDL_VideoDevice *_this)
SDL_bool X11_InitXinput2(SDL_VideoDevice *_this)
{
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
SDL_VideoData *data = _this->driverdata;
@ -140,13 +189,13 @@ void X11_InitXinput2(SDL_VideoDevice *_this)
*/
if (!SDL_X11_HAVE_XINPUT2 ||
!X11_XQueryExtension(data->display, "XInputExtension", &xinput2_opcode, &event, &err)) {
return; /* X server does not have XInput at all */
return SDL_FALSE; /* X server does not have XInput at all */
}
/* We need at least 2.2 for Multitouch, 2.0 otherwise. */
version = query_xinput2_version(data->display, 2, 2);
if (!xinput2_version_atleast(version, 2, 0)) {
return; /* X server does not support the version we want at all. */
return SDL_FALSE; /* X server does not support the version we want at all. */
}
xinput2_initialized = 1;
@ -156,6 +205,8 @@ void X11_InitXinput2(SDL_VideoDevice *_this)
#endif
/* Enable raw motion events for this display */
SDL_zero(eventmask);
SDL_zeroa(mask);
eventmask.deviceid = XIAllMasterDevices;
eventmask.mask_len = sizeof(mask);
eventmask.mask = mask;
@ -173,9 +224,7 @@ void X11_InitXinput2(SDL_VideoDevice *_this)
}
#endif
if (X11_XISelectEvents(data->display, DefaultRootWindow(data->display), &eventmask, 1) != Success) {
return;
}
X11_XISelectEvents(data->display, DefaultRootWindow(data->display), &eventmask, 1);
SDL_zero(eventmask);
SDL_zeroa(mask);
@ -184,9 +233,13 @@ void X11_InitXinput2(SDL_VideoDevice *_this)
eventmask.mask = mask;
XISetMask(mask, XI_HierarchyChanged);
if (X11_XISelectEvents(data->display, DefaultRootWindow(data->display), &eventmask, 1) != Success) {
return;
}
X11_XISelectEvents(data->display, DefaultRootWindow(data->display), &eventmask, 1);
xinput2_init_device_list(data);
return SDL_TRUE;
#else
return SDL_FALSE;
#endif
}
@ -512,42 +565,6 @@ int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
void X11_InitXinput2Multitouch(SDL_VideoDevice *_this)
{
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
SDL_VideoData *data = _this->driverdata;
XIDeviceInfo *info;
int ndevices, i, j;
if (!X11_Xinput2IsMultitouchSupported()) {
return;
}
info = X11_XIQueryDevice(data->display, XIAllDevices, &ndevices);
for (i = 0; i < ndevices; i++) {
XIDeviceInfo *dev = &info[i];
for (j = 0; j < dev->num_classes; j++) {
SDL_TouchID touchId;
SDL_TouchDeviceType touchType;
XIAnyClassInfo *class = dev->classes[j];
XITouchClassInfo *t = (XITouchClassInfo *)class;
/* Only touch devices */
if (class->type != XITouchClass) {
continue;
}
if (t->mode == XIDependentTouch) {
touchType = SDL_TOUCH_DEVICE_INDIRECT_RELATIVE;
} else { /* XIDirectTouch */
touchType = SDL_TOUCH_DEVICE_DIRECT;
}
touchId = t->sourceid;
SDL_AddTouch(touchId, touchType, dev->name);
}
}
X11_XIFreeDeviceInfo(info);
#endif
}
void X11_Xinput2SelectTouch(SDL_VideoDevice *_this, SDL_Window *window)

View File

@ -30,7 +30,7 @@ struct XGenericEventCookie;
typedef struct XGenericEventCookie XGenericEventCookie;
#endif
extern void X11_InitXinput2(SDL_VideoDevice *_this);
extern SDL_bool X11_InitXinput2(SDL_VideoDevice *_this);
extern void X11_InitXinput2Multitouch(SDL_VideoDevice *_this);
extern int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie);
extern int X11_Xinput2IsInitialized(void);