290 lines
12 KiB
Diff
290 lines
12 KiB
Diff
From 753e5eb654a5da96b5cb42e5d612380adac7229f Mon Sep 17 00:00:00 2001
|
|
From: Peter Hutterer <peter.hutterer@who-t.net>
|
|
Date: Fri, 26 Jun 2015 09:07:24 +1000
|
|
Subject: [PATCH libinput 7/9] Drop motion normalization of unaccelerated
|
|
deltas
|
|
|
|
This simply doesn't work for low-dpi mice. Normalizing a 400dpi mouse to a
|
|
1000dpi mouse forces a minimum movement of 2.5 units and the resulting pixel
|
|
jumps. It is impossible for the caller to detect whether the jump was caused
|
|
by a single motion or multiple motion events.
|
|
|
|
This is technically an API break, but not really.
|
|
|
|
The accelerated data was already relatively meaningless, even if normalized as
|
|
the data did not correspond predictably to any input motion (unless you know
|
|
the implementation acceleration function in the caller). So we can drop the
|
|
mention from there without expecting any ill effects in the caller.
|
|
|
|
The unaccelerated data was useless for low-dpi mice and could only be used to
|
|
measure the physical distance of the mouse movement - something not used in
|
|
any caller we're aware of (if needed, we can add that functionality as a
|
|
separate call). Dropping motion normalization for unaccelerated deltas also
|
|
restores true dpi capabilities to users of that API, mostly games that want to
|
|
make use of high-dpi mice.
|
|
|
|
This is a simplified patch, the normalization is still in place for most of
|
|
libinput, it merely carries the original coordinates in the event itself.
|
|
|
|
In the case of touchpads, the coordinates are unnormalized into the x-axis
|
|
coordinate space as per the documentation.
|
|
|
|
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
|
|
---
|
|
doc/normalization-of-relative-motion.dox | 31 +++++++++++++++++++++++++++----
|
|
src/evdev-mt-touchpad-gestures.c | 8 ++++++--
|
|
src/evdev-mt-touchpad.h | 15 +++++++++++++++
|
|
src/evdev.c | 5 ++++-
|
|
src/libinput-private.h | 2 +-
|
|
src/libinput.c | 10 +++++-----
|
|
src/libinput.h | 26 ++++++++++++++------------
|
|
7 files changed, 72 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/doc/normalization-of-relative-motion.dox b/doc/normalization-of-relative-motion.dox
|
|
index aaa1735..dd5d39b 100644
|
|
--- a/doc/normalization-of-relative-motion.dox
|
|
+++ b/doc/normalization-of-relative-motion.dox
|
|
@@ -12,10 +12,33 @@ physical movement or 10 millimeters, depending on the sensor. This
|
|
affects pointer acceleration in libinput and interpretation of relative
|
|
coordinates in callers.
|
|
|
|
-libinput normalizes all relative input to a physical resolution of
|
|
-1000dpi, the same delta from two different devices thus represents the
|
|
-same physical movement of those two devices (within sensor error
|
|
-margins).
|
|
+libinput does partial normalization of relative input. For devices with a
|
|
+resolution of 1000dpi and higher, motion events are normalized to a default
|
|
+of 1000dpi before pointer acceleration is applied. As a result, devices with
|
|
+1000dpi and above feel the same.
|
|
+
|
|
+Devices below 1000dpi are not normalized (normalization of a 1-device unit
|
|
+movement on a 400dpi mouse would cause a 2.5 pixel movement). Instead,
|
|
+libinput applies a dpi-dependent acceleration function. At low speeds, a
|
|
+1-device unit movement usually translates into a 1-pixel movements. As the
|
|
+movement speed increases, acceleration is applied - at high speeds a low-dpi
|
|
+device will roughly feel the same as a higher-dpi mouse.
|
|
+
|
|
+This normalization only applies to accelerated coordinates, unaccelerated
|
|
+coordiantes are left in device-units. It is up to the caller to interpret
|
|
+those coordinates correctly.
|
|
+
|
|
+@section Normalization of touchpad coordinates
|
|
+
|
|
+Touchpads may have a different resolution for the horizontal and vertical
|
|
+axis. Interpreting coordinates from the touchpad without taking resolutino
|
|
+into account results in uneven motion.
|
|
+
|
|
+libinput scales unaccelerated touchpad motion do the resolution of the
|
|
+touchpad's x axis, i.e. the unaccelerated value for the y axis is:
|
|
+ y = (x / resolution_x) * resolution_y
|
|
+
|
|
+@section Setting custom DPI settings
|
|
|
|
Devices usually do not advertise their resolution and libinput relies on
|
|
the udev property <b>MOUSE_DPI</b> for this information. This property is usually
|
|
diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c
|
|
index 328a744..e85a9d7 100644
|
|
--- a/src/evdev-mt-touchpad-gestures.c
|
|
+++ b/src/evdev-mt-touchpad-gestures.c
|
|
@@ -91,6 +91,7 @@ static void
|
|
tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
|
|
{
|
|
struct normalized_coords delta, unaccel;
|
|
+ struct device_float_coords raw;
|
|
|
|
/* When a clickpad is clicked, combine motion of all active touches */
|
|
if (tp->buttons.is_clickpad && tp->buttons.state)
|
|
@@ -101,8 +102,11 @@ tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
|
|
delta = tp_filter_motion(tp, &unaccel, time);
|
|
|
|
if (!normalized_is_zero(delta) || !normalized_is_zero(unaccel)) {
|
|
- pointer_notify_motion(&tp->device->base, time,
|
|
- &delta, &unaccel);
|
|
+ raw = tp_unnormalize_for_xaxis(tp, unaccel);
|
|
+ pointer_notify_motion(&tp->device->base,
|
|
+ time,
|
|
+ &delta,
|
|
+ &raw);
|
|
}
|
|
}
|
|
|
|
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
|
|
index 9357969..08c1732 100644
|
|
--- a/src/evdev-mt-touchpad.h
|
|
+++ b/src/evdev-mt-touchpad.h
|
|
@@ -316,6 +316,21 @@ tp_normalize_delta(struct tp_dispatch *tp, struct device_float_coords delta)
|
|
return normalized;
|
|
}
|
|
|
|
+/**
|
|
+ * Takes a dpi-normalized set of coordinates, returns a set of coordinates
|
|
+ * in the x-axis' coordinate space.
|
|
+ */
|
|
+static inline struct device_float_coords
|
|
+tp_unnormalize_for_xaxis(struct tp_dispatch *tp, struct normalized_coords delta)
|
|
+{
|
|
+ struct device_float_coords raw;
|
|
+
|
|
+ raw.x = delta.x / tp->accel.x_scale_coeff;
|
|
+ raw.y = delta.y / tp->accel.x_scale_coeff; /* <--- not a typo */
|
|
+
|
|
+ return raw;
|
|
+}
|
|
+
|
|
struct normalized_coords
|
|
tp_get_delta(struct tp_touch *t);
|
|
|
|
diff --git a/src/evdev.c b/src/evdev.c
|
|
index b2595d4..a5f1d47 100644
|
|
--- a/src/evdev.c
|
|
+++ b/src/evdev.c
|
|
@@ -280,6 +280,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|
struct libinput_seat *seat = base->seat;
|
|
struct normalized_coords accel, unaccel;
|
|
struct device_coords point;
|
|
+ struct device_float_coords raw;
|
|
|
|
slot = device->mt.slot;
|
|
|
|
@@ -288,6 +289,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|
return;
|
|
case EVDEV_RELATIVE_MOTION:
|
|
normalize_delta(device, &device->rel, &unaccel);
|
|
+ raw.x = device->rel.x;
|
|
+ raw.y = device->rel.y;
|
|
device->rel.x = 0;
|
|
device->rel.y = 0;
|
|
|
|
@@ -304,7 +307,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|
if (normalized_is_zero(accel) && normalized_is_zero(unaccel))
|
|
break;
|
|
|
|
- pointer_notify_motion(base, time, &accel, &unaccel);
|
|
+ pointer_notify_motion(base, time, &accel, &raw);
|
|
break;
|
|
case EVDEV_ABSOLUTE_MT_DOWN:
|
|
if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
|
|
diff --git a/src/libinput-private.h b/src/libinput-private.h
|
|
index a7c8838..2f94597 100644
|
|
--- a/src/libinput-private.h
|
|
+++ b/src/libinput-private.h
|
|
@@ -319,7 +319,7 @@ void
|
|
pointer_notify_motion(struct libinput_device *device,
|
|
uint64_t time,
|
|
const struct normalized_coords *delta,
|
|
- const struct normalized_coords *unaccel);
|
|
+ const struct device_float_coords *raw);
|
|
|
|
void
|
|
pointer_notify_motion_absolute(struct libinput_device *device,
|
|
diff --git a/src/libinput.c b/src/libinput.c
|
|
index 7a097c0..a6bd079 100644
|
|
--- a/src/libinput.c
|
|
+++ b/src/libinput.c
|
|
@@ -96,7 +96,7 @@ struct libinput_event_pointer {
|
|
struct libinput_event base;
|
|
uint32_t time;
|
|
struct normalized_coords delta;
|
|
- struct normalized_coords delta_unaccel;
|
|
+ struct device_float_coords delta_raw;
|
|
struct device_coords absolute;
|
|
struct discrete_coords discrete;
|
|
uint32_t button;
|
|
@@ -339,7 +339,7 @@ libinput_event_pointer_get_dx_unaccelerated(
|
|
0,
|
|
LIBINPUT_EVENT_POINTER_MOTION);
|
|
|
|
- return event->delta_unaccel.x;
|
|
+ return event->delta_raw.x;
|
|
}
|
|
|
|
LIBINPUT_EXPORT double
|
|
@@ -351,7 +351,7 @@ libinput_event_pointer_get_dy_unaccelerated(
|
|
0,
|
|
LIBINPUT_EVENT_POINTER_MOTION);
|
|
|
|
- return event->delta_unaccel.y;
|
|
+ return event->delta_raw.y;
|
|
}
|
|
|
|
LIBINPUT_EXPORT double
|
|
@@ -1130,7 +1130,7 @@ void
|
|
pointer_notify_motion(struct libinput_device *device,
|
|
uint64_t time,
|
|
const struct normalized_coords *delta,
|
|
- const struct normalized_coords *unaccel)
|
|
+ const struct device_float_coords *raw)
|
|
{
|
|
struct libinput_event_pointer *motion_event;
|
|
|
|
@@ -1144,7 +1144,7 @@ pointer_notify_motion(struct libinput_device *device,
|
|
*motion_event = (struct libinput_event_pointer) {
|
|
.time = time,
|
|
.delta = *delta,
|
|
- .delta_unaccel = *unaccel,
|
|
+ .delta_raw = *raw,
|
|
};
|
|
|
|
post_device_event(device, time,
|
|
diff --git a/src/libinput.h b/src/libinput.h
|
|
index 0d3200f..e76fa9a 100644
|
|
--- a/src/libinput.h
|
|
+++ b/src/libinput.h
|
|
@@ -460,8 +460,8 @@ libinput_event_pointer_get_time(struct libinput_event_pointer *event);
|
|
* If a device employs pointer acceleration, the delta returned by this
|
|
* function is the accelerated delta.
|
|
*
|
|
- * Relative motion deltas are normalized to represent those of a device with
|
|
- * 1000dpi resolution. See @ref motion_normalization for more details.
|
|
+ * Relative motion deltas are to be interpreted as pixel movement of a
|
|
+ * standardized mouse. See @ref motion_normalization for more details.
|
|
*
|
|
* @note It is an application bug to call this function for events other than
|
|
* @ref LIBINPUT_EVENT_POINTER_MOTION.
|
|
@@ -481,8 +481,8 @@ libinput_event_pointer_get_dx(struct libinput_event_pointer *event);
|
|
* If a device employs pointer acceleration, the delta returned by this
|
|
* function is the accelerated delta.
|
|
*
|
|
- * Relative motion deltas are normalized to represent those of a device with
|
|
- * 1000dpi resolution. See @ref motion_normalization for more details.
|
|
+ * Relative motion deltas are to be interpreted as pixel movement of a
|
|
+ * standardized mouse. See @ref motion_normalization for more details.
|
|
*
|
|
* @note It is an application bug to call this function for events other than
|
|
* @ref LIBINPUT_EVENT_POINTER_MOTION.
|
|
@@ -499,10 +499,11 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event);
|
|
* current event. For pointer events that are not of type @ref
|
|
* LIBINPUT_EVENT_POINTER_MOTION, this function returns 0.
|
|
*
|
|
- * Relative unaccelerated motion deltas are normalized to represent those of a
|
|
- * device with 1000dpi resolution. See @ref motion_normalization for more
|
|
- * details. Note that unaccelerated events are not equivalent to 'raw' events
|
|
- * as read from the device.
|
|
+ * Relative unaccelerated motion deltas are raw device coordinates.
|
|
+ * Note that these coordinates are subject to the device's native
|
|
+ * resolution. Touchpad coordinates represent raw device coordinates in the
|
|
+ * X resolution of the touchpad. See @ref motion_normalization for more
|
|
+ * details.
|
|
*
|
|
* @note It is an application bug to call this function for events other than
|
|
* @ref LIBINPUT_EVENT_POINTER_MOTION.
|
|
@@ -520,10 +521,11 @@ libinput_event_pointer_get_dx_unaccelerated(
|
|
* current event. For pointer events that are not of type @ref
|
|
* LIBINPUT_EVENT_POINTER_MOTION, this function returns 0.
|
|
*
|
|
- * Relative unaccelerated motion deltas are normalized to represent those of a
|
|
- * device with 1000dpi resolution. See @ref motion_normalization for more
|
|
- * details. Note that unaccelerated events are not equivalent to 'raw' events
|
|
- * as read from the device.
|
|
+ * Relative unaccelerated motion deltas are raw device coordinates.
|
|
+ * Note that these coordinates are subject to the device's native
|
|
+ * resolution. Touchpad coordinates represent raw device coordinates in the
|
|
+ * X resolution of the touchpad. See @ref motion_normalization for more
|
|
+ * details.
|
|
*
|
|
* @note It is an application bug to call this function for events other than
|
|
* @ref LIBINPUT_EVENT_POINTER_MOTION.
|
|
--
|
|
2.4.3
|
|
|