From f7bef28a54f27fa02ba548630a5f79d898c30c2a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 Feb 2015 10:16:30 +0100 Subject: [PATCH 01/13] touchpad: Change how we deal with scroll methods With the upcoming gesture support 2fg scrolling will be handled as part of the main gesture state machine, whereas edge scrolling has its own state machine, our current way of dispatching scroll "actions" does not play well with this. Change the scroll method handling to treat edge and 2fg scrolling as 2 separate state machines. The double scroll calls this introduces will mostly be removed when the gesture handling code lands. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer --- src/evdev-mt-touchpad-edge-scroll.c | 3 ++ src/evdev-mt-touchpad.c | 73 ++++++----------------------- 2 files changed, 17 insertions(+), 59 deletions(-) diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index 8d0a13e3..df181d51 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -317,6 +317,9 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) enum libinput_pointer_axis axis; double dx, dy, *delta; + if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE) + return 0; + tp_for_each_touch(tp, t) { if (!t->dirty) continue; diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index e0b0c364..779b1661 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -581,6 +581,9 @@ tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time) struct tp_touch *t; int nfingers_down = 0; + if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG) + return 0; + /* No 2fg scrolling during tap-n-drag */ if (tp_tap_dragging(tp)) return 0; @@ -605,60 +608,6 @@ tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time) return 0; } -static void -tp_scroll_handle_state(struct tp_dispatch *tp, uint64_t time) -{ - /* Note this must be always called, so that it knows the state of - * touches when the scroll-mode changes. - */ - tp_edge_scroll_handle_state(tp, time); -} - -static int -tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time) -{ - struct libinput *libinput = tp->device->base.seat->libinput; - - switch (tp->scroll.method) { - case LIBINPUT_CONFIG_SCROLL_NO_SCROLL: - break; - case LIBINPUT_CONFIG_SCROLL_2FG: - return tp_twofinger_scroll_post_events(tp, time); - case LIBINPUT_CONFIG_SCROLL_EDGE: - return tp_edge_scroll_post_events(tp, time); - case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN: - log_bug_libinput(libinput, "Unexpected scroll mode\n"); - break; - } - return 0; -} - -static void -tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time) -{ - struct libinput *libinput = tp->device->base.seat->libinput; - - switch (tp->scroll.method) { - case LIBINPUT_CONFIG_SCROLL_NO_SCROLL: - break; - case LIBINPUT_CONFIG_SCROLL_2FG: - tp_twofinger_stop_scroll(tp, time); - break; - case LIBINPUT_CONFIG_SCROLL_EDGE: - tp_edge_scroll_stop_events(tp, time); - break; - case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN: - log_bug_libinput(libinput, "Unexpected scroll mode\n"); - break; - } -} - -static void -tp_remove_scroll(struct tp_dispatch *tp) -{ - tp_remove_edge_scroll(tp); -} - static void tp_unhover_touches(struct tp_dispatch *tp, uint64_t time) { @@ -749,7 +698,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time) } tp_button_handle_state(tp, time); - tp_scroll_handle_state(tp, time); + tp_edge_scroll_handle_state(tp, time); /* * We have a physical button down event on a clickpad. To avoid @@ -862,11 +811,14 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time) filter_motion |= tp_post_button_events(tp, time); if (filter_motion || tp->sendevents.trackpoint_active) { - tp_stop_scroll_events(tp, time); + tp_edge_scroll_stop_events(tp, time); + tp_twofinger_stop_scroll(tp, time); return; } - if (tp_post_scroll_events(tp, time) != 0) + if (tp_edge_scroll_post_events(tp, time) != 0) + return; + if (tp_twofinger_scroll_post_events(tp, time) != 0) return; tp_post_pointer_motion(tp, time); @@ -925,7 +877,7 @@ tp_remove(struct evdev_dispatch *dispatch) tp_remove_tap(tp); tp_remove_buttons(tp); tp_remove_sendevents(tp); - tp_remove_scroll(tp); + tp_remove_edge_scroll(tp); } static void @@ -1254,11 +1206,14 @@ tp_scroll_config_scroll_method_set_method(struct libinput_device *device, { struct evdev_device *evdev = (struct evdev_device*)device; struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; + uint64_t time = libinput_now(device->seat->libinput); if (method == tp->scroll.method) return LIBINPUT_CONFIG_STATUS_SUCCESS; - tp_stop_scroll_events(tp, libinput_now(device->seat->libinput)); + tp_edge_scroll_stop_events(tp, time); + tp_twofinger_stop_scroll(tp, time); + tp->scroll.method = method; return LIBINPUT_CONFIG_STATUS_SUCCESS; From 0cd92aeacd66693585b7fea0e9007c3b9e59c853 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 Feb 2015 10:24:28 +0100 Subject: [PATCH 02/13] touchpad: Also stop edge scrolling when the trackpoint becomes active Not only stop 2fg scrolling, but also edge scrolling when the trackpoint becomes active. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 779b1661..19383718 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -969,9 +969,8 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data) return; if (!tp->sendevents.trackpoint_active) { - evdev_stop_scroll(tp->device, - time, - LIBINPUT_POINTER_AXIS_SOURCE_FINGER); + tp_edge_scroll_stop_events(tp, time); + tp_twofinger_stop_scroll(tp, time); tp_tap_suspend(tp, time); tp->sendevents.trackpoint_active = true; } From 6d032027305d1019bc76edee82341f6ab985e801 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 Feb 2015 14:49:40 +0100 Subject: [PATCH 03/13] touchpad: Add tp_get_average_touches_delta helper function Add a tp_get_average_touches_delta helper function, and rename tp_get_active_touches_delta to tp_get_combined_touches_delta to better differentiate the two. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 19383718..e281d489 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -513,20 +513,22 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) } static void -tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) +tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) { struct tp_touch *t; int nchanged = 0; - double dx = 0, dy =0; double tmpx, tmpy; + *dx = 0.0; + *dy = 0.0; + tp_for_each_touch(tp, t) { if (tp_touch_active(tp, t) && t->dirty) { nchanged++; tp_get_delta(t, &tmpx, &tmpy); - dx += tmpx; - dy += tmpy; + *dx += tmpx; + *dy += tmpy; } /* Stop spurious MOTION events at the end of scrolling */ t->is_pointer = false; @@ -535,9 +537,16 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) if (nchanged == 0) return; - dx /= nchanged; - dy /= nchanged; + *dx /= nchanged; + *dy /= nchanged; +} +static void +tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) +{ + double dx = 0, dy =0; + + tp_get_average_touches_delta(tp, &dx, &dy); tp_filter_motion(tp, &dx, &dy, NULL, NULL, time); evdev_post_scroll(tp->device, @@ -758,7 +767,7 @@ tp_get_pointer_delta(struct tp_dispatch *tp, double *dx, double *dy) } static void -tp_get_active_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) +tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) { struct tp_touch *t; double tdx, tdy; @@ -784,7 +793,7 @@ tp_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) /* When a clickpad is clicked, combine motion of all active touches */ if (tp->buttons.is_clickpad && tp->buttons.state) - tp_get_active_touches_delta(tp, &dx, &dy); + tp_get_combined_touches_delta(tp, &dx, &dy); else tp_get_pointer_delta(tp, &dx, &dy); From 18887f90ee02dc604267dca9632dd5ada10f593b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 Feb 2015 13:30:24 +0100 Subject: [PATCH 04/13] touchpad: Gesture support preparation Handle everything which is not handled by the tap, (soft)button or edge-scroll code/statemachines in a unified way. Everything is treated as a X-finger gesture now, and the action to take on finger movement is decided by the gesture.finger_count setting. Pointer control now simply is seen as a 1 finger gesture, and 2fg scrolling as a 2fg gesture. This removed the need for special-casing things like switching back to pointer mode when lifting a finger in 2fg scrolling mode, and also lays the groundwork for adding 3+ fg gesture support. Note that 1 test-case needs to be updated to wait for the finger mode switching when switching mode while a gesture has already been started. This is actually an improvement as this stops sending spurious pointer motion events at the end of 2fg scrolling when not lifting both fingers at exactly the same time. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer --- src/Makefile.am | 1 + src/evdev-mt-touchpad-buttons.c | 1 - src/evdev-mt-touchpad-edge-scroll.c | 1 - src/evdev-mt-touchpad-gestures.c | 146 ++++++++++++++++++++++++++++ src/evdev-mt-touchpad.c | 129 +++++------------------- src/evdev-mt-touchpad.h | 47 +++++++-- test/litest.c | 6 ++ test/litest.h | 1 + test/touchpad.c | 6 ++ 9 files changed, 219 insertions(+), 119 deletions(-) create mode 100644 src/evdev-mt-touchpad-gestures.c diff --git a/src/Makefile.am b/src/Makefile.am index b5eba731..ff65ff7f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,6 +15,7 @@ libinput_la_SOURCES = \ evdev-mt-touchpad-tap.c \ evdev-mt-touchpad-buttons.c \ evdev-mt-touchpad-edge-scroll.c \ + evdev-mt-touchpad-gestures.c \ filter.c \ filter.h \ filter-private.h \ diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index 9dbb5137..12f80234 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -156,7 +156,6 @@ tp_button_set_state(struct tp_dispatch *tp, struct tp_touch *t, break; case BUTTON_STATE_AREA: t->button.curr = BUTTON_EVENT_IN_AREA; - tp_set_pointer(tp, t); break; case BUTTON_STATE_BOTTOM: t->button.curr = event; diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index df181d51..28f29c2f 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -86,7 +86,6 @@ tp_edge_scroll_set_state(struct tp_dispatch *tp, break; case EDGE_SCROLL_TOUCH_STATE_AREA: t->scroll.edge = EDGE_NONE; - tp_set_pointer(tp, t); break; } } diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c new file mode 100644 index 00000000..4317d282 --- /dev/null +++ b/src/evdev-mt-touchpad-gestures.c @@ -0,0 +1,146 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "evdev-mt-touchpad.h" + +#define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */ + +void +tp_gesture_start(struct tp_dispatch *tp, uint64_t time) +{ + if (tp->gesture.started) + return; + + switch (tp->gesture.finger_count) { + case 2: + /* NOP */ + break; + } + tp->gesture.started = true; +} + +void +tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time) +{ + if (tp->gesture.finger_count == 0) + return; + + /* When tap-and-dragging, or a clickpad is clicked force 1fg mode */ + if (tp_tap_dragging(tp) || (tp->buttons.is_clickpad && tp->buttons.state)) { + tp_gesture_stop(tp, time); + tp->gesture.finger_count = 1; + tp->gesture.finger_count_pending = 0; + } + + /* Don't send events when we're unsure in which mode we are */ + if (tp->gesture.finger_count_pending) + return; + + switch (tp->gesture.finger_count) { + case 1: + tp_gesture_post_pointer_motion(tp, time); + break; + case 2: + tp_gesture_post_twofinger_scroll(tp, time); + break; + } +} + +void +tp_gesture_stop(struct tp_dispatch *tp, uint64_t time) +{ + if (!tp->gesture.started) + return; + + switch (tp->gesture.finger_count) { + case 2: + tp_gesture_stop_twofinger_scroll(tp, time); + break; + } + tp->gesture.started = false; +} + +static void +tp_gesture_finger_count_switch_timeout(uint64_t now, void *data) +{ + struct tp_dispatch *tp = data; + + if (!tp->gesture.finger_count_pending) + return; + + tp_gesture_stop(tp, now); /* End current gesture */ + tp->gesture.finger_count = tp->gesture.finger_count_pending; + tp->gesture.finger_count_pending = 0; +} + +void +tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time) +{ + unsigned int active_touches = 0; + struct tp_touch *t; + + tp_for_each_touch(tp, t) + if (tp_touch_active(tp, t)) + active_touches++; + + if (active_touches != tp->gesture.finger_count) { + /* If all fingers are lifted immediately end the gesture */ + if (active_touches == 0) { + tp_gesture_stop(tp, time); + tp->gesture.finger_count = 0; + tp->gesture.finger_count_pending = 0; + /* Immediately switch to new mode to avoid initial latency */ + } else if (!tp->gesture.started) { + tp->gesture.finger_count = active_touches; + tp->gesture.finger_count_pending = 0; + /* Else debounce finger changes */ + } else if (active_touches != tp->gesture.finger_count_pending) { + tp->gesture.finger_count_pending = active_touches; + libinput_timer_set(&tp->gesture.finger_count_switch_timer, + time + DEFAULT_GESTURE_SWITCH_TIMEOUT); + } + } else { + tp->gesture.finger_count_pending = 0; + } +} + +int +tp_init_gesture(struct tp_dispatch *tp) +{ + libinput_timer_init(&tp->gesture.finger_count_switch_timer, + tp->device->base.seat->libinput, + tp_gesture_finger_count_switch_timeout, tp); + return 0; +} + +void +tp_remove_gesture(struct tp_dispatch *tp) +{ + libinput_timer_cancel(&tp->gesture.finger_count_switch_timer); +} diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index e281d489..32ed7bf5 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -227,7 +227,6 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) } t->dirty = true; - t->is_pointer = false; t->palm.is_palm = false; t->state = TOUCH_END; t->pinned.is_pinned = false; @@ -424,7 +423,6 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t) if (xdist * xdist + ydist * ydist >= tp->buttons.motion_dist * tp->buttons.motion_dist) { t->pinned.is_pinned = false; - tp_set_pointer(tp, t); return; } @@ -439,14 +437,13 @@ tp_pin_fingers(struct tp_dispatch *tp) struct tp_touch *t; tp_for_each_touch(tp, t) { - t->is_pointer = false; t->pinned.is_pinned = true; t->pinned.center_x = t->x; t->pinned.center_y = t->y; } } -static int +int tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t) { return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) && @@ -456,21 +453,6 @@ tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t) tp_edge_scroll_touch_active(tp, t); } -void -tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t) -{ - struct tp_touch *tmp = NULL; - - /* Only set the touch as pointer if we don't have one yet */ - tp_for_each_touch(tp, tmp) { - if (tmp->is_pointer) - return; - } - - if (tp_touch_active(tp, t)) - t->is_pointer = true; -} - static void tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) { @@ -487,7 +469,6 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y); if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) { t->palm.is_palm = false; - tp_set_pointer(tp, t); } } return; @@ -530,8 +511,6 @@ tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) *dx += tmpx; *dy += tmpy; } - /* Stop spurious MOTION events at the end of scrolling */ - t->is_pointer = false; } if (nchanged == 0) @@ -541,80 +520,30 @@ tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) *dy /= nchanged; } -static void -tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) +void +tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) { double dx = 0, dy =0; tp_get_average_touches_delta(tp, &dx, &dy); tp_filter_motion(tp, &dx, &dy, NULL, NULL, time); + if (dx == 0.0 && dy == 0.0) + return; + + tp_gesture_start(tp, time); evdev_post_scroll(tp->device, time, LIBINPUT_POINTER_AXIS_SOURCE_FINGER, dx, dy); - tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_ACTIVE; } -static void -tp_twofinger_stop_scroll(struct tp_dispatch *tp, uint64_t time) +void +tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) { - struct tp_touch *t, *ptr = NULL; - int nfingers_down = 0; - evdev_stop_scroll(tp->device, time, LIBINPUT_POINTER_AXIS_SOURCE_FINGER); - - /* If we were scrolling and now there's exactly 1 active finger, - switch back to pointer movement */ - if (tp->scroll.twofinger_state == TWOFINGER_SCROLL_STATE_ACTIVE) { - tp_for_each_touch(tp, t) { - if (tp_touch_active(tp, t)) { - nfingers_down++; - if (ptr == NULL) - ptr = t; - } - } - - if (nfingers_down == 1) - tp_set_pointer(tp, ptr); - } - - tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_NONE; -} - -static int -tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time) -{ - struct tp_touch *t; - int nfingers_down = 0; - - if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG) - return 0; - - /* No 2fg scrolling during tap-n-drag */ - if (tp_tap_dragging(tp)) - return 0; - - /* No 2fg scrolling while a clickpad is clicked */ - if (tp->buttons.is_clickpad && tp->buttons.state) - return 0; - - /* Only count active touches for 2 finger scrolling */ - tp_for_each_touch(tp, t) { - if (tp_touch_active(tp, t)) - nfingers_down++; - } - - if (nfingers_down == 2) { - tp_post_twofinger_scroll(tp, time); - return 1; - } - - tp_twofinger_stop_scroll(tp, time); - - return 0; } static void @@ -718,6 +647,8 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time) if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) && tp->buttons.is_clickpad) tp_pin_fingers(tp); + + tp_gesture_handle_state(tp, time); } static void @@ -748,24 +679,6 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time) tp->queued = TOUCHPAD_EVENT_NONE; } -static void -tp_get_pointer_delta(struct tp_dispatch *tp, double *dx, double *dy) -{ - struct tp_touch *t = tp_current_touch(tp); - - if (!t->is_pointer) { - tp_for_each_touch(tp, t) { - if (t->is_pointer) - break; - } - } - - if (!t->is_pointer || !t->dirty) - return; - - tp_get_delta(t, dx, dy); -} - static void tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) { @@ -785,8 +698,8 @@ tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) } } -static void -tp_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) +void +tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) { double dx = 0.0, dy = 0.0; double dx_unaccel, dy_unaccel; @@ -795,7 +708,7 @@ tp_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) if (tp->buttons.is_clickpad && tp->buttons.state) tp_get_combined_touches_delta(tp, &dx, &dy); else - tp_get_pointer_delta(tp, &dx, &dy); + tp_get_average_touches_delta(tp, &dx, &dy); tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time); @@ -821,16 +734,14 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time) if (filter_motion || tp->sendevents.trackpoint_active) { tp_edge_scroll_stop_events(tp, time); - tp_twofinger_stop_scroll(tp, time); + tp_gesture_stop(tp, time); return; } if (tp_edge_scroll_post_events(tp, time) != 0) return; - if (tp_twofinger_scroll_post_events(tp, time) != 0) - return; - tp_post_pointer_motion(tp, time); + tp_gesture_post_events(tp, time); } static void @@ -887,6 +798,7 @@ tp_remove(struct evdev_dispatch *dispatch) tp_remove_buttons(tp); tp_remove_sendevents(tp); tp_remove_edge_scroll(tp); + tp_remove_gesture(tp); } static void @@ -979,7 +891,7 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data) if (!tp->sendevents.trackpoint_active) { tp_edge_scroll_stop_events(tp, time); - tp_twofinger_stop_scroll(tp, time); + tp_gesture_stop(tp, time); tp_tap_suspend(tp, time); tp->sendevents.trackpoint_active = true; } @@ -1220,7 +1132,7 @@ tp_scroll_config_scroll_method_set_method(struct libinput_device *device, return LIBINPUT_CONFIG_STATUS_SUCCESS; tp_edge_scroll_stop_events(tp, time); - tp_twofinger_stop_scroll(tp, time); + tp_gesture_stop_twofinger_scroll(tp, time); tp->scroll.method = method; @@ -1358,6 +1270,9 @@ tp_init(struct tp_dispatch *tp, if (tp_init_scroll(tp, device) != 0) return -1; + if (tp_init_gesture(tp) != 0) + return -1; + device->seat_caps |= EVDEV_DEVICE_POINTER; return 0; diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index d552c26d..3e4ac0fd 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -117,11 +117,6 @@ enum tp_edge_scroll_touch_state { EDGE_SCROLL_TOUCH_STATE_AREA, }; -enum tp_twofinger_scroll_state { - TWOFINGER_SCROLL_STATE_NONE, - TWOFINGER_SCROLL_STATE_ACTIVE, -}; - struct tp_motion { int32_t x; int32_t y; @@ -132,7 +127,6 @@ struct tp_touch { enum touch_state state; bool has_ended; /* TRACKING_ID == -1 */ bool dirty; - bool is_pointer; /* the pointer-controlling touch */ int32_t x; int32_t y; uint64_t millis; @@ -215,6 +209,13 @@ struct tp_dispatch { double y_scale_coeff; } accel; + struct { + bool started; + unsigned int finger_count; + unsigned int finger_count_pending; + struct libinput_timer finger_count_switch_timer; + } gesture; + struct { bool is_clickpad; /* true for clickpads */ bool has_topbuttons; @@ -252,7 +253,6 @@ struct tp_dispatch { enum libinput_config_scroll_method method; int32_t right_edge; int32_t bottom_edge; - enum tp_twofinger_scroll_state twofinger_state; } scroll; enum touchpad_event queued; @@ -286,15 +286,15 @@ struct tp_dispatch { void tp_get_delta(struct tp_touch *t, double *dx, double *dy); -void -tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t); - void tp_filter_motion(struct tp_dispatch *tp, double *dx, double *dy, double *dx_unaccel, double *dy_unaccel, uint64_t time); +int +tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t); + int tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time); @@ -367,4 +367,31 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time); int tp_edge_scroll_touch_active(struct tp_dispatch *tp, struct tp_touch *t); +int +tp_init_gesture(struct tp_dispatch *tp); + +void +tp_remove_gesture(struct tp_dispatch *tp); + +void +tp_gesture_start(struct tp_dispatch *tp, uint64_t time); + +void +tp_gesture_stop(struct tp_dispatch *tp, uint64_t time); + +void +tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time); + +void +tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time); + +void +tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time); + +void +tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time); + +void +tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time); + #endif diff --git a/test/litest.c b/test/litest.c index 16d92399..0660dabb 100644 --- a/test/litest.c +++ b/test/litest.c @@ -1380,6 +1380,12 @@ litest_timeout_buttonscroll(void) msleep(300); } +void +litest_timeout_finger_switch(void) +{ + msleep(120); +} + void litest_push_event_frame(struct litest_device *dev) { diff --git a/test/litest.h b/test/litest.h index 60ec4587..d78bf0eb 100644 --- a/test/litest.h +++ b/test/litest.h @@ -180,6 +180,7 @@ struct libevdev_uinput * litest_create_uinput_abs_device(const char *name, void litest_timeout_tap(void); void litest_timeout_softbuttons(void); void litest_timeout_buttonscroll(void); +void litest_timeout_finger_switch(void); void litest_push_event_frame(struct litest_device *dev); void litest_pop_event_frame(struct litest_device *dev); diff --git a/test/touchpad.c b/test/touchpad.c index 9b3ba812..b70d3732 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -1871,6 +1871,9 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0); litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0); litest_touch_up(dev, 1); + libinput_dispatch(li); + litest_timeout_finger_switch(); + libinput_dispatch(li); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); litest_touch_move_to(dev, 0, 47, 70, 47, 50, 10, 0); @@ -1881,6 +1884,9 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0); litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0); litest_touch_up(dev, 0); + libinput_dispatch(li); + litest_timeout_finger_switch(); + libinput_dispatch(li); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); /* move with second finger */ From ff02bd1b5b821d67efbf082fdca9f7109c10a025 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 17 Feb 2015 11:40:17 +0100 Subject: [PATCH 05/13] touchpad: Move gesture handling code to evdev-mt-touchpad-gestures.c Just moving some code around, no functional changes. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer --- src/evdev-mt-touchpad-gestures.c | 94 +++++++++++++++++++++++++++++++- src/evdev-mt-touchpad.c | 92 ------------------------------- src/evdev-mt-touchpad.h | 9 --- 3 files changed, 93 insertions(+), 102 deletions(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 4317d282..3a013f5a 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -31,7 +31,53 @@ #define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */ -void +static void +tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) +{ + struct tp_touch *t; + int nchanged = 0; + double tmpx, tmpy; + + *dx = 0.0; + *dy = 0.0; + + tp_for_each_touch(tp, t) { + if (tp_touch_active(tp, t) && t->dirty) { + nchanged++; + tp_get_delta(t, &tmpx, &tmpy); + + *dx += tmpx; + *dy += tmpy; + } + } + + if (nchanged == 0) + return; + + *dx /= nchanged; + *dy /= nchanged; +} + +static void +tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) +{ + struct tp_touch *t; + double tdx, tdy; + unsigned int i; + + for (i = 0; i < tp->real_touches; i++) { + t = &tp->touches[i]; + + if (!tp_touch_active(tp, t) || !t->dirty) + continue; + + tp_get_delta(t, &tdx, &tdy); + *dx += tdx; + *dy += tdy; + } +} + +static void tp_gesture_start(struct tp_dispatch *tp, uint64_t time) { if (tp->gesture.started) @@ -45,6 +91,44 @@ tp_gesture_start(struct tp_dispatch *tp, uint64_t time) tp->gesture.started = true; } +static void +tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) +{ + double dx = 0.0, dy = 0.0; + double dx_unaccel, dy_unaccel; + + /* When a clickpad is clicked, combine motion of all active touches */ + if (tp->buttons.is_clickpad && tp->buttons.state) + tp_get_combined_touches_delta(tp, &dx, &dy); + else + tp_get_average_touches_delta(tp, &dx, &dy); + + tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time); + + if (dx != 0.0 || dy != 0.0 || dx_unaccel != 0.0 || dy_unaccel != 0.0) { + pointer_notify_motion(&tp->device->base, time, + dx, dy, dx_unaccel, dy_unaccel); + } +} + +static void +tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) +{ + double dx = 0, dy =0; + + tp_get_average_touches_delta(tp, &dx, &dy); + tp_filter_motion(tp, &dx, &dy, NULL, NULL, time); + + if (dx == 0.0 && dy == 0.0) + return; + + tp_gesture_start(tp, time); + evdev_post_scroll(tp->device, + time, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER, + dx, dy); +} + void tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time) { @@ -72,6 +156,14 @@ tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time) } } +void +tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) +{ + evdev_stop_scroll(tp->device, + time, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); +} + void tp_gesture_stop(struct tp_dispatch *tp, uint64_t time) { diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 32ed7bf5..b90d84c5 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -493,59 +493,6 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) t->palm.y = t->y; } -static void -tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) -{ - struct tp_touch *t; - int nchanged = 0; - double tmpx, tmpy; - - *dx = 0.0; - *dy = 0.0; - - tp_for_each_touch(tp, t) { - if (tp_touch_active(tp, t) && t->dirty) { - nchanged++; - tp_get_delta(t, &tmpx, &tmpy); - - *dx += tmpx; - *dy += tmpy; - } - } - - if (nchanged == 0) - return; - - *dx /= nchanged; - *dy /= nchanged; -} - -void -tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) -{ - double dx = 0, dy =0; - - tp_get_average_touches_delta(tp, &dx, &dy); - tp_filter_motion(tp, &dx, &dy, NULL, NULL, time); - - if (dx == 0.0 && dy == 0.0) - return; - - tp_gesture_start(tp, time); - evdev_post_scroll(tp->device, - time, - LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - dx, dy); -} - -void -tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) -{ - evdev_stop_scroll(tp->device, - time, - LIBINPUT_POINTER_AXIS_SOURCE_FINGER); -} - static void tp_unhover_touches(struct tp_dispatch *tp, uint64_t time) { @@ -679,45 +626,6 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time) tp->queued = TOUCHPAD_EVENT_NONE; } -static void -tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) -{ - struct tp_touch *t; - double tdx, tdy; - unsigned int i; - - for (i = 0; i < tp->real_touches; i++) { - t = tp_get_touch(tp, i); - - if (!tp_touch_active(tp, t) || !t->dirty) - continue; - - tp_get_delta(t, &tdx, &tdy); - *dx += tdx; - *dy += tdy; - } -} - -void -tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) -{ - double dx = 0.0, dy = 0.0; - double dx_unaccel, dy_unaccel; - - /* When a clickpad is clicked, combine motion of all active touches */ - if (tp->buttons.is_clickpad && tp->buttons.state) - tp_get_combined_touches_delta(tp, &dx, &dy); - else - tp_get_average_touches_delta(tp, &dx, &dy); - - tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time); - - if (dx != 0.0 || dy != 0.0 || dx_unaccel != 0.0 || dy_unaccel != 0.0) { - pointer_notify_motion(&tp->device->base, time, - dx, dy, dx_unaccel, dy_unaccel); - } -} - static void tp_post_events(struct tp_dispatch *tp, uint64_t time) { diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 3e4ac0fd..f04cc112 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -373,9 +373,6 @@ tp_init_gesture(struct tp_dispatch *tp); void tp_remove_gesture(struct tp_dispatch *tp); -void -tp_gesture_start(struct tp_dispatch *tp, uint64_t time); - void tp_gesture_stop(struct tp_dispatch *tp, uint64_t time); @@ -385,13 +382,7 @@ tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time); void tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time); -void -tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time); - void tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time); -void -tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time); - #endif From 2e8403e7628fe87b7689d82efe61cf6465c6af12 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 17 Feb 2015 11:40:57 +0100 Subject: [PATCH 06/13] touchpad: Do not use fake touches when getting the average touches delta Only look at real touches when getting the average touches delta, otherwise the touch used to populate the fake touches gets an unfair weighing factor. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer --- src/evdev-mt-touchpad-gestures.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 3a013f5a..71a81ca6 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -35,13 +35,15 @@ static void tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) { struct tp_touch *t; - int nchanged = 0; + unsigned int i, nchanged = 0; double tmpx, tmpy; *dx = 0.0; *dy = 0.0; - tp_for_each_touch(tp, t) { + for (i = 0; i < tp->real_touches; i++) { + t = &tp->touches[i]; + if (tp_touch_active(tp, t) && t->dirty) { nchanged++; tp_get_delta(t, &tmpx, &tmpy); From 88d87e763ca7319570c5e1d4faf1c77e9cdd436c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 17 Feb 2015 11:44:06 +0100 Subject: [PATCH 07/13] touchpad: Refactor tp_get_*_touches_delta The two tp_get_*_touches_delta functions are almost identical, refactor them into one function. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer --- src/evdev-mt-touchpad-gestures.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 71a81ca6..c1ed1c26 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -32,7 +32,7 @@ #define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */ static void -tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) +tp_get_touches_delta(struct tp_dispatch *tp, double *dx, double *dy, bool average) { struct tp_touch *t; unsigned int i, nchanged = 0; @@ -53,30 +53,23 @@ tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) } } - if (nchanged == 0) + if (!average || nchanged == 0) return; *dx /= nchanged; *dy /= nchanged; } -static void +static inline void tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) { - struct tp_touch *t; - double tdx, tdy; - unsigned int i; + tp_get_touches_delta(tp, dx, dy, false); +} - for (i = 0; i < tp->real_touches; i++) { - t = &tp->touches[i]; - - if (!tp_touch_active(tp, t) || !t->dirty) - continue; - - tp_get_delta(t, &tdx, &tdy); - *dx += tdx; - *dy += tdy; - } +static inline void +tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) +{ + tp_get_touches_delta(tp, dx, dy, true); } static void From ae75a44e303e744e2034b93b55977c23fe16d533 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 20 Feb 2015 14:16:04 +1000 Subject: [PATCH 08/13] Clarify a comment, it's wheel clicks, not mouse clicks Signed-off-by: Peter Hutterer --- src/libinput.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libinput.h b/src/libinput.h index 56c3ca13..09e24cfb 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -747,7 +747,7 @@ libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event); * value translates into a discrete step depends on the source. * * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, the discrete - * value correspond to the number of physical mouse clicks. + * value correspond to the number of physical mouse wheel clicks. * * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS or @ref * LIBINPUT_POINTER_AXIS_SOURCE_FINGER, the discrete value is always 0. From bb78357f0479d3d44bb5896a30591e7f32fae1a1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 25 Feb 2015 16:04:04 +1000 Subject: [PATCH 09/13] evdev: force-assign 10 slots to mtdev devices If the device doesn't have any slots, mtdev->caps.slot.maximum is 0. Since we only use mtdev if we don't have slots, this caused protocol A devices to always fail. https://bugs.freedesktop.org/show_bug.cgi?id=89211 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index cf21d2e2..a0c020b8 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -524,6 +524,14 @@ evdev_process_touch(struct evdev_device *device, { switch (e->code) { case ABS_MT_SLOT: + if ((size_t)e->value >= device->mt.slots_len) { + log_bug_libinput(device->base.seat->libinput, + "%s exceeds slots (%d of %d)\n", + device->devname, + e->value, + device->mt.slots_len); + e->value = device->mt.slots_len - 1; + } evdev_flush_pending_event(device, time); device->mt.slot = e->value; break; @@ -1467,10 +1475,9 @@ evdev_configure_device(struct evdev_device *device) if (!device->mtdev) return -1; - num_slots = device->mtdev->caps.slot.maximum; - if (device->mtdev->caps.slot.minimum < 0 || - num_slots <= 0) - return -1; + /* pick 10 slots as default for type A + devices. */ + num_slots = 10; active_slot = device->mtdev->caps.slot.value; } else { num_slots = libevdev_get_num_slots(device->evdev); From 72cc6010076fdcfebf32d34d146a798bbfe212aa Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 25 Feb 2015 16:30:06 +1000 Subject: [PATCH 10/13] test: add protocol A touch screen tests Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/Makefile.am | 1 + test/litest-protocol-a-touch-screen.c | 97 ++++++++++++++++++++ test/litest.c | 2 + test/litest.h | 2 + test/pointer.c | 2 +- test/touch.c | 122 ++++++++++++++++++++++++++ test/valgrind.suppressions | 6 ++ 7 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 test/litest-protocol-a-touch-screen.c diff --git a/test/Makefile.am b/test/Makefile.am index 5743ca4f..4bafe980 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -19,6 +19,7 @@ liblitest_la_SOURCES = \ litest-keyboard.c \ litest-mouse.c \ litest-ms-surface-cover.c \ + litest-protocol-a-touch-screen.c \ litest-qemu-usb-tablet.c \ litest-synaptics.c \ litest-synaptics-hover.c \ diff --git a/test/litest-protocol-a-touch-screen.c b/test/litest-protocol-a-touch-screen.c new file mode 100644 index 00000000..2c930060 --- /dev/null +++ b/test/litest-protocol-a-touch-screen.c @@ -0,0 +1,97 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "litest.h" +#include "litest-int.h" + +static void +litest_protocol_a_touch_setup(void) +{ + struct litest_device *d = litest_create_device(LITEST_PROTOCOL_A_SCREEN); + litest_set_current_device(d); +} + +static struct input_event down[] = { + { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_SYN, .code = SYN_MT_REPORT, .value = 0 }, + { .type = EV_KEY, .code = BTN_TOUCH, .value = 1 }, + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, + { .type = -1, .code = -1 }, +}; + +static struct input_event move[] = { + { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_SYN, .code = SYN_MT_REPORT, .value = 0 }, + { .type = EV_KEY, .code = BTN_TOUCH, .value = 1 }, + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, + { .type = -1, .code = -1 }, +}; + +static struct litest_device_interface interface = { + .touch_down_events = down, + .touch_move_events = move, +}; + +static struct input_absinfo absinfo[] = { + { ABS_X, 0, 32767, 0, 0, 0 }, + { ABS_Y, 0, 32767, 0, 0, 0 }, + { ABS_MT_POSITION_X, 0, 32767, 0, 0, 0 }, + { ABS_MT_POSITION_Y, 0, 32767, 0, 0, 0 }, + { ABS_MT_PRESSURE, 0, 1, 0, 0, 0 }, + { .value = -1 }, +}; + +static struct input_id input_id = { + .bustype = 0x18, + .vendor = 0xeef, + .product = 0x20, +}; + +static int events[] = { + EV_KEY, BTN_TOUCH, + INPUT_PROP_MAX, INPUT_PROP_DIRECT, + -1, -1, +}; + +struct litest_test_device litest_protocol_a_screen = { + .type = LITEST_PROTOCOL_A_SCREEN, + .features = LITEST_PROTOCOL_A, + .shortname = "protocol A", + .setup = litest_protocol_a_touch_setup, + .interface = &interface, + + .name = "Protocol A touch screen", + .id = &input_id, + .events = events, + .absinfo = absinfo, +}; diff --git a/test/litest.c b/test/litest.c index 0660dabb..7585859f 100644 --- a/test/litest.c +++ b/test/litest.c @@ -96,6 +96,7 @@ extern struct litest_test_device litest_xen_virtual_pointer_device; extern struct litest_test_device litest_vmware_virtmouse_device; extern struct litest_test_device litest_synaptics_hover_device; extern struct litest_test_device litest_synaptics_carbon3rd_device; +extern struct litest_test_device litest_protocol_a_screen; struct litest_test_device* devices[] = { &litest_synaptics_clickpad_device, @@ -113,6 +114,7 @@ struct litest_test_device* devices[] = { &litest_vmware_virtmouse_device, &litest_synaptics_hover_device, &litest_synaptics_carbon3rd_device, + &litest_protocol_a_screen, NULL, }; diff --git a/test/litest.h b/test/litest.h index d78bf0eb..df5dd756 100644 --- a/test/litest.h +++ b/test/litest.h @@ -51,6 +51,7 @@ enum litest_device_type { LITEST_VMWARE_VIRTMOUSE = -15, LITEST_SYNAPTICS_HOVER_SEMI_MT = -16, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS = -17, + LITEST_PROTOCOL_A_SCREEN = -18, }; enum litest_device_feature { @@ -70,6 +71,7 @@ enum litest_device_feature { LITEST_POINTINGSTICK = 1 << 11, LITEST_FAKE_MT = 1 << 12, LITEST_ABSOLUTE = 1 << 13, + LITEST_PROTOCOL_A = 1 << 14, }; struct litest_device { diff --git a/test/pointer.c b/test/pointer.c index 24ea7266..23bf0d7c 100644 --- a/test/pointer.c +++ b/test/pointer.c @@ -826,7 +826,7 @@ int main (int argc, char **argv) { litest_add("pointer:scroll", pointer_scroll_natural_wheel, LITEST_WHEEL, LITEST_ANY); litest_add_no_device("pointer:seat button count", pointer_seat_button_count); - litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_ABSOLUTE); + litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_ABSOLUTE|LITEST_PROTOCOL_A); /* tests touchpads too */ litest_add("pointer:left-handed", pointer_left_handed_defaults, LITEST_BUTTON, LITEST_ANY); diff --git a/test/touch.c b/test/touch.c index 29890a41..2d918b2d 100644 --- a/test/touch.c +++ b/test/touch.c @@ -465,6 +465,124 @@ START_TEST(fake_mt_no_touch_events) } END_TEST +START_TEST(touch_protocol_a_init) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_device *device = dev->libinput_device; + + ck_assert_int_ne(libinput_next_event_type(li), + LIBINPUT_EVENT_NONE); + + ck_assert(libinput_device_has_capability(device, + LIBINPUT_DEVICE_CAP_TOUCH)); +} +END_TEST + +START_TEST(touch_protocol_a_touch) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *ev; + struct libinput_event_touch *tev; + double x, y, oldx, oldy; + + litest_drain_events(li); + + litest_touch_down(dev, 0, 5, 95); + + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_DOWN, -1); + + ev = libinput_get_event(li); + tev = libinput_event_get_touch_event(ev); + + oldx = libinput_event_touch_get_x(tev); + oldy = libinput_event_touch_get_y(tev); + + libinput_event_destroy(ev); + + litest_touch_move_to(dev, 0, 10, 90, 90, 10, 20, 1); + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_MOTION, -1); + + while ((ev = libinput_get_event(li))) { + if (libinput_event_get_type(ev) == + LIBINPUT_EVENT_TOUCH_FRAME) { + libinput_event_destroy(ev); + continue; + } + ck_assert_int_eq(libinput_event_get_type(ev), + LIBINPUT_EVENT_TOUCH_MOTION); + + tev = libinput_event_get_touch_event(ev); + x = libinput_event_touch_get_x(tev); + y = libinput_event_touch_get_y(tev); + + ck_assert_int_gt(x, oldx); + ck_assert_int_lt(y, oldy); + + oldx = x; + oldy = y; + + libinput_event_destroy(ev); + } + + litest_touch_up(dev, 0); + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_UP, -1); +} +END_TEST + +START_TEST(touch_protocol_a_2fg_touch) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *ev; + struct libinput_event_touch *tev; + int pos; + + litest_drain_events(li); + + litest_push_event_frame(dev); + litest_touch_down(dev, 0, 5, 95); + litest_touch_down(dev, 0, 95, 5); + litest_pop_event_frame(dev); + + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_DOWN, -1); + + ev = libinput_get_event(li); + libinput_event_destroy(ev); + + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_DOWN, -1); + + ev = libinput_get_event(li); + libinput_event_destroy(ev); + + for (pos = 10; pos < 100; pos += 10) { + litest_push_event_frame(dev); + litest_touch_move_to(dev, 0, pos, 100 - pos, pos, 100 - pos, 1, 1); + litest_touch_move_to(dev, 0, 100 - pos, pos, 100 - pos, pos, 1, 1); + litest_pop_event_frame(dev); + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_MOTION, -1); + ev = libinput_get_event(li); + tev = libinput_event_get_touch_event(ev); + ck_assert_int_eq(libinput_event_touch_get_slot(tev), + 0); + libinput_event_destroy(ev); + + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_MOTION, -1); + ev = libinput_get_event(li); + tev = libinput_event_get_touch_event(ev); + ck_assert_int_eq(libinput_event_touch_get_slot(tev), + 1); + libinput_event_destroy(ev); + } + + litest_event(dev, EV_SYN, SYN_MT_REPORT, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_UP, -1); + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_UP, -1); +} +END_TEST + int main(int argc, char **argv) { @@ -484,5 +602,9 @@ main(int argc, char **argv) litest_add("touch:fake-mt", fake_mt_exists, LITEST_FAKE_MT, LITEST_ANY); litest_add("touch:fake-mt", fake_mt_no_touch_events, LITEST_FAKE_MT, LITEST_ANY); + litest_add("touch:protocol a", touch_protocol_a_init, LITEST_PROTOCOL_A, LITEST_ANY); + litest_add("touch:protocol a", touch_protocol_a_touch, LITEST_PROTOCOL_A, LITEST_ANY); + litest_add("touch:protocol a", touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY); + return litest_run(argc, argv); } diff --git a/test/valgrind.suppressions b/test/valgrind.suppressions index 3ba7f292..5aef8a41 100644 --- a/test/valgrind.suppressions +++ b/test/valgrind.suppressions @@ -7,3 +7,9 @@ fun:litest_run fun:main } +{ + mtdev:conditional_jumps_uninitialized_value + Memcheck:Cond + ... + fun:mtdev_put_event +} From a626109d3149e6226f667385b499ce90b77b1aa0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 26 Feb 2015 15:52:41 +1000 Subject: [PATCH 11/13] evdev: ignore tablet pad devices explicitly We don't have real support for them yet but they have the ID_INPUT_TABLET tag set. Ignore them explicitly before someone thinks they're already working. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede Reviewed-and-tested-by: Benjamin Tissoires --- src/evdev.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index a0c020b8..70c60eea 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -58,6 +58,7 @@ enum evdev_device_udev_tags { EVDEV_UDEV_TAG_TABLET = (1 << 5), EVDEV_UDEV_TAG_JOYSTICK = (1 << 6), EVDEV_UDEV_TAG_ACCELEROMETER = (1 << 7), + EVDEV_UDEV_TAG_BUTTONSET = (1 << 8), }; struct evdev_udev_tag_match { @@ -73,6 +74,7 @@ static const struct evdev_udev_tag_match evdev_udev_tag_matches[] = { {"ID_INPUT_TOUCHPAD", EVDEV_UDEV_TAG_TOUCHPAD}, {"ID_INPUT_TOUCHSCREEN", EVDEV_UDEV_TAG_TOUCHSCREEN}, {"ID_INPUT_TABLET", EVDEV_UDEV_TAG_TABLET}, + {"ID_INPUT_TABLET_PAD", EVDEV_UDEV_TAG_BUTTONSET}, {"ID_INPUT_JOYSTICK", EVDEV_UDEV_TAG_JOYSTICK}, {"ID_INPUT_ACCELEROMETER", EVDEV_UDEV_TAG_ACCELEROMETER}, @@ -1408,7 +1410,7 @@ evdev_configure_device(struct evdev_device *device) } log_info(libinput, - "input device '%s', %s is tagged by udev as:%s%s%s%s%s%s%s\n", + "input device '%s', %s is tagged by udev as:%s%s%s%s%s%s%s%s\n", device->devname, devnode, udev_tags & EVDEV_UDEV_TAG_KEYBOARD ? " Keyboard" : "", udev_tags & EVDEV_UDEV_TAG_MOUSE ? " Mouse" : "", @@ -1416,7 +1418,8 @@ evdev_configure_device(struct evdev_device *device) udev_tags & EVDEV_UDEV_TAG_TOUCHSCREEN ? " Touchscreen" : "", udev_tags & EVDEV_UDEV_TAG_TABLET ? " Tablet" : "", udev_tags & EVDEV_UDEV_TAG_JOYSTICK ? " Joystick" : "", - udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : ""); + udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : "", + udev_tags & EVDEV_UDEV_TAG_BUTTONSET ? " Buttonset" : ""); /* libwacom *adds* TABLET, TOUCHPAD but leaves JOYSTICK in place, so make sure we only ignore real joystick devices */ @@ -1427,6 +1430,14 @@ evdev_configure_device(struct evdev_device *device) return -1; } + /* libwacom assigns tablet _and_ tablet_pad to the pad devices */ + if (udev_tags & EVDEV_UDEV_TAG_BUTTONSET) { + log_info(libinput, + "input device '%s', %s is a buttonset, ignoring\n", + device->devname, devnode); + return -1; + } + if (libevdev_has_event_type(evdev, EV_ABS)) { if ((absinfo = libevdev_get_abs_info(evdev, ABS_X))) { From 39004cd5c26019791cb690165ec167d51f16df6b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 26 Feb 2015 18:43:01 +1000 Subject: [PATCH 12/13] A whole bunch of documentation updates/improvements Signed-off-by: Peter Hutterer --- doc/device-configuration-via-udev.dox | 17 ++- src/libinput.h | 170 ++++++++++++++------------ 2 files changed, 105 insertions(+), 82 deletions(-) diff --git a/doc/device-configuration-via-udev.dox b/doc/device-configuration-via-udev.dox index 4107f943..fc1c0af8 100644 --- a/doc/device-configuration-via-udev.dox +++ b/doc/device-configuration-via-udev.dox @@ -11,7 +11,22 @@ The following udev properties are supported:
LIBINPUT_CALIBRATION_MATRIX
Sets the calibration matrix, see libinput_device_config_calibration_get_default_matrix(). If unset, -defaults to the identity matrix.
+defaults to the identity matrix. + +The udev property is parsed as 6 floating point numbers separated by a +single space each (scanf(3) format "%f %f %f %f %f %f"). +The 6 values represent the first two rows of the calibration matrix as +described in libinput_device_config_calibration_set_matrix(). + +Example values are: +@code + ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0" # default + ENV{LIBINPUT_CALIBRATION_MATRIX}="0 -1 1 1 0 0" # 90 degree clockwise + ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 -1 1" # 180 degree clockwise + ENV{LIBINPUT_CALIBRATION_MATRIX}="0 1 0 -1 0 1" # 270 degree clockwise + ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 1 0 0" # reflect along y axis +@endcode +
LIBINPUT_DEVICE_GROUP
A string identifying the @ref libinput_device_group for this device. Two devices with the same property value are grouped into the same device group, diff --git a/src/libinput.h b/src/libinput.h index 09e24cfb..4206a4a2 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -48,8 +48,7 @@ enum libinput_log_priority { * @ingroup device * * Capabilities on a device. A device may have one or more capabilities - * at a time, and capabilities may appear or disappear during the - * lifetime of the device. + * at a time, capabilities remain static for the lifetime of the device. */ enum libinput_device_capability { LIBINPUT_DEVICE_CAP_KEYBOARD = 0, @@ -93,7 +92,8 @@ enum libinput_button_state { /** * @ingroup device * - * Axes on a device that are not x or y coordinates. + * Axes on a device with the capability @ref LIBINPUT_DEVICE_CAP_POINTER + * that are not x or y coordinates. * * The two scroll axes @ref LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL and * @ref LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL are engaged separately, @@ -304,9 +304,9 @@ libinput_event_get_context(struct libinput_event *event); /** * @ingroup event * - * Return the device associated with this event, if applicable. For device - * added/removed events this is the device added or removed. For all other - * device events, this is the device that generated the event. + * Return the device associated with this event. For device added/removed + * events this is the device added or removed. For all other device events, + * this is the device that generated the event. * * This device is not refcounted and its lifetime is that of the event. Use * libinput_device_ref() before using the device outside of this scope. @@ -424,7 +424,7 @@ libinput_event_keyboard_get_base_event(struct libinput_event_keyboard *event); * of keys pressed on all devices on the associated seat after the event was * triggered. * - " @note It is an application bug to call this function for events other than + * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_KEYBOARD_KEY. For other events, this function returns 0. * * @return the seat wide pressed key count for the key of this event @@ -649,7 +649,7 @@ libinput_event_pointer_get_button_state(struct libinput_event_pointer *event); * total number of buttons pressed on all devices on the associated seat * after the event was triggered. * - " @note It is an application bug to call this function for events other than + * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_BUTTON. For other events, this function * returns 0. * @@ -1059,7 +1059,11 @@ libinput_get_fd(struct libinput *libinput); * and processes them internally. Use libinput_get_event() to retrieve the * events. * - * Dispatching does not necessarily queue libinput events. + * Dispatching does not necessarily queue libinput events. This function + * should be called immediately once data is available on the file + * descriptor returned by libinput_get_fd(). libinput has a number of + * timing-sensitive features (e.g. tap-to-click), any delay in calling + * libinput_dispatch() may prevent these features from working correctly. * * @param libinput A previously initialized libinput context * @@ -1090,8 +1094,8 @@ libinput_get_event(struct libinput *libinput); * libinput_get_event() returns that event. * * @param libinput A previously initialized libinput context - * @return The event type of the next available event or LIBINPUT_EVENT_NONE - * if no event is availble. + * @return The event type of the next available event or @ref + * LIBINPUT_EVENT_NONE if no event is availble. */ enum libinput_event_type libinput_next_event_type(struct libinput *libinput); @@ -1099,6 +1103,10 @@ libinput_next_event_type(struct libinput *libinput); /** * @ingroup base * + * Set caller-specific data associated with this context. libinput does + * not manage, look at, or modify this data. The caller must ensure the + * data is valid. + * * @param libinput A previously initialized libinput context * @param user_data Caller-specific data passed to the various callback * interfaces. @@ -1110,6 +1118,8 @@ libinput_set_user_data(struct libinput *libinput, /** * @ingroup base * + * Get the caller-specific data associated with this context, if any. + * * @param libinput A previously initialized libinput context * @return the caller-specific data previously assigned in * libinput_create_udev(). @@ -1171,10 +1181,11 @@ libinput_unref(struct libinput *libinput); /** * @ingroup base * - * Set the global log priority. Messages with priorities equal to or - * higher than the argument will be printed to the current log handler. + * Set the log priority for the libinput context. Messages with priorities + * equal to or higher than the argument will be printed to the context's + * log handler. * - * The default log priority is LIBINPUT_LOG_PRIORITY_ERROR. + * The default log priority is @ref LIBINPUT_LOG_PRIORITY_ERROR. * * @param libinput A previously initialized libinput context * @param priority The minimum priority of log messages to print. @@ -1189,10 +1200,10 @@ libinput_log_set_priority(struct libinput *libinput, /** * @ingroup base * - * Get the global log priority. Messages with priorities equal to or + * Get the context's log priority. Messages with priorities equal to or * higher than the argument will be printed to the current log handler. * - * The default log priority is LIBINPUT_LOG_PRIORITY_ERROR. + * The default log priority is @ref LIBINPUT_LOG_PRIORITY_ERROR. * * @param libinput A previously initialized libinput context * @return The minimum priority of log messages to print. @@ -1225,8 +1236,8 @@ typedef void (*libinput_log_handler)(struct libinput *libinput, /** * @ingroup base * - * Set the global log handler. Messages with priorities equal to or higher - * than the current log priority will be passed to the given + * Set the context's log handler. Messages with priorities equal to or + * higher than the context's log priority will be passed to the given * log handler. * * The default log handler prints to stderr. @@ -1254,7 +1265,7 @@ libinput_log_set_handler(struct libinput *libinput, * @ingroup seat * * Increase the refcount of the seat. A seat will be freed whenever the - * refcount reaches 0. This may happen during dispatch if the + * refcount reaches 0. This may happen during libinput_dispatch() if the * seat was removed from the system. A caller must ensure to reference * the seat correctly to avoid dangling pointers. * @@ -1268,7 +1279,7 @@ libinput_seat_ref(struct libinput_seat *seat); * @ingroup seat * * Decrease the refcount of the seat. A seat will be freed whenever the - * refcount reaches 0. This may happen during dispatch if the + * refcount reaches 0. This may happen during libinput_dispatch() if the * seat was removed from the system. A caller must ensure to reference * the seat correctly to avoid dangling pointers. * @@ -1354,9 +1365,9 @@ libinput_seat_get_logical_name(struct libinput_seat *seat); * @ingroup device * * Increase the refcount of the input device. An input device will be freed - * whenever the refcount reaches 0. This may happen during dispatch if the - * device was removed from the system. A caller must ensure to reference - * the device correctly to avoid dangling pointers. + * whenever the refcount reaches 0. This may happen during + * libinput_dispatch() if the device was removed from the system. A caller + * must ensure to reference the device correctly to avoid dangling pointers. * * @param device A previously obtained device * @return The passed device @@ -1368,9 +1379,9 @@ libinput_device_ref(struct libinput_device *device); * @ingroup device * * Decrease the refcount of the input device. An input device will be freed - * whenever the refcount reaches 0. This may happen during dispatch if the - * device was removed from the system. A caller must ensure to reference - * the device correctly to avoid dangling pointers. + * whenever the refcount reaches 0. This may happen during libinput_dispatch + * if the device was removed from the system. A caller must ensure to + * reference the device correctly to avoid dangling pointers. * * @param device A previously obtained device * @return NULL if the device was destroyed, otherwise the passed device @@ -1547,7 +1558,8 @@ libinput_device_get_output_name(struct libinput_device *device); /** * @ingroup device * - * Get the seat associated with this input device. + * Get the seat associated with this input device, see @ref seats for + * details. * * A seat can be uniquely identified by the physical and logical seat name. * There will ever be only one seat instance with a given physical and logical @@ -1567,10 +1579,13 @@ libinput_device_get_seat(struct libinput_device *device); * device and adding it to the new seat. * * This command is identical to physically unplugging the device, then - * re-plugging it as member of the new seat, - * @ref LIBINPUT_EVENT_DEVICE_REMOVED and @ref LIBINPUT_EVENT_DEVICE_ADDED - * events are sent accordingly. Those events mark the end of the lifetime - * of this device and the start of a new device. + * re-plugging it as member of the new seat. libinput will generate a + * @ref LIBINPUT_EVENT_DEVICE_REMOVED event and this @ref libinput_device is + * considered removed from the context; it will not generate further events + * and will be freed when the refcount reaches zero. + * A @ref LIBINPUT_EVENT_DEVICE_ADDED event is generated with a new @ref + * libinput_device handle. It is the caller's responsibility to update + * references to the new device accordingly. * * If the logical seat name already exists in the device's physical seat, * the device is added to this seat. Otherwise, a new seat is created. @@ -1591,7 +1606,9 @@ libinput_device_set_seat_logical_name(struct libinput_device *device, * * Return a udev handle to the device that is this libinput device, if any. * The returned handle has a refcount of at least 1, the caller must call - * udev_device_unref() once to release the associated resources. + * udev_device_unref() once to release the associated resources. + * See the [libudev documentation] + * (http://www.freedesktop.org/software/systemd/libudev/) for details. * * Some devices may not have a udev device, or the udev device may be * unobtainable. This function returns NULL if no udev device was available. @@ -1625,7 +1642,7 @@ libinput_device_led_update(struct libinput_device *device, * * Check if the given device has the specified capability * - * @return 1 if the given device has the capability or 0 if not + * @return Non-zero if the given device has the capability or zero otherwise */ int libinput_device_has_capability(struct libinput_device *device, @@ -1654,10 +1671,10 @@ libinput_device_get_size(struct libinput_device *device, * @ingroup device * * Check if a @ref LIBINPUT_DEVICE_CAP_POINTER device has a button with the - * passed in code (see linux/input.h). + * given code (see linux/input.h). * * @param device A current input device - * @param code button code to check for + * @param code Button code to check for, e.g. BTN_LEFT * * @return 1 if the device supports this button code, 0 if it does not, -1 * on error. @@ -1677,9 +1694,10 @@ libinput_device_has_button(struct libinput_device *device, uint32_t code) LIBINP * @ingroup device * * Increase the refcount of the device group. A device group will be freed - * whenever the refcount reaches 0. This may happen during dispatch if all - * devices of this group were removed from the system. A caller must ensure - * to reference the device group correctly to avoid dangling pointers. + * whenever the refcount reaches 0. This may happen during + * libinput_dispatch() if all devices of this group were removed from the + * system. A caller must ensure to reference the device group correctly to + * avoid dangling pointers. * * @param group A previously obtained device group * @return The passed device group @@ -1691,9 +1709,10 @@ libinput_device_group_ref(struct libinput_device_group *group); * @ingroup device * * Decrease the refcount of the device group. A device group will be freed - * whenever the refcount reaches 0. This may happen during dispatch if all - * devices of this group were removed from the system. A caller must ensure - * to reference the device group correctly to avoid dangling pointers. + * whenever the refcount reaches 0. This may happen during + * libinput_dispatch() if all devices of this group were removed from the + * system. A caller must ensure to reference the device group correctly to + * avoid dangling pointers. * * @param group A previously obtained device group * @return NULL if the device group was destroyed, otherwise the passed @@ -1740,7 +1759,7 @@ libinput_device_group_get_user_data(struct libinput_device_group *group); * * Some configuration option may be dependent on or mutually exclusive with * with other options. The behavior in those cases is - * implementation-defined, the caller must ensure that the options are set + * implementation-dependent, the caller must ensure that the options are set * in the right order. */ @@ -1781,7 +1800,8 @@ enum libinput_config_tap_state { /** * @ingroup config * - * Check if the device supports tap-to-click. See + * Check if the device supports tap-to-click and how many fingers can be + * used for tapping. See * libinput_device_config_tap_set_enabled() for more information. * * @param device The device to configure @@ -1827,8 +1847,8 @@ libinput_device_config_tap_set_enabled(struct libinput_device *device, * * @param device The device to configure * - * @return @ref LIBINPUT_CONFIG_TAP_ENABLED if tapping is currently enabled, - * or @ref LIBINPUT_CONFIG_TAP_DISABLED is currently disabled + * @retval LIBINPUT_CONFIG_TAP_ENABLED If tapping is currently enabled + * @retval LIBINPUT_CONFIG_TAP_DISABLED If tapping is currently disabled * * @see libinput_device_config_tap_get_finger_count * @see libinput_device_config_tap_set_enabled @@ -1840,11 +1860,12 @@ libinput_device_config_tap_get_enabled(struct libinput_device *device); /** * @ingroup config * - * Return the default setting for whether tapping is enabled on this device. + * Return the default setting for whether tap-to-click is enabled on this + * device. * * @param device The device to configure - * @return @ref LIBINPUT_CONFIG_TAP_ENABLED if tapping is enabled by default, - * or @ref LIBINPUT_CONFIG_TAP_DISABLED is disabled by default + * @retval LIBINPUT_CONFIG_TAP_ENABLED If tapping is enabled by default + * @retval LIBINPUT_CONFIG_TAP_DISABLED If tapping Is disabled by default * * @see libinput_device_config_tap_get_finger_count * @see libinput_device_config_tap_set_enabled @@ -1947,21 +1968,7 @@ libinput_device_config_calibration_get_matrix(struct libinput_device *device, * Return the default calibration matrix for this device. On most devices, * this is the identity matrix. If the udev property * LIBINPUT_CALIBRATION_MATRIX is set on the respective udev device, - * that property's value becomes the default matrix. - * - * The udev property is parsed as 6 floating point numbers separated by a - * single space each (scanf(3) format "%f %f %f %f %f %f"). - * The 6 values represent the first two rows of the calibration matrix as - * described in libinput_device_config_calibration_set_matrix(). - * - * Example values are: - * @code - * ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0" # default - * ENV{LIBINPUT_CALIBRATION_MATRIX}="0 -1 1 1 0 0" # 90 degree clockwise - * ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 -1 1" # 180 degree clockwise - * ENV{LIBINPUT_CALIBRATION_MATRIX}="0 1 0 -1 0 1" # 270 degree clockwise - * ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 1 0 0" # reflect along y axis - * @endcode + * that property's value becomes the default matrix, see @ref udev_config. * * @param device The device to configure * @param matrix Set to the array representing the first two rows of a 3x3 matrix as @@ -2179,7 +2186,7 @@ libinput_device_config_accel_get_default_speed(struct libinput_device *device); * * @param device The device to configure * - * @return 0 if natural scrolling is not supported, non-zero if natural + * @return Zero if natural scrolling is not supported, non-zero if natural * scrolling is supported by this device * * @see libinput_device_config_set_natural_scroll_enabled @@ -2257,9 +2264,7 @@ libinput_device_config_left_handed_is_available(struct libinput_device *device); /** * @ingroup config * - * Set the left-handed configuration of the device. For example, a pointing - * device may reverse it's buttons and send a right button click when the - * left button is pressed, and vice versa. + * Set the left-handed configuration of the device. * * The exact behavior is device-dependent. On a mouse and most pointing * devices, left and right buttons are swapped but the middle button is @@ -2325,7 +2330,7 @@ libinput_device_config_left_handed_get_default(struct libinput_device *device); enum libinput_config_click_method { /** * Do not send software-emulated button events. This has no effect - * on physical button generations. + * on events generated by physical buttons. */ LIBINPUT_CONFIG_CLICK_METHOD_NONE = 0, /** @@ -2425,15 +2430,16 @@ libinput_device_config_click_get_default_method(struct libinput_device *device); enum libinput_config_scroll_method { /** * Never send scroll events instead of pointer motion events. - * Note scroll wheels, etc. will still send scroll events. + * This has no effect on events generated by scroll wheels. */ LIBINPUT_CONFIG_SCROLL_NO_SCROLL = 0, /** - * Send scroll events when 2 fingers are down on the device. + * Send scroll events when two fingers are logically down on the + * device. */ LIBINPUT_CONFIG_SCROLL_2FG = (1 << 0), /** - * Send scroll events when a finger is moved along the bottom or + * Send scroll events when a finger moves along the bottom or * right edge of a device. */ LIBINPUT_CONFIG_SCROLL_EDGE = (1 << 1), @@ -2552,9 +2558,10 @@ libinput_device_config_scroll_get_default_method(struct libinput_device *device) * @param button The button which when pressed switches to sending scroll events * * @return a config status code - * @retval LIBINPUT_CONFIG_STATUS_SUCCESS on success - * @retval LIBINPUT_CONFIG_STATUS_UNSUPPORTED if @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN is not supported - * @retval LIBINPUT_CONFIG_STATUS_INVALID the given button does not + * @retval LIBINPUT_CONFIG_STATUS_SUCCESS On success + * @retval LIBINPUT_CONFIG_STATUS_UNSUPPORTED If @ref + * LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN is not supported + * @retval LIBINPUT_CONFIG_STATUS_INVALID The given button does not * exist on this device * * @see libinput_device_config_scroll_get_methods @@ -2571,11 +2578,11 @@ libinput_device_config_scroll_set_button(struct libinput_device *device, /** * @ingroup config * - * Get the button for the @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method for - * this device. + * Get the button for the @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method + * for this device. * - * If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not supported, - * or no button is set, this function returns 0. + * If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not + * supported, or no button is set, this function returns 0. * * @note The return value is independent of the currently selected * scroll-method. For button scrolling to activate, a device must have the @@ -2598,14 +2605,15 @@ libinput_device_config_scroll_get_button(struct libinput_device *device); /** * @ingroup config * - * Get the default button for LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method - * for this device. + * Get the default button for the @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN + * method for this device. * * If @ref LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN scroll method is not supported, * or no default button is set, this function returns 0. * * @param device The device to configure - * @return The default button for LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method + * @return The default button for the @ref + * LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN method * * @see libinput_device_config_scroll_get_methods * @see libinput_device_config_scroll_set_method From 01d415ccae168548925ddeef618a2eaea6d87079 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 2 Mar 2015 11:47:02 +1000 Subject: [PATCH 13/13] cosmetic: doxygen @return [a-z] -> @return [A-Z] Signed-off-by: Peter Hutterer --- src/libinput.h | 60 +++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/libinput.h b/src/libinput.h index 4206a4a2..22c02d69 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -427,7 +427,7 @@ libinput_event_keyboard_get_base_event(struct libinput_event_keyboard *event); * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_KEYBOARD_KEY. For other events, this function returns 0. * - * @return the seat wide pressed key count for the key of this event + * @return The seat wide pressed key count for the key of this event */ uint32_t libinput_event_keyboard_get_seat_key_count( @@ -464,7 +464,7 @@ libinput_event_pointer_get_time(struct libinput_event_pointer *event); * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_MOTION. * - * @return the relative x movement since the last event + * @return The relative x movement since the last event */ double libinput_event_pointer_get_dx(struct libinput_event_pointer *event); @@ -485,7 +485,7 @@ libinput_event_pointer_get_dx(struct libinput_event_pointer *event); * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_MOTION. * - * @return the relative y movement since the last event + * @return The relative y movement since the last event */ double libinput_event_pointer_get_dy(struct libinput_event_pointer *event); @@ -505,7 +505,7 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event); * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_MOTION. * - * @return the unaccelerated relative x movement since the last event + * @return The unaccelerated relative x movement since the last event */ double libinput_event_pointer_get_dx_unaccelerated( @@ -526,7 +526,7 @@ libinput_event_pointer_get_dx_unaccelerated( * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_MOTION. * - * @return the unaccelerated relative y movement since the last event + * @return The unaccelerated relative y movement since the last event */ double libinput_event_pointer_get_dy_unaccelerated( @@ -545,7 +545,7 @@ libinput_event_pointer_get_dy_unaccelerated( * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE. * - * @return the current absolute x coordinate + * @return The current absolute x coordinate */ double libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event); @@ -563,7 +563,7 @@ libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event); * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE. * - * @return the current absolute y coordinate + * @return The current absolute y coordinate */ double libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event); @@ -583,7 +583,7 @@ libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event); * * @param event The libinput pointer event * @param width The current output screen width - * @return the current absolute x coordinate transformed to a screen coordinate + * @return The current absolute x coordinate transformed to a screen coordinate */ double libinput_event_pointer_get_absolute_x_transformed( @@ -605,7 +605,7 @@ libinput_event_pointer_get_absolute_x_transformed( * * @param event The libinput pointer event * @param height The current output screen height - * @return the current absolute y coordinate transformed to a screen coordinate + * @return The current absolute y coordinate transformed to a screen coordinate */ double libinput_event_pointer_get_absolute_y_transformed( @@ -622,7 +622,7 @@ libinput_event_pointer_get_absolute_y_transformed( * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_BUTTON. * - * @return the button triggering this event + * @return The button triggering this event */ uint32_t libinput_event_pointer_get_button(struct libinput_event_pointer *event); @@ -637,7 +637,7 @@ libinput_event_pointer_get_button(struct libinput_event_pointer *event); * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_BUTTON. * - * @return the button state triggering this event + * @return The button state triggering this event */ enum libinput_button_state libinput_event_pointer_get_button_state(struct libinput_event_pointer *event); @@ -653,7 +653,7 @@ libinput_event_pointer_get_button_state(struct libinput_event_pointer *event); * @ref LIBINPUT_EVENT_POINTER_BUTTON. For other events, this function * returns 0. * - * @return the seat wide pressed button count for the key of this event + * @return The seat wide pressed button count for the key of this event */ uint32_t libinput_event_pointer_get_seat_button_count( @@ -668,7 +668,7 @@ libinput_event_pointer_get_seat_button_count( * libinput_event_pointer_get_axis_value() returns a value of 0, the event * is a scroll stop event. * - * @return non-zero if this event contains a value for this axis + * @return Non-zero if this event contains a value for this axis */ int libinput_event_pointer_has_axis(struct libinput_event_pointer *event, @@ -694,7 +694,7 @@ libinput_event_pointer_has_axis(struct libinput_event_pointer *event, * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_AXIS. * - * @return the axis value of this event + * @return The axis value of this event * * @see libinput_event_pointer_get_axis_value_discrete */ @@ -735,7 +735,7 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, * @note It is an application bug to call this function for events other than * @ref LIBINPUT_EVENT_POINTER_AXIS. * - * @return the source for this axis event + * @return The source for this axis event */ enum libinput_pointer_axis_source libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event); @@ -827,7 +827,7 @@ libinput_event_touch_get_seat_slot(struct libinput_event_touch *event); * LIBINPUT_EVENT_TOUCH_DOWN and @ref LIBINPUT_EVENT_TOUCH_MOTION. * * @param event The libinput touch event - * @return the current absolute x coordinate + * @return The current absolute x coordinate */ double libinput_event_touch_get_x(struct libinput_event_touch *event); @@ -845,7 +845,7 @@ libinput_event_touch_get_x(struct libinput_event_touch *event); * @ref LIBINPUT_EVENT_TOUCH_MOTION. * * @param event The libinput touch event - * @return the current absolute y coordinate + * @return The current absolute y coordinate */ double libinput_event_touch_get_y(struct libinput_event_touch *event); @@ -861,7 +861,7 @@ libinput_event_touch_get_y(struct libinput_event_touch *event); * * @param event The libinput touch event * @param width The current output screen width - * @return the current absolute x coordinate transformed to a screen coordinate + * @return The current absolute x coordinate transformed to a screen coordinate */ double libinput_event_touch_get_x_transformed(struct libinput_event_touch *event, @@ -878,7 +878,7 @@ libinput_event_touch_get_x_transformed(struct libinput_event_touch *event, * * @param event The libinput touch event * @param height The current output screen height - * @return the current absolute y coordinate transformed to a screen coordinate + * @return The current absolute y coordinate transformed to a screen coordinate */ double libinput_event_touch_get_y_transformed(struct libinput_event_touch *event, @@ -917,7 +917,7 @@ struct libinput_interface { * @param user_data The user_data provided in * libinput_udev_create_context() * - * @return the file descriptor, or a negative errno on failure. + * @return The file descriptor, or a negative errno on failure. */ int (*open_restricted)(const char *path, int flags, void *user_data); /** @@ -1047,7 +1047,7 @@ libinput_path_remove_device(struct libinput_device *device); * libinput keeps a single file descriptor for all events. Call into * libinput_dispatch() if any events become available on this fd. * - * @return the file descriptor used to notify of pending events. + * @return The file descriptor used to notify of pending events. */ int libinput_get_fd(struct libinput *libinput); @@ -1121,7 +1121,7 @@ libinput_set_user_data(struct libinput *libinput, * Get the caller-specific data associated with this context, if any. * * @param libinput A previously initialized libinput context - * @return the caller-specific data previously assigned in + * @return The caller-specific data previously assigned in * libinput_create_udev(). */ void * @@ -1340,7 +1340,7 @@ libinput_seat_get_context(struct libinput_seat *seat); * be available to the caller. * * @param seat A previously obtained seat - * @return the physical name of this seat + * @return The physical name of this seat */ const char * libinput_seat_get_physical_name(struct libinput_seat *seat); @@ -1352,7 +1352,7 @@ libinput_seat_get_physical_name(struct libinput_seat *seat); * of devices within the compositor. * * @param seat A previously obtained seat - * @return the logical name of this seat + * @return The logical name of this seat */ const char * libinput_seat_get_logical_name(struct libinput_seat *seat); @@ -1549,7 +1549,7 @@ libinput_device_get_id_vendor(struct libinput_device *device); * beyond the boundaries of this output. An absolute device has its input * coordinates mapped to the extents of this output. * - * @return the name of the output this device is mapped to, or NULL if no + * @return The name of the output this device is mapped to, or NULL if no * output is set */ const char * @@ -1880,7 +1880,7 @@ libinput_device_config_tap_get_default_enabled(struct libinput_device *device); * Check if the device can be calibrated via a calibration matrix. * * @param device The device to check - * @return non-zero if the device can be calibrated, zero otherwise. + * @return Non-zero if the device can be calibrated, zero otherwise. * * @see libinput_device_config_calibration_set_matrix * @see libinput_device_config_calibration_get_matrix @@ -2204,7 +2204,7 @@ libinput_device_config_scroll_has_natural_scroll(struct libinput_device *device) * @param device The device to configure * @param enable non-zero to enable, zero to disable natural scrolling * - * @return a config status code + * @return A config status code * * @see libinput_device_config_has_natural_scroll * @see libinput_device_config_get_natural_scroll_enabled @@ -2220,7 +2220,7 @@ libinput_device_config_scroll_set_natural_scroll_enabled(struct libinput_device * * @param device The device to configure * - * @return zero if natural scrolling is disabled, non-zero if enabled + * @return Zero if natural scrolling is disabled, non-zero if enabled * * @see libinput_device_config_has_natural_scroll * @see libinput_device_config_set_natural_scroll_enabled @@ -2236,7 +2236,7 @@ libinput_device_config_scroll_get_natural_scroll_enabled(struct libinput_device * * @param device The device to configure * - * @return zero if natural scrolling is disabled by default, non-zero if enabled + * @return Zero if natural scrolling is disabled by default, non-zero if enabled * * @see libinput_device_config_has_natural_scroll * @see libinput_device_config_set_natural_scroll_enabled @@ -2557,7 +2557,7 @@ libinput_device_config_scroll_get_default_method(struct libinput_device *device) * @param device The device to configure * @param button The button which when pressed switches to sending scroll events * - * @return a config status code + * @return A config status code * @retval LIBINPUT_CONFIG_STATUS_SUCCESS On success * @retval LIBINPUT_CONFIG_STATUS_UNSUPPORTED If @ref * LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN is not supported