diff --git a/doc/user/development.rst b/doc/user/development.rst index b96d365428e7024321298bed7f812f01a8c151a1..4b7e4a0da8ad1957203bf38f169055781f4e307d 100644 --- a/doc/user/development.rst +++ b/doc/user/development.rst @@ -36,6 +36,7 @@ Topics below explain some behaviors of libinput. normalization-of-relative-motion.rst seats.rst timestamps.rst + wheel-api.rst .. _hacking_on_libinput: diff --git a/doc/user/meson.build b/doc/user/meson.build index 8d2714b2c42e0109b1816b60b7f6c44ce146a118..332f67b947a7ab4783ad260739f0524e9950f8a1 100644 --- a/doc/user/meson.build +++ b/doc/user/meson.build @@ -167,6 +167,7 @@ src_rst = files( 'trackpoints.rst', 'trackpoint-configuration.rst', 'what-is-libinput.rst', + 'wheel-api.rst', 'features.rst', 'development.rst', 'troubleshooting.rst', diff --git a/doc/user/scrolling.rst b/doc/user/scrolling.rst index 82b88768554ca4975579b03817b911e4a28d1708..e568755d6729086f7eac267b1a416832e57a0734 100644 --- a/doc/user/scrolling.rst +++ b/doc/user/scrolling.rst @@ -130,6 +130,9 @@ button is logically held down, motion events are converted to scroll events. Scroll sources ------------------------------------------------------------------------------ +.. note:: Scroll sources are deprecated with libinput 1.19. The scroll + source is now encoded in the event type. + libinput provides a pointer axis *source* for each scroll event. The source can be obtained with the **libinput_event_pointer_get_axis_source()** function and is one of **wheel**, **finger**, or **continuous**. The source diff --git a/doc/user/wheel-api.rst b/doc/user/wheel-api.rst new file mode 100644 index 0000000000000000000000000000000000000000..e488a65a082974994a1c47208f1b169d96d9b8cb --- /dev/null +++ b/doc/user/wheel-api.rst @@ -0,0 +1,183 @@ +.. _wheel_scrolling: + +============================================================================== +Wheel scrolling +============================================================================== + +libinput provides two events to handle wheel scrolling: + +- ``LIBINPUT_EVENT_POINTER_AXIS`` events are sent for regular wheel clicks, + usually those representing one detent on the device. These wheel clicks + usually require a rotation of 15 or 20 degrees. + **This event is deprecated as of libinput 1.19.** + +- ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` events are sent for regular and/or + high resolution wheel movements. High-resolution events are often 4 or 8 + times more frequent than wheel clicks and require the device to be switched + into high-resolution mode (Linux kernel 5.0 and later). Where + high-resolution wheels are not provided by the kernel, libinput emulates + these events for regular wheel clicks. + **This event is available since libinput 1.19.** + +The events are separate for historical reasons. Both events are +generated for the same device but are independent event streams. Callers +must not assume any relation between the two, i.e. there is no guarantee +that an axis event is sent before or after any specific high-resolution +event and vice versa. Callers should not handle both events. + +.. warning:: do not handle both ``LIBINPUT_EVENT_POINTER_AXIS`` and + ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL``. Always use the latter where + possible, otherwise only use the former. + +Both events have their own set of APIs to access the data within: + +- ``LIBINPUT_EVENT_POINTER_AXIS``: Deprecated as of libinput 1.19, where + possible it is recommended to handle **only** + ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL``. + + * ``libinput_event_pointer_get_axis_value()`` returns the angle of movement + in degrees. + * ``libinput_event_pointer_get_axis_source()`` returns the source of the + event: wheel, finger or continuous. + * ``libinput_event_pointer_get_axis_value_discrete()`` returns the number of + logical wheel clicks. + +- ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` available since libinput 1.19. + + * ``libinput_event_pointer_get_scroll_value_v120()`` returns a value + normalized into the 0..120 range, see below. Any multiple of 120 should + be treated as one full wheel click. + +.. note:: Where possible, the ``libinput_event_pointer_get_axis_value()``, + ``libinput_event_pointer_get_axis_source()`` and + ``libinput_event_pointer_get_axis_value_discrete()`` API should be + avoided. + +------------------------------------------------------------------------------ +The v120 Wheel API +------------------------------------------------------------------------------ + +The ``v120`` value matches the Windows API for wheel scrolling. Wheel +movements are normalized into multiples (or fractions) of 120 with each +multiple of 120 representing one detent of movement. The ``v120`` API is the +recommended API for callers that do not care about the exact physical +motion and is the simplest API to handle high-resolution scrolling. + +Most wheels provide 24 detents per 360 degree rotation (click angle of 15), +others provide 18 detents per 360 degree rotation (click angle 20). Mice +falling outside these two are rare but do exist. Below is a table showing +the various values for a single event, depending on the click angle of the +wheel: + ++-------------+------------+---------------+------+ +| Click angle | Axis value | Discrete value| v120 | ++=============+============+===============+======+ +| 15 | 15 | 1 | 120 | ++-------------+------------+---------------+------+ +| 20 | 20 | 1 | 120 | ++-------------+------------+---------------+------+ + +Fast scrolling may trigger cover than one detent per event and thus each +event may contain multiples of the value, discrete or v120 value: + ++-------------+------------+---------------+------+ +| Click angle | Axis value | Discrete value| v120 | ++=============+============+===============+======+ +| 15 | 30 | 2 | 240 | ++-------------+------------+---------------+------+ +| 20 | 60 | 3 | 360 | ++-------------+------------+---------------+------+ + +Scrolling on high-resolution wheels will produce fractions of 120, depending +on the resolution of the wheel. The example below shows a mouse with click +angle 15 and a resolution of 3 events per wheel click and a mouse with click +angle 20 and a resolution of 2 events per wheel click. + ++-------------+------------+---------------+------+ +| Click angle | Axis value | Discrete value| v120 | ++=============+============+===============+======+ +| 15 | 5 | 0 | 40 | ++-------------+------------+---------------+------+ +| 20 | 10 | 0 | 60 | ++-------------+------------+---------------+------+ + +------------------------------------------------------------------------------ +Event sequences for high-resolution wheel mice +------------------------------------------------------------------------------ + +High-resolution scroll wheels provide multiple events for each detent is +hit. For those mice, an event sequence covering two detents may look like +this: + ++--------------+---------+------------+---------------+------+ +| Event number | Type | Axis value | Discrete value| v120 | ++==============+=========+============+===============+======+ +| 1 | WHEEL | 5 | n/a | 40 | ++--------------+---------+------------+---------------+------+ +| 2 | WHEEL | 5 | n/a | 40 | ++--------------+---------+------------+---------------+------+ +| 3 | WHEEL | 5 | n/a | 40 | ++--------------+---------+------------+---------------+------+ +| 4 | AXIS | 15 | 1 | 120 | ++--------------+---------+------------+---------------+------+ +| 5 | WHEEL | 5 | n/a | 40 | ++--------------+---------+------------+---------------+------+ +| 6 | WHEEL | 5 | n/a | 40 | ++--------------+---------+------------+---------------+------+ +| 7 | AXIS | 15 | 1 | 120 | ++--------------+---------+------------+---------------+------+ + +The above assumes a click angle of 15 for the physical detents. Note how the +second set of high-resolution events do **not** add up to a multiple of +120 before the low-resolution event. A caller must not assume any relation +between ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` and +``LIBINPUT_EVENT_POINTER_AXIS``. + +Fast-scrolling on a high-resolution mouse may trigger multiple fractions per +hardware scanout cycle and result in an event sequence like this: + ++---------------+---------+------------+---------------+------+ +| Event number | Type | Axis value | Discrete value| v120 | ++===============+=========+============+===============+======+ +| 1 | WHEEL | 5 | n/a | 40 | ++---------------+---------+------------+---------------+------+ +| 2 | WHEEL | 10 | n/a | 80 | ++---------------+---------+------------+---------------+------+ +| 3 | AXIS | 15 | 1 | 120 | ++---------------+---------+------------+---------------+------+ +| 4 | WHEEL | 10 | n/a | 80 | ++---------------+---------+------------+---------------+------+ +| 5 | WHEEL | 10 | n/a | 80 | ++---------------+---------+------------+---------------+------+ +| 6 | AXIS | 15 | 1 | 120 | ++---------------+---------+------------+---------------+------+ +| 7 | WHEEL | 5 | n/a | 40 | ++---------------+---------+------------+---------------+------+ + +Note how the first low-resolution event is sent at an accumulated 15 +degrees, the second at an accumulated 20 degrees. The libinput API does not +specify the smallest fraction a wheel supports. + +------------------------------------------------------------------------------ +Event sequences for regular wheel mice +------------------------------------------------------------------------------ + +``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` for low-resolution mice are virtually +identical to ``LIBINPUT_EVENT_POINTER_AXIS`` events. Note that the discrete +value is always 0 for ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL``. + ++--------------+---------+------------+---------------+------+ +| Event number | Type | Axis value | Discrete value| v120 | ++==============+=========+============+===============+======+ +| 1 | AXIS | 15 | 1 | 120 | ++--------------+---------+------------+---------------+------+ +| 2 | WHEEL | 15 | n/a | 120 | ++--------------+---------+------------+---------------+------+ +| 3 | WHEEL | 15 | n/a | 120 | ++--------------+---------+------------+---------------+------+ +| 4 | AXIS | 15 | 1 | 120 | ++--------------+---------+------------+---------------+------+ + +Note that the order of ``LIBINPUT_EVENT_POINTER_AXIS`` vs +``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` events is not guaranteed, as shown in +the example above. diff --git a/src/evdev-fallback.c b/src/evdev-fallback.c index f7c7e02b2d3bc2553c42b4de924c8cc9dec57e2e..85cf6ca9c5996f1755d6414ca52b428275b9d2ba 100644 --- a/src/evdev-fallback.c +++ b/src/evdev-fallback.c @@ -230,59 +230,88 @@ fallback_flush_wheels(struct fallback_dispatch *dispatch, { struct normalized_coords wheel_degrees = { 0.0, 0.0 }; struct discrete_coords discrete = { 0.0, 0.0 }; + struct wheel_v120 v120 = { 0.0, 0.0 }; if (!(device->seat_caps & EVDEV_DEVICE_POINTER)) return; if (dispatch->wheel.is_inhibited) { - dispatch->wheel.delta.x = 0; - dispatch->wheel.delta.y = 0; + dispatch->wheel.hi_res.x = 0; + dispatch->wheel.hi_res.y = 0; + dispatch->wheel.lo_res.x = 0; + dispatch->wheel.lo_res.y = 0; return; } if (device->model_flags & EVDEV_MODEL_LENOVO_SCROLLPOINT) { struct normalized_coords unaccel = { 0.0, 0.0 }; - dispatch->wheel.delta.y *= -1; - normalize_delta(device, &dispatch->wheel.delta, &unaccel); + dispatch->wheel.hi_res.y *= -1; + normalize_delta(device, &dispatch->wheel.hi_res, &unaccel); evdev_post_scroll(device, time, LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, &unaccel); - dispatch->wheel.delta.x = 0; - dispatch->wheel.delta.y = 0; + dispatch->wheel.hi_res.x = 0; + dispatch->wheel.hi_res.y = 0; return; } - if (dispatch->wheel.delta.y != 0) { - wheel_degrees.y = -1 * dispatch->wheel.delta.y * - device->scroll.wheel_click_angle.y; - discrete.y = -1 * dispatch->wheel.delta.y; + if (dispatch->wheel.hi_res.y != 0) { + int value = dispatch->wheel.hi_res.y; - evdev_notify_axis( + v120.y = -1 * value; + wheel_degrees.y = -1 * value/120.0 * device->scroll.wheel_click_angle.y; + evdev_notify_axis_wheel( + device, + time, + bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), + &wheel_degrees, + &v120); + dispatch->wheel.hi_res.y = 0; + } + + if (dispatch->wheel.lo_res.y != 0) { + int value = dispatch->wheel.lo_res.y; + + wheel_degrees.y = -1 * value * device->scroll.wheel_click_angle.y; + discrete.y = -1 * value; + evdev_notify_axis_legacy_wheel( device, time, bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), - LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, &wheel_degrees, &discrete); - dispatch->wheel.delta.y = 0; + dispatch->wheel.lo_res.y = 0; } - if (dispatch->wheel.delta.x != 0) { - wheel_degrees.x = dispatch->wheel.delta.x * - device->scroll.wheel_click_angle.x; - discrete.x = dispatch->wheel.delta.x; + if (dispatch->wheel.hi_res.x != 0) { + int value = dispatch->wheel.hi_res.x; - evdev_notify_axis( + v120.x = value; + wheel_degrees.x = value/120.0 * device->scroll.wheel_click_angle.x; + evdev_notify_axis_wheel( + device, + time, + bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL), + &wheel_degrees, + &v120); + dispatch->wheel.hi_res.x = 0; + } + + if (dispatch->wheel.lo_res.x != 0) { + int value = dispatch->wheel.lo_res.x; + + wheel_degrees.x = value * device->scroll.wheel_click_angle.x; + discrete.x = value; + evdev_notify_axis_legacy_wheel( device, time, bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL), - LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, &wheel_degrees, &discrete); - dispatch->wheel.delta.x = 0; + dispatch->wheel.lo_res.x = 0; } } @@ -855,11 +884,23 @@ fallback_process_relative(struct fallback_dispatch *dispatch, dispatch->pending_event |= EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: - dispatch->wheel.delta.y += e->value; + dispatch->wheel.lo_res.y += e->value; + if (dispatch->wheel.emulate_hi_res_wheel) + dispatch->wheel.hi_res.y += e->value * 120; dispatch->pending_event |= EVDEV_WHEEL; break; case REL_HWHEEL: - dispatch->wheel.delta.x += e->value; + dispatch->wheel.lo_res.x += e->value; + if (dispatch->wheel.emulate_hi_res_wheel) + dispatch->wheel.hi_res.x += e->value * 120; + dispatch->pending_event |= EVDEV_WHEEL; + break; + case REL_WHEEL_HI_RES: + dispatch->wheel.hi_res.y += e->value; + dispatch->pending_event |= EVDEV_WHEEL; + break; + case REL_HWHEEL_HI_RES: + dispatch->wheel.hi_res.x += e->value; dispatch->pending_event |= EVDEV_WHEEL; break; } @@ -1772,6 +1813,22 @@ fallback_dispatch_create(struct libinput_device *libinput_device) want_config); } + /* On kernel evdev, + EV_REL, + REL_WHEEL) && + !libevdev_has_event_code(device->evdev, + EV_REL, + REL_WHEEL_HI_RES)) || + (libevdev_has_event_code(device->evdev, + EV_REL, + REL_HWHEEL) && + !libevdev_has_event_code(device->evdev, + EV_REL, + REL_HWHEEL_HI_RES))) + dispatch->wheel.emulate_hi_res_wheel = true; + fallback_init_debounce(dispatch); fallback_init_arbitration(dispatch, device); diff --git a/src/evdev-fallback.h b/src/evdev-fallback.h index 58f324260d55a5ad9ad8f500bec9f0674d6f7bf5..fafd18218cc37ec790e29f11f27eaeb7a1b29ae9 100644 --- a/src/evdev-fallback.h +++ b/src/evdev-fallback.h @@ -98,7 +98,9 @@ struct fallback_dispatch { struct device_coords rel; struct { - struct device_coords delta; + struct device_coords lo_res; + struct device_coords hi_res; + bool emulate_hi_res_wheel; bool is_inhibited; } wheel; diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index d63cc74401d6330c2b6731ec5a2d0e03d8f2469a..08876bef0f61731eeea2bc10157c06047b349e56 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -426,7 +426,6 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) struct device_float_coords fraw; struct normalized_coords normalized, tmp; const struct normalized_coords zero = { 0.0, 0.0 }; - const struct discrete_coords zero_discrete = { 0.0, 0.0 }; tp_for_each_touch(tp, t) { if (!t->dirty) @@ -444,11 +443,10 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) case EDGE_NONE: if (t->scroll.direction != -1) { /* Send stop scroll event */ - evdev_notify_axis(device, time, - bit(t->scroll.direction), - LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - &zero, - &zero_discrete); + evdev_notify_axis_finger(device, + time, + bit(t->scroll.direction), + &zero); t->scroll.direction = -1; } continue; @@ -494,11 +492,9 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) if (*delta == 0.0) continue; - evdev_notify_axis(device, time, - bit(axis), - LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - &normalized, - &zero_discrete); + evdev_notify_axis_finger(device, time, + bit(axis), + &normalized); t->scroll.direction = axis; tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_POSTED, time); @@ -513,15 +509,13 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time) struct evdev_device *device = tp->device; struct tp_touch *t; const struct normalized_coords zero = { 0.0, 0.0 }; - const struct discrete_coords zero_discrete = { 0.0, 0.0 }; tp_for_each_touch(tp, t) { if (t->scroll.direction != -1) { - evdev_notify_axis(device, time, - bit(t->scroll.direction), - LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - &zero, - &zero_discrete); + evdev_notify_axis_finger(device, + time, + bit(t->scroll.direction), + &zero); t->scroll.direction = -1; /* reset touch to area state, avoids loading the * state machine with special case handling */ diff --git a/src/evdev.c b/src/evdev.c index 36c782f2ec7850661a47e66255ba6dd7393b7815..e8b376748f49906df1b3f42791fafefbb301521f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -375,12 +375,11 @@ evdev_device_transform_y(struct evdev_device *device, } void -evdev_notify_axis(struct evdev_device *device, - uint64_t time, - uint32_t axes, - enum libinput_pointer_axis_source source, - const struct normalized_coords *delta_in, - const struct discrete_coords *discrete_in) +evdev_notify_axis_legacy_wheel(struct evdev_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta_in, + const struct discrete_coords *discrete_in) { struct normalized_coords delta = *delta_in; struct discrete_coords discrete = *discrete_in; @@ -397,12 +396,73 @@ evdev_notify_axis(struct evdev_device *device, discrete.y *= -1; } - pointer_notify_axis(&device->base, - time, - axes, - source, - &delta, - &discrete); + pointer_notify_axis_legacy_wheel(&device->base, + time, + axes, + &delta, + &discrete); +} + +void +evdev_notify_axis_wheel(struct evdev_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta_in, + const struct wheel_v120 *v120_in) +{ + struct normalized_coords delta = *delta_in; + struct wheel_v120 v120 = *v120_in; + + if (device->scroll.natural_scrolling_enabled) { + delta.x *= -1; + delta.y *= -1; + v120.x *= -1; + v120.y *= -1; + } + + pointer_notify_axis_wheel(&device->base, + time, + axes, + &delta, + &v120); +} + +void +evdev_notify_axis_finger(struct evdev_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta_in) +{ + struct normalized_coords delta = *delta_in; + + if (device->scroll.natural_scrolling_enabled) { + delta.x *= -1; + delta.y *= -1; + } + + pointer_notify_axis_finger(&device->base, + time, + axes, + &delta); +} + +void +evdev_notify_axis_continous(struct evdev_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta_in) +{ + struct normalized_coords delta = *delta_in; + + if (device->scroll.natural_scrolling_enabled) { + delta.x *= -1; + delta.y *= -1; + } + + pointer_notify_axis_continuous(&device->base, + time, + axes, + &delta); } static void @@ -2688,7 +2748,6 @@ evdev_post_scroll(struct evdev_device *device, event.x = 0.0; if (!normalized_is_zero(event)) { - const struct discrete_coords zero_discrete = { 0.0, 0.0 }; uint32_t axes = device->scroll.direction; if (event.y == 0.0) @@ -2696,12 +2755,19 @@ evdev_post_scroll(struct evdev_device *device, if (event.x == 0.0) axes &= ~bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - evdev_notify_axis(device, - time, - axes, - source, - &event, - &zero_discrete); + switch (source) { + case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: + evdev_notify_axis_finger(device, time, axes, &event); + break; + case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: + evdev_notify_axis_continous(device, time, axes, &event); + break; + default: + evdev_log_bug_libinput(device, + "Posting invalid scroll source %d\n", + source); + break; + } } } @@ -2711,16 +2777,29 @@ evdev_stop_scroll(struct evdev_device *device, enum libinput_pointer_axis_source source) { const struct normalized_coords zero = { 0.0, 0.0 }; - const struct discrete_coords zero_discrete = { 0.0, 0.0 }; /* terminate scrolling with a zero scroll event */ - if (device->scroll.direction != 0) - pointer_notify_axis(&device->base, - time, - device->scroll.direction, - source, - &zero, - &zero_discrete); + if (device->scroll.direction != 0) { + switch (source) { + case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: + pointer_notify_axis_finger(&device->base, + time, + device->scroll.direction, + &zero); + break; + case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: + pointer_notify_axis_continuous(&device->base, + time, + device->scroll.direction, + &zero); + break; + default: + evdev_log_bug_libinput(device, + "Stopping invalid scroll source %d\n", + source); + break; + } + } device->scroll.buildup.x = 0; device->scroll.buildup.y = 0; diff --git a/src/evdev.h b/src/evdev.h index 0732063cb20beb2d9e943eb6cdb4e7160248af70..c7d130f88b13c889fbc10b1ec6203d1d88fda222 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -583,12 +583,28 @@ evdev_update_key_down_count(struct evdev_device *device, int pressed); void -evdev_notify_axis(struct evdev_device *device, - uint64_t time, - uint32_t axes, - enum libinput_pointer_axis_source source, - const struct normalized_coords *delta_in, - const struct discrete_coords *discrete_in); +evdev_notify_axis_legacy_wheel(struct evdev_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta_in, + const struct discrete_coords *discrete_in); +void +evdev_notify_axis_wheel(struct evdev_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta_in, + const struct wheel_v120 *v120_in); +void +evdev_notify_axis_finger(struct evdev_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta_in); +void +evdev_notify_axis_continous(struct evdev_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta_in); + void evdev_post_scroll(struct evdev_device *device, uint64_t time, diff --git a/src/libinput-private.h b/src/libinput-private.h index 172035abb2269e0e92e96ff74cdab5912f0628be..d5845420d9645464f27ccadaf47f95d1750695dc 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -77,6 +77,11 @@ struct wheel_angle { double x, y; }; +/* A pair of wheel click data for the 120-normalized range */ +struct wheel_v120 { + int x, y; +}; + /* A pair of angles in degrees */ struct tilt_degrees { double x, y; @@ -568,12 +573,29 @@ pointer_notify_button(struct libinput_device *device, enum libinput_button_state state); void -pointer_notify_axis(struct libinput_device *device, - uint64_t time, - uint32_t axes, - enum libinput_pointer_axis_source source, - const struct normalized_coords *delta, - const struct discrete_coords *discrete); +pointer_notify_axis_finger(struct libinput_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta); +void +pointer_notify_axis_continuous(struct libinput_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta); + +void +pointer_notify_axis_legacy_wheel(struct libinput_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta, + const struct discrete_coords *discrete); + +void +pointer_notify_axis_wheel(struct libinput_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta, + const struct wheel_v120 *v120); void touch_notify_touch_down(struct libinput_device *device, diff --git a/src/libinput.c b/src/libinput.c index 092762aab1705b67836462b2513420bb18783981..a0c85043c2e475b84fef4fb38bd1f6de11665cd1 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -87,6 +87,9 @@ event_type_to_str(enum libinput_event_type type) CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_BUTTON); CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_AXIS); + CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_SCROLL_WHEEL); + CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_SCROLL_FINGER); + CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_DOWN); CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_UP); CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_MOTION); @@ -175,6 +178,7 @@ struct libinput_event_pointer { struct device_float_coords delta_raw; struct device_coords absolute; struct discrete_coords discrete; + struct wheel_v120 v120; uint32_t button; uint32_t seat_button_count; enum libinput_button_state state; @@ -366,6 +370,9 @@ libinput_event_get_pointer_event(struct libinput_event *event) LIBINPUT_EVENT_POINTER_MOTION, LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, LIBINPUT_EVENT_POINTER_BUTTON, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, LIBINPUT_EVENT_POINTER_AXIS); return (struct libinput_event_pointer *) event; @@ -530,6 +537,9 @@ libinput_event_pointer_get_time(struct libinput_event_pointer *event) LIBINPUT_EVENT_POINTER_MOTION, LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, LIBINPUT_EVENT_POINTER_BUTTON, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, LIBINPUT_EVENT_POINTER_AXIS); return us2ms(event->time); @@ -544,6 +554,9 @@ libinput_event_pointer_get_time_usec(struct libinput_event_pointer *event) LIBINPUT_EVENT_POINTER_MOTION, LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, LIBINPUT_EVENT_POINTER_BUTTON, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, LIBINPUT_EVENT_POINTER_AXIS); return event->time; @@ -692,6 +705,9 @@ libinput_event_pointer_has_axis(struct libinput_event_pointer *event, require_event_type(libinput_event_get_context(&event->base), event->base.type, 0, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, LIBINPUT_EVENT_POINTER_AXIS); switch (axis) { @@ -758,6 +774,62 @@ libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *ev return value; } +LIBINPUT_EXPORT double +libinput_event_pointer_get_scroll_value(struct libinput_event_pointer *event, + enum libinput_pointer_axis axis) +{ + struct libinput *libinput = event->base.device->seat->libinput; + double value = 0; + + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0.0, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); + + if (!libinput_event_pointer_has_axis(event, axis)) { + log_bug_client(libinput, "value requested for unset axis\n"); + } else { + switch (axis) { + case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: + value = event->delta.x; + break; + case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: + value = event->delta.y; + break; + } + } + return value; +} + +LIBINPUT_EXPORT double +libinput_event_pointer_get_scroll_value_v120(struct libinput_event_pointer *event, + enum libinput_pointer_axis axis) +{ + struct libinput *libinput = event->base.device->seat->libinput; + double value = 0; + + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0.0, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL); + + if (!libinput_event_pointer_has_axis(event, axis)) { + log_bug_client(libinput, "value requested for unset axis\n"); + } else { + switch (axis) { + case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: + value = event->v120.x; + break; + case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: + value = event->v120.y; + break; + } + } + return value; +} + LIBINPUT_EXPORT enum libinput_pointer_axis_source libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event) { @@ -2438,14 +2510,82 @@ pointer_notify_button(struct libinput_device *device, } void -pointer_notify_axis(struct libinput_device *device, - uint64_t time, - uint32_t axes, - enum libinput_pointer_axis_source source, - const struct normalized_coords *delta, - const struct discrete_coords *discrete) +pointer_notify_axis_finger(struct libinput_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta) +{ + struct libinput_event_pointer *axis_event, *axis_event_legacy; + const struct discrete_coords zero_discrete = {0}; + const struct wheel_v120 zero_v120 = {0}; + + if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_POINTER)) + return; + + axis_event = zalloc(sizeof *axis_event); + axis_event_legacy = zalloc(sizeof *axis_event_legacy); + + *axis_event = (struct libinput_event_pointer) { + .time = time, + .delta = *delta, + .source = LIBINPUT_POINTER_AXIS_SOURCE_FINGER, + .axes = axes, + .discrete = zero_discrete, + .v120 = zero_v120, + }; + *axis_event_legacy = *axis_event; + + post_device_event(device, time, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + &axis_event->base); + post_device_event(device, time, + LIBINPUT_EVENT_POINTER_AXIS, + &axis_event_legacy->base); +} + +void +pointer_notify_axis_continuous(struct libinput_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta) +{ + struct libinput_event_pointer *axis_event, *axis_event_legacy; + const struct discrete_coords zero_discrete = {0}; + const struct wheel_v120 zero_v120 = {0}; + + if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_POINTER)) + return; + + axis_event = zalloc(sizeof *axis_event); + axis_event_legacy = zalloc(sizeof *axis_event_legacy); + + *axis_event = (struct libinput_event_pointer) { + .time = time, + .delta = *delta, + .source = LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, + .axes = axes, + .discrete = zero_discrete, + .v120 = zero_v120, + }; + *axis_event_legacy = *axis_event; + + post_device_event(device, time, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + &axis_event->base); + post_device_event(device, time, + LIBINPUT_EVENT_POINTER_AXIS, + &axis_event_legacy->base); +} + +void +pointer_notify_axis_legacy_wheel(struct libinput_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta, + const struct discrete_coords *discrete) { struct libinput_event_pointer *axis_event; + const struct wheel_v120 zero_v120 = {0}; if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_POINTER)) return; @@ -2455,9 +2595,10 @@ pointer_notify_axis(struct libinput_device *device, *axis_event = (struct libinput_event_pointer) { .time = time, .delta = *delta, - .source = source, + .source = LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, .axes = axes, .discrete = *discrete, + .v120 = zero_v120, }; post_device_event(device, time, @@ -2465,6 +2606,37 @@ pointer_notify_axis(struct libinput_device *device, &axis_event->base); } +void +pointer_notify_axis_wheel(struct libinput_device *device, + uint64_t time, + uint32_t axes, + const struct normalized_coords *delta, + const struct wheel_v120 *v120) +{ + struct libinput_event_pointer *axis_event; + + if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_POINTER)) + return; + + axis_event = zalloc(sizeof *axis_event); + + *axis_event = (struct libinput_event_pointer) { + .time = time, + .delta = *delta, + .source = LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, + .axes = axes, + .discrete.x = 0, + .discrete.y = 0, + .v120 = *v120, + }; + + post_device_event(device, time, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + &axis_event->base); + + /* legacy wheel events are sent separately */ +} + void touch_notify_touch_down(struct libinput_device *device, uint64_t time, @@ -3361,6 +3533,9 @@ libinput_event_pointer_get_base_event(struct libinput_event_pointer *event) LIBINPUT_EVENT_POINTER_MOTION, LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, LIBINPUT_EVENT_POINTER_BUTTON, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, LIBINPUT_EVENT_POINTER_AXIS); return &event->base; diff --git a/src/libinput.h b/src/libinput.h index 46b38a4d271040aa1c7b06739688357d86ed248c..e0a9df677a82cdf833e87b13159a9906f04c0b51 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -253,6 +253,12 @@ enum libinput_pointer_axis { * * The source for a libinput_pointer_axis event. See * libinput_event_pointer_get_axis_source() for details. + * + * @note Pointer axis sources are deprecated, the source is now encoded in + * the event types + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + * @ref LIBINPUT_EVENT_POINTER_SCROLL_FINGER, and + * @ref LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS. */ enum libinput_pointer_axis_source { /** @@ -742,8 +748,80 @@ enum libinput_event_type { LIBINPUT_EVENT_POINTER_MOTION = 400, LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, LIBINPUT_EVENT_POINTER_BUTTON, + /** + * A scroll event from various sources. + * + * This event is deprecated as of libinput 1.19. Use + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + * @ref LIBINPUT_EVENT_POINTER_SCROLL_FINGER, and + * @ref LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS instead. + * + * Use libinput_event_pointer_get_axis_source() to determine the + * source of a scroll event. For libinput versions 1.19 and later, + * the source is encoded in the event type. + * + * This event is sent **in addition** to events of type + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + * @ref LIBINPUT_EVENT_POINTER_SCROLL_FINGER, and + * @ref LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS. + * Do not mix and match, either use the old event or the new events. + * libinput makes no guarantee about the relation between + * @ref LIBINPUT_EVENT_POINTER_AXIS and the new event types + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + * @ref LIBINPUT_EVENT_POINTER_SCROLL_FINGER, and + * @ref LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS. You may receive + * multiple zero, one or more new events per legacy event. + * + * @warning Ignore this event if you are processing + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + * @ref LIBINPUT_EVENT_POINTER_SCROLL_FINGER, and + * @ref LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS. + */ LIBINPUT_EVENT_POINTER_AXIS, + /** + * A scroll event from a wheel. This event is sent is sent **in + * addition** to the @ref LIBINPUT_EVENT_POINTER_AXIS + * event for all events with a + * libinput_event_pointer_get_axis_source() of @ref + * LIBINPUT_POINTER_AXIS_SOURCE_WHEEL. Ignore @ref + * LIBINPUT_EVENT_POINTER_AXIS if you are processing this event. + * + * See the libinput documentation for details. + * + * @since 1.19 + */ + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + + /** + * A scroll event caused by the movement of one or more fingers on a + * device. This event is sent is sent **in addition** to the @ref + * LIBINPUT_EVENT_POINTER_AXIS event for all events with a + * libinput_event_pointer_get_axis_source() of @ref + * LIBINPUT_POINTER_AXIS_SOURCE_FINGER. Ignore @ref + * LIBINPUT_EVENT_POINTER_AXIS if you are processing this event. + * + * See the libinput documentation for details. + * + * @since 1.19 + */ + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + + /** + * A scroll event from a continuous scroll source, e.g. button + * scrolling. This event is sent is sent **in + * addition** to the @ref LIBINPUT_EVENT_POINTER_AXIS + * event for all events with a + * libinput_event_pointer_get_axis_source() of @ref + * LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS. Ignore @ref + * LIBINPUT_EVENT_POINTER_AXIS if you are processing this event. + * + * See the libinput documentation for details. + * + * @since 1.19 + */ + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_EVENT_TOUCH_DOWN = 500, LIBINPUT_EVENT_TOUCH_UP, LIBINPUT_EVENT_TOUCH_MOTION, @@ -1415,10 +1493,15 @@ libinput_event_pointer_get_seat_button_count( * is a scroll stop event. * * For pointer events that are not of type @ref LIBINPUT_EVENT_POINTER_AXIS, - * this function returns 0. + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, @ref + * LIBINPUT_EVENT_POINTER_SCROLL_FINGER, or @ref + * LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS this function returns 0. * * @note It is an application bug to call this function for events other than - * @ref LIBINPUT_EVENT_POINTER_AXIS. + * @ref LIBINPUT_EVENT_POINTER_AXIS, + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + * @ref LIBINPUT_EVENT_POINTER_SCROLL_FINGER, or + * @ref LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS. * * @return Non-zero if this event contains a value for this axis */ @@ -1474,7 +1557,9 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, * Scrolling is in discrete steps, the value is the angle the wheel moved * in degrees. The default is 15 degrees per wheel click, but some mice may * have differently grained wheels. It is up to the caller how to interpret - * such different step sizes. + * such different step sizes. Callers should use + * libinput_event_pointer_get_scroll_value_v120() for a simpler API of + * handling scroll wheel events of different step sizes. * * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, no * terminating event is guaranteed (though it may happen). @@ -1490,6 +1575,12 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_AXIS. * + * @note This function is superfluous as of libinput 1.19. The event + * codes for @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, @ref + * LIBINPUT_EVENT_POINTER_SCROLL_FINGER and @ref + * LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS have the axis source encoded in + * the event type. + * * @return The source for this axis event */ enum libinput_pointer_axis_source @@ -1501,6 +1592,14 @@ libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event); * Return the axis value in discrete steps for a given axis event. How a * value translates into a discrete step depends on the source. * + * @note This function does not support high-resolution mouse wheels and + * should be considered deprecated as of libinput 1.19. Callers should use + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL and + * libinput_event_pointer_get_scroll_value_v120() instead. + * + * If the event is not of type @ref LIBINPUT_EVENT_POINTER_AXIS, this + * function returns 0. + * * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, the discrete * value correspond to the number of physical mouse wheel clicks. * @@ -1510,11 +1609,104 @@ libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event); * @return The discrete value for the given event. * * @see libinput_event_pointer_get_axis_value + * @see libinput_event_pointer_get_scroll_value_v120 */ double libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *event, enum libinput_pointer_axis axis); +/** + * @ingroup event_pointer + * + * Return the axis value of the given axis. The interpretation of the value + * depends on the axis. For the two scrolling axes + * @ref LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL and + * @ref LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, the value of the event is in + * relative scroll units, with the positive direction being down or right, + * respectively. If libinput_event_pointer_has_axis() returns 0 for an axis, + * this function returns 0 for that axis. + * + * If the event is @ref LIBINPUT_EVENT_POINTER_SCROLL_FINGER, libinput + * guarantees that a scroll sequence is terminated with a scroll value of 0. + * A caller may use this information to decide on whether kinetic scrolling + * should be triggered on this scroll sequence. + * The coordinate system is identical to the cursor movement, i.e. a + * scroll value of 1 represents the equivalent relative motion of 1. + * + * If the event is @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, no terminating + * event is guaranteed (though it may happen). + * Scrolling is in discrete steps, the value is the angle the wheel moved + * in degrees. The default is 15 degrees per wheel click, but some mice may + * have differently grained wheels. It is up to the caller how to interpret + * such different step sizes. Callers should use + * libinput_event_pointer_get_scroll_value_v120() for a simpler API of + * handling scroll wheel events of different step sizes. + * + * If the event is @ref LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, no + * terminating event is guaranteed (though it may happen). + * The coordinate system is identical to the cursor movement, i.e. a + * scroll value of 1 represents the equivalent relative motion of 1. + * + * For pointer events that are not of type + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + * @ref LIBINPUT_EVENT_POINTER_SCROLL_FINGER, or + * @ref LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, this function returns zero. + * + * @note It is an application bug to call this function for events other than + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + * @ref LIBINPUT_EVENT_POINTER_SCROLL_FINGER, or + * @ref LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS. + * + * @return The axis value of this event + * + * @see libinput_event_pointer_get_scroll_value_v120 + * + * @since 1.19 + */ +double +libinput_event_pointer_get_scroll_value(struct libinput_event_pointer *event, + enum libinput_pointer_axis axis); + +/** + * @ingroup event_pointer + * + * For events of type @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL + * the v120-normalized value represents the movement in logical mouse wheel + * clicks, normalized to the -120..+120 range. + * + * A value that is a fraction of ±120 indicates a wheel movement less than + * one logical click, a caller should either scroll by the respective + * fraction of the normal scroll distance or accumulate that value until a + * multiple of 120 is reached. + * + * For most callers, this is the preferred way of handling high-resolution + * scroll events. + * + * The normalized v120 value does not take device-specific physical angles + * or distances into account, i.e. a wheel with a click angle of 20 degrees + * produces only 18 logical clicks per 360 degree rotation, a wheel with a + * click angle of 15 degrees produces 24 logical clicks per 360 degree + * rotation. Where the physical angle matters, use + * libinput_event_pointer_get_axis_value() instead. + * + * The magic number 120 originates from the + * Windows Vista Mouse Wheel design document. + * + * @note It is an application bug to call this function for events other than + * @ref LIBINPUT_EVENT_POINTER_SCROLL_WHEEL. + * + * @return A value normalized to the 0-±120 range + * + * @see libinput_event_pointer_get_axis_value + * @see libinput_event_pointer_get_axis_value_discrete + * + * @since 1.19 + */ +double +libinput_event_pointer_get_scroll_value_v120(struct libinput_event_pointer *event, + enum libinput_pointer_axis axis); + /** * @ingroup event_pointer * diff --git a/src/libinput.sym b/src/libinput.sym index b45838e0b12936543cceb51d9f19c66ae1efa238..7e6fa06bd77ef7f5008757ffbd78db7ae7567d58 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -314,3 +314,8 @@ LIBINPUT_1.15 { libinput_event_tablet_pad_get_key; libinput_event_tablet_pad_get_key_state; } LIBINPUT_1.14; + +LIBINPUT_1.19 { + libinput_event_pointer_get_scroll_value_v120; + libinput_event_pointer_get_scroll_value; +} LIBINPUT_1.15; diff --git a/test/litest-device-mouse-low-dpi.c b/test/litest-device-mouse-low-dpi.c index 9525058e41a5d74249ea3c33008dd693ac06b6ab..a01b89f19fed57aa79b0343ff2f20bd635fef3ea 100644 --- a/test/litest-device-mouse-low-dpi.c +++ b/test/litest-device-mouse-low-dpi.c @@ -39,6 +39,9 @@ static int events[] = { EV_REL, REL_X, EV_REL, REL_Y, EV_REL, REL_WHEEL, + EV_REL, REL_WHEEL_HI_RES, + EV_REL, REL_HWHEEL, + EV_REL, REL_HWHEEL_HI_RES, -1 , -1, }; diff --git a/test/litest-device-mouse.c b/test/litest-device-mouse.c index 68275be8a4d426f1e1fb85680155aa83ff7dfd35..d2c02fa349dd3874a6afa46540f0c3dfd8116be5 100644 --- a/test/litest-device-mouse.c +++ b/test/litest-device-mouse.c @@ -39,6 +39,7 @@ static int events[] = { EV_REL, REL_X, EV_REL, REL_Y, EV_REL, REL_WHEEL, + EV_REL, REL_WHEEL_HI_RES, -1 , -1, }; diff --git a/test/litest.c b/test/litest.c index b000fe8b1782181009c595dbdb7dae9e1f9c43e0..a900c1c8d7eb9de5d4ee9e782e0d3c4cd27af299 100644 --- a/test/litest.c +++ b/test/litest.c @@ -3097,6 +3097,15 @@ litest_event_type_str(enum libinput_event_type type) case LIBINPUT_EVENT_POINTER_AXIS: str = "AXIS"; break; + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: + str = "SCROLL_WHEEL"; + break; + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: + str = "SCROLL_FINGER"; + break; + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: + str = "SCROLL_CONTINUOUS"; + break; case LIBINPUT_EVENT_TOUCH_DOWN: str = "TOUCH DOWN"; break; @@ -3549,24 +3558,42 @@ litest_is_button_event(struct libinput_event *event, struct libinput_event_pointer * litest_is_axis_event(struct libinput_event *event, + enum libinput_event_type axis_type, enum libinput_pointer_axis axis, enum libinput_pointer_axis_source source) { struct libinput_event_pointer *ptrev; - enum libinput_event_type type = LIBINPUT_EVENT_POINTER_AXIS; + + litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL || + axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER || + axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); litest_assert_ptr_notnull(event); - litest_assert_event_type(event, type); + litest_assert_event_type_is_one_of(event, + LIBINPUT_EVENT_POINTER_AXIS, + axis_type); ptrev = libinput_event_get_pointer_event(event); litest_assert(libinput_event_pointer_has_axis(ptrev, axis)); if (source != 0) - litest_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev), + litest_assert_int_eq(litest_event_pointer_get_axis_source(ptrev), source); return ptrev; } +bool +litest_is_high_res_axis_event(struct libinput_event *event) +{ + litest_assert_event_type_is_one_of(event, + LIBINPUT_EVENT_POINTER_AXIS, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); + + return (libinput_event_get_type(event) != LIBINPUT_EVENT_POINTER_AXIS); +} + struct libinput_event_pointer * litest_is_motion_event(struct libinput_event *event) { @@ -3751,6 +3778,53 @@ litest_is_proximity_event(struct libinput_event *event, return tev; } +double +litest_event_pointer_get_value(struct libinput_event_pointer *ptrev, + enum libinput_pointer_axis axis) +{ + struct libinput_event *event; + enum libinput_event_type type; + + event = libinput_event_pointer_get_base_event(ptrev); + type = libinput_event_get_type(event); + + switch (type) { + case LIBINPUT_EVENT_POINTER_AXIS: + return libinput_event_pointer_get_axis_value(ptrev, axis); + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: + return libinput_event_pointer_get_scroll_value_v120(ptrev, axis); + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: + return libinput_event_pointer_get_scroll_value(ptrev, axis); + default: + abort(); + } +} + +enum libinput_pointer_axis_source +litest_event_pointer_get_axis_source(struct libinput_event_pointer *ptrev) +{ + struct libinput_event *event; + enum libinput_event_type type; + + event = libinput_event_pointer_get_base_event(ptrev); + type = libinput_event_get_type(event); + + if (type == LIBINPUT_EVENT_POINTER_AXIS) + return libinput_event_pointer_get_axis_source(ptrev); + + switch (type) { + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: + return LIBINPUT_POINTER_AXIS_SOURCE_WHEEL; + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: + return LIBINPUT_POINTER_AXIS_SOURCE_FINGER; + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: + return LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS; + default: + abort(); + } +} + void litest_assert_tablet_proximity_event(struct libinput *li, enum libinput_tablet_tool_proximity_state state) { @@ -3912,50 +3986,109 @@ litest_assert_pad_key_event(struct libinput *li, void litest_assert_scroll(struct libinput *li, + enum libinput_event_type axis_type, enum libinput_pointer_axis axis, int minimum_movement) { - struct libinput_event *event, *next_event; + struct libinput_event *event; struct libinput_event_pointer *ptrev; + bool last_hi_res_event_found, last_low_res_event_found; int value; int nevents = 0; + litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL || + axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER || + axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); + + last_hi_res_event_found = false; + last_low_res_event_found = false; event = libinput_get_event(li); - next_event = libinput_get_event(li); - litest_assert_ptr_notnull(next_event); /* At least 1 scroll + stop scroll */ + litest_assert_ptr_notnull(event); while (event) { - ptrev = litest_is_axis_event(event, axis, 0); + int min = minimum_movement; + + ptrev = litest_is_axis_event(event, axis_type, axis, 0); nevents++; - if (next_event) { - int min = minimum_movement; + /* Due to how the hysteresis works on touchpad + * events, the first event is reduced by the + * hysteresis margin that can cause the first event + * go under the minimum we expect for all other + * events */ + if (nevents == 1) + min = minimum_movement/2; + + value = litest_event_pointer_get_value(ptrev, axis); + if (litest_is_high_res_axis_event(event)) { + litest_assert(!last_hi_res_event_found); - value = libinput_event_pointer_get_axis_value(ptrev, - axis); - /* Due to how the hysteresis works on touchpad - * events, the first event is reduced by the - * hysteresis margin that can cause the first event - * go under the minimum we expect for all other - * events */ - if (nevents == 1) - min = minimum_movement/2; + if (axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL) + min *= 120; - /* Normal scroll event, check dir */ + if (value == 0) + last_hi_res_event_found = true; + } else { + litest_assert(!last_low_res_event_found); + + if (value == 0) + last_low_res_event_found = true; + } + + if (value != 0) { if (minimum_movement > 0) litest_assert_int_ge(value, min); else litest_assert_int_le(value, min); + } + + libinput_event_destroy(event); + event = libinput_get_event(li); + } + + litest_assert(last_low_res_event_found); + litest_assert(last_hi_res_event_found); +} + +void +litest_assert_axis_end_sequence(struct libinput *li, + enum libinput_event_type axis_type, + enum libinput_pointer_axis axis, + enum libinput_pointer_axis_source source) +{ + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + bool last_hi_res_event_found, last_low_res_event_found; + double val; + int i; + + litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL || + axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER || + axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); + + last_hi_res_event_found = false; + last_low_res_event_found = false; + + /* both high and low scroll end events must be sent */ + for (i = 0; i libinput; struct libinput_event *event; struct libinput_event_pointer *pev; - int code; + bool hi_res_event_found, low_res_event_found; + int code, i; + + hi_res_event_found = false; + low_res_event_found = false; litest_drain_events(li); @@ -1345,11 +1349,27 @@ START_TEST(device_quirks_no_abs_mt_y) litest_event(dev, EV_SYN, SYN_REPORT, 0); libinput_dispatch(li); - event = libinput_get_event(li); - pev = litest_is_axis_event(event, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, - LIBINPUT_POINTER_AXIS_SOURCE_WHEEL); - libinput_event_destroy(libinput_event_pointer_get_base_event(pev)); + /* both high and low scroll end events must be sent */ + for (i = 0; i libinput; struct libinput_event *event; @@ -611,40 +613,64 @@ test_wheel_event(struct litest_device *dev, int which, int amount) enum libinput_pointer_axis axis; enum libinput_pointer_axis_source source; - double scroll_step, expected, discrete; + double scroll_step, expected, discrete, v120; scroll_step = wheel_click_angle(dev, which); source = LIBINPUT_POINTER_AXIS_SOURCE_WHEEL; - expected = amount * scroll_step; - discrete = amount; + expected = scroll_step * (v120_amount/120); + discrete = v120_amount/120; + v120 = v120_amount; if (libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device)) { expected *= -1; discrete *= -1; + v120 *= -1; + } + + axis = (which == REL_WHEEL || which == REL_WHEEL_HI_RES) ? + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL : + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; + + event = libinput_get_event(li); + + while(event) { + ptrev = litest_is_axis_event(event, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, + axis, + source); + + if (!litest_is_high_res_axis_event(event)) { + litest_assert_double_eq( + libinput_event_pointer_get_axis_value(ptrev, axis), + expected); + litest_assert_double_eq( + libinput_event_pointer_get_axis_value_discrete(ptrev, axis), + discrete); + } else { + litest_assert_double_eq( + libinput_event_pointer_get_scroll_value_v120(ptrev, axis), + v120); + } + libinput_event_destroy(event); + event = libinput_get_event(li); } +} + +static void +test_wheel_event(struct litest_device *dev, int which, int amount) +{ + struct libinput *li = dev->libinput; + int event_amount = amount; /* mouse scroll wheels are 'upside down' */ if (which == REL_WHEEL) - amount *= -1; - litest_event(dev, EV_REL, which, amount); + event_amount *= -1; + litest_event(dev, EV_REL, which, event_amount); litest_event(dev, EV_SYN, SYN_REPORT, 0); libinput_dispatch(li); - axis = (which == REL_WHEEL) ? - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL : - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; - - event = libinput_get_event(li); - ptrev = litest_is_axis_event(event, axis, source); - - litest_assert_double_eq( - libinput_event_pointer_get_axis_value(ptrev, axis), - expected); - litest_assert_double_eq( - libinput_event_pointer_get_axis_value_discrete(ptrev, axis), - discrete); - libinput_event_destroy(event); + test_high_and_low_wheel_events_value(dev, which, amount * 120); } START_TEST(pointer_scroll_wheel) @@ -699,6 +725,84 @@ START_TEST(pointer_scroll_wheel_pressed_noscroll) } END_TEST +START_TEST(pointer_scroll_hi_res_wheel_pressed_noscroll) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + litest_drain_events(li); + + litest_button_click_debounced(dev, li, BTN_MIDDLE, true); + litest_drain_events(li); + + for (int i = 0; i libinput; + + switch(which) { + case REL_WHEEL_HI_RES: + /* mouse scroll wheels are 'upside down' */ + litest_event(dev, EV_REL, REL_WHEEL_HI_RES, -1 * v120_amount); + litest_event(dev, EV_REL, REL_WHEEL, -1 * v120_amount/120); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + break; + case REL_HWHEEL_HI_RES: + litest_event(dev, EV_REL, REL_HWHEEL_HI_RES, v120_amount); + litest_event(dev, EV_REL, REL_HWHEEL, v120_amount/120); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + break; + default: + abort(); + } + + libinput_dispatch(li); + + test_high_and_low_wheel_events_value(dev, which, v120_amount); +} + +START_TEST(pointer_scroll_wheel_hires) +{ + struct litest_device *dev = litest_current_device(); + + if (!libevdev_has_event_code(dev->evdev, EV_REL, REL_WHEEL_HI_RES) && + !libevdev_has_event_code(dev->evdev, EV_REL, REL_HWHEEL_HI_RES)) + return; + + litest_drain_events(dev->libinput); + + for (int axis = REL_WHEEL_HI_RES; axis evdev, EV_REL, axis)) + continue; + + test_hi_res_wheel_event(dev, axis, -120); + test_hi_res_wheel_event(dev, axis, 120); + + test_hi_res_wheel_event(dev, axis, -5 * 120); + test_hi_res_wheel_event(dev, axis, 6 * 120); + + test_hi_res_wheel_event(dev, axis, 30); + test_hi_res_wheel_event(dev, axis, -40); + test_hi_res_wheel_event(dev, axis, -60); + test_hi_res_wheel_event(dev, axis, 180); + } +} +END_TEST + START_TEST(pointer_scroll_natural_defaults) { struct litest_device *dev = litest_current_device(); @@ -785,6 +889,7 @@ START_TEST(pointer_scroll_has_axis_invalid) libinput_dispatch(li); event = libinput_get_event(li); pev = litest_is_axis_event(event, + LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 0); @@ -1054,13 +1159,25 @@ START_TEST(pointer_scroll_button) litest_drain_events(li); litest_button_scroll(dev, BTN_LEFT, 1, 6); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 6); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 6); litest_button_scroll(dev, BTN_LEFT, 1, -7); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -7); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + -7); litest_button_scroll(dev, BTN_LEFT, 8, 1); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 8); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + 8); litest_button_scroll(dev, BTN_LEFT, -9, 1); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -9); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + -9); /* scroll smaller than the threshold should not generate axis events */ litest_button_scroll(dev, BTN_LEFT, 1, 1); @@ -1185,7 +1302,10 @@ START_TEST(pointer_scroll_button_middle_emulation) litest_button_click(dev, BTN_RIGHT, 0); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -1); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + -1); litest_assert_empty_queue(li); /* Restore default scroll behavior */ @@ -1273,7 +1393,10 @@ START_TEST(pointer_scroll_button_lock) litest_button_click_debounced(dev, li, BTN_LEFT, false); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 6); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 6); litest_assert_empty_queue(li); @@ -1374,7 +1497,10 @@ START_TEST(pointer_scroll_button_lock_enable_while_down) litest_button_click_debounced(dev, li, BTN_LEFT, true); litest_button_click_debounced(dev, li, BTN_LEFT, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 6); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 6); litest_assert_empty_queue(li); @@ -1437,7 +1563,10 @@ START_TEST(pointer_scroll_button_lock_enable_while_down_just_lock) litest_button_click_debounced(dev, li, BTN_LEFT, true); litest_button_click_debounced(dev, li, BTN_LEFT, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 6); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 6); litest_assert_empty_queue(li); @@ -1479,7 +1608,8 @@ START_TEST(pointer_scroll_button_lock_otherbutton) litest_event(dev, EV_REL, REL_Y, 6); litest_event(dev, EV_SYN, SYN_REPORT, 0); } - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); /* other button passes on normally */ litest_button_click_debounced(dev, li, BTN_RIGHT, true); @@ -1490,7 +1620,8 @@ START_TEST(pointer_scroll_button_lock_otherbutton) /* stop scroll lock */ litest_button_click_debounced(dev, li, BTN_LEFT, true); litest_button_click_debounced(dev, li, BTN_LEFT, false); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); /* other button passes on normally */ litest_button_click_debounced(dev, li, BTN_RIGHT, true); @@ -1551,7 +1682,10 @@ START_TEST(pointer_scroll_button_lock_enable_while_otherbutton_down) litest_button_click_debounced(dev, li, BTN_LEFT, true); litest_button_click_debounced(dev, li, BTN_LEFT, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 6); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 6); litest_assert_empty_queue(li); /* back to motion */ @@ -1666,7 +1800,10 @@ START_TEST(pointer_scroll_button_lock_middlebutton) LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_RELEASED); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 6); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 6); litest_assert_empty_queue(li); break; case LRLR: @@ -2511,10 +2648,11 @@ START_TEST(middlebutton_button_scrolling) ev = libinput_get_event(li); do { pev = litest_is_axis_event(ev, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS); - ck_assert_double_gt(libinput_event_pointer_get_axis_value(pev, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), + ck_assert_double_gt(litest_event_pointer_get_value(pev, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), 0.0); libinput_event_destroy(ev); ev = libinput_get_event(li); @@ -2524,14 +2662,10 @@ START_TEST(middlebutton_button_scrolling) litest_event(dev, EV_SYN, SYN_REPORT, 0); libinput_dispatch(li); - ev = libinput_get_event(li); - pev = litest_is_axis_event(ev, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, - LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS); - ck_assert_double_eq(libinput_event_pointer_get_axis_value(pev, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), - 0.0); - libinput_event_destroy(ev); + litest_assert_axis_end_sequence(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS); /* no button release */ litest_assert_empty_queue(li); @@ -3293,6 +3427,8 @@ TEST_COLLECTION(pointer) litest_add(pointer_recover_from_lost_button_count, LITEST_BUTTON, LITEST_CLICKPAD); litest_add(pointer_scroll_wheel, LITEST_WHEEL, LITEST_TABLET); litest_add_for_device(pointer_scroll_wheel_pressed_noscroll, LITEST_MOUSE); + litest_add_for_device(pointer_scroll_hi_res_wheel_pressed_noscroll, LITEST_MOUSE); + litest_add(pointer_scroll_wheel_hires, LITEST_WHEEL, LITEST_TABLET); litest_add(pointer_scroll_button, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); litest_add(pointer_scroll_button_noscroll, LITEST_ABSOLUTE|LITEST_BUTTON, LITEST_RELATIVE); litest_add(pointer_scroll_button_noscroll, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON); diff --git a/test/test-switch.c b/test/test-switch.c index 8d6f56b3795870081a73e81019ee683c306cfab3..f4f3402e0df077f1a5556031c025d914b5fbdf89 100644 --- a/test/test-switch.c +++ b/test/test-switch.c @@ -406,18 +406,17 @@ START_TEST(switch_disable_touchpad_edge_scroll_interrupt) litest_timeout_edgescroll(); litest_touch_move_to(touchpad, 0, 99, 20, 99, 30, 10); libinput_dispatch(li); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); litest_grab_device(sw); litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON); litest_ungrab_device(sw); libinput_dispatch(li); - event = libinput_get_event(li); - litest_is_axis_event(event, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, - LIBINPUT_POINTER_AXIS_SOURCE_FINGER); - libinput_event_destroy(event); + litest_assert_axis_end_sequence(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); event = libinput_get_event(li); litest_is_switch_event(event, which, LIBINPUT_SWITCH_STATE_ON); diff --git a/test/test-touchpad-tap.c b/test/test-touchpad-tap.c index b9d57ce873ed47d9cfe3fbb42077d2e01e53254d..064c9159e1987da07df77b6d41502f85a001d57b 100644 --- a/test/test-touchpad-tap.c +++ b/test/test-touchpad-tap.c @@ -1735,7 +1735,7 @@ START_TEST(touchpad_tap_n_drag_2fg_scroll) litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); litest_assert_empty_queue(li); } @@ -1824,7 +1824,7 @@ START_TEST(touchpad_tap_n_drag_draglock_2fg_scroll) litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); litest_assert_empty_queue(li); } diff --git a/test/test-touchpad.c b/test/test-touchpad.c index 4043199bdab3facb665003c9aa94568ba02392e7..b7b34598847b8da597e2866e87961d36ba6af63f 100644 --- a/test/test-touchpad.c +++ b/test/test-touchpad.c @@ -149,13 +149,25 @@ START_TEST(touchpad_2fg_scroll) litest_drain_events(li); test_2fg_scroll(dev, 0.1, 40, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 9); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 9); test_2fg_scroll(dev, 0.1, -40, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -9); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + -9); test_2fg_scroll(dev, 40, 0.1, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 9); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + 9); test_2fg_scroll(dev, -40, 0.1, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -9); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + -9); /* 2fg scroll smaller than the threshold should not generate events */ test_2fg_scroll(dev, 0.1, 0.1, true); @@ -206,6 +218,9 @@ START_TEST(touchpad_2fg_scroll_initially_diagonal) expected_nevents++; } + /* both high-resolution and low-resolution events are generated */ + expected_nevents *= 2; + libinput_dispatch(li); event = libinput_get_event(li); @@ -213,6 +228,7 @@ START_TEST(touchpad_2fg_scroll_initially_diagonal) struct libinput_event_pointer *ptrev; ptrev = litest_is_axis_event(event, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, LIBINPUT_POINTER_AXIS_SOURCE_FINGER); ck_assert(!libinput_event_pointer_has_axis(ptrev, @@ -247,15 +263,27 @@ is_single_axis_2fg_scroll(struct litest_device *dev, event = libinput_get_event(li); while (event) { - litest_assert_event_type(event, LIBINPUT_EVENT_POINTER_AXIS); - ptrev = litest_is_axis_event(event, on_axis, + ptrev = litest_is_axis_event(event, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + on_axis, LIBINPUT_POINTER_AXIS_SOURCE_FINGER); has_on_axis = libinput_event_pointer_has_axis(ptrev, on_axis); has_off_axis = libinput_event_pointer_has_axis(ptrev, off_axis); if (has_on_axis && has_off_axis) { - val = (libinput_event_pointer_get_axis_value(ptrev, off_axis) == 0.0); + val = (litest_event_pointer_get_value(ptrev, off_axis) == 0.0); + + /* There must be an extra low/high-resolution event with + * the same axis value (0.0). */ + libinput_event_destroy(event); + event = libinput_get_event(li); + ck_assert_notnull(event); + ptrev = litest_is_axis_event(event, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + on_axis, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); + ck_assert(val == (litest_event_pointer_get_value(ptrev, off_axis) == 0.0)); break; } @@ -380,10 +408,14 @@ START_TEST(touchpad_2fg_scroll_slow_distance) struct libinput_event *event; double width, height; double y_move = 100; + bool last_hi_res_event_found, last_low_res_event_found; if (!litest_has_2fg_scroll(dev)) return; + last_hi_res_event_found = false; + last_low_res_event_found = false; + /* We want to move > 5 mm. */ ck_assert_int_eq(libinput_device_get_size(dev->libinput_device, &width, @@ -404,17 +436,28 @@ START_TEST(touchpad_2fg_scroll_slow_distance) event = libinput_get_event(li); ck_assert_notnull(event); - /* last event is value 0, tested elsewhere */ - while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) { + while (event) { struct libinput_event_pointer *ptrev; double axisval; ptrev = litest_is_axis_event(event, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 0); - axisval = libinput_event_pointer_get_axis_value(ptrev, + axisval = litest_event_pointer_get_value(ptrev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - ck_assert(axisval > 0.0); + + if (litest_is_high_res_axis_event(event)) { + litest_assert(!last_hi_res_event_found); + if (axisval == 0) + last_hi_res_event_found = true; + } else { + litest_assert(!last_low_res_event_found); + if (axisval == 0) + last_low_res_event_found = true; + } + + ck_assert(axisval >= 0.0); /* this is to verify we test the right thing, if the value is greater than scroll.threshold we triggered the wrong @@ -425,6 +468,8 @@ START_TEST(touchpad_2fg_scroll_slow_distance) event = libinput_get_event(li); } + litest_assert(last_low_res_event_found); + litest_assert(last_hi_res_event_found); litest_assert_empty_queue(li); libinput_event_destroy(event); } @@ -447,6 +492,7 @@ START_TEST(touchpad_2fg_scroll_source) while ((event = libinput_get_event(li))) { litest_is_axis_event(event, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, LIBINPUT_POINTER_AXIS_SOURCE_FINGER); libinput_event_destroy(event); @@ -474,7 +520,7 @@ START_TEST(touchpad_2fg_scroll_semi_mt) 30, 40, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); } END_TEST @@ -501,7 +547,7 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) libinput_dispatch(li); litest_timeout_finger_switch(); libinput_dispatch(li); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); litest_touch_move_to(dev, 0, 49, 70, 49, 50, 10); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); @@ -513,7 +559,7 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) libinput_dispatch(li); litest_timeout_finger_switch(); libinput_dispatch(li); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); /* move with second finger */ litest_touch_move_to(dev, 1, 51, 70, 51, 50, 10); @@ -557,7 +603,7 @@ START_TEST(touchpad_2fg_scroll_from_btnareas) litest_touch_up(dev, 0); litest_touch_up(dev, 1); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); } END_TEST @@ -600,13 +646,25 @@ START_TEST(touchpad_scroll_natural_2fg) libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1); test_2fg_scroll(dev, 0.1, 40, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -9); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + -9); test_2fg_scroll(dev, 0.1, -40, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 9); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 9); test_2fg_scroll(dev, 40, 0.1, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -9); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + -9); test_2fg_scroll(dev, -40, 0.1, false); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 9); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + 9); } END_TEST @@ -626,7 +684,10 @@ START_TEST(touchpad_scroll_natural_edge) litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -4); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + -4); litest_assert_empty_queue(li); litest_touch_down(dev, 0, 99, 80); @@ -634,7 +695,10 @@ START_TEST(touchpad_scroll_natural_edge) litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 4); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 4); litest_assert_empty_queue(li); } @@ -657,7 +721,10 @@ START_TEST(touchpad_edge_scroll_vert) litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 4); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 4); litest_assert_empty_queue(li); litest_touch_down(dev, 0, 99, 80); @@ -665,7 +732,10 @@ START_TEST(touchpad_edge_scroll_vert) litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -4); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + -4); litest_assert_empty_queue(li); } END_TEST @@ -701,7 +771,10 @@ START_TEST(touchpad_edge_scroll_horiz) litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 4); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + 4); litest_assert_empty_queue(li); litest_touch_down(dev, 0, 70, 99); @@ -709,7 +782,10 @@ START_TEST(touchpad_edge_scroll_horiz) litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -4); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + -4); litest_assert_empty_queue(li); } END_TEST @@ -727,7 +803,10 @@ START_TEST(touchpad_edge_scroll_horiz_clickpad) litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 4); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + 4); litest_assert_empty_queue(li); litest_touch_down(dev, 0, 70, 99); @@ -735,7 +814,10 @@ START_TEST(touchpad_edge_scroll_horiz_clickpad) litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -4); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + -4); litest_assert_empty_queue(li); } END_TEST @@ -861,10 +943,11 @@ START_TEST(touchpad_edge_scroll_timeout) double value; ptrev = litest_is_axis_event(event, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 0); - value = libinput_event_pointer_get_axis_value(ptrev, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + value = litest_event_pointer_get_value(ptrev, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); ck_assert_double_lt(value, 5.0); libinput_event_destroy(event); nevents++; @@ -896,7 +979,10 @@ START_TEST(touchpad_edge_scroll_no_motion) litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 4); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 4); litest_assert_empty_queue(li); } END_TEST @@ -938,10 +1024,11 @@ START_TEST(touchpad_edge_scroll_source) while ((event = libinput_get_event(li))) { struct libinput_event_pointer *ptrev; - ck_assert_int_eq(libinput_event_get_type(event), - LIBINPUT_EVENT_POINTER_AXIS); - ptrev = libinput_event_get_pointer_event(event); - ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev), + ptrev = litest_is_axis_event(event, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); + ck_assert_int_eq(litest_event_pointer_get_axis_source(ptrev), LIBINPUT_POINTER_AXIS_SOURCE_FINGER); libinput_event_destroy(event); } @@ -979,18 +1066,18 @@ START_TEST(touchpad_edge_scroll_into_buttonareas) litest_touch_down(dev, 0, 99, 40); litest_touch_move_to(dev, 0, 99, 40, 99, 95, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); /* in the button zone now, make sure we still get events */ litest_touch_move_to(dev, 0, 99, 95, 99, 100, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); /* and out of the zone again */ litest_touch_move_to(dev, 0, 99, 100, 99, 70, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); /* still out of the zone */ litest_touch_move_to(dev, 0, 99, 70, 99, 50, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); } END_TEST @@ -1010,15 +1097,15 @@ START_TEST(touchpad_edge_scroll_within_buttonareas) /* within left button */ litest_touch_move_to(dev, 0, 20, 99, 40, 99, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); /* over to right button */ litest_touch_move_to(dev, 0, 40, 99, 60, 99, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); /* within right button */ litest_touch_move_to(dev, 0, 60, 99, 80, 99, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); } END_TEST @@ -1027,8 +1114,6 @@ START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct libinput_event *event; - struct libinput_event_pointer *ptrev; - double val; if (!touchpad_has_horiz_edge_scroll_size(dev)) return; @@ -1039,19 +1124,15 @@ START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll) litest_touch_down(dev, 0, 20, 95); litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); litest_button_click(dev, BTN_LEFT, true); libinput_dispatch(li); - event = libinput_get_event(li); - ptrev = litest_is_axis_event(event, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, - LIBINPUT_POINTER_AXIS_SOURCE_FINGER); - val = libinput_event_pointer_get_axis_value(ptrev, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - ck_assert(val == 0.0); - libinput_event_destroy(event); + litest_assert_axis_end_sequence(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); event = libinput_get_event(li); litest_is_button_event(event, @@ -1083,8 +1164,6 @@ START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct libinput_event *event; - struct libinput_event_pointer *ptrev; - double val; if (!touchpad_has_horiz_edge_scroll_size(dev)) return; @@ -1095,19 +1174,15 @@ START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll) litest_touch_down(dev, 0, 20, 95); litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); litest_button_click(dev, BTN_LEFT, true); libinput_dispatch(li); - event = libinput_get_event(li); - ptrev = litest_is_axis_event(event, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, - LIBINPUT_POINTER_AXIS_SOURCE_FINGER); - val = libinput_event_pointer_get_axis_value(ptrev, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - ck_assert(val == 0.0); - libinput_event_destroy(event); + litest_assert_axis_end_sequence(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); event = libinput_get_event(li); litest_is_button_event(event, @@ -1142,15 +1217,14 @@ START_TEST(touchpad_edge_scroll_into_area) litest_touch_down(dev, 0, 99, 20); litest_touch_move_to(dev, 0, 99, 20, 99, 50, 15); litest_touch_move_to(dev, 0, 99, 50, 20, 50, 15); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); + litest_touch_move_to(dev, 0, 20, 50, 20, 20, 15); litest_touch_move_to(dev, 0, 20, 20, 99, 20, 15); litest_assert_empty_queue(li); litest_touch_move_to(dev, 0, 99, 20, 99, 50, 15); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); } END_TEST @@ -1233,7 +1307,7 @@ START_TEST(touchpad_no_palm_detect_at_edge_for_edge_scrolling) litest_touch_move_to(dev, 0, 99, 50, 99, 70, 5); litest_touch_up(dev, 0); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); } END_TEST @@ -1636,7 +1710,7 @@ START_TEST(touchpad_no_palm_detect_2fg_scroll) litest_assert_empty_queue(li); litest_touch_move_two_touches(dev, 99, 50, 50, 50, 0, -20, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); } END_TEST @@ -3322,7 +3396,8 @@ START_TEST(touchpad_trackpoint_mb_scroll) litest_event(trackpoint, EV_SYN, SYN_REPORT, 0); litest_button_click(touchpad, BTN_2, false); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); litest_delete_device(trackpoint); } @@ -3436,9 +3511,10 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll) struct libinput_event_pointer *pev; pev = litest_is_axis_event(e, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 0); - val = libinput_event_pointer_get_axis_value(pev, + val = litest_event_pointer_get_value(pev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); ck_assert(val != 0.0); libinput_event_destroy(e); @@ -3452,15 +3528,16 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll) litest_touch_move_to(touchpad, 0, 40, 30, 40, 70, 10); litest_touch_move_to(touchpad, 1, 60, 30, 60, 70, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); while ((e = libinput_get_event(li))) { struct libinput_event_pointer *pev; pev = litest_is_axis_event(e, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 0); - val = libinput_event_pointer_get_axis_value(pev, + val = litest_event_pointer_get_value(pev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); ck_assert(val != 0.0); libinput_event_destroy(e); @@ -3479,7 +3556,7 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll) */ litest_touch_move_to(touchpad, 0, 40, 70, 40, 60, 10); litest_touch_move_to(touchpad, 1, 60, 70, 60, 60, 10); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); litest_touch_move_to(touchpad, 0, 40, 60, 40, 30, 10); litest_touch_move_to(touchpad, 1, 60, 60, 60, 30, 10); @@ -3489,6 +3566,7 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll) libinput_dispatch(li); litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -1); @@ -3684,7 +3762,7 @@ START_TEST(touchpad_state_after_syn_dropped_2fg_change) litest_touch_move_two_touches(dev, 50, 50, 70, 50, 0, -20, 10); litest_touch_up(dev, 0); litest_touch_up(dev, 1); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); /* pointer motion still works? */ litest_touch_down(dev, 0, 50, 50); @@ -4497,7 +4575,6 @@ START_TEST(touchpad_dwt_edge_scroll_interrupt) struct litest_device *touchpad = litest_current_device(); struct litest_device *keyboard; struct libinput *li = touchpad->libinput; - struct libinput_event_pointer *stop_event; if (!has_disable_while_typing(touchpad)) return; @@ -4512,19 +4589,20 @@ START_TEST(touchpad_dwt_edge_scroll_interrupt) litest_timeout_edgescroll(); litest_touch_move_to(touchpad, 0, 99, 20, 99, 30, 10); libinput_dispatch(li); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); litest_keyboard_key(keyboard, KEY_A, true); litest_keyboard_key(keyboard, KEY_A, false); litest_keyboard_key(keyboard, KEY_A, true); litest_keyboard_key(keyboard, KEY_A, false); - /* scroll stop event */ + /* scroll stop events (low and high resolution) */ litest_wait_for_event(li); - stop_event = litest_is_axis_event(libinput_get_event(li), - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, - LIBINPUT_POINTER_AXIS_SOURCE_FINGER); - libinput_event_destroy(libinput_event_pointer_get_base_event(stop_event)); + litest_assert_axis_end_sequence(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); litest_timeout_dwt_long(); @@ -5243,7 +5321,10 @@ START_TEST(touchpad_thumb_speed_empty_slots) litest_touch_up(dev, 1); litest_touch_up(dev, 2); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 2); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 2); } END_TEST @@ -5368,7 +5449,7 @@ START_TEST(touchpad_thumb_no_doublethumb) litest_touch_up(dev, 0); litest_touch_up(dev, 1); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); } END_TEST @@ -6272,7 +6353,10 @@ START_TEST(touchpad_pressure_semi_mt_2fg_goes_light) litest_pop_event_frame(dev); libinput_dispatch(li); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 0); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_FINGER, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 0); litest_push_event_frame(dev); litest_touch_move_extended(dev, 0, 40, 35, axes); @@ -6603,7 +6687,7 @@ START_TEST(touchpad_speed_allow_nearby_finger) litest_touch_up(dev, 0); litest_touch_up(dev, 1); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); } END_TEST @@ -6671,7 +6755,7 @@ START_TEST(touchpad_speed_ignore_hovering_finger) litest_touch_up(dev, 1); litest_touch_up(dev, 0); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER); } END_TEST diff --git a/test/test-trackpoint.c b/test/test-trackpoint.c index 46484b4cea060ca641da3cc3cf00a7bf57a6eec2..86f70296891cb37d69dd7d28622e7abd2f4919ed 100644 --- a/test/test-trackpoint.c +++ b/test/test-trackpoint.c @@ -77,13 +77,25 @@ START_TEST(trackpoint_scroll) litest_drain_events(li); litest_button_scroll(dev, BTN_MIDDLE, 1, 6); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 6); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + 6); litest_button_scroll(dev, BTN_MIDDLE, 1, -7); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -7); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + -7); litest_button_scroll(dev, BTN_MIDDLE, 8, 1); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 8); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + 8); litest_button_scroll(dev, BTN_MIDDLE, -9, 1); - litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -9); + litest_assert_scroll(li, + LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + -9); /* scroll smaller than the threshold should not generate axis events */ litest_button_scroll(dev, BTN_MIDDLE, 1, 1); @@ -147,7 +159,7 @@ START_TEST(trackpoint_scroll_source) while ((event = libinput_get_event(li))) { ptrev = libinput_event_get_pointer_event(event); - ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev), + ck_assert_int_eq(litest_event_pointer_get_axis_source(ptrev), LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS); libinput_event_destroy(event); diff --git a/tools/libinput-debug-events.c b/tools/libinput-debug-events.c index 9ac2b0c681b603c427db450b20247a25779147c4..1fed8cb8776d950c5431208c4d26a9fe78b8dbef 100644 --- a/tools/libinput-debug-events.c +++ b/tools/libinput-debug-events.c @@ -86,6 +86,15 @@ print_event_header(struct libinput_event *ev) case LIBINPUT_EVENT_POINTER_AXIS: type = "POINTER_AXIS"; break; + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: + type = "POINTER_SCROLL_WHEEL"; + break; + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: + type = "POINTER_SCROLL_FINGER"; + break; + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: + type = "POINTER_SCROLL_CONTINUOUS"; + break; case LIBINPUT_EVENT_TOUCH_DOWN: type = "TOUCH_DOWN"; break; @@ -156,7 +165,7 @@ print_event_header(struct libinput_event *ev) prefix = (last_device != dev) ? '-' : ' '; - printq("%c%-7s %-16s ", + printq("%c%-7s %-23s ", prefix, libinput_device_get_sysname(dev), type); @@ -474,46 +483,49 @@ static void print_pointer_axis_event(struct libinput_event *ev) { struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); - double v = 0, h = 0; - int dv = 0, dh = 0; + double v = 0, h = 0, v120 = 0, h120 = 0; const char *have_vert = "", *have_horiz = ""; const char *source = "invalid"; + enum libinput_pointer_axis axis; + enum libinput_event_type type; + + type = libinput_event_get_type(ev); - switch (libinput_event_pointer_get_axis_source(p)) { - case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: + switch (type) { + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: source = "wheel"; break; - case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: source = "finger"; break; - case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: source = "continuous"; break; - case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT: - source = "tilt"; + default: + abort(); break; } - if (libinput_event_pointer_has_axis(p, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { - v = libinput_event_pointer_get_axis_value(p, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - dv = libinput_event_pointer_get_axis_value_discrete(p, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; + if (libinput_event_pointer_has_axis(p, axis)) { + v = libinput_event_pointer_get_scroll_value(p, axis); + if (type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL) + v120 = libinput_event_pointer_get_scroll_value_v120(p, axis); have_vert = "*"; } - if (libinput_event_pointer_has_axis(p, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { - h = libinput_event_pointer_get_axis_value(p, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - dh = libinput_event_pointer_get_axis_value_discrete(p, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; + if (libinput_event_pointer_has_axis(p, axis)) { + h = libinput_event_pointer_get_scroll_value(p, axis); + if (type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL) + h120 = libinput_event_pointer_get_scroll_value_v120(p, axis); have_horiz = "*"; } + print_event_time(libinput_event_pointer_get_time(p)); - printq("vert %.2f/%d%s horiz %.2f/%d%s (%s)\n", - v, dv, have_vert, h, dh, have_horiz, source); + printq("vert %.2f/%.1f%s horiz %.2f/%.1f%s (%s)\n", + v, v120, have_vert, + h, h120, have_horiz, source); } static void @@ -833,9 +845,12 @@ handle_and_print_events(struct libinput *li) tools_dispatch(li); while ((ev = libinput_get_event(li))) { - print_event_header(ev); + enum libinput_event_type type = libinput_event_get_type(ev); - switch (libinput_event_get_type(ev)) { + if (type != LIBINPUT_EVENT_POINTER_AXIS) + print_event_header(ev); + + switch (type) { case LIBINPUT_EVENT_NONE: abort(); case LIBINPUT_EVENT_DEVICE_ADDED: @@ -859,6 +874,11 @@ handle_and_print_events(struct libinput *li) print_pointer_button_event(ev); break; case LIBINPUT_EVENT_POINTER_AXIS: + /* ignore */ + break; + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: print_pointer_axis_event(ev); break; case LIBINPUT_EVENT_TOUCH_DOWN: diff --git a/tools/libinput-debug-gui.c b/tools/libinput-debug-gui.c index 861116e41f2872797d2163006e4739b7bfbcbfc8..0ef661457e1c703dab1bd85ddc3819ced18be9e6 100644 --- a/tools/libinput-debug-gui.c +++ b/tools/libinput-debug-gui.c @@ -85,10 +85,6 @@ struct point { double x, y; }; -struct device_user_data { - struct point scroll_accumulated; -}; - struct evdev_device { struct list node; struct libevdev *evdev; @@ -1287,7 +1283,6 @@ register_evdev_device(struct window *w, struct libinput_device *dev) const char *device_node; int fd; struct evdev_device *d; - struct device_user_data *data; ud = libinput_device_get_udev_device(dev); device_node = udev_device_get_devnode(ud); @@ -1310,9 +1305,6 @@ register_evdev_device(struct window *w, struct libinput_device *dev) d->evdev = evdev; d->libinput_device =libinput_device_ref(dev); - data = zalloc(sizeof *data); - libinput_device_set_user_data(dev, data); - c = g_io_channel_unix_new(fd); g_io_channel_set_encoding(c, NULL, NULL); d->source_id = g_io_add_watch(c, G_IO_IN, @@ -1463,44 +1455,33 @@ static void handle_event_axis(struct libinput_event *ev, struct window *w) { struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); - struct libinput_device *dev = libinput_event_get_device(ev); - struct device_user_data *data = libinput_device_get_user_data(dev); double value; - int discrete; + enum libinput_pointer_axis axis; + enum libinput_event_type type; - assert(data); + type = libinput_event_get_type(ev); - if (libinput_event_pointer_has_axis(p, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { - value = libinput_event_pointer_get_axis_value(p, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; + if (libinput_event_pointer_has_axis(p, axis)) { + value = libinput_event_pointer_get_scroll_value(p, axis); w->scroll.vy += value; w->scroll.vy = clip(w->scroll.vy, 0, w->height); - data->scroll_accumulated.y += value; - discrete = libinput_event_pointer_get_axis_value_discrete(p, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - if (discrete) { - w->scroll.vy_discrete += data->scroll_accumulated.y; + if (type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL) { + w->scroll.vy_discrete += value; w->scroll.vy_discrete = clip(w->scroll.vy_discrete, 0, w->height); - data->scroll_accumulated.y = 0; } } - if (libinput_event_pointer_has_axis(p, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { - value = libinput_event_pointer_get_axis_value(p, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; + if (libinput_event_pointer_has_axis(p, axis)) { + value = libinput_event_pointer_get_scroll_value(p, axis); w->scroll.hx += value; w->scroll.hx = clip(w->scroll.hx, 0, w->width); - data->scroll_accumulated.x += value; - discrete = libinput_event_pointer_get_axis_value_discrete(p, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - if (discrete) { - w->scroll.hx_discrete += data->scroll_accumulated.x; + if (type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL) { + w->scroll.hx_discrete += value; w->scroll.hx_discrete = clip(w->scroll.hx_discrete, 0, w->width); - data->scroll_accumulated.x = 0; } } } @@ -1798,6 +1779,11 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data) case LIBINPUT_EVENT_TOUCH_FRAME: break; case LIBINPUT_EVENT_POINTER_AXIS: + /* ignore */ + break; + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: handle_event_axis(ev, w); break; case LIBINPUT_EVENT_POINTER_BUTTON: