evdev-mt-touchpad-gestures.c 17.3 KB
Newer Older
1 2 3
/*
 * Copyright © 2015 Red Hat, Inc.
 *
4 5 6 7 8 9
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
10
 *
11 12 13 14 15 16 17 18 19 20 21
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
22 23 24 25 26 27 28 29 30 31
 */

#include "config.h"

#include <math.h>
#include <stdbool.h>
#include <limits.h>

#include "evdev-mt-touchpad.h"

32
#define DEFAULT_GESTURE_SWITCH_TIMEOUT ms2us(100)
33
#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT ms2us(150)
34

35
static inline const char*
36
gesture_state_to_str(enum tp_gesture_state state)
37 38
{
	switch (state) {
39 40 41 42
	CASE_RETURN_STRING(GESTURE_STATE_NONE);
	CASE_RETURN_STRING(GESTURE_STATE_UNKNOWN);
	CASE_RETURN_STRING(GESTURE_STATE_SCROLL);
	CASE_RETURN_STRING(GESTURE_STATE_PINCH);
43
	CASE_RETURN_STRING(GESTURE_STATE_SWIPE);
44 45 46 47
	}
	return NULL;
}

48 49
static struct normalized_coords
tp_get_touches_delta(struct tp_dispatch *tp, bool average)
50 51
{
	struct tp_touch *t;
52
	unsigned int i, nactive = 0;
53 54
	struct normalized_coords normalized;
	struct normalized_coords delta = {0.0, 0.0};
55

56
	for (i = 0; i < tp->num_slots; i++) {
57 58
		t = &tp->touches[i];

59 60 61 62 63 64
		if (!tp_touch_active(tp, t))
			continue;

		nactive++;

		if (t->dirty) {
65
			normalized = tp_get_delta(t);
66

67 68
			delta.x += normalized.x;
			delta.y += normalized.y;
69 70 71
		}
	}

72
	if (!average || nactive == 0)
73 74
		return delta;

75 76
	delta.x /= nactive;
	delta.y /= nactive;
77

78
	return delta;
79 80
}

81 82
static inline struct normalized_coords
tp_get_combined_touches_delta(struct tp_dispatch *tp)
83
{
84
	return tp_get_touches_delta(tp, false);
85
}
86

87 88
static inline struct normalized_coords
tp_get_average_touches_delta(struct tp_dispatch *tp)
89
{
90
	return tp_get_touches_delta(tp, true);
91 92 93
}

static void
94 95
tp_gesture_start(struct tp_dispatch *tp, uint64_t time)
{
96 97
	const struct normalized_coords zero = { 0.0, 0.0 };

98 99 100
	if (tp->gesture.started)
		return;

101 102 103
	switch (tp->gesture.state) {
	case GESTURE_STATE_NONE:
	case GESTURE_STATE_UNKNOWN:
104 105 106
		evdev_log_bug_libinput(tp->device,
				       "%s in unknown gesture mode\n",
				       __func__);
107
		break;
108 109 110 111 112 113 114 115 116 117
	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:
118 119 120 121 122
		gesture_notify_swipe(&tp->device->base, time,
				     LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
				     tp->gesture.finger_count,
				     &zero, &zero);
		break;
123
	}
124

125 126 127
	tp->gesture.started = true;
}

128 129 130
static void
tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
{
131
	struct normalized_coords delta, unaccel;
132
	struct device_float_coords raw;
133 134 135

	/* When a clickpad is clicked, combine motion of all active touches */
	if (tp->buttons.is_clickpad && tp->buttons.state)
136
		unaccel = tp_get_combined_touches_delta(tp);
137
	else
138
		unaccel = tp_get_average_touches_delta(tp);
139

140
	delta = tp_filter_motion(tp, &unaccel, time);
141

142
	if (!normalized_is_zero(delta) || !normalized_is_zero(unaccel)) {
143 144 145 146 147
		raw = tp_unnormalize_for_xaxis(tp, unaccel);
		pointer_notify_motion(&tp->device->base,
				      time,
				      &delta,
				      &raw);
148 149 150
	}
}

151
static unsigned int
152
tp_gesture_get_active_touches(const struct tp_dispatch *tp,
153 154 155
			      struct tp_touch **touches,
			      unsigned int count)
{
156
	unsigned int n = 0;
157 158 159 160
	struct tp_touch *t;

	memset(touches, 0, count * sizeof(struct tp_touch *));

161
	tp_for_each_touch(tp, t) {
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
		if (tp_touch_active(tp, t)) {
			touches[n++] = t;
			if (n == count)
				return count;
		}
	}

	/*
	 * This can happen when the user does .e.g:
	 * 1) Put down 1st finger in center (so active)
	 * 2) Put down 2nd finger in a button area (so inactive)
	 * 3) Put down 3th finger somewhere, gets reported as a fake finger,
	 *    so gets same coordinates as 1st -> active
	 *
	 * We could avoid this by looking at all touches, be we really only
	 * want to look at real touches.
	 */
	return n;
}

182
static uint32_t
183 184
tp_gesture_get_direction(struct tp_dispatch *tp, struct tp_touch *touch,
			 unsigned int nfingers)
185
{
186
	struct phys_coords mm;
187
	struct device_float_coords delta;
188
	double move_threshold = 1.0; /* mm */
189

190 191
	move_threshold *= (nfingers - 1);

192
	delta = device_delta(touch->point, touch->gesture.initial);
193
	mm = tp_phys_delta(tp, delta);
194

195
	if (length_in_mm(mm) < move_threshold)
196 197
		return UNDEFINED_DIRECTION;

198
	return phys_get_direction(mm);
199 200
}

201
static void
202 203 204 205 206 207 208 209 210 211 212 213 214
tp_gesture_get_pinch_info(struct tp_dispatch *tp,
			  double *distance,
			  double *angle,
			  struct device_float_coords *center)
{
	struct normalized_coords normalized;
	struct device_float_coords delta;
	struct tp_touch *first = tp->gesture.touches[0],
			*second = tp->gesture.touches[1];

	delta = device_delta(first->point, second->point);
	normalized = tp_normalize_delta(tp, delta);
	*distance = normalized_length(normalized);
215
	*angle = atan2(normalized.y, normalized.x) * 180.0 / M_PI;
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234

	*center = device_average(first->point, second->point);
}

static void
tp_gesture_set_scroll_buildup(struct tp_dispatch *tp)
{
	struct device_float_coords d0, d1;
	struct device_float_coords average;
	struct tp_touch *first = tp->gesture.touches[0],
			*second = tp->gesture.touches[1];

	d0 = device_delta(first->point, first->gesture.initial);
	d1 = device_delta(second->point, second->gesture.initial);

	average = device_float_average(d0, d1);
	tp->device->scroll.buildup = tp_normalize_delta(tp, average);
}

235
static enum tp_gesture_state
236
tp_gesture_handle_state_none(struct tp_dispatch *tp, uint64_t time)
237 238
{
	struct tp_touch *first, *second;
239 240 241
	struct tp_touch *touches[4];
	unsigned int ntouches;
	unsigned int i;
242

243 244
	ntouches = tp_gesture_get_active_touches(tp, touches, 4);
	if (ntouches < 2)
245
		return GESTURE_STATE_NONE;
246

247 248 249 250
	if (!tp->gesture.enabled) {
		if (ntouches == 2)
			return GESTURE_STATE_SCROLL;
		else
251
			return GESTURE_STATE_NONE;
252 253
	}

254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
	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 (first == second)
			return GESTURE_STATE_NONE;
284

285
	}
286 287 288 289

	tp->gesture.initial_time = time;
	first->gesture.initial = first->point;
	second->gesture.initial = second->point;
290 291
	tp->gesture.touches[0] = first;
	tp->gesture.touches[1] = second;
292

293
	return GESTURE_STATE_UNKNOWN;
294 295
}

296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
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));
}

312
static inline void
Peter Hutterer's avatar
Peter Hutterer committed
313
tp_gesture_init_pinch(struct tp_dispatch *tp)
314 315 316 317 318 319 320 321
{
	tp_gesture_get_pinch_info(tp,
				  &tp->gesture.initial_distance,
				  &tp->gesture.angle,
				  &tp->gesture.center);
	tp->gesture.prev_scale = 1.0;
}

322
static enum tp_gesture_state
323
tp_gesture_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
324 325 326
{
	struct tp_touch *first = tp->gesture.touches[0],
			*second = tp->gesture.touches[1];
327
	uint32_t dir1, dir2;
328 329
	int yres = tp->device->abs.absinfo_y->resolution;
	int vert_distance;
330

331 332 333 334
	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) {
335 336
			tp_gesture_set_scroll_buildup(tp);
			return GESTURE_STATE_SCROLL;
337 338 339 340
		/* more fingers than slots, don't bother with pinch, always
		 * assume swipe */
		} else if (tp->gesture.finger_count > tp->num_slots) {
			return GESTURE_STATE_SWIPE;
341
		}
342

343 344
		/* for 3+ finger gestures, check if one finger is > 20mm
		   below the others */
345 346 347 348 349
		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;
350 351
		} else {
			return GESTURE_STATE_SWIPE;
352
		}
353 354
	}

355
	/* Else wait for both fingers to have moved */
356 357
	dir1 = tp_gesture_get_direction(tp, first, tp->gesture.finger_count);
	dir2 = tp_gesture_get_direction(tp, second, tp->gesture.finger_count);
358
	if (dir1 == UNDEFINED_DIRECTION || dir2 == UNDEFINED_DIRECTION)
359
		return GESTURE_STATE_UNKNOWN;
360

361 362
	/* If both touches are moving in the same direction assume
	 * scroll or swipe */
363 364
	if (tp->gesture.finger_count > tp->num_slots ||
	    tp_gesture_same_directions(dir1, dir2)) {
365 366 367 368 369 370
		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;
		}
371
	} else {
372
		tp_gesture_init_pinch(tp);
373
		return GESTURE_STATE_PINCH;
374
	}
375

376
	return GESTURE_STATE_UNKNOWN;
377 378
}

379
static enum tp_gesture_state
380
tp_gesture_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
381
{
382
	struct normalized_coords delta;
383

384
	if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
385
		return GESTURE_STATE_SCROLL;
386

387
	delta = tp_get_average_touches_delta(tp);
388

389 390
	/* scroll is not accelerated */
	delta = tp_filter_motion_unaccelerated(tp, &delta, time);
391

392
	if (normalized_is_zero(delta))
393
		return GESTURE_STATE_SCROLL;
394 395 396 397 398

	tp_gesture_start(tp, time);
	evdev_post_scroll(tp->device,
			  time,
			  LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
399
			  &delta);
400

401
	return GESTURE_STATE_SCROLL;
402 403
}

404
static enum tp_gesture_state
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
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_state
tp_gesture_handle_state_pinch(struct tp_dispatch *tp, uint64_t time)
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
{
	double angle, angle_delta, distance, scale;
	struct device_float_coords center, fdelta;
	struct normalized_coords delta, unaccel;

	tp_gesture_get_pinch_info(tp, &distance, &angle, &center);

	scale = distance / tp->gesture.initial_distance;

	angle_delta = angle - tp->gesture.angle;
	tp->gesture.angle = angle;
	if (angle_delta > 180.0)
		angle_delta -= 360.0;
	else if (angle_delta < -180.0)
		angle_delta += 360.0;

	fdelta = device_float_delta(center, tp->gesture.center);
	tp->gesture.center = center;
	unaccel = tp_normalize_delta(tp, fdelta);
	delta = tp_filter_motion(tp, &unaccel, time);

	if (normalized_is_zero(delta) && normalized_is_zero(unaccel) &&
	    scale == tp->gesture.prev_scale && angle_delta == 0.0)
448
		return GESTURE_STATE_PINCH;
449 450 451 452

	tp_gesture_start(tp, time);
	gesture_notify_pinch(&tp->device->base, time,
			     LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
453
			     tp->gesture.finger_count,
454 455 456 457
			     &delta, &unaccel, scale, angle_delta);

	tp->gesture.prev_scale = scale;

458
	return GESTURE_STATE_PINCH;
459 460 461
}

static void
462
tp_gesture_post_gesture(struct tp_dispatch *tp, uint64_t time)
463
{
464
	enum tp_gesture_state oldstate = tp->gesture.state;
465

466 467
	if (tp->gesture.state == GESTURE_STATE_NONE)
		tp->gesture.state =
468
			tp_gesture_handle_state_none(tp, time);
469

470 471
	if (tp->gesture.state == GESTURE_STATE_UNKNOWN)
		tp->gesture.state =
472
			tp_gesture_handle_state_unknown(tp, time);
473

474 475
	if (tp->gesture.state == GESTURE_STATE_SCROLL)
		tp->gesture.state =
476 477 478 479 480
			tp_gesture_handle_state_scroll(tp, time);

	if (tp->gesture.state == GESTURE_STATE_SWIPE)
		tp->gesture.state =
			tp_gesture_handle_state_swipe(tp, time);
481

482 483
	if (tp->gesture.state == GESTURE_STATE_PINCH)
		tp->gesture.state =
484
			tp_gesture_handle_state_pinch(tp, time);
485

486 487 488 489
	evdev_log_debug(tp->device,
			"gesture state: %s → %s\n",
			gesture_state_to_str(oldstate),
			gesture_state_to_str(tp->gesture.state));
490 491
}

492 493 494 495 496 497 498 499
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)) {
500
		tp_gesture_cancel(tp, time);
501 502 503 504 505 506 507 508 509 510
		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:
511 512
		if (tp->queued & TOUCHPAD_EVENT_MOTION)
			tp_gesture_post_pointer_motion(tp, time);
513 514
		break;
	case 2:
515 516
	case 3:
	case 4:
517
		tp_gesture_post_gesture(tp, time);
518
		break;
519 520 521
	}
}

522 523 524
void
tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
{
525 526 527
	if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
		return;

528 529 530 531 532
	evdev_stop_scroll(tp->device,
			  time,
			  LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
}

533 534
static void
tp_gesture_end(struct tp_dispatch *tp, uint64_t time, bool cancelled)
535
{
536
	enum tp_gesture_state state = tp->gesture.state;
537

538
	tp->gesture.state = GESTURE_STATE_NONE;
539

540 541 542
	if (!tp->gesture.started)
		return;

543 544 545
	switch (state) {
	case GESTURE_STATE_NONE:
	case GESTURE_STATE_UNKNOWN:
546 547 548
		evdev_log_bug_libinput(tp->device,
				       "%s in unknown gesture mode\n",
				       __func__);
549
		break;
550 551 552 553 554 555 556 557 558 559 560 561 562 563
	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);
564
		break;
565
	}
566

567 568 569
	tp->gesture.started = false;
}

570 571 572 573 574 575 576 577 578 579 580 581
void
tp_gesture_cancel(struct tp_dispatch *tp, uint64_t time)
{
	tp_gesture_end(tp, time, true);
}

void
tp_gesture_stop(struct tp_dispatch *tp, uint64_t time)
{
	tp_gesture_end(tp, time, false);
}

582 583 584 585 586 587 588 589
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;

590
	tp_gesture_cancel(tp, now); /* End current gesture */
591 592 593 594 595 596 597 598 599 600
	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;

601
	tp_for_each_touch(tp, t) {
602 603
		if (tp_touch_active(tp, t))
			active_touches++;
604 605
	}

606 607 608
	if (active_touches != tp->gesture.finger_count) {
		/* If all fingers are lifted immediately end the gesture */
		if (active_touches == 0) {
609
			tp_gesture_stop(tp, time);
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
			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;
	}
}

627
void
628 629
tp_init_gesture(struct tp_dispatch *tp)
{
630 631
	char timer_name[64];

632 633 634
	/* two-finger scrolling is always enabled, this flag just
	 * decides whether we detect pinch. semi-mt devices are too
	 * unreliable to do pinch gestures. */
635
	tp->gesture.enabled = !tp->semi_mt && tp->num_slots > 1;
636

637
	tp->gesture.state = GESTURE_STATE_NONE;
638

639 640 641 642
	snprintf(timer_name,
		 sizeof(timer_name),
		 "%s gestures",
		 evdev_device_get_sysname(tp->device));
643
	libinput_timer_init(&tp->gesture.finger_count_switch_timer,
644
			    tp_libinput_context(tp),
645
			    timer_name,
646 647 648 649 650 651 652 653
			    tp_gesture_finger_count_switch_timeout, tp);
}

void
tp_remove_gesture(struct tp_dispatch *tp)
{
	libinput_timer_cancel(&tp->gesture.finger_count_switch_timer);
}