[PATCH 3/3] evdev: Add middle buttton scrolling for trackpoints

Hans de Goede hdegoede at redhat.com
Tue Sep 2 07:34:50 PDT 2014


Most trackpoint users want to be able to scroll using the trackpoint with
the middle button pressed, add support for this.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 include/linux/input.h |  1 +
 src/evdev.c           | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/evdev.h           |  5 +++++
 3 files changed, 61 insertions(+)

diff --git a/include/linux/input.h b/include/linux/input.h
index aa98ce7..39b550b 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -163,6 +163,7 @@ struct input_keymap_entry {
 #define INPUT_PROP_BUTTONPAD		0x02	/* has button(s) under pad */
 #define INPUT_PROP_SEMI_MT		0x03	/* touch rectangle only */
 #define INPUT_PROP_TOPBUTTONPAD		0x04	/* softbuttons at top of pad */
+#define INPUT_PROP_POINTING_STICK	0x05	/* is a pointing stick */
 
 #define INPUT_PROP_MAX			0x1f
 #define INPUT_PROP_CNT			(INPUT_PROP_MAX + 1)
diff --git a/src/evdev.c b/src/evdev.c
index b45f7ec..f013362 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -40,6 +40,7 @@
 #include "libinput-private.h"
 
 #define DEFAULT_AXIS_STEP_DISTANCE 10
+#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT 200
 
 enum evdev_key_type {
 	EVDEV_KEY_TYPE_NONE,
@@ -208,6 +209,14 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
 		if (motion.dx == 0.0 && motion.dy == 0.0)
 			break;
 
+		if (device->scroll.middle_button_scroll &&
+		    is_key_down(device, BTN_MIDDLE)) {
+			if (device->scroll.middle_button_scroll_active)
+				evdev_post_scroll(device, time,
+						  motion.dx, motion.dy, 5.0);
+			break;
+		}
+
 		pointer_notify_motion(base, time, motion.dx, motion.dy);
 		break;
 	case EVDEV_ABSOLUTE_MT_DOWN:
@@ -345,6 +354,37 @@ get_key_type(uint16_t code)
 }
 
 static void
+evdev_middle_button_scroll_timeout(uint64_t time, void *data)
+{
+	struct evdev_device *device = data;
+
+	device->scroll.middle_button_scroll_active = true;
+}
+
+static void
+evdev_middle_button_scroll_button(struct evdev_device *device,
+				 uint64_t time, int value)
+{
+	if (value) {
+		libinput_timer_set(&device->scroll.timer,
+				time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT);
+	} else {
+		libinput_timer_cancel(&device->scroll.timer);
+		if (device->scroll.middle_button_scroll_active) {
+			evdev_stop_scroll(device, time);
+			device->scroll.middle_button_scroll_active = false;
+		} else {
+			/* If the button is released early enough emit the
+			 * button press/release events. */
+			evdev_pointer_notify_button(device, time, BTN_MIDDLE,
+					LIBINPUT_BUTTON_STATE_PRESSED);
+			evdev_pointer_notify_button(device, time, BTN_MIDDLE,
+					LIBINPUT_BUTTON_STATE_RELEASED);
+		}
+	}
+}
+
+static void
 evdev_process_touch_button(struct evdev_device *device,
 			   uint64_t time, int value)
 {
@@ -404,6 +444,12 @@ evdev_process_key(struct evdev_device *device,
 				   LIBINPUT_KEY_STATE_RELEASED);
 		break;
 	case EVDEV_KEY_TYPE_BUTTON:
+		if (device->scroll.middle_button_scroll &&
+		    e->code == BTN_MIDDLE) {
+			evdev_middle_button_scroll_button(device, time,
+							  e->value);
+			break;
+		}
 		evdev_pointer_notify_button(
 			device,
 			time,
@@ -836,6 +882,15 @@ evdev_configure_device(struct evdev_device *device)
 			device->mt.slot = active_slot;
 		}
 	}
+
+	if (libevdev_has_property(evdev, INPUT_PROP_POINTING_STICK)) {
+		libinput_timer_init(&device->scroll.timer,
+				    device->base.seat->libinput,
+				    evdev_middle_button_scroll_timeout,
+				    device);
+		device->scroll.middle_button_scroll = true;
+	}
+
 	if (libevdev_has_event_code(evdev, EV_REL, REL_X) ||
 	    libevdev_has_event_code(evdev, EV_REL, REL_Y))
 		has_rel = 1;
diff --git a/src/evdev.h b/src/evdev.h
index 1cb6bea..2617b7f 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -26,10 +26,12 @@
 
 #include "config.h"
 
+#include <stdbool.h>
 #include "linux/input.h"
 #include <libevdev/libevdev.h>
 
 #include "libinput-private.h"
+#include "timer.h"
 
 enum evdev_event_type {
 	EVDEV_NONE,
@@ -90,6 +92,9 @@ struct evdev_device {
 	} rel;
 
 	struct {
+		struct libinput_timer timer;
+		bool middle_button_scroll;
+		bool middle_button_scroll_active;
 		int32_t direction;
 	} scroll;
 
-- 
2.1.0



More information about the wayland-devel mailing list