summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2016-01-20 15:38:17 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2016-01-20 15:38:17 +1000
commita4adea1646606cd386015ecf13391af3a2a0ccd5 (patch)
treea5f3033d955e61bdaaac823cc912bcdf2dc816e1 /src
parent82335b0ab91db7965cd25f1a7e1666f27f9f47cd (diff)
parentcab2c1640d4c35c25dd186c1fc2fc052af9dd17a (diff)
Merge branch 'wip/3-finger-pinch-gesture'
Diffstat (limited to 'src')
-rw-r--r--src/evdev-mt-touchpad-buttons.c27
-rw-r--r--src/evdev-mt-touchpad-edge-scroll.c5
-rw-r--r--src/evdev-mt-touchpad-gestures.c331
-rw-r--r--src/evdev-mt-touchpad-tap.c2
-rw-r--r--src/evdev-mt-touchpad.c12
-rw-r--r--src/evdev-mt-touchpad.h32
-rw-r--r--src/libinput-private.h2
-rw-r--r--src/libinput.c8
8 files changed, 255 insertions, 164 deletions
diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
index 8822e08c..82c99c76 100644
--- a/src/evdev-mt-touchpad-buttons.c
+++ b/src/evdev-mt-touchpad-buttons.c
@@ -78,47 +78,54 @@ button_event_to_str(enum button_event event) {
}
static inline bool
-is_inside_bottom_button_area(struct tp_dispatch *tp, struct tp_touch *t)
+is_inside_bottom_button_area(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
{
return t->point.y >= tp->buttons.bottom_area.top_edge;
}
static inline bool
-is_inside_bottom_right_area(struct tp_dispatch *tp, struct tp_touch *t)
+is_inside_bottom_right_area(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
{
return is_inside_bottom_button_area(tp, t) &&
t->point.x > tp->buttons.bottom_area.rightbutton_left_edge;
}
static inline bool
-is_inside_bottom_left_area(struct tp_dispatch *tp, struct tp_touch *t)
+is_inside_bottom_left_area(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
{
return is_inside_bottom_button_area(tp, t) &&
!is_inside_bottom_right_area(tp, t);
}
static inline bool
-is_inside_top_button_area(struct tp_dispatch *tp, struct tp_touch *t)
+is_inside_top_button_area(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
{
return t->point.y <= tp->buttons.top_area.bottom_edge;
}
static inline bool
-is_inside_top_right_area(struct tp_dispatch *tp, struct tp_touch *t)
+is_inside_top_right_area(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
{
return is_inside_top_button_area(tp, t) &&
t->point.x > tp->buttons.top_area.rightbutton_left_edge;
}
static inline bool
-is_inside_top_left_area(struct tp_dispatch *tp, struct tp_touch *t)
+is_inside_top_left_area(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
{
return is_inside_top_button_area(tp, t) &&
t->point.x < tp->buttons.top_area.leftbutton_right_edge;
}
static inline bool
-is_inside_top_middle_area(struct tp_dispatch *tp, struct tp_touch *t)
+is_inside_top_middle_area(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
{
return is_inside_top_button_area(tp, t) &&
t->point.x >= tp->buttons.top_area.leftbutton_right_edge &&
@@ -1042,13 +1049,15 @@ tp_post_button_events(struct tp_dispatch *tp, uint64_t time)
}
int
-tp_button_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
+tp_button_touch_active(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
{
return t->button.state == BUTTON_STATE_AREA;
}
bool
-tp_button_is_inside_softbutton_area(struct tp_dispatch *tp, struct tp_touch *t)
+tp_button_is_inside_softbutton_area(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
{
return is_inside_top_button_area(tp, t) ||
is_inside_bottom_button_area(tp, t);
diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c
index b572a9fb..fcc05121 100644
--- a/src/evdev-mt-touchpad-edge-scroll.c
+++ b/src/evdev-mt-touchpad-edge-scroll.c
@@ -73,7 +73,7 @@ edge_event_to_str(enum scroll_event event)
}
uint32_t
-tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *t)
+tp_touch_get_edge(const struct tp_dispatch *tp, const struct tp_touch *t)
{
uint32_t edge = EDGE_NONE;
@@ -455,7 +455,8 @@ 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)
+tp_edge_scroll_touch_active(const struct tp_dispatch *tp,
+ const struct tp_touch *t)
{
return t->scroll.edge_state == EDGE_SCROLL_TOUCH_STATE_AREA;
}
diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c
index 80aa89ff..93581f4d 100644
--- a/src/evdev-mt-touchpad-gestures.c
+++ b/src/evdev-mt-touchpad-gestures.c
@@ -33,13 +33,14 @@
#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT ms2us(500)
static inline const char*
-gesture_state_to_str(enum tp_gesture_2fg_state state)
+gesture_state_to_str(enum tp_gesture_state state)
{
switch (state) {
- CASE_RETURN_STRING(GESTURE_2FG_STATE_NONE);
- CASE_RETURN_STRING(GESTURE_2FG_STATE_UNKNOWN);
- CASE_RETURN_STRING(GESTURE_2FG_STATE_SCROLL);
- CASE_RETURN_STRING(GESTURE_2FG_STATE_PINCH);
+ CASE_RETURN_STRING(GESTURE_STATE_NONE);
+ CASE_RETURN_STRING(GESTURE_STATE_UNKNOWN);
+ CASE_RETURN_STRING(GESTURE_STATE_SCROLL);
+ CASE_RETURN_STRING(GESTURE_STATE_PINCH);
+ CASE_RETURN_STRING(GESTURE_STATE_SWIPE);
}
return NULL;
}
@@ -94,33 +95,30 @@ tp_gesture_start(struct tp_dispatch *tp, uint64_t time)
if (tp->gesture.started)
return;
- switch (tp->gesture.finger_count) {
- case 2:
- switch (tp->gesture.twofinger_state) {
- case GESTURE_2FG_STATE_NONE:
- case GESTURE_2FG_STATE_UNKNOWN:
- log_bug_libinput(libinput,
- "%s in unknown gesture mode\n",
- __func__);
- break;
- case GESTURE_2FG_STATE_SCROLL:
- /* NOP */
- break;
- case GESTURE_2FG_STATE_PINCH:
- gesture_notify_pinch(&tp->device->base, time,
- LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
- &zero, &zero, 1.0, 0.0);
- break;
- }
+ switch (tp->gesture.state) {
+ case GESTURE_STATE_NONE:
+ case GESTURE_STATE_UNKNOWN:
+ log_bug_libinput(libinput,
+ "%s in unknown gesture mode\n",
+ __func__);
break;
- case 3:
- case 4:
+ case GESTURE_STATE_SCROLL:
+ /* NOP */
+ break;
+ case GESTURE_STATE_PINCH:
+ gesture_notify_pinch(&tp->device->base, time,
+ LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
+ tp->gesture.finger_count,
+ &zero, &zero, 1.0, 0.0);
+ break;
+ case GESTURE_STATE_SWIPE:
gesture_notify_swipe(&tp->device->base, time,
LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
tp->gesture.finger_count,
&zero, &zero);
break;
}
+
tp->gesture.started = true;
}
@@ -148,7 +146,7 @@ tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
}
static unsigned int
-tp_gesture_get_active_touches(struct tp_dispatch *tp,
+tp_gesture_get_active_touches(const struct tp_dispatch *tp,
struct tp_touch **touches,
unsigned int count)
{
@@ -245,83 +243,146 @@ tp_gesture_set_scroll_buildup(struct tp_dispatch *tp)
tp->device->scroll.buildup = tp_normalize_delta(tp, average);
}
-static enum tp_gesture_2fg_state
-tp_gesture_twofinger_handle_state_none(struct tp_dispatch *tp, uint64_t time)
+static enum tp_gesture_state
+tp_gesture_handle_state_none(struct tp_dispatch *tp, uint64_t time)
{
struct tp_touch *first, *second;
+ struct tp_touch *touches[4];
+ unsigned int ntouches;
+ unsigned int i;
+
+ ntouches = tp_gesture_get_active_touches(tp, touches, 4);
+ if (ntouches < 2)
+ return GESTURE_STATE_NONE;
+
+ first = touches[0];
+ second = touches[1];
+
+ /* For 3+ finger gestures we cheat. A human hand's finger
+ * arrangement means that for a 3 or 4 finger swipe gesture, the
+ * fingers are roughly arranged in a horizontal line.
+ * They will all move in the same direction, so we can simply look
+ * at the left and right-most ones only. If we have fake touches, we
+ * just take the left/right-most real touch position, since the fake
+ * touch has the same location as one of those.
+ *
+ * For a 3 or 4 finger pinch gesture, 2 or 3 fingers are roughly in
+ * a horizontal line, with the thumb below and left (right-handed
+ * users) or right (left-handed users). Again, the row of non-thumb
+ * fingers moves identically so we can look at the left and
+ * right-most only and then treat it like a two-finger
+ * gesture.
+ */
+ if (ntouches > 2) {
+ second = touches[0];
+
+ for (i = 1; i < ntouches && i < tp->num_slots; i++) {
+ if (touches[i]->point.x < first->point.x)
+ first = touches[i];
+ else if (touches[i]->point.x > second->point.x)
+ second = touches[i];
+ }
- if (tp_gesture_get_active_touches(tp, tp->gesture.touches, 2) != 2)
- return GESTURE_2FG_STATE_NONE;
-
- first = tp->gesture.touches[0];
- second = tp->gesture.touches[1];
+ if (first == second)
+ return GESTURE_STATE_NONE;
+ }
tp->gesture.initial_time = time;
first->gesture.initial = first->point;
second->gesture.initial = second->point;
+ tp->gesture.touches[0] = first;
+ tp->gesture.touches[1] = second;
+
+ return GESTURE_STATE_UNKNOWN;
+}
+
+static inline int
+tp_gesture_same_directions(int dir1, int dir2)
+{
+ /*
+ * In some cases (semi-mt touchpads) we may seen one finger move
+ * e.g. N/NE and the other W/NW so we not only check for overlapping
+ * directions, but also for neighboring bits being set.
+ * The ((dira & 0x80) && (dirb & 0x01)) checks are to check for bit 0
+ * and 7 being set as they also represent neighboring directions.
+ */
+ return ((dir1 | (dir1 >> 1)) & dir2) ||
+ ((dir2 | (dir2 >> 1)) & dir1) ||
+ ((dir1 & 0x80) && (dir2 & 0x01)) ||
+ ((dir2 & 0x80) && (dir1 & 0x01));
+}
- return GESTURE_2FG_STATE_UNKNOWN;
+static inline void
+tp_gesture_init_pinch( struct tp_dispatch *tp)
+{
+ tp_gesture_get_pinch_info(tp,
+ &tp->gesture.initial_distance,
+ &tp->gesture.angle,
+ &tp->gesture.center);
+ tp->gesture.prev_scale = 1.0;
}
-static enum tp_gesture_2fg_state
-tp_gesture_twofinger_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
+static enum tp_gesture_state
+tp_gesture_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
{
struct tp_touch *first = tp->gesture.touches[0],
*second = tp->gesture.touches[1];
int dir1, dir2;
+ int yres = tp->device->abs.absinfo_y->resolution;
+ int vert_distance;
- /* if fingers stay unmoving for a while, assume (slow) scroll */
- if (time > (tp->gesture.initial_time + DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT)) {
+ /* for two-finger gestures, if the fingers stay unmoving for a
+ * while, assume (slow) scroll */
+ if (tp->gesture.finger_count == 2 &&
+ time > (tp->gesture.initial_time + DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT)) {
tp_gesture_set_scroll_buildup(tp);
- return GESTURE_2FG_STATE_SCROLL;
+ return GESTURE_STATE_SCROLL;
+ }
+
+ /* Else check if one finger is > 20mm below the others */
+ vert_distance = abs(first->point.y - second->point.y);
+ if (vert_distance > 20 * yres &&
+ tp->gesture.enabled) {
+ tp_gesture_init_pinch(tp);
+ return GESTURE_STATE_PINCH;
}
/* Else wait for both fingers to have moved */
dir1 = tp_gesture_get_direction(tp, first);
dir2 = tp_gesture_get_direction(tp, second);
if (dir1 == UNDEFINED_DIRECTION || dir2 == UNDEFINED_DIRECTION)
- return GESTURE_2FG_STATE_UNKNOWN;
-
- /*
- * If both touches are moving in the same direction assume scroll.
- *
- * In some cases (semi-mt touchpads) We may seen one finger move
- * e.g. N/NE and the other W/NW so we not only check for overlapping
- * directions, but also for neighboring bits being set.
- * The ((dira & 0x80) && (dirb & 0x01)) checks are to check for bit 0
- * and 7 being set as they also represent neighboring directions.
- */
- if (((dir1 | (dir1 >> 1)) & dir2) ||
- ((dir2 | (dir2 >> 1)) & dir1) ||
- ((dir1 & 0x80) && (dir2 & 0x01)) ||
- ((dir2 & 0x80) && (dir1 & 0x01))) {
- tp_gesture_set_scroll_buildup(tp);
- return GESTURE_2FG_STATE_SCROLL;
+ return GESTURE_STATE_UNKNOWN;
+
+ /* If both touches are moving in the same direction assume
+ * scroll or swipe */
+ if (tp_gesture_same_directions(dir1, dir2)) {
+ if (tp->gesture.finger_count == 2) {
+ tp_gesture_set_scroll_buildup(tp);
+ return GESTURE_STATE_SCROLL;
+ } else if (tp->gesture.enabled) {
+ return GESTURE_STATE_SWIPE;
+ }
} else if (tp->gesture.enabled) {
- tp_gesture_get_pinch_info(tp,
- &tp->gesture.initial_distance,
- &tp->gesture.angle,
- &tp->gesture.center);
- tp->gesture.prev_scale = 1.0;
- return GESTURE_2FG_STATE_PINCH;
+ tp_gesture_init_pinch(tp);
+ return GESTURE_STATE_PINCH;
}
- return GESTURE_2FG_STATE_UNKNOWN;
+ return GESTURE_STATE_UNKNOWN;
}
-static enum tp_gesture_2fg_state
-tp_gesture_twofinger_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
+static enum tp_gesture_state
+tp_gesture_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
{
struct normalized_coords delta;
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
- return GESTURE_2FG_STATE_SCROLL;
+ return GESTURE_STATE_SCROLL;
/* On some semi-mt models slot 0 is more accurate, so for semi-mt
* we only use slot 0. */
if (tp->semi_mt) {
if (!tp->touches[0].dirty)
- return GESTURE_2FG_STATE_SCROLL;
+ return GESTURE_STATE_SCROLL;
delta = tp_get_delta(&tp->touches[0]);
} else {
@@ -332,7 +393,7 @@ tp_gesture_twofinger_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
delta = tp_filter_motion_unaccelerated(tp, &delta, time);
if (normalized_is_zero(delta))
- return GESTURE_2FG_STATE_SCROLL;
+ return GESTURE_STATE_SCROLL;
tp_gesture_start(tp, time);
evdev_post_scroll(tp->device,
@@ -340,11 +401,30 @@ tp_gesture_twofinger_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
&delta);
- return GESTURE_2FG_STATE_SCROLL;
+ return GESTURE_STATE_SCROLL;
+}
+
+static enum tp_gesture_state
+tp_gesture_handle_state_swipe(struct tp_dispatch *tp, uint64_t time)
+{
+ struct normalized_coords delta, unaccel;
+
+ unaccel = tp_get_average_touches_delta(tp);
+ delta = tp_filter_motion(tp, &unaccel, time);
+
+ if (!normalized_is_zero(delta) || !normalized_is_zero(unaccel)) {
+ tp_gesture_start(tp, time);
+ gesture_notify_swipe(&tp->device->base, time,
+ LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
+ tp->gesture.finger_count,
+ &delta, &unaccel);
+ }
+
+ return GESTURE_STATE_SWIPE;
}
-static enum tp_gesture_2fg_state
-tp_gesture_twofinger_handle_state_pinch(struct tp_dispatch *tp, uint64_t time)
+static enum tp_gesture_state
+tp_gesture_handle_state_pinch(struct tp_dispatch *tp, uint64_t time)
{
double angle, angle_delta, distance, scale;
struct device_float_coords center, fdelta;
@@ -368,60 +448,48 @@ tp_gesture_twofinger_handle_state_pinch(struct tp_dispatch *tp, uint64_t time)
if (normalized_is_zero(delta) && normalized_is_zero(unaccel) &&
scale == tp->gesture.prev_scale && angle_delta == 0.0)
- return GESTURE_2FG_STATE_PINCH;
+ return GESTURE_STATE_PINCH;
tp_gesture_start(tp, time);
gesture_notify_pinch(&tp->device->base, time,
LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
+ tp->gesture.finger_count,
&delta, &unaccel, scale, angle_delta);
tp->gesture.prev_scale = scale;
- return GESTURE_2FG_STATE_PINCH;
+ return GESTURE_STATE_PINCH;
}
static void
-tp_gesture_post_twofinger(struct tp_dispatch *tp, uint64_t time)
+tp_gesture_post_gesture(struct tp_dispatch *tp, uint64_t time)
{
- enum tp_gesture_2fg_state oldstate = tp->gesture.twofinger_state;
+ enum tp_gesture_state oldstate = tp->gesture.state;
- if (tp->gesture.twofinger_state == GESTURE_2FG_STATE_NONE)
- tp->gesture.twofinger_state =
- tp_gesture_twofinger_handle_state_none(tp, time);
+ if (tp->gesture.state == GESTURE_STATE_NONE)
+ tp->gesture.state =
+ tp_gesture_handle_state_none(tp, time);
- if (tp->gesture.twofinger_state == GESTURE_2FG_STATE_UNKNOWN)
- tp->gesture.twofinger_state =
- tp_gesture_twofinger_handle_state_unknown(tp, time);
+ if (tp->gesture.state == GESTURE_STATE_UNKNOWN)
+ tp->gesture.state =
+ tp_gesture_handle_state_unknown(tp, time);
- if (tp->gesture.twofinger_state == GESTURE_2FG_STATE_SCROLL)
- tp->gesture.twofinger_state =
- tp_gesture_twofinger_handle_state_scroll(tp, time);
+ if (tp->gesture.state == GESTURE_STATE_SCROLL)
+ tp->gesture.state =
+ tp_gesture_handle_state_scroll(tp, time);
- if (tp->gesture.twofinger_state == GESTURE_2FG_STATE_PINCH)
- tp->gesture.twofinger_state =
- tp_gesture_twofinger_handle_state_pinch(tp, time);
+ if (tp->gesture.state == GESTURE_STATE_SWIPE)
+ tp->gesture.state =
+ tp_gesture_handle_state_swipe(tp, time);
+
+ if (tp->gesture.state == GESTURE_STATE_PINCH)
+ tp->gesture.state =
+ tp_gesture_handle_state_pinch(tp, time);
log_debug(tp_libinput_context(tp),
"gesture state: %s → %s\n",
gesture_state_to_str(oldstate),
- gesture_state_to_str(tp->gesture.twofinger_state));
-}
-
-static void
-tp_gesture_post_swipe(struct tp_dispatch *tp, uint64_t time)
-{
- struct normalized_coords delta, unaccel;
-
- unaccel = tp_get_average_touches_delta(tp);
- delta = tp_filter_motion(tp, &unaccel, time);
-
- if (!normalized_is_zero(delta) || !normalized_is_zero(unaccel)) {
- tp_gesture_start(tp, time);
- gesture_notify_swipe(&tp->device->base, time,
- LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
- tp->gesture.finger_count,
- &delta, &unaccel);
- }
+ gesture_state_to_str(tp->gesture.state));
}
void
@@ -446,11 +514,9 @@ tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time)
tp_gesture_post_pointer_motion(tp, time);
break;
case 2:
- tp_gesture_post_twofinger(tp, time);
- break;
case 3:
case 4:
- tp_gesture_post_swipe(tp, time);
+ tp_gesture_post_gesture(tp, time);
break;
}
}
@@ -470,38 +536,37 @@ static void
tp_gesture_end(struct tp_dispatch *tp, uint64_t time, bool cancelled)
{
struct libinput *libinput = tp->device->base.seat->libinput;
- enum tp_gesture_2fg_state twofinger_state = tp->gesture.twofinger_state;
+ enum tp_gesture_state state = tp->gesture.state;
- tp->gesture.twofinger_state = GESTURE_2FG_STATE_NONE;
+ tp->gesture.state = GESTURE_STATE_NONE;
if (!tp->gesture.started)
return;
- switch (tp->gesture.finger_count) {
- case 2:
- switch (twofinger_state) {
- case GESTURE_2FG_STATE_NONE:
- case GESTURE_2FG_STATE_UNKNOWN:
- log_bug_libinput(libinput,
- "%s in unknown gesture mode\n",
- __func__);
- break;
- case GESTURE_2FG_STATE_SCROLL:
- tp_gesture_stop_twofinger_scroll(tp, time);
- break;
- case GESTURE_2FG_STATE_PINCH:
- gesture_notify_pinch_end(&tp->device->base, time,
- tp->gesture.prev_scale,
- cancelled);
- break;
- }
+ switch (state) {
+ case GESTURE_STATE_NONE:
+ case GESTURE_STATE_UNKNOWN:
+ log_bug_libinput(libinput,
+ "%s in unknown gesture mode\n",
+ __func__);
break;
- case 3:
- case 4:
- gesture_notify_swipe_end(&tp->device->base, time,
- tp->gesture.finger_count, cancelled);
+ case GESTURE_STATE_SCROLL:
+ tp_gesture_stop_twofinger_scroll(tp, time);
+ break;
+ case GESTURE_STATE_PINCH:
+ gesture_notify_pinch_end(&tp->device->base, time,
+ tp->gesture.finger_count,
+ tp->gesture.prev_scale,
+ cancelled);
+ break;
+ case GESTURE_STATE_SWIPE:
+ gesture_notify_swipe_end(&tp->device->base,
+ time,
+ tp->gesture.finger_count,
+ cancelled);
break;
}
+
tp->gesture.started = false;
}
@@ -573,7 +638,7 @@ tp_init_gesture(struct tp_dispatch *tp)
else
tp->gesture.enabled = true;
- tp->gesture.twofinger_state = GESTURE_2FG_STATE_NONE;
+ tp->gesture.state = GESTURE_STATE_NONE;
libinput_timer_init(&tp->gesture.finger_count_switch_timer,
tp->device->base.seat->libinput,
diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c
index dda528a8..a4c38a81 100644
--- a/src/evdev-mt-touchpad-tap.c
+++ b/src/evdev-mt-touchpad-tap.c
@@ -1022,7 +1022,7 @@ tp_tap_resume(struct tp_dispatch *tp, uint64_t time)
}
bool
-tp_tap_dragging(struct tp_dispatch *tp)
+tp_tap_dragging(const struct tp_dispatch *tp)
{
switch (tp->tap.state) {
case TAP_STATE_DRAGGING:
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 6f834fb1..aa65ab40 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -140,6 +140,14 @@ tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
static inline unsigned int
tp_fake_finger_count(struct tp_dispatch *tp)
{
+ /* Only one of BTN_TOOL_DOUBLETAP/TRIPLETAP/... may be set at any
+ * time */
+ if (__builtin_popcount(
+ tp->fake_touches & ~(FAKE_FINGER_OVERFLOW|0x1)) > 1)
+ log_bug_kernel(tp->device->base.seat->libinput,
+ "Invalid fake finger state %#x\n",
+ tp->fake_touches);
+
if (tp->fake_touches & FAKE_FINGER_OVERFLOW)
return FAKE_FINGER_OVERFLOW;
else /* don't count BTN_TOUCH */
@@ -510,7 +518,7 @@ tp_pin_fingers(struct tp_dispatch *tp)
}
int
-tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
+tp_touch_active(const struct tp_dispatch *tp, const struct tp_touch *t)
{
return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
t->palm.state == PALM_NONE &&
@@ -521,7 +529,7 @@ tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
}
bool
-tp_palm_tap_is_palm(struct tp_dispatch *tp, struct tp_touch *t)
+tp_palm_tap_is_palm(const struct tp_dispatch *tp, const struct tp_touch *t)
{
if (t->state != TOUCH_BEGIN)
return false;
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index eb6702d3..174fed6a 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -130,11 +130,12 @@ enum tp_edge_scroll_touch_state {
EDGE_SCROLL_TOUCH_STATE_AREA,
};
-enum tp_gesture_2fg_state {
- GESTURE_2FG_STATE_NONE,
- GESTURE_2FG_STATE_UNKNOWN,
- GESTURE_2FG_STATE_SCROLL,
- GESTURE_2FG_STATE_PINCH,
+enum tp_gesture_state {
+ GESTURE_STATE_NONE,
+ GESTURE_STATE_UNKNOWN,
+ GESTURE_STATE_SCROLL,
+ GESTURE_STATE_PINCH,
+ GESTURE_STATE_SWIPE,
};
enum tp_thumb_state {
@@ -251,7 +252,7 @@ struct tp_dispatch {
unsigned int finger_count;
unsigned int finger_count_pending;
struct libinput_timer finger_count_switch_timer;
- enum tp_gesture_2fg_state twofinger_state;
+ enum tp_gesture_state state;
struct tp_touch *touches[2];
uint64_t initial_time;
double initial_distance;
@@ -357,7 +358,7 @@ struct tp_dispatch {
for (unsigned int _i = 0; _i < (_tp)->ntouches && (_t = &(_tp)->touches[_i]); _i++)
static inline struct libinput*
-tp_libinput_context(struct tp_dispatch *tp)
+tp_libinput_context(const struct tp_dispatch *tp)
{
return tp->device->base.seat->libinput;
}
@@ -402,7 +403,7 @@ tp_filter_motion_unaccelerated(struct tp_dispatch *tp,
uint64_t time);
int
-tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t);
+tp_touch_active(const struct tp_dispatch *tp, const struct tp_touch *t);
int
tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time);
@@ -440,10 +441,12 @@ int
tp_button_handle_state(struct tp_dispatch *tp, uint64_t time);
int
-tp_button_touch_active(struct tp_dispatch *tp, struct tp_touch *t);
+tp_button_touch_active(const struct tp_dispatch *tp,
+ const struct tp_touch *t);
bool
-tp_button_is_inside_softbutton_area(struct tp_dispatch *tp, struct tp_touch *t);
+tp_button_is_inside_softbutton_area(const struct tp_dispatch *tp,
+ const struct tp_touch *t);
void
tp_release_all_taps(struct tp_dispatch *tp,
@@ -456,7 +459,7 @@ void
tp_tap_resume(struct tp_dispatch *tp, uint64_t time);
bool
-tp_tap_dragging(struct tp_dispatch *tp);
+tp_tap_dragging(const struct tp_dispatch *tp);
int
tp_edge_scroll_init(struct tp_dispatch *tp, struct evdev_device *device);
@@ -474,10 +477,11 @@ void
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);
+tp_edge_scroll_touch_active(const struct tp_dispatch *tp,
+ const struct tp_touch *t);
uint32_t
-tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *t);
+tp_touch_get_edge(const struct tp_dispatch *tp, const struct tp_touch *t);
int
tp_init_gesture(struct tp_dispatch *tp);
@@ -501,6 +505,6 @@ void
tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time);
bool
-tp_palm_tap_is_palm(struct tp_dispatch *tp, struct tp_touch *t);
+tp_palm_tap_is_palm(const struct tp_dispatch *tp, const struct tp_touch *t);
#endif
diff --git a/src/libinput-private.h b/src/libinput-private.h
index e146c260..efffe35c 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -429,6 +429,7 @@ void
gesture_notify_pinch(struct libinput_device *device,
uint64_t time,
enum libinput_event_type type,
+ int finger_count,
const struct normalized_coords *delta,
const struct normalized_coords *unaccel,
double scale,
@@ -437,6 +438,7 @@ gesture_notify_pinch(struct libinput_device *device,
void
gesture_notify_pinch_end(struct libinput_device *device,
uint64_t time,
+ int finger_count,
double scale,
int cancelled);
diff --git a/src/libinput.c b/src/libinput.c
index 24f2b693..756edfad 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -1673,25 +1673,27 @@ void
gesture_notify_pinch(struct libinput_device *device,
uint64_t time,
enum libinput_event_type type,
+ int finger_count,
const struct normalized_coords *delta,
const struct normalized_coords *unaccel,
double scale,
double angle)
{
- gesture_notify(device, time, type, 2, 0, delta, unaccel,
- scale, angle);
+ gesture_notify(device, time, type, finger_count, 0,
+ delta, unaccel, scale, angle);
}
void
gesture_notify_pinch_end(struct libinput_device *device,
uint64_t time,
+ int finger_count,
double scale,
int cancelled)
{
const struct normalized_coords zero = { 0.0, 0.0 };
gesture_notify(device, time, LIBINPUT_EVENT_GESTURE_PINCH_END,
- 2, cancelled, &zero, &zero, scale, 0.0);
+ finger_count, cancelled, &zero, &zero, scale, 0.0);
}
static void