evdev: Add support for REL_WHEEL_HI_RES and REL_HWHEEL_HI_RES If supported, these come alongside the regular REL_WHEEL and REL_HWHEEL events so it's important that we only process one or the other.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c
index 9d7c39a..33128e6 100644
--- a/src/core/linux/SDL_evdev.c
+++ b/src/core/linux/SDL_evdev.c
@@ -57,6 +57,10 @@
#define ABS_MT_TRACKING_ID 0x39
#define ABS_MT_PRESSURE 0x3a
#endif
+#ifndef REL_WHEEL_HI_RES
+#define REL_WHEEL_HI_RES 0x0b
+#define REL_HWHEEL_HI_RES 0x0c
+#endif
typedef struct SDL_evdevlist_item
{
@@ -92,6 +96,9 @@ typedef struct SDL_evdevlist_item
} * touchscreen_data;
+ SDL_bool high_res_wheel;
+ SDL_bool high_res_hwheel;
+
struct SDL_evdevlist_item *next;
} SDL_evdevlist_item;
@@ -378,10 +385,20 @@ SDL_EVDEV_Poll(void)
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value);
break;
case REL_WHEEL:
- SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value, SDL_MOUSEWHEEL_NORMAL);
+ if (!item->high_res_wheel)
+ SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value, SDL_MOUSEWHEEL_NORMAL);
+ break;
+ case REL_WHEEL_HI_RES:
+ SDL_assert(item->high_res_wheel);
+ SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value / 120.0f, SDL_MOUSEWHEEL_NORMAL);
break;
case REL_HWHEEL:
- SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
+ if (!item->high_res_hwheel)
+ SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
+ break;
+ case REL_HWHEEL_HI_RES:
+ SDL_assert(item->high_res_hwheel);
+ SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value / 120.0f, 0, SDL_MOUSEWHEEL_NORMAL);
break;
default:
break;
@@ -715,6 +732,7 @@ SDL_EVDEV_device_added(const char *dev_path, int udev_class)
{
int ret;
SDL_evdevlist_item *item;
+ unsigned long relbit[NBITS(REL_MAX)] = { 0 };
/* Check to make sure it's not already in list. */
for (item = _this->first; item != NULL; item = item->next) {
@@ -741,11 +759,17 @@ SDL_EVDEV_device_added(const char *dev_path, int udev_class)
return SDL_OutOfMemory();
}
+ if (ioctl(item->fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) {
+ item->high_res_wheel = test_bit(REL_WHEEL_HI_RES, relbit);
+ item->high_res_hwheel = test_bit(REL_HWHEEL_HI_RES, relbit);
+ }
+
if (udev_class & SDL_UDEV_DEVICE_TOUCHSCREEN) {
item->is_touchscreen = 1;
if ((ret = SDL_EVDEV_init_touchscreen(item)) < 0) {
close(item->fd);
+ SDL_free(item->path);
SDL_free(item);
return ret;
}