static inline void evdev_process_relative(struct evdev_device *device, struct input_event *e, uint32_t time) { struct libinput_device *base = &device->base; switch (e->code) { case REL_X: if (device->pending_event != EVDEV_RELATIVE_MOTION) evdev_flush_pending_event(device, time); device->rel.dx += li_fixed_from_int(e->value); device->pending_event = EVDEV_RELATIVE_MOTION; break; case REL_Y: if (device->pending_event != EVDEV_RELATIVE_MOTION) evdev_flush_pending_event(device, time); device->rel.dy += li_fixed_from_int(e->value); device->pending_event = EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: evdev_flush_pending_event(device, time); switch (e->value) { case -1: /* Scroll down */ case 1: /* Scroll up */ pointer_notify_axis( base, time, LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL, -1 * e->value * DEFAULT_AXIS_STEP_DISTANCE); break; default: break; } break; case REL_HWHEEL: evdev_flush_pending_event(device, time); switch (e->value) { case -1: /* Scroll left */ case 1: /* Scroll right */ pointer_notify_axis( base, time, LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL, e->value * DEFAULT_AXIS_STEP_DISTANCE); break; default: break; } } }
static void test_relative_event(struct litest_device *dev, int dx, int dy) { struct libinput *li = dev->libinput; struct libinput_event *event; struct libinput_event_pointer *ptrev; 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); event = libinput_get_event(li); ck_assert(event != NULL); ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_POINTER_MOTION); ptrev = libinput_event_get_pointer_event(event); ck_assert(ptrev != NULL); ck_assert_int_eq(libinput_event_pointer_get_dx(ptrev), li_fixed_from_int(dx)); ck_assert_int_eq(libinput_event_pointer_get_dy(ptrev), li_fixed_from_int(dy)); libinput_event_destroy(event); }
END_TEST static void test_wheel_event(struct litest_device *dev, int which, int amount) { struct libinput *li = dev->libinput; struct libinput_event *event; struct libinput_event_pointer *ptrev; /* the current evdev implementation scales the scroll wheel events up by a factor 10 */ const int scroll_step = 10; int expected = amount * scroll_step; /* mouse scroll wheels are 'upside down' */ if (which == REL_WHEEL) amount *= -1; litest_event(dev, EV_REL, which, amount); litest_event(dev, EV_SYN, SYN_REPORT, 0); libinput_dispatch(li); event = libinput_get_event(li); ck_assert(event != NULL); ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_POINTER_AXIS); ptrev = libinput_event_get_pointer_event(event); ck_assert(ptrev != NULL); ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev), which == REL_WHEEL ? LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL : LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL); ck_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev), li_fixed_from_int(expected)); libinput_event_destroy(event); }
static void evdev_flush_pending_event(struct evdev_device *device, uint32_t time) { int32_t cx, cy; int slot; struct libinput_device *base = &device->base; slot = device->mt.slot; switch (device->pending_event) { case EVDEV_NONE: return; case EVDEV_RELATIVE_MOTION: pointer_notify_motion(base, time, device->rel.dx, device->rel.dy); device->rel.dx = 0; device->rel.dy = 0; goto handled; case EVDEV_ABSOLUTE_MT_DOWN: touch_notify_touch(base, time, slot, li_fixed_from_int(device->mt.slots[slot].x), li_fixed_from_int(device->mt.slots[slot].y), LIBINPUT_TOUCH_TYPE_DOWN); goto handled; case EVDEV_ABSOLUTE_MT_MOTION: touch_notify_touch(base, time, slot, li_fixed_from_int(device->mt.slots[slot].x), li_fixed_from_int(device->mt.slots[slot].y), LIBINPUT_TOUCH_TYPE_MOTION); goto handled; case EVDEV_ABSOLUTE_MT_UP: touch_notify_touch(base, time, slot, 0, 0, LIBINPUT_TOUCH_TYPE_UP); goto handled; case EVDEV_ABSOLUTE_TOUCH_DOWN: transform_absolute(device, &cx, &cy); touch_notify_touch(base, time, slot, li_fixed_from_int(cx), li_fixed_from_int(cy), LIBINPUT_TOUCH_TYPE_DOWN); goto handled; case EVDEV_ABSOLUTE_MOTION: transform_absolute(device, &cx, &cy); if (device->caps & EVDEV_TOUCH) { touch_notify_touch(base, time, slot, li_fixed_from_int(cx), li_fixed_from_int(cy), LIBINPUT_TOUCH_TYPE_DOWN); } else { pointer_notify_motion_absolute(base, time, li_fixed_from_int(cx), li_fixed_from_int(cy)); } goto handled; case EVDEV_ABSOLUTE_TOUCH_UP: touch_notify_touch(base, time, 0, 0, 0, LIBINPUT_TOUCH_TYPE_UP); goto handled; } assert(0 && "Unknown pending event type"); handled: device->pending_event = EVDEV_NONE; }