mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-10 21:00:21 +01:00
wheel: centralize wheel handling
Move the logic to handle wheels to its own file. Refactor, no functional changes. Signed-off-by: José Expósito <jose.exposito89@gmail.com>
This commit is contained in:
parent
5e44861e0e
commit
4e52f03580
4 changed files with 244 additions and 160 deletions
|
|
@ -368,6 +368,7 @@ src_libinput = src_libfilter + [
|
|||
'src/evdev-tablet-pad.c',
|
||||
'src/evdev-tablet-pad.h',
|
||||
'src/evdev-tablet-pad-leds.c',
|
||||
'src/evdev-wheel.c',
|
||||
'src/path-seat.c',
|
||||
'src/udev-seat.c',
|
||||
'src/udev-seat.h',
|
||||
|
|
|
|||
|
|
@ -68,18 +68,8 @@ fallback_notify_physical_button(struct fallback_dispatch *dispatch,
|
|||
int button,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
if (button == BTN_MIDDLE)
|
||||
dispatch->wheel.is_inhibited = (state == LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
/* Lenovo TrackPoint Keyboard II sends its own scroll events when its
|
||||
* trackpoint is moved while the middle button is pressed.
|
||||
* Do not inhibit the scroll events.
|
||||
* https://gitlab.freedesktop.org/libinput/libinput/-/issues/651
|
||||
*/
|
||||
if (evdev_device_has_model_quirk(device,
|
||||
QUIRK_MODEL_LENOVO_TRACKPOINT_KEYBOARD_2))
|
||||
dispatch->wheel.is_inhibited = false;
|
||||
|
||||
fallback_wheel_notify_physical_button(dispatch, device, time,
|
||||
button, state);
|
||||
evdev_pointer_notify_physical_button(device, time, button, state);
|
||||
}
|
||||
|
||||
|
|
@ -102,10 +92,10 @@ fallback_interface_get_switch_state(struct evdev_dispatch *evdev_dispatch,
|
|||
LIBINPUT_SWITCH_STATE_OFF;
|
||||
}
|
||||
|
||||
static inline void
|
||||
normalize_delta(struct evdev_device *device,
|
||||
const struct device_coords *delta,
|
||||
struct normalized_coords *normalized)
|
||||
void
|
||||
fallback_normalize_delta(struct evdev_device *device,
|
||||
const struct device_coords *delta,
|
||||
struct normalized_coords *normalized)
|
||||
{
|
||||
normalized->x = delta->x * DEFAULT_MOUSE_DPI / (double)device->dpi;
|
||||
normalized->y = delta->y * DEFAULT_MOUSE_DPI / (double)device->dpi;
|
||||
|
|
@ -195,7 +185,7 @@ fallback_flush_relative_motion(struct fallback_dispatch *dispatch,
|
|||
|
||||
fallback_rotate_relative(dispatch, device);
|
||||
|
||||
normalize_delta(device, &dispatch->rel, &unaccel);
|
||||
fallback_normalize_delta(device, &dispatch->rel, &unaccel);
|
||||
raw.x = dispatch->rel.x;
|
||||
raw.y = dispatch->rel.y;
|
||||
dispatch->rel.x = 0;
|
||||
|
|
@ -223,110 +213,6 @@ fallback_flush_relative_motion(struct fallback_dispatch *dispatch,
|
|||
pointer_notify_motion(base, time, &accel, &raw);
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_flush_wheels(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
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.emulate_hi_res_wheel &&
|
||||
!dispatch->wheel.hi_res_event_received &&
|
||||
(dispatch->wheel.lo_res.x != 0 || dispatch->wheel.lo_res.y != 0)) {
|
||||
evdev_log_bug_kernel(device,
|
||||
"device supports high-resolution scroll but only low-resolution events have been received.\n"
|
||||
"See %s/incorrectly-enabled-hires.html for details\n",
|
||||
HTTP_DOC_LINK);
|
||||
dispatch->wheel.emulate_hi_res_wheel = true;
|
||||
dispatch->wheel.hi_res.x = dispatch->wheel.lo_res.x * 120;
|
||||
dispatch->wheel.hi_res.y = dispatch->wheel.lo_res.y * 120;
|
||||
}
|
||||
|
||||
if (dispatch->wheel.is_inhibited) {
|
||||
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.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.hi_res.x = 0;
|
||||
dispatch->wheel.hi_res.y = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (dispatch->wheel.hi_res.y != 0) {
|
||||
int value = dispatch->wheel.hi_res.y;
|
||||
|
||||
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),
|
||||
&wheel_degrees,
|
||||
&discrete);
|
||||
dispatch->wheel.lo_res.y = 0;
|
||||
}
|
||||
|
||||
if (dispatch->wheel.hi_res.x != 0) {
|
||||
int value = dispatch->wheel.hi_res.x;
|
||||
|
||||
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),
|
||||
&wheel_degrees,
|
||||
&discrete);
|
||||
dispatch->wheel.lo_res.x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_flush_absolute_motion(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -895,29 +781,9 @@ fallback_process_relative(struct fallback_dispatch *dispatch,
|
|||
dispatch->rel.y += e->value;
|
||||
dispatch->pending_event |= EVDEV_RELATIVE_MOTION;
|
||||
break;
|
||||
case REL_WHEEL:
|
||||
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.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->wheel.hi_res_event_received = true;
|
||||
dispatch->pending_event |= EVDEV_WHEEL;
|
||||
break;
|
||||
case REL_HWHEEL_HI_RES:
|
||||
dispatch->wheel.hi_res.x += e->value;
|
||||
dispatch->wheel.hi_res_event_received = true;
|
||||
dispatch->pending_event |= EVDEV_WHEEL;
|
||||
break;
|
||||
}
|
||||
|
||||
fallback_wheel_process_relative(dispatch, device, e, time);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -1079,7 +945,7 @@ fallback_handle_state(struct fallback_dispatch *dispatch,
|
|||
if (need_touch_frame)
|
||||
touch_notify_frame(&device->base, time);
|
||||
|
||||
fallback_flush_wheels(dispatch, device, time);
|
||||
fallback_wheel_handle_state(dispatch, device, time);
|
||||
|
||||
/* Buttons and keys */
|
||||
if (dispatch->pending_event & EVDEV_KEY) {
|
||||
|
|
@ -1827,22 +1693,7 @@ fallback_dispatch_create(struct libinput_device *libinput_device)
|
|||
want_config);
|
||||
}
|
||||
|
||||
/* On kernel < 5.0 we need to emulate high-resolution
|
||||
wheel scroll events */
|
||||
if ((libevdev_has_event_code(device->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_wheel(dispatch, device);
|
||||
fallback_init_debounce(dispatch);
|
||||
fallback_init_arbitration(dispatch, device);
|
||||
|
||||
|
|
|
|||
|
|
@ -254,5 +254,30 @@ fallback_notify_physical_button(struct fallback_dispatch *dispatch,
|
|||
uint64_t time,
|
||||
int button,
|
||||
enum libinput_button_state state);
|
||||
void
|
||||
fallback_normalize_delta(struct evdev_device *device,
|
||||
const struct device_coords *delta,
|
||||
struct normalized_coords *normalized);
|
||||
|
||||
void
|
||||
fallback_init_wheel(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device);
|
||||
|
||||
void
|
||||
fallback_wheel_notify_physical_button(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time,
|
||||
int button,
|
||||
enum libinput_button_state state);
|
||||
|
||||
void
|
||||
fallback_wheel_process_relative(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e, uint64_t time);
|
||||
|
||||
void
|
||||
fallback_wheel_handle_state(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
207
src/evdev-wheel.c
Normal file
207
src/evdev-wheel.c
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
* Copyright © 2013 Jonas Ådahl
|
||||
* Copyright © 2013-2017 Red Hat, Inc.
|
||||
* Copyright © 2017 James Ye <jye836@gmail.com>
|
||||
* Copyright © 2021 José Expósito
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "evdev-fallback.h"
|
||||
#include "util-input-event.h"
|
||||
|
||||
void
|
||||
fallback_wheel_process_relative(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e, uint64_t time)
|
||||
{
|
||||
switch (e->code) {
|
||||
case REL_WHEEL:
|
||||
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.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->wheel.hi_res_event_received = true;
|
||||
dispatch->pending_event |= EVDEV_WHEEL;
|
||||
break;
|
||||
case REL_HWHEEL_HI_RES:
|
||||
dispatch->wheel.hi_res.x += e->value;
|
||||
dispatch->wheel.hi_res_event_received = true;
|
||||
dispatch->pending_event |= EVDEV_WHEEL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fallback_wheel_notify_physical_button(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time,
|
||||
int button,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
if (button == BTN_MIDDLE)
|
||||
dispatch->wheel.is_inhibited = (state == LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
/* Lenovo TrackPoint Keyboard II sends its own scroll events when its
|
||||
* trackpoint is moved while the middle button is pressed.
|
||||
* Do not inhibit the scroll events.
|
||||
* https://gitlab.freedesktop.org/libinput/libinput/-/issues/651
|
||||
*/
|
||||
if (evdev_device_has_model_quirk(device,
|
||||
QUIRK_MODEL_LENOVO_TRACKPOINT_KEYBOARD_2))
|
||||
dispatch->wheel.is_inhibited = false;
|
||||
}
|
||||
|
||||
void
|
||||
fallback_wheel_handle_state(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
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.emulate_hi_res_wheel &&
|
||||
!dispatch->wheel.hi_res_event_received &&
|
||||
(dispatch->wheel.lo_res.x != 0 || dispatch->wheel.lo_res.y != 0)) {
|
||||
evdev_log_bug_kernel(device,
|
||||
"device supports high-resolution scroll but only low-resolution events have been received.\n"
|
||||
"See %s/incorrectly-enabled-hires.html for details\n",
|
||||
HTTP_DOC_LINK);
|
||||
dispatch->wheel.emulate_hi_res_wheel = true;
|
||||
dispatch->wheel.hi_res.x = dispatch->wheel.lo_res.x * 120;
|
||||
dispatch->wheel.hi_res.y = dispatch->wheel.lo_res.y * 120;
|
||||
}
|
||||
|
||||
if (dispatch->wheel.is_inhibited) {
|
||||
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.hi_res.y *= -1;
|
||||
fallback_normalize_delta(device, &dispatch->wheel.hi_res, &unaccel);
|
||||
evdev_post_scroll(device,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
|
||||
&unaccel);
|
||||
dispatch->wheel.hi_res.x = 0;
|
||||
dispatch->wheel.hi_res.y = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (dispatch->wheel.hi_res.y != 0) {
|
||||
int value = dispatch->wheel.hi_res.y;
|
||||
|
||||
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),
|
||||
&wheel_degrees,
|
||||
&discrete);
|
||||
dispatch->wheel.lo_res.y = 0;
|
||||
}
|
||||
|
||||
if (dispatch->wheel.hi_res.x != 0) {
|
||||
int value = dispatch->wheel.hi_res.x;
|
||||
|
||||
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),
|
||||
&wheel_degrees,
|
||||
&discrete);
|
||||
dispatch->wheel.lo_res.x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fallback_init_wheel(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
/* On kernel < 5.0 we need to emulate high-resolution
|
||||
wheel scroll events */
|
||||
if ((libevdev_has_event_code(device->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;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue