From: Peter Hutterer Date: Wed, 24 Dec 2014 01:10:04 +0000 (+1000) Subject: Change axis events to carry all directions X-Git-Tag: 0.8.0~5^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1baf109b40e5d610cb46d313d7c412419af8c9e0;p=platform%2Fupstream%2Flibinput.git Change axis events to carry all directions Sending separate axis events instead of one unified events is limiting, especially when simultaneously scrolling in both directions and the caller tries to implement kinetic scrolling. Take a page from the tablet-support branch and instead implement the axis event as a generic event that can contain multiple axes simultaneously. Right now we only have two (scroll) axes and we could easily just check both for non-zero values. If we want to allow further axes in the future, we need a check whether an axis is set in an event, that's what libinput_event_pointer_has_axis to scroll events() is for. We also need the mask to notify of a scroll stop event, which could otherwise be confused as a vertical-only or horizontal-only event. This is an API and ABI break. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index a4dc0939..6268986a 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -325,9 +325,9 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) if (t->scroll.direction != -1) { /* Send stop scroll event */ pointer_notify_axis(device, time, - t->scroll.direction, + AS_MASK(t->scroll.direction), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - 0.0); + 0.0, 0.0); t->scroll.direction = -1; } continue; @@ -349,9 +349,10 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) if (fabs(*delta) < t->scroll.threshold) continue; - pointer_notify_axis(device, time, axis, + pointer_notify_axis(device, time, + AS_MASK(axis), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - *delta); + dx, dy); t->scroll.direction = axis; tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_POSTED); @@ -369,9 +370,9 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time) tp_for_each_touch(tp, t) { if (t->scroll.direction != -1) { pointer_notify_axis(device, time, - t->scroll.direction, + AS_MASK(t->scroll.direction), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - 0.0); + 0.0, 0.0); t->scroll.direction = -1; } } diff --git a/src/evdev.c b/src/evdev.c index d80594df..076db29f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -539,18 +539,20 @@ evdev_process_absolute_motion(struct evdev_device *device, static void evdev_notify_axis(struct evdev_device *device, uint64_t time, - enum libinput_pointer_axis axis, + uint32_t axes, enum libinput_pointer_axis_source source, - double value) + double x, double y) { - if (device->scroll.natural_scrolling_enabled) - value *= -1; + if (device->scroll.natural_scrolling_enabled) { + x *= -1; + y *= -1; + } pointer_notify_axis(&device->base, time, - axis, + axes, source, - value); + x, y); } static inline void @@ -575,8 +577,9 @@ evdev_process_relative(struct evdev_device *device, evdev_notify_axis( device, time, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, + 0, -1 * e->value * device->scroll.wheel_click_angle); break; case REL_HWHEEL: @@ -584,9 +587,10 @@ evdev_process_relative(struct evdev_device *device, evdev_notify_axis( device, time, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL), LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, - e->value * device->scroll.wheel_click_angle); + e->value * device->scroll.wheel_click_angle, + 0); break; } } @@ -1796,7 +1800,7 @@ evdev_is_scrolling(const struct evdev_device *device, assert(axis == LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL || axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - return (device->scroll.direction & (1 << axis)) != 0; + return (device->scroll.direction & AS_MASK(axis)) != 0; } static inline void @@ -1806,7 +1810,7 @@ evdev_start_scrolling(struct evdev_device *device, assert(axis == LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL || axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - device->scroll.direction |= (1 << axis); + device->scroll.direction |= AS_MASK(axis); } void @@ -1857,25 +1861,20 @@ evdev_post_scroll(struct evdev_device *device, /* We use the trigger to enable, but the delta from this event for * the actual scroll movement. Otherwise we get a jump once * scrolling engages */ - if (dy != 0.0 && - evdev_is_scrolling(device, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { - evdev_notify_axis(device, - time, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, - source, - dy); - } + if (!evdev_is_scrolling(device, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) + dy = 0.0; + if (!evdev_is_scrolling(device, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) + dx = 0.0; - if (dx != 0.0 && - evdev_is_scrolling(device, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { + if (dx != 0.0 || dy != 0.0) evdev_notify_axis(device, time, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + device->scroll.direction, source, - dx); - } + dx, + dy); } void @@ -1884,18 +1883,12 @@ evdev_stop_scroll(struct evdev_device *device, enum libinput_pointer_axis_source source) { /* terminate scrolling with a zero scroll event */ - if (device->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) - pointer_notify_axis(&device->base, - time, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, - source, - 0); - if (device->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) + if (device->scroll.direction != 0) pointer_notify_axis(&device->base, time, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + device->scroll.direction, source, - 0); + 0.0, 0.0); device->scroll.buildup_horizontal = 0; device->scroll.buildup_vertical = 0; diff --git a/src/libinput-private.h b/src/libinput-private.h index 84a0d440..0cb9b259 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -278,9 +278,9 @@ pointer_notify_button(struct libinput_device *device, void pointer_notify_axis(struct libinput_device *device, uint64_t time, - enum libinput_pointer_axis axis, + uint32_t axes, enum libinput_pointer_axis_source source, - double value); + double x, double y); void touch_notify_touch_down(struct libinput_device *device, diff --git a/src/libinput-util.h b/src/libinput-util.h index dc70bcd2..f76439f1 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -79,6 +79,7 @@ int list_empty(const struct list *list); #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) #define ARRAY_FOR_EACH(_arr, _elem) \ for (size_t _i = 0; _i < ARRAY_LENGTH(_arr) && (_elem = &_arr[_i]); _i++) +#define AS_MASK(v) (1 << (v)) #define min(a, b) (((a) < (b)) ? (a) : (b)) #define max(a, b) (((a) > (b)) ? (a) : (b)) diff --git a/src/libinput.c b/src/libinput.c index 426c3069..2442b065 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -64,9 +64,8 @@ struct libinput_event_pointer { uint32_t button; uint32_t seat_button_count; enum libinput_button_state state; - enum libinput_pointer_axis axis; enum libinput_pointer_axis_source source; - double value; + uint32_t axes; }; struct libinput_event_touch { @@ -379,16 +378,41 @@ libinput_event_pointer_get_seat_button_count( return event->seat_button_count; } -LIBINPUT_EXPORT enum libinput_pointer_axis -libinput_event_pointer_get_axis(struct libinput_event_pointer *event) -{ - return event->axis; +LIBINPUT_EXPORT int +libinput_event_pointer_has_axis(struct libinput_event_pointer *event, + enum libinput_pointer_axis axis) +{ + if (event->base.type == LIBINPUT_EVENT_POINTER_AXIS) { + switch (axis) { + case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: + case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: + return !!(event->axes & AS_MASK(axis)); + } + } + return 0; } LIBINPUT_EXPORT double -libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event) +libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, + enum libinput_pointer_axis axis) { - return event->value; + struct libinput *libinput = event->base.device->seat->libinput; + double value = 0; + + if (!libinput_event_pointer_has_axis(event, axis)) { + log_bug_client(libinput, "value requested for unset axis\n"); + } else { + switch (axis) { + case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: + value = event->x; + break; + case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: + value = event->y; + break; + } + } + + return value; } LIBINPUT_EXPORT enum libinput_pointer_axis_source @@ -992,9 +1016,9 @@ pointer_notify_button(struct libinput_device *device, void pointer_notify_axis(struct libinput_device *device, uint64_t time, - enum libinput_pointer_axis axis, + uint32_t axes, enum libinput_pointer_axis_source source, - double value) + double x, double y) { struct libinput_event_pointer *axis_event; @@ -1004,9 +1028,10 @@ pointer_notify_axis(struct libinput_device *device, *axis_event = (struct libinput_event_pointer) { .time = time, - .axis = axis, - .value = value, + .x = x, + .y = y, .source = source, + .axes = axes, }; post_device_event(device, time, diff --git a/src/libinput.h b/src/libinput.h index f605e52b..89cc0f09 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -653,17 +653,17 @@ libinput_event_pointer_get_seat_button_count( /** * @ingroup event_pointer * - * Return the axis that triggered this event. - * For pointer events that are not of type @ref LIBINPUT_EVENT_POINTER_AXIS, - * this function returns 0. + * Check if the event has a valid value for the given axis. * - * @note It is an application bug to call this function for events other than - * @ref LIBINPUT_EVENT_POINTER_AXIS. + * If this function returns non-zero for an axis and + * libinput_event_pointer_get_axis_value() returns a value of 0, the event + * is a scroll stop event. * - * @return the axis triggering this event + * @return non-zero if this event contains a value for this axis */ -enum libinput_pointer_axis -libinput_event_pointer_get_axis(struct libinput_event_pointer *event); +int +libinput_event_pointer_has_axis(struct libinput_event_pointer *event, + enum libinput_pointer_axis axis); /** * @ingroup event_pointer @@ -676,6 +676,9 @@ libinput_event_pointer_get_axis(struct libinput_event_pointer *event); * respectively. For the interpretation of the value, see * libinput_event_pointer_get_axis_source(). * + * If libinput_event_pointer_has_axis() returns 0 for an axis, this function + * returns 0 for that axis. + * * For pointer events that are not of type @ref LIBINPUT_EVENT_POINTER_AXIS, * this function returns 0. * @@ -685,7 +688,8 @@ libinput_event_pointer_get_axis(struct libinput_event_pointer *event); * @return the axis value of this event */ double -libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event); +libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, + enum libinput_pointer_axis axis); /** * @ingroup event_pointer diff --git a/src/libinput.sym b/src/libinput.sym index 826bfde4..c5d9b63f 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -82,6 +82,7 @@ global: libinput_event_pointer_get_dy_unaccelerated; libinput_event_pointer_get_seat_button_count; libinput_event_pointer_get_time; + libinput_event_pointer_has_axis; libinput_event_touch_get_base_event; libinput_event_touch_get_seat_slot; libinput_event_touch_get_slot; diff --git a/test/litest.c b/test/litest.c index 392ffe25..757f445d 100644 --- a/test/litest.c +++ b/test/litest.c @@ -983,11 +983,11 @@ litest_print_event(struct libinput_event *event) case LIBINPUT_EVENT_POINTER_AXIS: p = libinput_event_get_pointer_event(event); fprintf(stderr, - "axis %s value %.2f", - libinput_event_pointer_get_axis(p) == - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL ? - "vert" : "horiz", - libinput_event_pointer_get_axis_value(p)); + "vert %.f horiz %.2f", + libinput_event_pointer_get_axis_value(p, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), + libinput_event_pointer_get_axis_value(p, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)); break; default: break; @@ -1198,23 +1198,24 @@ litest_assert_scroll(struct libinput *li, 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), axis); if (next_event) { /* Normal scroll event, check dir */ if (minimum_movement > 0) { ck_assert_int_ge( - libinput_event_pointer_get_axis_value(ptrev), + libinput_event_pointer_get_axis_value(ptrev, + axis), minimum_movement); } else { ck_assert_int_le( - libinput_event_pointer_get_axis_value(ptrev), + libinput_event_pointer_get_axis_value(ptrev, + axis), minimum_movement); } } else { /* Last scroll event, must be 0 */ ck_assert_int_eq( - libinput_event_pointer_get_axis_value(ptrev), + libinput_event_pointer_get_axis_value(ptrev, axis), 0); } libinput_event_destroy(event); diff --git a/test/pointer.c b/test/pointer.c index d12c9f6b..dd9ea0da 100644 --- a/test/pointer.c +++ b/test/pointer.c @@ -348,6 +348,7 @@ 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; + enum libinput_pointer_axis axis; /* the current evdev implementation scales the scroll wheel events up by a factor 15 */ @@ -372,11 +373,13 @@ test_wheel_event(struct litest_device *dev, int which, int amount) ptrev = libinput_event_get_pointer_event(event); ck_assert(ptrev != NULL); - ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev), - which == REL_WHEEL ? + + axis = (which == REL_WHEEL) ? LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL : - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - ck_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev), expected); + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; + + ck_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev, axis), + expected); ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev), LIBINPUT_POINTER_AXIS_SOURCE_WHEEL); libinput_event_destroy(event); diff --git a/test/touchpad.c b/test/touchpad.c index 422e8fe6..dbe16a3a 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -1439,18 +1439,19 @@ START_TEST(touchpad_2fg_scroll_slow_distance) /* last event is value 0, tested elsewhere */ while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) { + double axisval; ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_POINTER_AXIS); ptrev = libinput_event_get_pointer_event(event); - ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev), - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - ck_assert(libinput_event_pointer_get_axis_value(ptrev) > 0.0); + axisval = libinput_event_pointer_get_axis_value(ptrev, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + ck_assert(axisval > 0.0); /* this is to verify we test the right thing, if the value is greater than scroll.threshold we triggered the wrong condition */ - ck_assert(libinput_event_pointer_get_axis_value(ptrev) < 5.0); + ck_assert(axisval < 5.0); libinput_event_destroy(event); event = libinput_get_event(li); @@ -1627,18 +1628,19 @@ START_TEST(touchpad_edge_scroll_slow_distance) ck_assert_notnull(event); while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) { + double axisval; ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_POINTER_AXIS); ptrev = libinput_event_get_pointer_event(event); - ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev), + axisval = libinput_event_pointer_get_axis_value(ptrev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - ck_assert(libinput_event_pointer_get_axis_value(ptrev) > 0.0); + ck_assert(axisval > 0.0); /* this is to verify we test the right thing, if the value is greater than scroll.threshold we triggered the wrong condition */ - ck_assert(libinput_event_pointer_get_axis_value(ptrev) < 5.0); + ck_assert(axisval < 5.0); libinput_event_destroy(event); event = libinput_get_event(li); diff --git a/tools/event-debug.c b/tools/event-debug.c index 090fc3f0..4d845ced 100644 --- a/tools/event-debug.c +++ b/tools/event-debug.c @@ -225,24 +225,18 @@ static void print_axis_event(struct libinput_event *ev) { struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); - enum libinput_pointer_axis axis = libinput_event_pointer_get_axis(p); - const char *ax; - double val; - - switch (axis) { - case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: - ax = "vscroll"; - break; - case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: - ax = "hscroll"; - break; - default: - abort(); - } - + double v = 0, h = 0; + + if (libinput_event_pointer_has_axis(p, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) + v = libinput_event_pointer_get_axis_value(p, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + if (libinput_event_pointer_has_axis(p, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) + h = libinput_event_pointer_get_axis_value(p, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); print_event_time(libinput_event_pointer_get_time(p)); - val = libinput_event_pointer_get_axis_value(p); - printf("%s %.2f\n", ax, val); + printf("vert %.2f horiz %.2f\n", v, h); } static void diff --git a/tools/event-gui.c b/tools/event-gui.c index 9a08d8ef..4f9d7e67 100644 --- a/tools/event-gui.c +++ b/tools/event-gui.c @@ -358,20 +358,20 @@ static void handle_event_axis(struct libinput_event *ev, struct window *w) { struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); - enum libinput_pointer_axis axis = libinput_event_pointer_get_axis(p); - double v = libinput_event_pointer_get_axis_value(p); + double v, h; - switch (axis) { - case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: + v = libinput_event_pointer_get_axis_value(p, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + h = libinput_event_pointer_get_axis_value(p, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + + if (v != 0.0) { w->vy += (int)v; w->vy = clip(w->vy, 0, w->height); - break; - case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: + } + if (h != 0.0) { w->hx += (int)v; w->hx = clip(w->hx, 0, w->width); - break; - default: - abort(); } }