summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2014-11-06 13:39:51 +0100
committerPeter Hutterer <peter.hutterer@who-t.net>2014-11-11 12:11:24 +1000
commitebe34d1c18ef5fc975a7d63bcb8c2f3c6bcda519 (patch)
tree05b8a37bf3ca3c425ecba782139891cb226d782f /src
parent2ca425dc287171c001c3a58544d0e014346176a4 (diff)
downloadlibinput-ebe34d1c18ef5fc975a7d63bcb8c2f3c6bcda519.tar.gz
evdev: Hookup scroll mode configuration
Keep the default behavior of middle button scrolling on trackpoints, this allows turning off middle button scrolling on trackpoints, as well as turning on button scrolling on trackballs. BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=85535 Signed-off-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'src')
-rw-r--r--src/evdev.c165
-rw-r--r--src/evdev.h13
2 files changed, 153 insertions, 25 deletions
diff --git a/src/evdev.c b/src/evdev.c
index 14da3690..cc5b19cc 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -123,6 +123,10 @@ evdev_pointer_notify_button(struct evdev_device *device,
if (state == LIBINPUT_BUTTON_STATE_RELEASED &&
device->buttons.change_to_left_handed)
device->buttons.change_to_left_handed(device);
+
+ if (state == LIBINPUT_BUTTON_STATE_RELEASED &&
+ device->scroll.change_scroll_mode)
+ device->scroll.change_scroll_mode(device);
}
}
@@ -213,9 +217,9 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
device->rel.dy = 0;
/* Use unaccelerated deltas for pointing stick scroll */
- if (device->scroll.has_middle_button_scroll &&
- hw_is_key_down(device, BTN_MIDDLE)) {
- if (device->scroll.middle_button_scroll_active)
+ if (device->scroll.mode == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN &&
+ hw_is_key_down(device, device->scroll.button)) {
+ if (device->scroll.button_scroll_active)
evdev_post_scroll(device, time,
motion.dx, motion.dy);
break;
@@ -364,31 +368,33 @@ get_key_type(uint16_t code)
}
static void
-evdev_middle_button_scroll_timeout(uint64_t time, void *data)
+evdev_button_scroll_timeout(uint64_t time, void *data)
{
struct evdev_device *device = data;
- device->scroll.middle_button_scroll_active = true;
+ device->scroll.button_scroll_active = true;
}
static void
-evdev_middle_button_scroll_button(struct evdev_device *device,
- uint64_t time, int is_press)
+evdev_button_scroll_button(struct evdev_device *device,
+ uint64_t time, int is_press)
{
if (is_press) {
libinput_timer_set(&device->scroll.timer,
time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT);
} else {
libinput_timer_cancel(&device->scroll.timer);
- if (device->scroll.middle_button_scroll_active) {
+ if (device->scroll.button_scroll_active) {
evdev_stop_scroll(device, time);
- device->scroll.middle_button_scroll_active = false;
+ device->scroll.button_scroll_active = false;
} else {
/* If the button is released quickly enough emit the
* button press/release events. */
- evdev_pointer_notify_button(device, time, BTN_MIDDLE,
+ evdev_pointer_notify_button(device, time,
+ device->scroll.button,
LIBINPUT_BUTTON_STATE_PRESSED);
- evdev_pointer_notify_button(device, time, BTN_MIDDLE,
+ evdev_pointer_notify_button(device, time,
+ device->scroll.button,
LIBINPUT_BUTTON_STATE_RELEASED);
}
}
@@ -454,10 +460,9 @@ evdev_process_key(struct evdev_device *device,
LIBINPUT_KEY_STATE_RELEASED);
break;
case EVDEV_KEY_TYPE_BUTTON:
- if (device->scroll.has_middle_button_scroll &&
- e->code == BTN_MIDDLE) {
- evdev_middle_button_scroll_button(device, time,
- e->value);
+ if (device->scroll.mode == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN &&
+ e->code == device->scroll.button) {
+ evdev_button_scroll_button(device, time, e->value);
break;
}
evdev_pointer_notify_button(
@@ -829,6 +834,115 @@ evdev_init_left_handed(struct evdev_device *device,
return 0;
}
+static uint32_t
+evdev_scroll_get_modes(struct libinput_device *device)
+{
+ return LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
+}
+
+static void
+evdev_change_scroll_mode(struct evdev_device *device)
+{
+ if (device->scroll.want_mode == device->scroll.mode &&
+ device->scroll.want_button == device->scroll.button)
+ return;
+
+ if (evdev_any_button_down(device))
+ return;
+
+ device->scroll.mode = device->scroll.want_mode;
+ device->scroll.button = device->scroll.want_button;
+}
+
+static enum libinput_config_status
+evdev_scroll_set_mode(struct libinput_device *device,
+ enum libinput_config_scroll_mode mode)
+{
+ struct evdev_device *evdev = (struct evdev_device*)device;
+
+ evdev->scroll.want_mode = mode;
+ evdev->scroll.change_scroll_mode(evdev);
+
+ return LIBINPUT_CONFIG_STATUS_SUCCESS;
+}
+
+static enum libinput_config_scroll_mode
+evdev_scroll_get_mode(struct libinput_device *device)
+{
+ struct evdev_device *evdev = (struct evdev_device *)device;
+
+ /* return the wanted configuration, even if it hasn't taken
+ * effect yet! */
+ return evdev->scroll.want_mode;
+}
+
+static enum libinput_config_scroll_mode
+evdev_scroll_get_default_mode(struct libinput_device *device)
+{
+ struct evdev_device *evdev = (struct evdev_device *)device;
+
+ if (libevdev_has_property(evdev->evdev, INPUT_PROP_POINTING_STICK))
+ return LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
+ else
+ return LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
+}
+
+static enum libinput_config_status
+evdev_scroll_set_button(struct libinput_device *device,
+ uint32_t button)
+{
+ struct evdev_device *evdev = (struct evdev_device*)device;
+
+ evdev->scroll.want_button = button;
+ evdev->scroll.change_scroll_mode(evdev);
+
+ return LIBINPUT_CONFIG_STATUS_SUCCESS;
+}
+
+static uint32_t
+evdev_scroll_get_button(struct libinput_device *device)
+{
+ struct evdev_device *evdev = (struct evdev_device *)device;
+
+ /* return the wanted configuration, even if it hasn't taken
+ * effect yet! */
+ return evdev->scroll.want_button;
+}
+
+static uint32_t
+evdev_scroll_get_default_button(struct libinput_device *device)
+{
+ struct evdev_device *evdev = (struct evdev_device *)device;
+
+ if (libevdev_has_property(evdev->evdev, INPUT_PROP_POINTING_STICK))
+ return BTN_MIDDLE;
+ else
+ return 0;
+}
+
+static int
+evdev_init_button_scroll(struct evdev_device *device,
+ void (*change_scroll_mode)(struct evdev_device *))
+{
+ libinput_timer_init(&device->scroll.timer, device->base.seat->libinput,
+ evdev_button_scroll_timeout, device);
+ device->scroll.config.get_modes = evdev_scroll_get_modes;
+ device->scroll.config.set_mode = evdev_scroll_set_mode;
+ device->scroll.config.get_mode = evdev_scroll_get_mode;
+ device->scroll.config.get_default_mode = evdev_scroll_get_default_mode;
+ 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->base.config.scroll_mode = &device->scroll.config;
+ device->scroll.mode = evdev_scroll_get_default_mode((struct libinput_device *)device);
+ device->scroll.want_mode = device->scroll.mode;
+ device->scroll.button = evdev_scroll_get_default_button((struct libinput_device *)device);
+ device->scroll.want_button = device->scroll.button;
+ device->scroll.change_scroll_mode = change_scroll_mode;
+
+ return 0;
+}
+
static struct evdev_dispatch *
fallback_dispatch_create(struct libinput_device *device)
{
@@ -847,6 +961,13 @@ fallback_dispatch_create(struct libinput_device *device)
return NULL;
}
+ if (evdev_device->scroll.want_button &&
+ evdev_init_button_scroll(evdev_device,
+ evdev_change_scroll_mode) == -1) {
+ free(dispatch);
+ return NULL;
+ }
+
device->config.calibration = &dispatch->calibration;
dispatch->calibration.has_matrix = evdev_calibration_has_matrix;
@@ -1158,14 +1279,6 @@ evdev_configure_device(struct evdev_device *device)
}
}
- if (libevdev_has_property(evdev, INPUT_PROP_POINTING_STICK)) {
- libinput_timer_init(&device->scroll.timer,
- device->base.seat->libinput,
- evdev_middle_button_scroll_timeout,
- device);
- device->scroll.has_middle_button_scroll = true;
- }
-
if (libevdev_has_event_code(evdev, EV_REL, REL_X) ||
libevdev_has_event_code(evdev, EV_REL, REL_Y))
has_rel = 1;
@@ -1219,6 +1332,12 @@ evdev_configure_device(struct evdev_device *device)
/* want left-handed config option */
device->buttons.want_left_handed = true;
}
+
+ if (has_rel && has_button) {
+ /* want button scrolling config option */
+ device->scroll.want_button = 1;
+ }
+
if (has_keyboard) {
device->seat_caps |= EVDEV_DEVICE_KEYBOARD;
log_info(libinput,
diff --git a/src/evdev.h b/src/evdev.h
index 49a01494..a1613b49 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -100,8 +100,17 @@ struct evdev_device {
struct {
struct libinput_timer timer;
- bool has_middle_button_scroll;
- bool middle_button_scroll_active;
+ struct libinput_device_config_scroll_mode config;
+ /* Currently enabled mode, button */
+ enum libinput_config_scroll_mode mode;
+ uint32_t button;
+ /* set during device init, used at runtime to delay changes
+ * until all buttons are up */
+ enum libinput_config_scroll_mode want_mode;
+ uint32_t want_button;
+ /* Checks if buttons are down and commits the setting */
+ void (*change_scroll_mode)(struct evdev_device *device);
+ bool button_scroll_active;
double threshold;
uint32_t direction;
double buildup_vertical;