mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-03 10:00:27 +01:00
Add a scroll button lock feature
Scroll button locking is an accessibility feature. When enabled, the scroll button does not need to be held down, the first click holds it logically down, to be released on the second click of that same button. This is implemented as simple event filter, so we still get the same behavior from the emulated logical button, i.e. a physical double click results in a single logical click of that button provided no scrolling was triggered. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
12eb14846a
commit
63f9923013
14 changed files with 785 additions and 1 deletions
|
|
@ -117,6 +117,13 @@ the motion events. Cross-device scrolling is not supported but
|
|||
for one exception: libinput's :ref:`t440_support` enables the use of the middle
|
||||
button for button scrolling (even when the touchpad is disabled).
|
||||
|
||||
If the scroll button lock is enabled (see
|
||||
**libinput_device_config_scroll_set_button_lock()**), the button does not
|
||||
need to be held down. Pressing and releasing the button once enables the
|
||||
button lock, the button is now considered logically held down. Pressing and
|
||||
releasing the button a second time logically releases the button. While the
|
||||
button is logically held down, motion events are converted to scroll events.
|
||||
|
||||
.. _scroll_sources:
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1499,7 +1499,8 @@ fallback_change_scroll_method(struct evdev_device *device)
|
|||
struct fallback_dispatch *dispatch = fallback_dispatch(device->dispatch);
|
||||
|
||||
if (device->scroll.want_method == device->scroll.method &&
|
||||
device->scroll.want_button == device->scroll.button)
|
||||
device->scroll.want_button == device->scroll.button &&
|
||||
device->scroll.want_lock_enabled == device->scroll.lock_enabled)
|
||||
return;
|
||||
|
||||
if (fallback_any_button_down(dispatch, device))
|
||||
|
|
@ -1507,6 +1508,8 @@ fallback_change_scroll_method(struct evdev_device *device)
|
|||
|
||||
device->scroll.method = device->scroll.want_method;
|
||||
device->scroll.button = device->scroll.want_button;
|
||||
device->scroll.lock_enabled = device->scroll.want_lock_enabled;
|
||||
evdev_set_button_scroll_lock_enabled(device, device->scroll.lock_enabled);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
81
src/evdev.c
81
src/evdev.c
|
|
@ -198,6 +198,34 @@ static void
|
|||
evdev_button_scroll_button(struct evdev_device *device,
|
||||
uint64_t time, int is_press)
|
||||
{
|
||||
/* Where the button lock is enabled, we wrap the buttons into
|
||||
their own little state machine and filter out the events.
|
||||
*/
|
||||
switch (device->scroll.lock_state) {
|
||||
case BUTTONSCROLL_LOCK_DISABLED:
|
||||
break;
|
||||
case BUTTONSCROLL_LOCK_IDLE:
|
||||
assert(is_press);
|
||||
device->scroll.lock_state = BUTTONSCROLL_LOCK_FIRSTDOWN;
|
||||
evdev_log_debug(device, "scroll lock: first down\n");
|
||||
break; /* handle event */
|
||||
case BUTTONSCROLL_LOCK_FIRSTDOWN:
|
||||
assert(!is_press);
|
||||
device->scroll.lock_state = BUTTONSCROLL_LOCK_FIRSTUP;
|
||||
evdev_log_debug(device, "scroll lock: first up\n");
|
||||
return; /* filter release event */
|
||||
case BUTTONSCROLL_LOCK_FIRSTUP:
|
||||
assert(is_press);
|
||||
device->scroll.lock_state = BUTTONSCROLL_LOCK_SECONDDOWN;
|
||||
evdev_log_debug(device, "scroll lock: second down\n");
|
||||
return; /* filter press event */
|
||||
case BUTTONSCROLL_LOCK_SECONDDOWN:
|
||||
assert(!is_press);
|
||||
device->scroll.lock_state = BUTTONSCROLL_LOCK_IDLE;
|
||||
evdev_log_debug(device, "scroll lock: idle\n");
|
||||
break; /* handle event */
|
||||
}
|
||||
|
||||
if (is_press) {
|
||||
enum timer_flags flags = TIMER_FLAG_NONE;
|
||||
|
||||
|
|
@ -705,6 +733,56 @@ evdev_scroll_get_default_button(struct libinput_device *device)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static enum libinput_config_status
|
||||
evdev_scroll_set_button_lock(struct libinput_device *device,
|
||||
enum libinput_config_scroll_button_lock_state state)
|
||||
{
|
||||
struct evdev_device *evdev = evdev_device(device);
|
||||
|
||||
switch (state) {
|
||||
case LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED:
|
||||
evdev->scroll.want_lock_enabled = false;
|
||||
break;
|
||||
case LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED:
|
||||
evdev->scroll.want_lock_enabled = true;
|
||||
break;
|
||||
default:
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
}
|
||||
|
||||
evdev->scroll.change_scroll_method(evdev);
|
||||
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static enum libinput_config_scroll_button_lock_state
|
||||
evdev_scroll_get_button_lock(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = evdev_device(device);
|
||||
|
||||
if (evdev->scroll.lock_state == BUTTONSCROLL_LOCK_DISABLED)
|
||||
return LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED;
|
||||
else
|
||||
return LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED;
|
||||
}
|
||||
|
||||
static enum libinput_config_scroll_button_lock_state
|
||||
evdev_scroll_get_default_button_lock(struct libinput_device *device)
|
||||
{
|
||||
return LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
evdev_set_button_scroll_lock_enabled(struct evdev_device *device,
|
||||
bool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
device->scroll.lock_state = BUTTONSCROLL_LOCK_IDLE;
|
||||
else
|
||||
device->scroll.lock_state = BUTTONSCROLL_LOCK_DISABLED;
|
||||
}
|
||||
|
||||
void
|
||||
evdev_init_button_scroll(struct evdev_device *device,
|
||||
void (*change_scroll_method)(struct evdev_device *))
|
||||
|
|
@ -726,6 +804,9 @@ evdev_init_button_scroll(struct evdev_device *device,
|
|||
device->scroll.config.set_button = evdev_scroll_set_button;
|
||||
device->scroll.config.get_button = evdev_scroll_get_button;
|
||||
device->scroll.config.get_default_button = evdev_scroll_get_default_button;
|
||||
device->scroll.config.set_button_lock = evdev_scroll_set_button_lock;
|
||||
device->scroll.config.get_button_lock = evdev_scroll_get_button_lock;
|
||||
device->scroll.config.get_default_button_lock = evdev_scroll_get_default_button_lock;
|
||||
device->base.config.scroll_method = &device->scroll.config;
|
||||
device->scroll.method = evdev_scroll_get_default_method((struct libinput_device *)device);
|
||||
device->scroll.want_method = device->scroll.method;
|
||||
|
|
|
|||
16
src/evdev.h
16
src/evdev.h
|
|
@ -125,6 +125,14 @@ enum evdev_button_scroll_state {
|
|||
BUTTONSCROLL_SCROLLING, /* have sent scroll events */
|
||||
};
|
||||
|
||||
enum evdev_button_scroll_lock_state {
|
||||
BUTTONSCROLL_LOCK_DISABLED,
|
||||
BUTTONSCROLL_LOCK_IDLE,
|
||||
BUTTONSCROLL_LOCK_FIRSTDOWN,
|
||||
BUTTONSCROLL_LOCK_FIRSTUP,
|
||||
BUTTONSCROLL_LOCK_SECONDDOWN,
|
||||
};
|
||||
|
||||
enum evdev_debounce_state {
|
||||
/**
|
||||
* Initial state, no debounce but monitoring events
|
||||
|
|
@ -224,6 +232,10 @@ struct evdev_device {
|
|||
struct wheel_angle wheel_click_angle;
|
||||
|
||||
struct wheel_tilt_flags is_tilt;
|
||||
|
||||
enum evdev_button_scroll_lock_state lock_state;
|
||||
bool want_lock_enabled;
|
||||
bool lock_enabled;
|
||||
} scroll;
|
||||
|
||||
struct {
|
||||
|
|
@ -557,6 +569,10 @@ void
|
|||
evdev_init_button_scroll(struct evdev_device *device,
|
||||
void (*change_scroll_method)(struct evdev_device *));
|
||||
|
||||
void
|
||||
evdev_set_button_scroll_lock_enabled(struct evdev_device *device,
|
||||
bool enabled);
|
||||
|
||||
int
|
||||
evdev_update_key_down_count(struct evdev_device *device,
|
||||
int code,
|
||||
|
|
|
|||
|
|
@ -272,6 +272,10 @@ struct libinput_device_config_scroll_method {
|
|||
uint32_t button);
|
||||
uint32_t (*get_button)(struct libinput_device *device);
|
||||
uint32_t (*get_default_button)(struct libinput_device *device);
|
||||
enum libinput_config_status (*set_button_lock)(struct libinput_device *device,
|
||||
enum libinput_config_scroll_button_lock_state);
|
||||
enum libinput_config_scroll_button_lock_state (*get_button_lock)(struct libinput_device *device);
|
||||
enum libinput_config_scroll_button_lock_state (*get_default_button_lock)(struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config_click_method {
|
||||
|
|
|
|||
|
|
@ -4149,6 +4149,45 @@ libinput_device_config_scroll_get_default_button(struct libinput_device *device)
|
|||
return device->config.scroll_method->get_default_button(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_scroll_set_button_lock(struct libinput_device *device,
|
||||
enum libinput_config_scroll_button_lock_state state)
|
||||
{
|
||||
if ((libinput_device_config_scroll_get_methods(device) &
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) == 0)
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
switch (state) {
|
||||
case LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED:
|
||||
case LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED:
|
||||
break;
|
||||
default:
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
}
|
||||
|
||||
return device->config.scroll_method->set_button_lock(device, state);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_scroll_button_lock_state
|
||||
libinput_device_config_scroll_get_button_lock(struct libinput_device *device)
|
||||
{
|
||||
if ((libinput_device_config_scroll_get_methods(device) &
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) == 0)
|
||||
return LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED;
|
||||
|
||||
return device->config.scroll_method->get_button_lock(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_scroll_button_lock_state
|
||||
libinput_device_config_scroll_get_default_button_lock(struct libinput_device *device)
|
||||
{
|
||||
if ((libinput_device_config_scroll_get_methods(device) &
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) == 0)
|
||||
return LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED;
|
||||
|
||||
return device->config.scroll_method->get_default_button_lock(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_dwt_is_available(struct libinput_device *device)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5594,6 +5594,81 @@ libinput_device_config_scroll_get_button(struct libinput_device *device);
|
|||
uint32_t
|
||||
libinput_device_config_scroll_get_default_button(struct libinput_device *device);
|
||||
|
||||
enum libinput_config_scroll_button_lock_state {
|
||||
LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED,
|
||||
LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED,
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Set the scroll button lock. If the state is
|
||||
* @ref LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED, the button must
|
||||
* physically be held down for button scrolling to work.
|
||||
* If the state is
|
||||
* @ref LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED, the button is considered
|
||||
* logically down after the first press and release sequence, and logically
|
||||
* up after the second press and release sequence.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @param state The state to set the scroll button lock to
|
||||
*
|
||||
* @return A config status code. Disabling the scroll button lock on
|
||||
* device that does not support button scrolling always succeeds.
|
||||
*
|
||||
* @see libinput_device_config_scroll_set_button
|
||||
* @see libinput_device_config_scroll_get_button
|
||||
* @see libinput_device_config_scroll_get_default_button
|
||||
*/
|
||||
enum libinput_config_status
|
||||
libinput_device_config_scroll_set_button_lock(struct libinput_device *device,
|
||||
enum libinput_config_scroll_button_lock_state state);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Get the current scroll button lock state.
|
||||
*
|
||||
* If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not
|
||||
* supported, or no button is set, this function returns @ref
|
||||
* LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED.
|
||||
*
|
||||
* @note The return value is independent of the currently selected
|
||||
* scroll-method. For the scroll button lock to activate, a device must have
|
||||
* the @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method enabled, and a
|
||||
* non-zero button set as scroll button.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @return The scroll button lock state
|
||||
*
|
||||
* @see libinput_device_config_scroll_set_button
|
||||
* @see libinput_device_config_scroll_set_button_lock
|
||||
* @see libinput_device_config_scroll_get_button_lock
|
||||
* @see libinput_device_config_scroll_get_default_button_lock
|
||||
*/
|
||||
enum libinput_config_scroll_button_lock_state
|
||||
libinput_device_config_scroll_get_button_lock(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Get the default scroll button lock state.
|
||||
*
|
||||
* If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not
|
||||
* supported, or no button is set, this function returns @ref
|
||||
* LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @return The default scroll button lock state
|
||||
*
|
||||
* @see libinput_device_config_scroll_set_button
|
||||
* @see libinput_device_config_scroll_set_button_lock
|
||||
* @see libinput_device_config_scroll_get_button_lock
|
||||
* @see libinput_device_config_scroll_get_default_button_lock
|
||||
*/
|
||||
enum libinput_config_scroll_button_lock_state
|
||||
libinput_device_config_scroll_get_default_button_lock(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
|
|
|
|||
|
|
@ -305,3 +305,9 @@ LIBINPUT_1.14 {
|
|||
libinput_event_tablet_tool_size_major_has_changed;
|
||||
libinput_event_tablet_tool_size_minor_has_changed;
|
||||
} LIBINPUT_1.11;
|
||||
|
||||
LIBINPUT_1.15 {
|
||||
libinput_device_config_scroll_set_button_lock;
|
||||
libinput_device_config_scroll_get_button_lock;
|
||||
libinput_device_config_scroll_get_default_button_lock;
|
||||
} LIBINPUT_1.14;
|
||||
|
|
|
|||
|
|
@ -2495,6 +2495,27 @@ litest_button_scroll(struct litest_device *dev,
|
|||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
void
|
||||
litest_button_scroll_locked(struct litest_device *dev,
|
||||
unsigned int button,
|
||||
double dx, double dy)
|
||||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_button_click_debounced(dev, li, button, 1);
|
||||
litest_button_click_debounced(dev, li, button, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_buttonscroll();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_event(dev, EV_REL, REL_X, dx);
|
||||
litest_event(dev, EV_REL, REL_Y, dy);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
void
|
||||
litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -663,6 +663,10 @@ void
|
|||
litest_button_scroll(struct litest_device *d,
|
||||
unsigned int button,
|
||||
double dx, double dy);
|
||||
void
|
||||
litest_button_scroll_locked(struct litest_device *d,
|
||||
unsigned int button,
|
||||
double dx, double dy);
|
||||
|
||||
void
|
||||
litest_keyboard_key(struct litest_device *d,
|
||||
|
|
|
|||
|
|
@ -1227,6 +1227,503 @@ START_TEST(pointer_scroll_button_device_remove_while_down)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
litest_enable_scroll_button_lock(struct litest_device *dev,
|
||||
unsigned int button)
|
||||
{
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_scroll_set_method(device,
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
status = libinput_device_config_scroll_set_button(device, button);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
status = libinput_device_config_scroll_set_button_lock(device,
|
||||
LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
START_TEST(pointer_scroll_button_lock)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_enable_scroll_button_lock(dev, BTN_LEFT);
|
||||
litest_disable_middleemu(dev);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_timeout_buttonscroll();
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
litest_event(dev, EV_REL, REL_Y, 6);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 6);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* back to motion */
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
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_MOTION);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_button_lock_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
enum libinput_config_scroll_button_lock_state state;
|
||||
|
||||
state = libinput_device_config_scroll_get_button_lock(dev->libinput_device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED);
|
||||
state = libinput_device_config_scroll_get_default_button_lock(dev->libinput_device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_button_lock_config)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
enum libinput_config_status status;
|
||||
enum libinput_config_scroll_button_lock_state state;
|
||||
|
||||
state = libinput_device_config_scroll_get_button_lock(dev->libinput_device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED);
|
||||
state = libinput_device_config_scroll_get_default_button_lock(dev->libinput_device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED);
|
||||
|
||||
status = libinput_device_config_scroll_set_button_lock(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
state = libinput_device_config_scroll_get_button_lock(dev->libinput_device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED);
|
||||
|
||||
|
||||
status = libinput_device_config_scroll_set_button_lock(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
state = libinput_device_config_scroll_get_button_lock(dev->libinput_device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED);
|
||||
|
||||
status = libinput_device_config_scroll_set_button_lock(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED + 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_button_lock_enable_while_down)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
|
||||
/* Enable lock while button is down */
|
||||
litest_enable_scroll_button_lock(dev, BTN_LEFT);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
litest_event(dev, EV_REL, REL_Y, 6);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
/* no scrolling yet */
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
/* but on the next button press we scroll lock */
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_buttonscroll();
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
litest_event(dev, EV_REL, REL_Y, 6);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
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_empty_queue(li);
|
||||
|
||||
/* back to motion */
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
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_MOTION);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_button_lock_enable_while_down_just_lock)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* switch method first, but enable lock when we already have a
|
||||
* button down */
|
||||
libinput_device_config_scroll_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN);
|
||||
libinput_device_config_scroll_set_button(dev->libinput_device,
|
||||
BTN_LEFT);
|
||||
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
libinput_device_config_scroll_set_button_lock(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED);
|
||||
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
litest_event(dev, EV_REL, REL_Y, 6);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
/* no scrolling yet */
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
/* but on the next button press we scroll lock */
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_buttonscroll();
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
litest_event(dev, EV_REL, REL_Y, 6);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
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_empty_queue(li);
|
||||
|
||||
/* back to motion */
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
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_MOTION);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_button_lock_otherbutton)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_enable_scroll_button_lock(dev, BTN_LEFT);
|
||||
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_timeout_buttonscroll();
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* other button passes on normally */
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
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);
|
||||
|
||||
/* other button passes on normally */
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* other button passes on normally */
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_button_lock_enable_while_otherbutton_down)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_timeout_middlebutton();
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Enable lock while button is down */
|
||||
litest_enable_scroll_button_lock(dev, BTN_LEFT);
|
||||
|
||||
/* We only enable once we go to a neutral state so this still counts
|
||||
* as normal button event */
|
||||
for (int twice = 0; twice < 2; twice++) {
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
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_MOTION);
|
||||
}
|
||||
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* now we should trigger it */
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_timeout_buttonscroll();
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
litest_event(dev, EV_REL, REL_Y, 6);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
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_empty_queue(li);
|
||||
|
||||
/* back to motion */
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
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_MOTION);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
enum mb_buttonorder {
|
||||
LLRR, /* left down, left up, r down, r up */
|
||||
LRLR, /* left down, right down, left up, right up */
|
||||
LRRL,
|
||||
RRLL,
|
||||
RLRL,
|
||||
RLLR,
|
||||
_MB_BUTTONORDER_COUNT
|
||||
};
|
||||
|
||||
START_TEST(pointer_scroll_button_lock_middlebutton)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
enum mb_buttonorder buttonorder = _i; /* ranged test */
|
||||
|
||||
if (!libinput_device_config_middle_emulation_is_available(dev->libinput_device))
|
||||
return;
|
||||
|
||||
litest_enable_middleemu(dev);
|
||||
|
||||
litest_enable_scroll_button_lock(dev, BTN_LEFT);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* We expect scroll lock to work only where left and right are never
|
||||
* held down simultaneously. Everywhere else we expect middle button
|
||||
* instead.
|
||||
*/
|
||||
switch (buttonorder) {
|
||||
case LLRR:
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
break;
|
||||
case LRLR:
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
break;
|
||||
case LRRL:
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
break;
|
||||
case RRLL:
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
break;
|
||||
case RLRL:
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
break;
|
||||
case RLLR:
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_middlebutton();
|
||||
litest_timeout_buttonscroll();
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* motion events are the same for all of them */
|
||||
for (int i = 0; i < 10; i++) {
|
||||
litest_event(dev, EV_REL, REL_X, 1);
|
||||
litest_event(dev, EV_REL, REL_Y, 6);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
switch (buttonorder) {
|
||||
case LLRR:
|
||||
case RRLL:
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
switch (buttonorder) {
|
||||
case LLRR:
|
||||
case RRLL:
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
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_empty_queue(li);
|
||||
break;
|
||||
case LRLR:
|
||||
case LRRL:
|
||||
case RLRL:
|
||||
case RLLR:
|
||||
litest_assert_button_event(li, BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_button_lock_doubleclick_nomove)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
litest_enable_scroll_button_lock(dev, BTN_LEFT);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* double click without move in between counts as single click */
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* But a non-scroll button it should work normally */
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, false);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_nowheel_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -2691,6 +3188,7 @@ TEST_COLLECTION(pointer)
|
|||
struct range axis_range = {ABS_X, ABS_Y + 1};
|
||||
struct range compass = {0, 7}; /* cardinal directions */
|
||||
struct range buttons = {BTN_LEFT, BTN_TASK + 1};
|
||||
struct range buttonorder = {0, _MB_BUTTONORDER_COUNT};
|
||||
|
||||
litest_add("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, LITEST_POINTINGSTICK);
|
||||
litest_add_for_device("pointer:motion", pointer_motion_relative_zero, LITEST_MOUSE);
|
||||
|
|
@ -2709,6 +3207,17 @@ TEST_COLLECTION(pointer)
|
|||
litest_add("pointer:scroll", pointer_scroll_button_no_event_before_timeout, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_button_middle_emulation, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_button_device_remove_while_down, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON);
|
||||
|
||||
litest_add("pointer:scroll", pointer_scroll_button_lock, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_button_lock_defaults, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_button_lock_config, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_button_lock_enable_while_down, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_button_lock_enable_while_down_just_lock, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_button_lock_otherbutton, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_button_lock_enable_while_otherbutton_down, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add_ranged("pointer:scroll", pointer_scroll_button_lock_middlebutton, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY, &buttonorder);
|
||||
litest_add("pointer:scroll", pointer_scroll_button_lock_doubleclick_nomove, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
|
||||
litest_add("pointer:scroll", pointer_scroll_nowheel_defaults, LITEST_RELATIVE|LITEST_BUTTON, LITEST_WHEEL);
|
||||
litest_add_for_device("pointer:scroll", pointer_scroll_defaults_logitech_marble , LITEST_LOGITECH_TRACKBALL);
|
||||
litest_add("pointer:scroll", pointer_scroll_natural_defaults, LITEST_WHEEL, LITEST_TABLET);
|
||||
|
|
|
|||
|
|
@ -79,6 +79,9 @@ Enable or disable middle button emulation
|
|||
.B \-\-enable\-dwt|\-\-disable\-dwt
|
||||
Enable or disable disable-while-typing
|
||||
.TP 8
|
||||
.B \-\-enable\scroll-button-lock|\-\-disable\-scroll-button-lock
|
||||
Enable or disable the scroll button lock
|
||||
.TP 8
|
||||
.B \-\-set\-click\-method=[none|clickfinger|buttonareas]
|
||||
Set the desired click method
|
||||
.TP 8
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ tools_init_options(struct tools_options *options)
|
|||
options->click_method = -1;
|
||||
options->scroll_method = -1;
|
||||
options->scroll_button = -1;
|
||||
options->scroll_button_lock = -1;
|
||||
options->speed = 0.0;
|
||||
options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
|
||||
}
|
||||
|
|
@ -198,6 +199,12 @@ tools_parse_option(int option,
|
|||
return 1;
|
||||
}
|
||||
break;
|
||||
case OPT_SCROLL_BUTTON_LOCK_ENABLE:
|
||||
options->scroll_button_lock = true;
|
||||
break;
|
||||
case OPT_SCROLL_BUTTON_LOCK_DISABLE:
|
||||
options->scroll_button_lock = false;
|
||||
break;
|
||||
case OPT_SPEED:
|
||||
if (!optarg)
|
||||
return 1;
|
||||
|
|
@ -407,6 +414,10 @@ tools_device_apply_config(struct libinput_device *device,
|
|||
if (options->scroll_button != -1)
|
||||
libinput_device_config_scroll_set_button(device,
|
||||
options->scroll_button);
|
||||
if (options->scroll_button_lock != -1)
|
||||
libinput_device_config_scroll_set_button_lock(device,
|
||||
options->scroll_button_lock);
|
||||
|
||||
|
||||
if (libinput_device_config_accel_is_available(device)) {
|
||||
libinput_device_config_accel_set_speed(device,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ enum configuration_options {
|
|||
OPT_CLICK_METHOD,
|
||||
OPT_SCROLL_METHOD,
|
||||
OPT_SCROLL_BUTTON,
|
||||
OPT_SCROLL_BUTTON_LOCK_ENABLE,
|
||||
OPT_SCROLL_BUTTON_LOCK_DISABLE,
|
||||
OPT_SPEED,
|
||||
OPT_PROFILE,
|
||||
OPT_DISABLE_SENDEVENTS,
|
||||
|
|
@ -73,6 +75,8 @@ enum configuration_options {
|
|||
{ "disable-middlebutton", no_argument, 0, OPT_MIDDLEBUTTON_DISABLE }, \
|
||||
{ "enable-dwt", no_argument, 0, OPT_DWT_ENABLE }, \
|
||||
{ "disable-dwt", no_argument, 0, OPT_DWT_DISABLE }, \
|
||||
{ "enable-scroll-button-lock", no_argument, 0, OPT_SCROLL_BUTTON_LOCK_ENABLE }, \
|
||||
{ "disable-scroll-button-lock",no_argument, 0, OPT_SCROLL_BUTTON_LOCK_DISABLE }, \
|
||||
{ "set-click-method", required_argument, 0, OPT_CLICK_METHOD }, \
|
||||
{ "set-scroll-method", required_argument, 0, OPT_SCROLL_METHOD }, \
|
||||
{ "set-scroll-button", required_argument, 0, OPT_SCROLL_BUTTON }, \
|
||||
|
|
@ -100,6 +104,7 @@ struct tools_options {
|
|||
enum libinput_config_scroll_method scroll_method;
|
||||
enum libinput_config_tap_button_map tap_map;
|
||||
int scroll_button;
|
||||
int scroll_button_lock;
|
||||
double speed;
|
||||
int dwt;
|
||||
enum libinput_config_accel_profile profile;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue