Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
---
 src/evdev-tablet-pad.c |  55 ++++++++++++++++++++++-
 test/pad.c             | 115 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+), 2 deletions(-)

diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c
index 810b241..c2fe379 100644
--- a/src/evdev-tablet-pad.c
+++ b/src/evdev-tablet-pad.c
@@ -62,6 +62,19 @@ pad_button_is_down(const struct pad_dispatch *pad,
        return bit_is_set(pad->button_state.bits, button);
 }
 
+static inline bool
+pad_any_button_down(const struct pad_dispatch *pad)
+{
+       const struct button_state *state = &pad->button_state;
+       unsigned int i;
+
+       for (i = 0; i < sizeof(state->bits); i++)
+               if (state->bits[i] != 0)
+                       return true;
+
+       return false;
+}
+
 static inline void
 pad_button_set_down(struct pad_dispatch *pad,
                    uint32_t button,
@@ -161,11 +174,17 @@ pad_handle_ring(struct pad_dispatch *pad,
                unsigned int code)
 {
        const struct input_absinfo *absinfo;
+       double degrees;
 
        absinfo = libevdev_get_abs_info(device->evdev, code);
        assert(absinfo);
 
-       return normalize_ring(absinfo) * 360;
+       degrees = normalize_ring(absinfo) * 360;
+
+       if (device->left_handed.enabled)
+               degrees = fmod(degrees + 180, 360);
+
+       return degrees;
 }
 
 static inline double
@@ -174,6 +193,7 @@ pad_handle_strip(struct pad_dispatch *pad,
                 unsigned int code)
 {
        const struct input_absinfo *absinfo;
+       double pos;
 
        absinfo = libevdev_get_abs_info(device->evdev, code);
        assert(absinfo);
@@ -181,7 +201,12 @@ pad_handle_strip(struct pad_dispatch *pad,
        if (absinfo->value == 0)
                return 0.0;
 
-       return normalize_strip(absinfo);
+       pos = normalize_strip(absinfo);
+
+       if (device->left_handed.enabled)
+               pos = 1.0 - pos;
+
+       return pos;
 }
 
 static void
@@ -313,6 +338,20 @@ pad_notify_buttons(struct pad_dispatch *pad,
 }
 
 static void
+pad_change_to_left_handed(struct evdev_device *device)
+{
+       struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch;
+
+       if (device->left_handed.enabled == device->left_handed.want_enabled)
+               return;
+
+       if (pad_any_button_down(pad))
+               return;
+
+       device->left_handed.enabled = device->left_handed.want_enabled;
+}
+
+static void
 pad_flush(struct pad_dispatch *pad,
          struct evdev_device *device,
          uint64_t time)
@@ -328,6 +367,8 @@ pad_flush(struct pad_dispatch *pad,
                                   time,
                                   LIBINPUT_BUTTON_STATE_RELEASED);
                pad_unset_status(pad, PAD_BUTTONS_RELEASED);
+
+               pad_change_to_left_handed(device);
        }
 
        if (pad_has_status(pad, PAD_BUTTONS_PRESSED)) {
@@ -407,6 +448,14 @@ static struct evdev_dispatch_interface pad_interface = {
        NULL, /* post_added */
 };
 
+static void
+pad_init_left_handed(struct evdev_device *device)
+{
+       if (evdev_tablet_has_left_handed(device))
+               evdev_init_left_handed(device,
+                                      pad_change_to_left_handed);
+}
+
 static int
 pad_init(struct pad_dispatch *pad, struct evdev_device *device)
 {
@@ -415,6 +464,8 @@ pad_init(struct pad_dispatch *pad, struct evdev_device 
*device)
        pad->status = PAD_NONE;
        pad->changed_axes = PAD_AXIS_NONE;
 
+       pad_init_left_handed(device);
+
        return 0;
 }
 
diff --git a/test/pad.c b/test/pad.c
index 0286bd0..53a907f 100644
--- a/test/pad.c
+++ b/test/pad.c
@@ -359,6 +359,117 @@ START_TEST(pad_strip_finger_up)
 }
 END_TEST
 
+START_TEST(pad_left_handed_default)
+{
+#if HAVE_LIBWACOM
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+       enum libinput_config_status status;
+
+       ck_assert(libinput_device_config_left_handed_is_available(device));
+
+       ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
+                        0);
+       ck_assert_int_eq(libinput_device_config_left_handed_get(device),
+                        0);
+
+       status = libinput_device_config_left_handed_set(dev->libinput_device, 
1);
+       ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+
+       ck_assert_int_eq(libinput_device_config_left_handed_get(device),
+                        1);
+       ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
+                        0);
+
+       status = libinput_device_config_left_handed_set(dev->libinput_device, 
0);
+       ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+
+       ck_assert_int_eq(libinput_device_config_left_handed_get(device),
+                        0);
+       ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
+                        0);
+
+#endif
+}
+END_TEST
+
+START_TEST(pad_no_left_handed)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+       enum libinput_config_status status;
+
+       ck_assert(!libinput_device_config_left_handed_is_available(device));
+
+       ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
+                        0);
+       ck_assert_int_eq(libinput_device_config_left_handed_get(device),
+                        0);
+
+       status = libinput_device_config_left_handed_set(dev->libinput_device, 
1);
+       ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
+
+       ck_assert_int_eq(libinput_device_config_left_handed_get(device),
+                        0);
+       ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
+                        0);
+
+       status = libinput_device_config_left_handed_set(dev->libinput_device, 
0);
+       ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
+
+       ck_assert_int_eq(libinput_device_config_left_handed_get(device),
+                        0);
+       ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
+                        0);
+}
+END_TEST
+
+START_TEST(pad_left_handed_ring)
+{
+#if HAVE_LIBWACOM
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+       struct libinput_event *ev;
+       struct libinput_event_tablet_pad *pev;
+       int val;
+       double degrees, expected;
+
+       libinput_device_config_left_handed_set(dev->libinput_device, 1);
+
+       litest_pad_ring_start(dev, 10);
+
+       litest_drain_events(li);
+
+       /* Wacom's 0 value is at 275 degrees -> 90 in left-handed mode*/
+       expected = 90;
+
+       for (val = 0; val < 100; val += 10) {
+               litest_pad_ring_change(dev, val);
+               libinput_dispatch(li);
+
+               ev = libinput_get_event(li);
+               pev = litest_is_pad_ring_event(ev,
+                                              0,
+                                              
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
+
+               degrees = libinput_event_tablet_pad_get_ring_position(pev);
+               ck_assert_double_ge(degrees, 0.0);
+               ck_assert_double_lt(degrees, 360.0);
+
+               /* rounding errors, mostly caused by small physical range */
+               ck_assert_double_ge(degrees, expected - 2);
+               ck_assert_double_le(degrees, expected + 2);
+
+               libinput_event_destroy(ev);
+
+               expected = fmod(degrees + 36, 360);
+       }
+
+       litest_pad_ring_end(dev);
+#endif
+}
+END_TEST
+
 void
 litest_setup_tests(void)
 {
@@ -378,4 +489,8 @@ litest_setup_tests(void)
        litest_add("pad:strip", pad_strip, LITEST_STRIP, LITEST_ANY);
        litest_add("pad:strip", pad_strip_finger_up, LITEST_STRIP, LITEST_ANY);
 
+       litest_add_for_device("pad:left_handed", pad_left_handed_default, 
LITEST_WACOM_INTUOS5_PAD);
+       litest_add_for_device("pad:left_handed", pad_no_left_handed, 
LITEST_WACOM_INTUOS3_PAD);
+       litest_add_for_device("pad:left_handed", pad_left_handed_ring, 
LITEST_WACOM_INTUOS5_PAD);
+       /* None of the current strip tablets are left-handed */
 }
-- 
2.5.0

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to