[PATCH libinput] Add libinput_event_pointer_get_axis_click_count() to count wheel clicks

Peter Hutterer peter.hutterer at who-t.net
Mon Jan 12 21:21:24 PST 2015


The recent normalization of wheel events means we get the angle in degrees but
we don't know how this corresponds to clicks. The M325 has a 20 degree click
angle, most other mice have 15 degrees. So an angle of 60 can be 3 or 4 click
events.

Most clients care more about the click count than the angle on a mouse wheel.
Provide that value when needed.

Adding click_count to the axis event leaves the possibility of defining
discrete units for finger/continuous scroll sources in the future. Right now,
these will always reuturn 0.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-mt-touchpad-edge-scroll.c |  9 ++++++---
 src/evdev.c                         | 26 +++++++++++++++++---------
 src/libinput-private.h              |  1 +
 src/libinput.c                      | 11 ++++++++++-
 src/libinput.h                      | 19 +++++++++++++++++++
 src/libinput.sym                    |  1 +
 test/pointer.c                      |  7 ++++++-
 7 files changed, 60 insertions(+), 14 deletions(-)

diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c
index a4dc093..8605034 100644
--- a/src/evdev-mt-touchpad-edge-scroll.c
+++ b/src/evdev-mt-touchpad-edge-scroll.c
@@ -327,7 +327,8 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
 					pointer_notify_axis(device, time,
 						t->scroll.direction,
 						LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
-						0.0);
+						0.0,
+						0);
 					t->scroll.direction = -1;
 				}
 				continue;
@@ -351,7 +352,8 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
 
 		pointer_notify_axis(device, time, axis,
 				    LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
-				    *delta);
+				    *delta,
+				    0);
 		t->scroll.direction = axis;
 
 		tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_POSTED);
@@ -371,7 +373,8 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time)
 			pointer_notify_axis(device, time,
 					    t->scroll.direction,
 					    LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
-					    0.0);
+					    0.0,
+					    0);
 			t->scroll.direction = -1;
 		}
 	}
diff --git a/src/evdev.c b/src/evdev.c
index d80594d..10ee367 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -541,16 +541,20 @@ evdev_notify_axis(struct evdev_device *device,
 		  uint64_t time,
 		  enum libinput_pointer_axis axis,
 		  enum libinput_pointer_axis_source source,
-		  double value)
+		  double value,
+		  double click_count)
 {
-	if (device->scroll.natural_scrolling_enabled)
+	if (device->scroll.natural_scrolling_enabled) {
 		value *= -1;
+		click_count *= -1;
+	}
 
 	pointer_notify_axis(&device->base,
 			    time,
 			    axis,
 			    source,
-			    value);
+			    value,
+			    click_count);
 }
 
 static inline void
@@ -577,7 +581,8 @@ evdev_process_relative(struct evdev_device *device,
 			time,
 			LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
 			LIBINPUT_POINTER_AXIS_SOURCE_WHEEL,
-			-1 * e->value * device->scroll.wheel_click_angle);
+			-1 * e->value * device->scroll.wheel_click_angle,
+			-1 * e->value);
 		break;
 	case REL_HWHEEL:
 		evdev_flush_pending_event(device, time);
@@ -586,7 +591,8 @@ evdev_process_relative(struct evdev_device *device,
 			time,
 			LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
 			LIBINPUT_POINTER_AXIS_SOURCE_WHEEL,
-			e->value * device->scroll.wheel_click_angle);
+			e->value * device->scroll.wheel_click_angle,
+			e->value);
 		break;
 	}
 }
@@ -1864,7 +1870,8 @@ evdev_post_scroll(struct evdev_device *device,
 				  time,
 				  LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
 				  source,
-				  dy);
+				  dy,
+				  0);
 	}
 
 	if (dx != 0.0 &&
@@ -1874,7 +1881,8 @@ evdev_post_scroll(struct evdev_device *device,
 				  time,
 				  LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
 				  source,
-				  dx);
+				  dx,
+				  0);
 	}
 }
 
