#include "libinput-private.h"
#define DEFAULT_AXIS_STEP_DISTANCE 10
+#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT 200
enum evdev_key_type {
EVDEV_KEY_TYPE_NONE,
device->rel.dx = 0;
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)
+ evdev_post_scroll(device, time,
+ motion.dx, motion.dy);
+ break;
+ }
+
/* Apply pointer acceleration. */
filter_dispatch(device->pointer.filter, &motion, device, time);
}
static void
+evdev_middle_button_scroll_timeout(uint64_t time, void *data)
+{
+ struct evdev_device *device = data;
+
+ device->scroll.middle_button_scroll_active = true;
+}
+
+static void
+evdev_middle_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) {
+ evdev_stop_scroll(device, time);
+ device->scroll.middle_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,
+ LIBINPUT_BUTTON_STATE_PRESSED);
+ evdev_pointer_notify_button(device, time, BTN_MIDDLE,
+ LIBINPUT_BUTTON_STATE_RELEASED);
+ }
+ }
+}
+
+static void
evdev_process_touch_button(struct evdev_device *device,
uint64_t time, int value)
{
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);
+ break;
+ }
evdev_pointer_notify_button(
device,
time,
}
static void
+evdev_tag_trackpoint(struct evdev_device *device,
+ struct udev_device *udev_device)
+{
+ if (libevdev_has_property(device->evdev, INPUT_PROP_POINTING_STICK))
+ device->tags |= EVDEV_TAG_TRACKPOINT;
+}
+
+static void
fallback_process(struct evdev_dispatch *dispatch,
struct evdev_device *device,
struct input_event *event,
struct udev_device *udev_device)
{
evdev_tag_external_mouse(device, udev_device);
+ evdev_tag_trackpoint(device, udev_device);
}
static int
fallback_destroy,
NULL, /* device_added */
NULL, /* device_removed */
+ NULL, /* device_suspended */
+ NULL, /* device_resumed */
fallback_tag_device,
};
{
device->pointer.filter =
create_pointer_accelator_filter(
- pointer_accel_profile_smooth_simple);
+ pointer_accel_profile_linear);
if (!device->pointer.filter)
return -1;
device->mt.slot = active_slot;
}
}
+
+ 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;
if (dev == &device->base)
continue;
+ /* Notify existing device d about addition of device device */
if (d->dispatch->interface->device_added)
d->dispatch->interface->device_added(d, device);
+ /* Notify new device device about existing device d */
if (device->dispatch->interface->device_added)
device->dispatch->interface->device_added(device, d);
+
+ /* Notify new device device if existing device d is suspended */
+ if (d->suspended && device->dispatch->interface->device_suspended)
+ device->dispatch->interface->device_suspended(device, d);
}
notify_added_device(&device->base);
}
}
+void
+evdev_notify_suspended_device(struct evdev_device *device)
+{
+ struct libinput_device *it;
+
+ if (device->suspended)
+ return;
+
+ list_for_each(it, &device->base.seat->devices_list, link) {
+ struct evdev_device *d = (struct evdev_device*)it;
+ if (it == &device->base)
+ continue;
+
+ if (d->dispatch->interface->device_suspended)
+ d->dispatch->interface->device_suspended(d, device);
+ }
+
+ device->suspended = 1;
+}
+
+void
+evdev_notify_resumed_device(struct evdev_device *device)
+{
+ struct libinput_device *it;
+
+ if (!device->suspended)
+ return;
+
+ list_for_each(it, &device->base.seat->devices_list, link) {
+ struct evdev_device *d = (struct evdev_device*)it;
+ if (it == &device->base)
+ continue;
+
+ if (d->dispatch->interface->device_resumed)
+ d->dispatch->interface->device_resumed(d, device);
+ }
+
+ device->suspended = 0;
+}
+
int
evdev_device_suspend(struct evdev_device *device)
{
+ evdev_notify_suspended_device(device);
+
if (device->source) {
libinput_remove_source(device->base.seat->libinput,
device->source);
memset(device->hw_key_mask, 0, sizeof(device->hw_key_mask));
+ evdev_notify_resumed_device(device);
+
return 0;
}