[PATCH libinput 6/6] pad: add support for left-handed configurations

Peter Hutterer peter.hutterer at who-t.net
Wed Feb 10 06:17:34 UTC 2016


Signed-off-by: Peter Hutterer <peter.hutterer at 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



More information about the wayland-devel mailing list