[PATCH libinput v2 05/11] evdev: Hookup scroll mode configuration

Hans de Goede hdegoede at redhat.com
Mon Nov 10 02:59:16 PST 2014


Keep the default behavior of middle button scrolling on trackpoints, this
allows turning off middle button scrolling on trackpoints, as well as turning
on button scrolling on trackballs.

BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=85535
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 src/evdev.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++---------
 src/evdev.h |  13 ++++-
 2 files changed, 153 insertions(+), 25 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 8ae2785..2a28b6d 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -123,6 +123,10 @@ evdev_pointer_notify_button(struct evdev_device *device,
 		if (state == LIBINPUT_BUTTON_STATE_RELEASED &&
 		    device->buttons.change_to_left_handed)
 			device->buttons.change_to_left_handed(device);
+
+		if (state == LIBINPUT_BUTTON_STATE_RELEASED &&
+		    device->scroll.change_scroll_mode)
+			device->scroll.change_scroll_mode(device);
 	}
 
 }
@@ -213,9 +217,9 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
 		device->rel.dy = 0;
 
 		/* Use unaccelerated deltas for pointing stick scroll */
-		if (device->scroll.has_middle_button_scroll &&
-		    hw_is_key_down(device, BTN_MIDDLE)) {
-			if (device->scroll.middle_button_scroll_active)
+		if (device->scroll.mode == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN &&
+		    hw_is_key_down(device, device->scroll.button)) {
+			if (device->scroll.button_scroll_active)
 				evdev_post_scroll(device, time,
 						  motion.dx, motion.dy);
 			break;
@@ -364,31 +368,33 @@ get_key_type(uint16_t code)
 }
 
 static void
-evdev_middle_button_scroll_timeout(uint64_t time, void *data)
+evdev_button_scroll_timeout(uint64_t time, void *data)
 {
 	struct evdev_device *device = data;
 
-	device->scroll.middle_button_scroll_active = true;
+	device->scroll.button_scroll_active = true;
 }
 
 static void
-evdev_middle_button_scroll_button(struct evdev_device *device,
-				 uint64_t time, int is_press)
+evdev_button_scroll_button(struct evdev_device *device,
+			   uint64_t time, int is_press)
 {
 	if (is_press) {
 		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) {
+		if (device->scroll.button_scroll_active) {
 			evdev_stop_scroll(device, time);
-			device->scroll.middle_button_scroll_active = false;
+			device->scroll.button_scroll_active = false;
 		} else {
 			/* If the button is released quickly enough emit the
 			 * button press/release events. */
-			evdev_pointer_notify_button(device, time, BTN_MIDDLE,
+			evdev_pointer_notify_button(device, time,
+					device->scroll.button,
 					LIBINPUT_BUTTON_STATE_PRESSED);
-			evdev_pointer_notify_button(device, time, BTN_MIDDLE,
+			evdev_pointer_notify_button(device, time,
+					device->scroll.button,
 					LIBINPUT_BUTTON_STATE_RELEASED);
 		}
 	}
@@ -454,10 +460,9 @@ evdev_process_key(struct evdev_device *device,
 				   LIBINPUT_KEY_STATE_RELEASED);
 		break;
 	case EVDEV_KEY_TYPE_BUTTON:
-		if (device->scroll.has_middle_button_scroll &&
-		    e->code == BTN_MIDDLE) {
-			evdev_middle_button_scroll_button(device, time,
-							  e->value);
+		if (device->scroll.mode == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN &&
+		    e->code == device->scroll.button) {
+			evdev_button_scroll_button(device, time, e->value);
 			break;
 		}
 		evdev_pointer_notify_button(
@@ -838,6 +843,115 @@ evdev_init_left_handed(struct evdev_device *device,
 	return 0;
 }
 
+static uint32_t
+evdev_scroll_get_modes(struct libinput_device *device)
+{
+	return LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
+}
+
+static void
+evdev_change_scroll_mode(struct evdev_device *device)
+{
+	if (device->scroll.want_mode == device->scroll.mode &&
+	    device->scroll.want_button == device->scroll.button)
+		return;
+
+	if (evdev_any_button_down(device))
+		return;
+
+	device->scroll.mode = device->scroll.want_mode;
+	device->scroll.button = device->scroll.want_button;
+}
+
+static enum libinput_config_status
+evdev_scroll_set_mode(struct libinput_device *device,
+		      enum libinput_config_scroll_mode mode)
+{
+	struct evdev_device *evdev = (struct evdev_device*)device;
+
+	evdev->scroll.want_mode = mode;
+	evdev->scroll.change_scroll_mode(evdev);
+
+	return LIBINPUT_CONFIG_STATUS_SUCCESS;
+}
+
+static enum libinput_config_scroll_mode
+evdev_scroll_get_mode(struct libinput_device *device)
+{
+	struct evdev_device *evdev = (struct evdev_device *)device;
+
+	/* return the wanted configuration, even if it hasn't taken
+	 * effect yet! */
+	return evdev->scroll.want_mode;
+}
+
+static enum libinput_config_scroll_mode
+evdev_scroll_get_default_mode(struct libinput_device *device)
+{
+	struct evdev_device *evdev = (struct evdev_device *)device;
+
+	if (libevdev_has_property(evdev->evdev, INPUT_PROP_POINTING_STICK))
+		return LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
+	else
+		return LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
+}
+
+static enum libinput_config_status
+evdev_scroll_set_button(struct libinput_device *device,
+			uint32_t button)
+{
+	struct evdev_device *evdev = (struct evdev_device*)device;
+
+	evdev->scroll.want_button = button;
+	evdev->scroll.change_scroll_mode(evdev);
+
+	return LIBINPUT_CONFIG_STATUS_SUCCESS;
+}
+
+static uint32_t
+evdev_scroll_get_button(struct libinput_device *device)
+{
+	struct evdev_device *evdev = (struct evdev_device *)device;
+
+	/* return the wanted configuration, even if it hasn't taken
+	 * effect yet! */
+	return evdev->scroll.want_button;
+}
+
+static uint32_t
+evdev_scroll_get_default_button(struct libinput_device *device)
+{
+	struct evdev_device *evdev = (struct evdev_device *)device;
+
+	if (libevdev_has_property(evdev->evdev, INPUT_PROP_POINTING_STICK))
+		return BTN_MIDDLE;
+	else
+		return 0;
+}
+
+static int
+evdev_init_button_scroll(struct evdev_device *device,
+			 void (*change_scroll_mode)(struct evdev_device *))
+{
+	libinput_timer_init(&device->scroll.timer, device->base.seat->libinput,
+			    evdev_button_scroll_timeout, device);
+	device->scroll.config.get_modes = evdev_scroll_get_modes;
+	device->scroll.config.set_mode = evdev_scroll_set_mode;
+	device->scroll.config.get_mode = evdev_scroll_get_mode;
+	device->scroll.config.get_default_mode = evdev_scroll_get_default_mode;
+	device->scroll.config.set_button = evdev_scroll_set_button;
+	device->scroll.config.get_button = evdev_scroll_get_button;
+	device->scroll.config.get_default_button = evdev_scroll_get_default_button;
+	device->base.config.scroll_mode = &device->scroll.config;
+	device->scroll.mode = evdev_scroll_get_default_mode((struct libinput_device *)device);
+	device->scroll.want_mode = device->scroll.mode;
+	device->scroll.button = evdev_scroll_get_default_button((struct libinput_device *)device);
+	device->scroll.want_button = device->scroll.button;
+	device->scroll.change_scroll_mode = change_scroll_mode;
+
+	return 0;
+}
+
 static struct evdev_dispatch *
 fallback_dispatch_create(struct libinput_device *device)
 {
@@ -856,6 +970,13 @@ fallback_dispatch_create(struct libinput_device *device)
 		return NULL;
 	}
 
+	if (evdev_device->scroll.want_button &&
+	    evdev_init_button_scroll(evdev_device,
+				     evdev_change_scroll_mode) == -1) {
+		free(dispatch);
+		return NULL;
+	}
+
 	device->config.calibration = &dispatch->calibration;
 
 	dispatch->calibration.has_matrix = evdev_calibration_has_matrix;
@@ -1167,14 +1288,6 @@ evdev_configure_device(struct evdev_device *device)
 		}
 	}
 
-	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.has_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;
@@ -1228,6 +1341,12 @@ evdev_configure_device(struct evdev_device *device)
 		/* want left-handed config option */
 		device->buttons.want_left_handed = true;
 	}
+
+	if (has_rel && has_button) {
+		/* want button scrolling config option */
+		device->scroll.want_button = 1;
+	}
+
 	if (has_keyboard) {
 		device->seat_caps |= EVDEV_DEVICE_KEYBOARD;
 		log_info(libinput,
diff --git a/src/evdev.h b/src/evdev.h
index 3a02384..6c59766 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -100,8 +100,17 @@ struct evdev_device {
 
 	struct {
 		struct libinput_timer timer;
-		bool has_middle_button_scroll;
-		bool middle_button_scroll_active;
+		struct libinput_device_config_scroll_mode config;
+		/* Currently enabled mode, button */
+		enum libinput_config_scroll_mode mode;
+		uint32_t button;
+		/* set during device init, used at runtime to delay changes
+		 * until all buttons are up */
+		enum libinput_config_scroll_mode want_mode;
+		uint32_t want_button;
+		/* Checks if buttons are down and commits the setting */
+		void (*change_scroll_mode)(struct evdev_device *device);
+		bool button_scroll_active;
 		double threshold;
 		uint32_t direction;
 	} scroll;
-- 
2.1.0



More information about the wayland-devel mailing list