[PATCH libinput 16/19] touchpad: add support for clickfingers

Peter Hutterer peter.hutterer at who-t.net
Sun Feb 16 22:48:35 PST 2014


On touchpads without physical buttons, the number of fingers on the touchpad
at the time the physical click happens decides the button type. 1/2/3 fingers
is handled left/right/middle.

We also swallow the motion event on the actual click event, this reduces
erroneous motion events by a bit. More processing is needed here though.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-mt-touchpad.c | 67 +++++++++++++++++++++++++++++++++++++++++++------
 src/evdev-mt-touchpad.h |  1 +
 test/pointer.c          |  2 +-
 3 files changed, 62 insertions(+), 8 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index d0864fe..154df85 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -461,14 +461,42 @@ tp_post_scroll_events(struct tp_dispatch *tp, uint32_t time)
 	return 0;
 }
 
-static void
-tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
+static int
+tp_post_clickfinger_buttons(struct tp_dispatch *tp, uint32_t time)
 {
 	uint32_t current, old, button;
+	enum libinput_pointer_button_state state;
 
-	if ((tp->queued &
-		(TOUCHPAD_EVENT_BUTTON_PRESS|TOUCHPAD_EVENT_BUTTON_RELEASE)) == 0)
-				return;
+	current = tp->buttons.state;
+	old = tp->buttons.old_state;
+
+	if (current == old)
+		return 0;
+
+	switch (tp->nfingers_down) {
+		case 1: button = BTN_LEFT; break;
+		case 2: button = BTN_RIGHT; break;
+		case 3: button = BTN_MIDDLE; break;
+		default:
+			return 0;
+	}
+
+	if (current)
+		state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
+	else
+		state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
+
+	pointer_notify_button(&tp->device->base,
+			      time,
+			      button,
+			      state);
+	return 1;
+}
+
+static int
+tp_post_physical_buttons(struct tp_dispatch *tp, uint32_t time)
+{
+	uint32_t current, old, button;
 
 	current = tp->buttons.state;
 	old = tp->buttons.old_state;
@@ -493,6 +521,25 @@ tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
 		current >>= 1;
 		old >>= 1;
 	}
+
+	return 0;
+}
+
+static int
+tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
+{
+	int rc;
+
+	if ((tp->queued &
+		(TOUCHPAD_EVENT_BUTTON_PRESS|TOUCHPAD_EVENT_BUTTON_RELEASE)) == 0)
+				return 0;
+
+	if (tp->buttons.has_buttons)
+		rc = tp_post_physical_buttons(tp, time);
+	else
+		rc = tp_post_clickfinger_buttons(tp, time);
+
+	return rc;
 }
 
 static void
@@ -501,6 +548,9 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
 	struct tp_touch *t = tp_current_touch(tp);
 	double dx, dy;
 
+	if (tp_post_button_events(tp, time) != 0)
+		return;
+
 	if (tp_tap_handle_state(tp, time) != 0)
 		return;
 
@@ -519,8 +569,6 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
 				li_fixed_from_double(dx),
 				li_fixed_from_double(dy));
 	}
-
-	tp_post_button_events(tp, time);
 }
 
 static void
@@ -622,6 +670,7 @@ tp_init(struct tp_dispatch *tp,
 {
 	int width, height;
 	double diagonal;
+	unsigned long key_bits[NBITS(KEY_MAX)];
 
 	tp->base.interface = &tp_interface;
 	tp->device = device;
@@ -638,6 +687,10 @@ tp_init(struct tp_dispatch *tp,
 	tp->hysteresis.margin_y =
 		diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
 
+	ioctl(device->fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits);
+	if (TEST_BIT(key_bits, BTN_RIGHT) || TEST_BIT(key_bits, BTN_MIDDLE))
+		tp->buttons.has_buttons = true;
+
 	if (tp_init_scroll(tp) != 0)
 		return -1;
 
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 84d8cec..327ce11 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -117,6 +117,7 @@ struct tp_dispatch {
 	} accel;
 
 	struct {
+		bool has_buttons;		/* true for physical LMR buttons */
 		uint32_t state;
 		uint32_t old_state;
 	} buttons;				/* physical buttons */
diff --git a/test/pointer.c b/test/pointer.c
index e864169..59fe818 100644
--- a/test/pointer.c
+++ b/test/pointer.c
@@ -186,7 +186,7 @@ END_TEST
 int main (int argc, char **argv) {
 
 	litest_add("pointer:motion", pointer_motion_relative, LITEST_POINTER, LITEST_ANY);
-	litest_add("pointer:button", pointer_button, LITEST_BUTTON, LITEST_ANY);
+	litest_add("pointer:button", pointer_button, LITEST_BUTTON, LITEST_CLICKPAD);
 	litest_add("pointer:scroll", pointer_scroll_wheel, LITEST_WHEEL, LITEST_ANY);
 
 	return litest_run(argc, argv);
-- 
1.8.4.2



More information about the wayland-devel mailing list