Skip to content

Draft: Add support for ABS_MT_ORIENTATION

José Expósito requested to merge JoseExposito/libinput:touch-orientation into main

Overview:

This MR adds support for ABS_MT_ORIENTATION.

The kernel reports orientation information as described in its documentation:

The value should describe a signed quarter of a revolution clockwise around the touch center. The signed value range is arbitrary, but zero should be returned for an ellipse aligned with the Y axis (north) of the surface, a negative value when the ellipse is turned to the left, and a positive value when the ellipse is turned to the right. When aligned with the X axis in the positive direction, the range max should be returned; when aligned with the X axis in the negative direction, the range -max should be returned.

Touch ellipses are symmetrical by default. For devices capable of true 360 degree orientation, the reported orientation must exceed the range max to indicate more than a quarter of a revolution. For an upside-down finger, range max * 2 should be returned.

Orientation can be omitted if the touch area is circular, or if the information is not available in the kernel driver. Partial orientation support is possible if the device can distinguish between the two axes, but not (uniquely) any values in between. In such cases, the range of ABS_MT_ORIENTATION should be [0, 1].

Wayland supports orientation events since version 6, however there is no way to get it from libinput.

Add a new API (libinput_event_touch_get_orientation) to be able to access the touch orientation. The orientation describes the clockwise angle of a touchpoint's major axis to the positive surface y-axis and is normalized to the -180 to +180 degree range.

Status:

Tooling support (debug-events and debug-gui) is ready, but it is marked as draft because I'd prefer to wait for feedback before implementing the unit tests.

Also, I have a couple of questions I'd like to share:

  • Do single touch devices support orientation? I didn't want to add a new field in fallback_dispatch->abs before checking. Unfortunately, I don't have any of those devices.
  • Do you think that an API like libinput_event_touch_has_orientation could make sense? @emersion, you might be interested in it.

Testing:

I only have 1 device with touch capabilities, however, it doesn't report orientation... Which is not that bad, because at least I can test that such device works.

Fortunately, my touchpad does report orientation and with the following diff it is easy to make libinput handle it as a touchscreen:

Click to expand
diff --git a/src/evdev.c b/src/evdev.c
index be0349a7..c7076545 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -2061,15 +2061,15 @@ evdev_configure_device(struct evdev_device *device)
                return dispatch;
        }
 
-       if (udev_tags & EVDEV_UDEV_TAG_TOUCHPAD) {
-               if (udev_tags & EVDEV_UDEV_TAG_TABLET)
-                       evdev_tag_tablet_touchpad(device);
-               /* whether velocity should be averaged, false by default */
-               device->use_velocity_averaging = evdev_need_velocity_averaging(device);
-               dispatch = evdev_mt_touchpad_create(device);
-               evdev_log_info(device, "device is a touchpad\n");
-               return dispatch;
-       }
+       // if (udev_tags & EVDEV_UDEV_TAG_TOUCHPAD) {
+       //      if (udev_tags & EVDEV_UDEV_TAG_TABLET)
+       //              evdev_tag_tablet_touchpad(device);
+       //      /* whether velocity should be averaged, false by default */
+       //      device->use_velocity_averaging = evdev_need_velocity_averaging(device);
+       //      dispatch = evdev_mt_touchpad_create(device);
+       //      evdev_log_info(device, "device is a touchpad\n");
+       //      return dispatch;
+       // }
 
        if (udev_tags & EVDEV_UDEV_TAG_MOUSE ||
            udev_tags & EVDEV_UDEV_TAG_POINTINGSTICK) {
@@ -2108,7 +2108,8 @@ evdev_configure_device(struct evdev_device *device)
                evdev_tag_keyboard(device, device->udev_device);
        }
 
-       if (udev_tags & EVDEV_UDEV_TAG_TOUCHSCREEN) {
+       // if (udev_tags & EVDEV_UDEV_TAG_TOUCHSCREEN) {
+       if (udev_tags & EVDEV_UDEV_TAG_TOUCHPAD) {
                device->seat_caps |= EVDEV_DEVICE_TOUCH;
                evdev_log_info(device, "device is a touch device\n");
        }

Hardware I couldn't test: Wacom devices with touch capabilities and single touch devices.

Related to #746

Edited by José Expósito

Merge request reports