Largely based on work by Peter Hutterer, this patch makes composite relative + absolute devices work with the driver. Such devices are anything that presents itself as both a mouse, and - for example - a touch screen, like the Keyboardio Model 01 (or anything that uses Nico Hood's HID library for Arduino).
If a device has both capabilities present, we split them into two separate devices for X (see xf86libinput_pre_init()), like we do with the composite keyboard + mouse devices. Then, we route absolute events to the absolute subdevice (see xf86libinput_pick_device()). The rest of the patch is mostly small updates to support the newly introduced CAP_POINTER_ABSOLUTE flag. There's one missing thing, however: event routing for buttons. At the moment, button routing is simply not done, but in practice, this does not seem to have any ill side effects. https://bugs.freedesktop.org/show_bug.cgi?id=99914 Signed-off-by: Gergely Nagy <[email protected]> --- src/xf86libinput.c | 81 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 23 deletions(-) diff --git a/src/xf86libinput.c b/src/xf86libinput.c index 888c8f2..a099c5b 100644 --- a/src/xf86libinput.c +++ b/src/xf86libinput.c @@ -87,6 +87,7 @@ #define CAP_TABLET 0x8 #define CAP_TABLET_TOOL 0x10 #define CAP_TABLET_PAD 0x20 +#define CAP_POINTER_ABSOLUTE 0x40 struct xf86libinput_driver { struct libinput *libinput; @@ -805,6 +806,20 @@ xf86libinput_init_pointer_absolute(InputInfoPtr pInfo) Atom btnlabels[MAX_BUTTONS]; Atom axislabels[TOUCHPAD_NUM_AXES]; + /* We always initialize rel as parent on absrel devices */ + if (xf86libinput_is_subdevice(pInfo)) { + /* + * FIXME: well, we can't really know which buttons belong to + * which device here, but adding it to both doesn't make + * sense either. Options are: assume LMR is on rel, BTN_0 + * and friends on absolute. That's not always correct but + * that's as best as we can do. + * + * FIXME: event routing for buttons isn't set up correctly + * yet. + */ + } + for (i = BTN_BACK; i >= BTN_SIDE; i--) { if (libinput_device_pointer_has_button(device, i)) { nbuttons += i - BTN_SIDE + 1; @@ -1179,13 +1194,10 @@ xf86libinput_init(DeviceIntPtr dev) if (driver_data->capabilities & CAP_KEYBOARD) xf86libinput_init_keyboard(pInfo); - if (driver_data->capabilities & CAP_POINTER) { - if (libinput_device_config_calibration_has_matrix(device) && - !libinput_device_config_accel_is_available(device)) - xf86libinput_init_pointer_absolute(pInfo); - else - xf86libinput_init_pointer(pInfo); - } + if (driver_data->capabilities & CAP_POINTER) + xf86libinput_init_pointer(pInfo); + if (driver_data->capabilities & CAP_POINTER_ABSOLUTE) + xf86libinput_init_pointer_absolute(pInfo); if (driver_data->capabilities & CAP_TOUCH) xf86libinput_init_touch(pInfo); if (driver_data->capabilities & CAP_TABLET_TOOL) @@ -1347,7 +1359,7 @@ xf86libinput_handle_absmotion(InputInfoPtr pInfo, struct libinput_event_pointer return; } - if ((driver_data->capabilities & CAP_POINTER) == 0) + if ((driver_data->capabilities & CAP_POINTER_ABSOLUTE) == 0) return; x = libinput_event_pointer_get_absolute_x_transformed(event, TOUCH_AXIS_MAX); @@ -1368,7 +1380,7 @@ xf86libinput_handle_button(InputInfoPtr pInfo, struct libinput_event_pointer *ev int button; int is_press; - if ((driver_data->capabilities & CAP_POINTER) == 0) + if ((driver_data->capabilities & (CAP_POINTER|CAP_POINTER_ABSOLUTE)) == 0) return; button = btn_linux2xorg(libinput_event_pointer_get_button(event)); @@ -1493,7 +1505,7 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *even double value; enum libinput_pointer_axis_source source; - if ((driver_data->capabilities & CAP_POINTER) == 0) + if ((driver_data->capabilities & (CAP_POINTER|CAP_POINTER_ABSOLUTE)) == 0) return; valuator_mask_zero(mask); @@ -1600,6 +1612,9 @@ xf86libinput_pick_device(struct xf86libinput_device *shared_device, case LIBINPUT_EVENT_TABLET_TOOL_TIP: needed_cap = CAP_TABLET_TOOL; break; + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + needed_cap = CAP_POINTER_ABSOLUTE; + break; default: needed_cap = ~CAP_KEYBOARD; break; @@ -2940,7 +2955,7 @@ xf86libinput_get_type_name(struct libinput_device *device, /* now pick an actual type */ if (libinput_device_config_tap_get_finger_count(device) > 0) type_name = XI_TOUCHPAD; - else if (driver_data->capabilities & CAP_TOUCH) + else if (driver_data->capabilities & (CAP_TOUCH|CAP_POINTER_ABSOLUTE)) type_name = XI_TOUCHSCREEN; else if (driver_data->capabilities & CAP_POINTER) type_name = XI_MOUSE; @@ -3054,6 +3069,8 @@ xf86libinput_create_subdevice(InputInfoPtr pInfo, options = xf86ReplaceBoolOption(options, "_libinput/cap-keyboard", 1); if (capabilities & CAP_POINTER) options = xf86ReplaceBoolOption(options, "_libinput/cap-pointer", 1); + if (capabilities & CAP_POINTER_ABSOLUTE) + options = xf86ReplaceBoolOption(options, "_libinput/cap-pointer-absolute", 1); if (capabilities & CAP_TOUCH) options = xf86ReplaceBoolOption(options, "_libinput/cap-touch", 1); if (capabilities & CAP_TABLET_TOOL) @@ -3092,6 +3109,8 @@ caps_from_options(InputInfoPtr pInfo) capabilities |= CAP_KEYBOARD; if (xf86CheckBoolOption(pInfo->options, "_libinput/cap-pointer", 0)) capabilities |= CAP_POINTER; + if (xf86CheckBoolOption(pInfo->options, "_libinput/cap-pointer-absolute", 0)) + capabilities |= CAP_POINTER_ABSOLUTE; if (xf86CheckBoolOption(pInfo->options, "_libinput/cap-touch", 0)) capabilities |= CAP_TOUCH; if (xf86CheckBoolOption(pInfo->options, "_libinput/cap-tablet-tool", 0)) @@ -3230,8 +3249,13 @@ xf86libinput_pre_init(InputDriverPtr drv, driver_data->scroll.hdist = 15; if (!is_subdevice) { - if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) - driver_data->capabilities |= CAP_POINTER; + if (libinput_device_has_capability(device, + LIBINPUT_DEVICE_CAP_POINTER)) { + if (libinput_device_config_calibration_has_matrix(device)) + driver_data->capabilities |= CAP_POINTER_ABSOLUTE; + if (libinput_device_config_accel_is_available(device)) + driver_data->capabilities |= CAP_POINTER; + } if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD)) driver_data->capabilities |= CAP_KEYBOARD; if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH)) @@ -3254,15 +3278,26 @@ xf86libinput_pre_init(InputDriverPtr drv, xf86libinput_parse_options(pInfo, driver_data, device); - /* Device is both keyboard and pointer. Drop the keyboard cap from - * this device, create a separate device instead */ - if (!is_subdevice && - driver_data->capabilities & CAP_KEYBOARD && - driver_data->capabilities & (CAP_POINTER|CAP_TOUCH)) { - driver_data->capabilities &= ~CAP_KEYBOARD; - xf86libinput_create_subdevice(pInfo, - CAP_KEYBOARD, - NULL); + if (!is_subdevice) { + /* Device is both keyboard and pointer. Drop the keyboard cap from + * this device, create a separate device instead */ + if (driver_data->capabilities & CAP_KEYBOARD && + driver_data->capabilities & (CAP_POINTER|CAP_POINTER_ABSOLUTE|CAP_TOUCH)) { + driver_data->capabilities &= ~CAP_KEYBOARD; + xf86libinput_create_subdevice(pInfo, + CAP_KEYBOARD, + NULL); + } + /* Device is both relative and absolute. Drop the absolute + * cap from this device, create a separate device instead */ + if (driver_data->capabilities & CAP_POINTER && + driver_data->capabilities & CAP_POINTER_ABSOLUTE) { + driver_data->capabilities &= ~CAP_POINTER_ABSOLUTE; + xf86libinput_create_subdevice(pInfo, + CAP_POINTER_ABSOLUTE, + NULL); + } + } pInfo->type_name = xf86libinput_get_type_name(device, driver_data); @@ -4571,7 +4606,7 @@ LibinputInitAccelProperty(DeviceIntPtr dev, BOOL profiles[2] = {FALSE}; if (!libinput_device_config_accel_is_available(device) || - driver_data->capabilities & CAP_TABLET) + driver_data->capabilities & (CAP_TABLET|CAP_POINTER_ABSOLUTE)) return; prop_accel = LibinputMakeProperty(dev, -- 2.11.0 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel
