1 /*
2 * Copyright © 2015 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "config.h"
25
26 #include <math.h>
27 #include <stdbool.h>
28 #include <limits.h>
29
30 #include "evdev-mt-touchpad.h"
31
32 #define DEFAULT_GESTURE_SWITCH_TIMEOUT ms2us(100)
33 #define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT ms2us(150)
34 #define DEFAULT_GESTURE_2FG_PINCH_TIMEOUT ms2us(75)
35
36 static inline const char*
gesture_state_to_str(enum tp_gesture_state state)37 gesture_state_to_str(enum tp_gesture_state state)
38 {
39 switch (state) {
40 CASE_RETURN_STRING(GESTURE_STATE_NONE);
41 CASE_RETURN_STRING(GESTURE_STATE_UNKNOWN);
42 CASE_RETURN_STRING(GESTURE_STATE_SCROLL);
43 CASE_RETURN_STRING(GESTURE_STATE_PINCH);
44 CASE_RETURN_STRING(GESTURE_STATE_SWIPE);
45 }
46 return NULL;
47 }
48
49 static struct device_float_coords
tp_get_touches_delta(struct tp_dispatch * tp,bool average)50 tp_get_touches_delta(struct tp_dispatch *tp, bool average)
51 {
52 struct tp_touch *t;
53 unsigned int i, nactive = 0;
54 struct device_float_coords delta = {0.0, 0.0};
55
56 for (i = 0; i < tp->num_slots; i++) {
57 t = &tp->touches[i];
58
59 if (!tp_touch_active(tp, t))
60 continue;
61
62 nactive++;
63
64 if (t->dirty) {
65 struct device_coords d;
66
67 d = tp_get_delta(t);
68
69 delta.x += d.x;
70 delta.y += d.y;
71 }
72 }
73
74 if (!average || nactive == 0)
75 return delta;
76
77 delta.x /= nactive;
78 delta.y /= nactive;
79
80 return delta;
81 }
82
83 static void
tp_gesture_init_scroll(struct tp_dispatch * tp)84 tp_gesture_init_scroll(struct tp_dispatch *tp)
85 {
86 struct phys_coords zero = {0.0, 0.0};
87 tp->scroll.active.h = false;
88 tp->scroll.active.v = false;
89 tp->scroll.duration.h = 0;
90 tp->scroll.duration.v = 0;
91 tp->scroll.vector = zero;
92 tp->scroll.time_prev = 0;
93 }
94
95 static inline struct device_float_coords
tp_get_combined_touches_delta(struct tp_dispatch * tp)96 tp_get_combined_touches_delta(struct tp_dispatch *tp)
97 {
98 return tp_get_touches_delta(tp, false);
99 }
100
101 static inline struct device_float_coords
tp_get_average_touches_delta(struct tp_dispatch * tp)102 tp_get_average_touches_delta(struct tp_dispatch *tp)
103 {
104 return tp_get_touches_delta(tp, true);
105 }
106
107 static void
tp_gesture_start(struct tp_dispatch * tp,uint64_t time)108 tp_gesture_start(struct tp_dispatch *tp, uint64_t time)
109 {
110 const struct normalized_coords zero = { 0.0, 0.0 };
111
112 if (tp->gesture.started)
113 return;
114
115 switch (tp->gesture.state) {
116 case GESTURE_STATE_NONE:
117 case GESTURE_STATE_UNKNOWN:
118 evdev_log_bug_libinput(tp->device,
119 "%s in unknown gesture mode\n",
120 __func__);
121 break;
122 case GESTURE_STATE_SCROLL:
123 tp_gesture_init_scroll(tp);
124 break;
125 case GESTURE_STATE_PINCH:
126 gesture_notify_pinch(&tp->device->base, time,
127 LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
128 tp->gesture.finger_count,
129 &zero, &zero, 1.0, 0.0);
130 break;
131 case GESTURE_STATE_SWIPE:
132 gesture_notify_swipe(&tp->device->base, time,
133 LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
134 tp->gesture.finger_count,
135 &zero, &zero);
136 break;
137 }
138
139 tp->gesture.started = true;
140 }
141
142 static void
tp_gesture_post_pointer_motion(struct tp_dispatch * tp,uint64_t time)143 tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
144 {
145 struct device_float_coords raw;
146 struct normalized_coords delta;
147
148 /* When a clickpad is clicked, combine motion of all active touches */
149 if (tp->buttons.is_clickpad && tp->buttons.state)
150 raw = tp_get_combined_touches_delta(tp);
151 else
152 raw = tp_get_average_touches_delta(tp);
153
154 delta = tp_filter_motion(tp, &raw, time);
155
156 if (!normalized_is_zero(delta) || !device_float_is_zero(raw)) {
157 struct device_float_coords unaccel;
158
159 unaccel = tp_scale_to_xaxis(tp, raw);
160 pointer_notify_motion(&tp->device->base,
161 time,
162 &delta,
163 &unaccel);
164 }
165 }
166
167 static unsigned int
tp_gesture_get_active_touches(const struct tp_dispatch * tp,struct tp_touch ** touches,unsigned int count)168 tp_gesture_get_active_touches(const struct tp_dispatch *tp,
169 struct tp_touch **touches,
170 unsigned int count)
171 {
172 unsigned int n = 0;
173 struct tp_touch *t;
174
175 memset(touches, 0, count * sizeof(struct tp_touch *));
176
177 tp_for_each_touch(tp, t) {
178 if (tp_touch_active(tp, t)) {
179 touches[n++] = t;
180 if (n == count)
181 return count;
182 }
183 }
184
185 /*
186 * This can happen when the user does .e.g:
187 * 1) Put down 1st finger in center (so active)
188 * 2) Put down 2nd finger in a button area (so inactive)
189 * 3) Put down 3th finger somewhere, gets reported as a fake finger,
190 * so gets same coordinates as 1st -> active
191 *
192 * We could avoid this by looking at all touches, be we really only
193 * want to look at real touches.
194 */
195 return n;
196 }
197
198 static uint32_t
tp_gesture_get_direction(struct tp_dispatch * tp,struct tp_touch * touch,unsigned int nfingers)199 tp_gesture_get_direction(struct tp_dispatch *tp, struct tp_touch *touch,
200 unsigned int nfingers)
201 {
202 struct phys_coords mm;
203 struct device_float_coords delta;
204 double move_threshold = 1.0; /* mm */
205
206 move_threshold *= (nfingers - 1);
207
208 delta = device_delta(touch->point, touch->gesture.initial);
209 mm = tp_phys_delta(tp, delta);
210
211 if (length_in_mm(mm) < move_threshold)
212 return UNDEFINED_DIRECTION;
213
214 return phys_get_direction(mm);
215 }
216
217 static void
tp_gesture_get_pinch_info(struct tp_dispatch * tp,double * distance,double * angle,struct device_float_coords * center)218 tp_gesture_get_pinch_info(struct tp_dispatch *tp,
219 double *distance,
220 double *angle,
221 struct device_float_coords *center)
222 {
223 struct normalized_coords normalized;
224 struct device_float_coords delta;
225 struct tp_touch *first = tp->gesture.touches[0],
226 *second = tp->gesture.touches[1];
227
228 delta = device_delta(first->point, second->point);
229 normalized = tp_normalize_delta(tp, delta);
230 *distance = normalized_length(normalized);
231 *angle = atan2(normalized.y, normalized.x) * 180.0 / M_PI;
232
233 *center = device_average(first->point, second->point);
234 }
235
236 static void
tp_gesture_set_scroll_buildup(struct tp_dispatch * tp)237 tp_gesture_set_scroll_buildup(struct tp_dispatch *tp)
238 {
239 struct device_float_coords d0, d1;
240 struct device_float_coords average;
241 struct tp_touch *first = tp->gesture.touches[0],
242 *second = tp->gesture.touches[1];
243
244 d0 = device_delta(first->point, first->gesture.initial);
245 d1 = device_delta(second->point, second->gesture.initial);
246
247 average = device_float_average(d0, d1);
248 tp->device->scroll.buildup = tp_normalize_delta(tp, average);
249 }
250
251 static void
tp_gesture_apply_scroll_constraints(struct tp_dispatch * tp,struct device_float_coords * raw,struct normalized_coords * delta,uint64_t time)252 tp_gesture_apply_scroll_constraints(struct tp_dispatch *tp,
253 struct device_float_coords *raw,
254 struct normalized_coords *delta,
255 uint64_t time)
256 {
257 uint64_t tdelta = 0;
258 struct phys_coords delta_mm, vector;
259 double vector_decay, vector_length, slope;
260
261 const uint64_t ACTIVE_THRESHOLD = ms2us(100),
262 INACTIVE_THRESHOLD = ms2us(50),
263 EVENT_TIMEOUT = ms2us(100);
264
265 /* Both axes active == true means free scrolling is enabled */
266 if (tp->scroll.active.h && tp->scroll.active.v)
267 return;
268
269 /* Determine time delta since last movement event */
270 if (tp->scroll.time_prev != 0)
271 tdelta = time - tp->scroll.time_prev;
272 if (tdelta > EVENT_TIMEOUT)
273 tdelta = 0;
274 tp->scroll.time_prev = time;
275
276 /* Delta since last movement event in mm */
277 delta_mm = tp_phys_delta(tp, *raw);
278
279 /* Old vector data "fades" over time. This is a two-part linear
280 * approximation of an exponential function - for example, for
281 * EVENT_TIMEOUT of 100, vector_decay = (0.97)^tdelta. This linear
282 * approximation allows easier tweaking of EVENT_TIMEOUT and is faster.
283 */
284 if (tdelta > 0) {
285 double recent, later;
286 recent = ((EVENT_TIMEOUT / 2.0) - tdelta) /
287 (EVENT_TIMEOUT / 2.0);
288 later = (EVENT_TIMEOUT - tdelta) /
289 (EVENT_TIMEOUT * 2.0);
290 vector_decay = tdelta <= (0.33 * EVENT_TIMEOUT) ?
291 recent : later;
292 } else {
293 vector_decay = 0.0;
294 }
295
296 /* Calculate windowed vector from delta + weighted historic data */
297 vector.x = (tp->scroll.vector.x * vector_decay) + delta_mm.x;
298 vector.y = (tp->scroll.vector.y * vector_decay) + delta_mm.y;
299 vector_length = hypot(vector.x, vector.y);
300 tp->scroll.vector = vector;
301
302 /* We care somewhat about distance and speed, but more about
303 * consistency of direction over time. Keep track of the time spent
304 * primarily along each axis. If one axis is active, time spent NOT
305 * moving much in the other axis is subtracted, allowing a switch of
306 * axes in a single scroll + ability to "break out" and go diagonal.
307 *
308 * Slope to degree conversions (infinity = 90°, 0 = 0°):
309 */
310 const double DEGREE_75 = 3.73;
311 const double DEGREE_60 = 1.73;
312 const double DEGREE_30 = 0.57;
313 const double DEGREE_15 = 0.27;
314 slope = (vector.x != 0) ? fabs(vector.y / vector.x) : INFINITY;
315
316 /* Ensure vector is big enough (in mm per EVENT_TIMEOUT) to be confident
317 * of direction. Larger = harder to enable diagonal/free scrolling.
318 */
319 const double MIN_VECTOR = 0.15;
320
321 if (slope >= DEGREE_30 && vector_length > MIN_VECTOR) {
322 tp->scroll.duration.v += tdelta;
323 if (tp->scroll.duration.v > ACTIVE_THRESHOLD)
324 tp->scroll.duration.v = ACTIVE_THRESHOLD;
325 if (slope >= DEGREE_75) {
326 if (tp->scroll.duration.h > tdelta)
327 tp->scroll.duration.h -= tdelta;
328 else
329 tp->scroll.duration.h = 0;
330 }
331 }
332 if (slope < DEGREE_60 && vector_length > MIN_VECTOR) {
333 tp->scroll.duration.h += tdelta;
334 if (tp->scroll.duration.h > ACTIVE_THRESHOLD)
335 tp->scroll.duration.h = ACTIVE_THRESHOLD;
336 if (slope < DEGREE_15) {
337 if (tp->scroll.duration.v > tdelta)
338 tp->scroll.duration.v -= tdelta;
339 else
340 tp->scroll.duration.v = 0;
341 }
342 }
343
344 if (tp->scroll.duration.h == ACTIVE_THRESHOLD) {
345 tp->scroll.active.h = true;
346 if (tp->scroll.duration.v < INACTIVE_THRESHOLD)
347 tp->scroll.active.v = false;
348 }
349 if (tp->scroll.duration.v == ACTIVE_THRESHOLD) {
350 tp->scroll.active.v = true;
351 if (tp->scroll.duration.h < INACTIVE_THRESHOLD)
352 tp->scroll.active.h = false;
353 }
354
355 /* If vector is big enough in a diagonal direction, always unlock
356 * both axes regardless of thresholds
357 */
358 if (vector_length > 5.0 && slope < 1.73 && slope >= 0.57) {
359 tp->scroll.active.v = true;
360 tp->scroll.active.h = true;
361 }
362
363 /* If only one axis is active, constrain motion accordingly. If both
364 * are set, we've detected deliberate diagonal movement; enable free
365 * scrolling for the life of the gesture.
366 */
367 if (!tp->scroll.active.h && tp->scroll.active.v)
368 delta->x = 0.0;
369 if (tp->scroll.active.h && !tp->scroll.active.v)
370 delta->y = 0.0;
371
372 /* If we haven't determined an axis, use the slope in the meantime */
373 if (!tp->scroll.active.h && !tp->scroll.active.v) {
374 delta->x = (slope >= DEGREE_60) ? 0.0 : delta->x;
375 delta->y = (slope < DEGREE_30) ? 0.0 : delta->y;
376 }
377 }
378
379 static enum tp_gesture_state
tp_gesture_handle_state_none(struct tp_dispatch * tp,uint64_t time)380 tp_gesture_handle_state_none(struct tp_dispatch *tp, uint64_t time)
381 {
382 struct tp_touch *first, *second;
383 struct tp_touch *touches[4];
384 unsigned int ntouches;
385 unsigned int i;
386
387 ntouches = tp_gesture_get_active_touches(tp, touches, 4);
388 if (ntouches < 2)
389 return GESTURE_STATE_NONE;
390
391 if (!tp->gesture.enabled) {
392 if (ntouches == 2)
393 return GESTURE_STATE_SCROLL;
394 else
395 return GESTURE_STATE_NONE;
396 }
397
398 first = touches[0];
399 second = touches[1];
400
401 /* For 3+ finger gestures we cheat. A human hand's finger
402 * arrangement means that for a 3 or 4 finger swipe gesture, the
403 * fingers are roughly arranged in a horizontal line.
404 * They will all move in the same direction, so we can simply look
405 * at the left and right-most ones only. If we have fake touches, we
406 * just take the left/right-most real touch position, since the fake
407 * touch has the same location as one of those.
408 *
409 * For a 3 or 4 finger pinch gesture, 2 or 3 fingers are roughly in
410 * a horizontal line, with the thumb below and left (right-handed
411 * users) or right (left-handed users). Again, the row of non-thumb
412 * fingers moves identically so we can look at the left and
413 * right-most only and then treat it like a two-finger
414 * gesture.
415 */
416 if (ntouches > 2) {
417 second = touches[0];
418
419 for (i = 1; i < ntouches && i < tp->num_slots; i++) {
420 if (touches[i]->point.x < first->point.x)
421 first = touches[i];
422 else if (touches[i]->point.x > second->point.x)
423 second = touches[i];
424 }
425
426 if (first == second)
427 return GESTURE_STATE_NONE;
428
429 }
430
431 tp->gesture.initial_time = time;
432 first->gesture.initial = first->point;
433 second->gesture.initial = second->point;
434 tp->gesture.touches[0] = first;
435 tp->gesture.touches[1] = second;
436
437 return GESTURE_STATE_UNKNOWN;
438 }
439
440 static inline int
tp_gesture_same_directions(int dir1,int dir2)441 tp_gesture_same_directions(int dir1, int dir2)
442 {
443 /*
444 * In some cases (semi-mt touchpads) we may seen one finger move
445 * e.g. N/NE and the other W/NW so we not only check for overlapping
446 * directions, but also for neighboring bits being set.
447 * The ((dira & 0x80) && (dirb & 0x01)) checks are to check for bit 0
448 * and 7 being set as they also represent neighboring directions.
449 */
450 return ((dir1 | (dir1 >> 1)) & dir2) ||
451 ((dir2 | (dir2 >> 1)) & dir1) ||
452 ((dir1 & 0x80) && (dir2 & 0x01)) ||
453 ((dir2 & 0x80) && (dir1 & 0x01));
454 }
455
456 static inline void
tp_gesture_init_pinch(struct tp_dispatch * tp)457 tp_gesture_init_pinch(struct tp_dispatch *tp)
458 {
459 tp_gesture_get_pinch_info(tp,
460 &tp->gesture.initial_distance,
461 &tp->gesture.angle,
462 &tp->gesture.center);
463 tp->gesture.prev_scale = 1.0;
464 }
465
466 static enum tp_gesture_state
tp_gesture_handle_state_unknown(struct tp_dispatch * tp,uint64_t time)467 tp_gesture_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
468 {
469 struct tp_touch *first = tp->gesture.touches[0],
470 *second = tp->gesture.touches[1];
471 uint32_t dir1, dir2;
472 struct phys_coords mm;
473 int vert_distance, horiz_distance;
474
475 vert_distance = abs(first->point.y - second->point.y);
476 horiz_distance = abs(first->point.x - second->point.x);
477
478 if (time > (tp->gesture.initial_time + DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT)) {
479 /* for two-finger gestures, if the fingers stay unmoving for a
480 * while, assume (slow) scroll */
481 if (tp->gesture.finger_count == 2) {
482 tp_gesture_set_scroll_buildup(tp);
483 return GESTURE_STATE_SCROLL;
484 /* more fingers than slots, don't bother with pinch, always
485 * assume swipe */
486 } else if (tp->gesture.finger_count > tp->num_slots) {
487 return GESTURE_STATE_SWIPE;
488 }
489
490 /* for 3+ finger gestures, check if one finger is > 20mm
491 below the others */
492 mm = evdev_convert_xy_to_mm(tp->device,
493 horiz_distance,
494 vert_distance);
495 if (mm.y > 20 && tp->gesture.enabled) {
496 tp_gesture_init_pinch(tp);
497 return GESTURE_STATE_PINCH;
498 } else {
499 return GESTURE_STATE_SWIPE;
500 }
501 }
502
503 if (time > (tp->gesture.initial_time + DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT)) {
504 mm = evdev_convert_xy_to_mm(tp->device, horiz_distance, vert_distance);
505 if (tp->gesture.finger_count == 2 && mm.x > 40 && mm.y > 40)
506 return GESTURE_STATE_PINCH;
507 }
508
509 /* Else wait for both fingers to have moved */
510 dir1 = tp_gesture_get_direction(tp, first, tp->gesture.finger_count);
511 dir2 = tp_gesture_get_direction(tp, second, tp->gesture.finger_count);
512 if (dir1 == UNDEFINED_DIRECTION || dir2 == UNDEFINED_DIRECTION)
513 return GESTURE_STATE_UNKNOWN;
514
515 /* If both touches are moving in the same direction assume
516 * scroll or swipe */
517 if (tp->gesture.finger_count > tp->num_slots ||
518 tp_gesture_same_directions(dir1, dir2)) {
519 if (tp->gesture.finger_count == 2) {
520 tp_gesture_set_scroll_buildup(tp);
521 return GESTURE_STATE_SCROLL;
522 } else if (tp->gesture.enabled) {
523 return GESTURE_STATE_SWIPE;
524 }
525 } else {
526 tp_gesture_init_pinch(tp);
527 return GESTURE_STATE_PINCH;
528 }
529
530 return GESTURE_STATE_UNKNOWN;
531 }
532
533 static enum tp_gesture_state
tp_gesture_handle_state_scroll(struct tp_dispatch * tp,uint64_t time)534 tp_gesture_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
535 {
536 struct device_float_coords raw;
537 struct normalized_coords delta;
538
539 if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
540 return GESTURE_STATE_SCROLL;
541
542 raw = tp_get_average_touches_delta(tp);
543
544 /* scroll is not accelerated */
545 delta = tp_filter_motion_unaccelerated(tp, &raw, time);
546
547 if (normalized_is_zero(delta))
548 return GESTURE_STATE_SCROLL;
549
550 tp_gesture_start(tp, time);
551 tp_gesture_apply_scroll_constraints(tp, &raw, &delta, time);
552 evdev_post_scroll(tp->device,
553 time,
554 LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
555 &delta);
556
557 return GESTURE_STATE_SCROLL;
558 }
559
560 static enum tp_gesture_state
tp_gesture_handle_state_swipe(struct tp_dispatch * tp,uint64_t time)561 tp_gesture_handle_state_swipe(struct tp_dispatch *tp, uint64_t time)
562 {
563 struct device_float_coords raw;
564 struct normalized_coords delta, unaccel;
565
566 raw = tp_get_average_touches_delta(tp);
567 delta = tp_filter_motion(tp, &raw, time);
568
569 if (!normalized_is_zero(delta) || !device_float_is_zero(raw)) {
570 unaccel = tp_normalize_delta(tp, raw);
571 tp_gesture_start(tp, time);
572 gesture_notify_swipe(&tp->device->base, time,
573 LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
574 tp->gesture.finger_count,
575 &delta, &unaccel);
576 }
577
578 return GESTURE_STATE_SWIPE;
579 }
580
581 static enum tp_gesture_state
tp_gesture_handle_state_pinch(struct tp_dispatch * tp,uint64_t time)582 tp_gesture_handle_state_pinch(struct tp_dispatch *tp, uint64_t time)
583 {
584 double angle, angle_delta, distance, scale;
585 struct device_float_coords center, fdelta;
586 struct normalized_coords delta, unaccel;
587
588 tp_gesture_get_pinch_info(tp, &distance, &angle, ¢er);
589
590 scale = distance / tp->gesture.initial_distance;
591
592 angle_delta = angle - tp->gesture.angle;
593 tp->gesture.angle = angle;
594 if (angle_delta > 180.0)
595 angle_delta -= 360.0;
596 else if (angle_delta < -180.0)
597 angle_delta += 360.0;
598
599 fdelta = device_float_delta(center, tp->gesture.center);
600 tp->gesture.center = center;
601
602 delta = tp_filter_motion(tp, &fdelta, time);
603
604 if (normalized_is_zero(delta) && device_float_is_zero(fdelta) &&
605 scale == tp->gesture.prev_scale && angle_delta == 0.0)
606 return GESTURE_STATE_PINCH;
607
608 unaccel = tp_normalize_delta(tp, fdelta);
609 tp_gesture_start(tp, time);
610 gesture_notify_pinch(&tp->device->base, time,
611 LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
612 tp->gesture.finger_count,
613 &delta, &unaccel, scale, angle_delta);
614
615 tp->gesture.prev_scale = scale;
616
617 return GESTURE_STATE_PINCH;
618 }
619
620 static void
tp_gesture_post_gesture(struct tp_dispatch * tp,uint64_t time)621 tp_gesture_post_gesture(struct tp_dispatch *tp, uint64_t time)
622 {
623 enum tp_gesture_state oldstate = tp->gesture.state;
624
625 if (tp->gesture.state == GESTURE_STATE_NONE)
626 tp->gesture.state =
627 tp_gesture_handle_state_none(tp, time);
628
629 if (tp->gesture.state == GESTURE_STATE_UNKNOWN)
630 tp->gesture.state =
631 tp_gesture_handle_state_unknown(tp, time);
632
633 if (tp->gesture.state == GESTURE_STATE_SCROLL)
634 tp->gesture.state =
635 tp_gesture_handle_state_scroll(tp, time);
636
637 if (tp->gesture.state == GESTURE_STATE_SWIPE)
638 tp->gesture.state =
639 tp_gesture_handle_state_swipe(tp, time);
640
641 if (tp->gesture.state == GESTURE_STATE_PINCH)
642 tp->gesture.state =
643 tp_gesture_handle_state_pinch(tp, time);
644
645 evdev_log_debug(tp->device,
646 "gesture state: %s → %s\n",
647 gesture_state_to_str(oldstate),
648 gesture_state_to_str(tp->gesture.state));
649 }
650
651 void
tp_gesture_post_events(struct tp_dispatch * tp,uint64_t time)652 tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time)
653 {
654 if (tp->gesture.finger_count == 0)
655 return;
656
657 /* When tap-and-dragging, or a clickpad is clicked force 1fg mode */
658 if (tp_tap_dragging(tp) || (tp->buttons.is_clickpad && tp->buttons.state)) {
659 tp_gesture_cancel(tp, time);
660 tp->gesture.finger_count = 1;
661 tp->gesture.finger_count_pending = 0;
662 }
663
664 /* Don't send events when we're unsure in which mode we are */
665 if (tp->gesture.finger_count_pending)
666 return;
667
668 switch (tp->gesture.finger_count) {
669 case 1:
670 if (tp->queued & TOUCHPAD_EVENT_MOTION)
671 tp_gesture_post_pointer_motion(tp, time);
672 break;
673 case 2:
674 case 3:
675 case 4:
676 tp_gesture_post_gesture(tp, time);
677 break;
678 }
679 }
680
681 void
tp_gesture_stop_twofinger_scroll(struct tp_dispatch * tp,uint64_t time)682 tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
683 {
684 if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
685 return;
686
687 evdev_stop_scroll(tp->device,
688 time,
689 LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
690 }
691
692 static void
tp_gesture_end(struct tp_dispatch * tp,uint64_t time,bool cancelled)693 tp_gesture_end(struct tp_dispatch *tp, uint64_t time, bool cancelled)
694 {
695 enum tp_gesture_state state = tp->gesture.state;
696
697 tp->gesture.state = GESTURE_STATE_NONE;
698
699 if (!tp->gesture.started)
700 return;
701
702 switch (state) {
703 case GESTURE_STATE_NONE:
704 case GESTURE_STATE_UNKNOWN:
705 evdev_log_bug_libinput(tp->device,
706 "%s in unknown gesture mode\n",
707 __func__);
708 break;
709 case GESTURE_STATE_SCROLL:
710 tp_gesture_stop_twofinger_scroll(tp, time);
711 break;
712 case GESTURE_STATE_PINCH:
713 gesture_notify_pinch_end(&tp->device->base, time,
714 tp->gesture.finger_count,
715 tp->gesture.prev_scale,
716 cancelled);
717 break;
718 case GESTURE_STATE_SWIPE:
719 gesture_notify_swipe_end(&tp->device->base,
720 time,
721 tp->gesture.finger_count,
722 cancelled);
723 break;
724 }
725
726 tp->gesture.started = false;
727 }
728
729 void
tp_gesture_cancel(struct tp_dispatch * tp,uint64_t time)730 tp_gesture_cancel(struct tp_dispatch *tp, uint64_t time)
731 {
732 tp_gesture_end(tp, time, true);
733 }
734
735 void
tp_gesture_stop(struct tp_dispatch * tp,uint64_t time)736 tp_gesture_stop(struct tp_dispatch *tp, uint64_t time)
737 {
738 tp_gesture_end(tp, time, false);
739 }
740
741 static void
tp_gesture_finger_count_switch_timeout(uint64_t now,void * data)742 tp_gesture_finger_count_switch_timeout(uint64_t now, void *data)
743 {
744 struct tp_dispatch *tp = data;
745
746 if (!tp->gesture.finger_count_pending)
747 return;
748
749 tp_gesture_cancel(tp, now); /* End current gesture */
750 tp->gesture.finger_count = tp->gesture.finger_count_pending;
751 tp->gesture.finger_count_pending = 0;
752 }
753
754 void
tp_gesture_handle_state(struct tp_dispatch * tp,uint64_t time)755 tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time)
756 {
757 unsigned int active_touches = 0;
758 struct tp_touch *t;
759
760 tp_for_each_touch(tp, t) {
761 if (tp_touch_active(tp, t))
762 active_touches++;
763 }
764
765 if (active_touches != tp->gesture.finger_count) {
766 /* If all fingers are lifted immediately end the gesture */
767 if (active_touches == 0) {
768 tp_gesture_stop(tp, time);
769 tp->gesture.finger_count = 0;
770 tp->gesture.finger_count_pending = 0;
771 /* Immediately switch to new mode to avoid initial latency */
772 } else if (!tp->gesture.started) {
773 tp->gesture.finger_count = active_touches;
774 tp->gesture.finger_count_pending = 0;
775 /* Else debounce finger changes */
776 } else if (active_touches != tp->gesture.finger_count_pending) {
777 tp->gesture.finger_count_pending = active_touches;
778 libinput_timer_set(&tp->gesture.finger_count_switch_timer,
779 time + DEFAULT_GESTURE_SWITCH_TIMEOUT);
780 }
781 } else {
782 tp->gesture.finger_count_pending = 0;
783 }
784 }
785
786 void
tp_init_gesture(struct tp_dispatch * tp)787 tp_init_gesture(struct tp_dispatch *tp)
788 {
789 char timer_name[64];
790
791 /* two-finger scrolling is always enabled, this flag just
792 * decides whether we detect pinch. semi-mt devices are too
793 * unreliable to do pinch gestures. */
794 tp->gesture.enabled = !tp->semi_mt && tp->num_slots > 1;
795
796 tp->gesture.state = GESTURE_STATE_NONE;
797
798 snprintf(timer_name,
799 sizeof(timer_name),
800 "%s gestures",
801 evdev_device_get_sysname(tp->device));
802 libinput_timer_init(&tp->gesture.finger_count_switch_timer,
803 tp_libinput_context(tp),
804 timer_name,
805 tp_gesture_finger_count_switch_timeout, tp);
806 }
807
808 void
tp_remove_gesture(struct tp_dispatch * tp)809 tp_remove_gesture(struct tp_dispatch *tp)
810 {
811 libinput_timer_cancel(&tp->gesture.finger_count_switch_timer);
812 }
813