[PATCH xf86-input-libinput] Support for rel+abs composite devices on the same node
Gergely Nagy
algernon at madhouse-project.org
Sat Mar 11 11:26:38 UTC 2017
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 <algernon at madhouse-project.org>
---
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
More information about the xorg-devel
mailing list