linux: Distinguish between "device with keys" and a full keyboard

udev distinguishes between ID_INPUT_KEY, a device with any keyboard keys
at all (including for example USB numeric keypads, Bluetooth headsets
with volume control buttons, and some game controllers; and
ID_INPUT_KEYBOARD, a reasonably fully-featured keyboard that you could
use for general-purpose text entry. If we do the same here, then it's
useful input to our heuristics for identifying devices: for example,
a device with ID_INPUT_KEY could reasonably be a gamepad, but a device
with ID_INPUT_KEYBOARD certainly isn't.

Resolves: https://github.com/libsdl-org/SDL/issues/7827
Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
Simon McVittie
2023-06-16 14:53:29 +01:00
committed by Sam Lantinga
parent 9b7a9ca666
commit fa0ca3d41e
5 changed files with 36 additions and 31 deletions

View File

@@ -245,7 +245,7 @@ static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_cl
switch (udev_event) {
case SDL_UDEV_DEVICEADDED:
if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD | SDL_UDEV_DEVICE_TOUCHSCREEN | SDL_UDEV_DEVICE_TOUCHPAD))) {
if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_HAS_KEYS | SDL_UDEV_DEVICE_TOUCHSCREEN | SDL_UDEV_DEVICE_TOUCHPAD))) {
return;
}

View File

@@ -131,14 +131,15 @@ SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_ev[NBITS(EV_MAX)],
}
if (found > 0) {
devclass |= SDL_UDEV_DEVICE_KEYBOARD; /* ID_INPUT_KEY */
devclass |= SDL_UDEV_DEVICE_HAS_KEYS; /* ID_INPUT_KEY */
}
}
/* the first 32 bits are ESC, numbers, and Q to D; if we have any of
* those, consider it a keyboard device; do not test KEY_RESERVED, though */
/* the first 32 bits are ESC, numbers, and Q to D, so if we have all of
* those, consider it to be a fully-featured keyboard;
* do not test KEY_RESERVED, though */
keyboard_mask = 0xFFFFFFFE;
if ((bitmask_key[0] & keyboard_mask) != 0) {
if ((bitmask_key[0] & keyboard_mask) == keyboard_mask) {
devclass |= SDL_UDEV_DEVICE_KEYBOARD; /* ID_INPUT_KEYBOARD */
}

View File

@@ -38,7 +38,8 @@ typedef enum
SDL_UDEV_DEVICE_SOUND = 0x0008,
SDL_UDEV_DEVICE_TOUCHSCREEN = 0x0010,
SDL_UDEV_DEVICE_ACCELEROMETER = 0x0020,
SDL_UDEV_DEVICE_TOUCHPAD = 0x0040
SDL_UDEV_DEVICE_TOUCHPAD = 0x0040,
SDL_UDEV_DEVICE_HAS_KEYS = 0x0080,
} SDL_UDEV_deviceclass;
#define BITS_PER_LONG (sizeof(unsigned long) * 8)

View File

@@ -435,6 +435,11 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
Ref: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c#n183
*/
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_KEY");
if (val != NULL && SDL_strcmp(val, "1") == 0) {
devclass |= SDL_UDEV_DEVICE_HAS_KEYS;
}
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");
if (val != NULL && SDL_strcmp(val, "1") == 0) {
devclass |= SDL_UDEV_DEVICE_KEYBOARD;
}
@@ -448,7 +453,7 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
} else if (SDL_strcmp(val, "mouse") == 0) {
devclass = SDL_UDEV_DEVICE_MOUSE;
} else if (SDL_strcmp(val, "kbd") == 0) {
devclass = SDL_UDEV_DEVICE_KEYBOARD;
devclass = SDL_UDEV_DEVICE_HAS_KEYS | SDL_UDEV_DEVICE_KEYBOARD;
} else {
return;
}