@@ -1889,13 +1897,13 @@ evdev_stop_scroll(struct evdev_device *device,
 				    time,
 				    LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
 				    source,
-				    0);
+				    0, 0);
 	if (device->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
 		pointer_notify_axis(&device->base,
 				    time,
 				    LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
 				    source,
-				    0);
+				    0, 0);
 
 	device->scroll.buildup_horizontal = 0;
 	device->scroll.buildup_vertical = 0;
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 84a0d44..2b73286 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -280,6 +280,7 @@ pointer_notify_axis(struct libinput_device *device,
 		    uint64_t time,
 		    enum libinput_pointer_axis axis,
 		    enum libinput_pointer_axis_source source,
+		    double click_count,
 		    double value);
 
 void
diff --git a/src/libinput.c b/src/libinput.c
index 426c306..dd30518 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -67,6 +67,7 @@ struct libinput_event_pointer {
 	enum libinput_pointer_axis axis;
 	enum libinput_pointer_axis_source source;
 	double value;
+	double click_count;
 };
 
 struct libinput_event_touch {
@@ -391,6 +392,12 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event)
 	return event->value;
 }
 
+LIBINPUT_EXPORT double
+libinput_event_pointer_get_axis_click_count(struct libinput_event_pointer *event)
+{
+	return event->click_count;
+}
+
 LIBINPUT_EXPORT enum libinput_pointer_axis_source
 libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event)
 {
@@ -994,7 +1001,8 @@ pointer_notify_axis(struct libinput_device *device,
 		    uint64_t time,
 		    enum libinput_pointer_axis axis,
 		    enum libinput_pointer_axis_source source,
-		    double value)
+		    double value,
+		    double click_count)
 {
 	struct libinput_event_pointer *axis_event;
 
@@ -1007,6 +1015,7 @@ pointer_notify_axis(struct libinput_device *device,
 		.axis = axis,
 		.value = value,
 		.source = source,
+		.click_count = click_count,
 	};
 
 	post_device_event(device, time,
diff --git a/src/libinput.h b/src/libinput.h
index f605e52..4009df3 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -726,6 +726,25 @@ enum libinput_pointer_axis_source
 libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event);
 
 /**
+ * @ingroup pointer
+ *
+ * Return the number of "clicks" for a given axis event. Clicks are a
+ * discrete scrolling unit when the value returned by
+ * libinput_event_pointer_get_axis_value() is not suitable.
+ *
+ * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, the clicks
+ * correspond to the number of physical mouse clicks.
+ *
+ * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS or @ref
+ * LIBINPUT_POINTER_AXIS_SOURCE_FINGER, the click count is always 0.
+ *
+ * @return The click count for the given event. A negative number indicates
+ * a click count along the axis' negative direction.
+ */
+double
+libinput_event_pointer_get_axis_click_count(struct libinput_event_pointer *event);
+
+/**
  * @ingroup event_pointer
  *
  * @return The generic libinput_event of this event
diff --git a/src/libinput.sym b/src/libinput.sym
index 826bfde..8fccb8c 100644
--- a/src/libinput.sym
+++ b/src/libinput.sym
@@ -71,6 +71,7 @@ global:
 	libinput_event_pointer_get_absolute_y;
 	libinput_event_pointer_get_absolute_y_transformed;
 	libinput_event_pointer_get_axis;
+	libinput_event_pointer_get_axis_click_count;
 	libinput_event_pointer_get_axis_source;
 	libinput_event_pointer_get_axis_value;
 	libinput_event_pointer_get_base_event;
diff --git a/test/pointer.c b/test/pointer.c
index d12c9f6..7581945 100644
--- a/test/pointer.c
+++ b/test/pointer.c
@@ -353,9 +353,12 @@ test_wheel_event(struct litest_device *dev, int which, int amount)
 	   up by a factor 15 */
 	const int scroll_step = 15;
 	int expected = amount * scroll_step;
+	int click_count = amount;
 
-	if (libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device))
+	if (libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device)) {
 		expected *= -1;
+		click_count *= -1;
+	}
 
 	/* mouse scroll wheels are 'upside down' */
 	if (which == REL_WHEEL)
@@ -379,6 +382,8 @@ test_wheel_event(struct litest_device *dev, int which, int amount)
 	ck_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev), expected);
 	ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
 			 LIBINPUT_POINTER_AXIS_SOURCE_WHEEL);
+	ck_assert_int_eq(libinput_event_pointer_get_axis_click_count(ptrev),
+			 click_count);
 	libinput_event_destroy(event);
 }
 
-- 
2.1.0



More information about the wayland-devel mailing list