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

Reply via email to