evdev-mt-touchpad-gestures.c 15.5 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 33
#define DEFAULT_GESTURE_SWITCH_TIMEOUT ms2us(100)
#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT ms2us(1000)
34

35 36 37 38 39 40 41 42 43 44 45 46
static inline const char*
gesture_state_to_str(enum tp_gesture_2fg_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);
	}
	return NULL;
}

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

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

58 59
		if (tp_touch_active(tp, t) && t->dirty) {
			nchanged++;
60
			normalized = tp_get_delta(t);
61

62 63
			delta.x += normalized.x;
			delta.y += normalized.y;
64 65 66
		}
	}

67
	if (!average || nchanged == 0)
68 69 70 71
		return delta;

	delta.x /= nchanged;
	delta.y /= nchanged;
72

73
	return delta;
74 75
}

76 77
static inline struct normalized_coords
tp_get_combined_touches_delta(struct tp_dispatch *tp)
78
{
79
	return tp_get_touches_delta(tp, false);
80
}
81

82 83
static inline struct normalized_coords
tp_get_average_touches_delta(struct tp_dispatch *tp)
84
{
85
	return tp_get_touches_delta(tp, true);
86 87 88
}

static void
89 90
tp_gesture_start(struct tp_dispatch *tp, uint64_t time)
{
91
	struct libinput *libinput = tp->device->base.seat->libinput;
92 93
	const struct normalized_coords zero = { 0.0, 0.0 };

94 95 96 97 98
	if (tp->gesture.started)
		return;

	switch (tp->gesture.finger_count) {
	case 2:
99 100 101 102 103 104 105 106 107 108 109 110 111
		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,
112
					    &zero, &zero, 1.0, 0.0);
113 114
			break;
		}
115
		break;
116 117 118 119 120 121 122
	case 3:
	case 4:
		gesture_notify_swipe(&tp->device->base, time,
				     LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
				     tp->gesture.finger_count,
				     &zero, &zero);
		break;
123 124 125 126
	}
	tp->gesture.started = true;
}

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

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

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

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

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

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

160
	for (i = 0; i < tp->ntouches; i++) {
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
		t = &tp->touches[i];
		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;
}

static int
tp_gesture_get_direction(struct tp_dispatch *tp, struct tp_touch *touch)
{
	struct normalized_coords normalized;
	struct device_float_coords delta;
	double move_threshold;

	/*
	 * Semi-mt touchpads have somewhat inaccurate coordinates when
	 * 2 fingers are down, so use a slightly larger threshold.
	 */
	if (tp->semi_mt)
		move_threshold = TP_MM_TO_DPI_NORMALIZED(4);
	else
196
		move_threshold = TP_MM_TO_DPI_NORMALIZED(2);
197 198

	delta = device_delta(touch->point, touch->gesture.initial);
199

200 201 202 203 204 205 206 207
	normalized = tp_normalize_delta(tp, delta);

	if (normalized_length(normalized) < move_threshold)
		return UNDEFINED_DIRECTION;

	return normalized_get_direction(normalized);
}

208
static void
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
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);

	if (!tp->semi_mt)
		*angle = atan2(normalized.y, normalized.x) * 180.0 / M_PI;
	else
		*angle = 0.0;

	*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);
}

static enum tp_gesture_2fg_state
tp_gesture_twofinger_handle_state_none(struct tp_dispatch *tp, uint64_t time)
{
	struct tp_touch *first, *second;

	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];

	tp->gesture.initial_time = time;
	first->gesture.initial = first->point;
	second->gesture.initial = second->point;

	return GESTURE_2FG_STATE_UNKNOWN;
}

static enum tp_gesture_2fg_state
tp_gesture_twofinger_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;

271
	/* if fingers stay unmoving for a while, assume (slow) scroll */
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
	if (time > (tp->gesture.initial_time + DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT)) {
		tp_gesture_set_scroll_buildup(tp);
		return GESTURE_2FG_STATE_SCROLL;
	}

	/* 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;
298
	} else if (tp->gesture.enabled) {
299 300 301 302 303 304 305
		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;
	}
306 307

	return GESTURE_2FG_STATE_UNKNOWN;
308 309 310 311
}

static enum tp_gesture_2fg_state
tp_gesture_twofinger_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
312
{
313
	struct normalized_coords delta;
314

315
	if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
316
		return GESTURE_2FG_STATE_SCROLL;
317

318 319 320 321
	/* 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)
322
			return GESTURE_2FG_STATE_SCROLL;
323 324 325 326 327 328

		delta = tp_get_delta(&tp->touches[0]);
	} else {
		delta = tp_get_average_touches_delta(tp);
	}

329
	delta = tp_filter_motion(tp, &delta, time);
330

331
	if (normalized_is_zero(delta))
332
		return GESTURE_2FG_STATE_SCROLL;
333 334 335 336 337

	tp_gesture_start(tp, time);
	evdev_post_scroll(tp->device,
			  time,
			  LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
338
			  &delta);
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382

	return GESTURE_2FG_STATE_SCROLL;
}

static enum tp_gesture_2fg_state
tp_gesture_twofinger_handle_state_pinch(struct tp_dispatch *tp, uint64_t time)
{
	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)
		return GESTURE_2FG_STATE_PINCH;

	tp_gesture_start(tp, time);
	gesture_notify_pinch(&tp->device->base, time,
			     LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
			     &delta, &unaccel, scale, angle_delta);

	tp->gesture.prev_scale = scale;

	return GESTURE_2FG_STATE_PINCH;
}

static void
tp_gesture_post_twofinger(struct tp_dispatch *tp, uint64_t time)
{
383 384
	enum tp_gesture_2fg_state oldstate = tp->gesture.twofinger_state;

385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
	if (tp->gesture.twofinger_state == GESTURE_2FG_STATE_NONE)
		tp->gesture.twofinger_state =
			tp_gesture_twofinger_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.twofinger_state == GESTURE_2FG_STATE_SCROLL)
		tp->gesture.twofinger_state =
			tp_gesture_twofinger_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);
400 401 402 403 404

	log_debug(tp_libinput_context(tp),
		  "gesture state: %s → %s\n",
		  gesture_state_to_str(oldstate),
		  gesture_state_to_str(tp->gesture.twofinger_state));
405 406
}

407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
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);
	}
}

424 425 426 427 428 429 430 431
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)) {
432
		tp_gesture_cancel(tp, time);
433 434 435 436 437 438 439 440 441 442 443 444 445
		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:
446
		tp_gesture_post_twofinger(tp, time);
447
		break;
448 449 450 451
	case 3:
	case 4:
		tp_gesture_post_swipe(tp, time);
		break;
452 453 454
	}
}

455 456 457
void
tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
{
458 459 460
	if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
		return;

461 462 463 464 465
	evdev_stop_scroll(tp->device,
			  time,
			  LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
}

466 467
static void
tp_gesture_end(struct tp_dispatch *tp, uint64_t time, bool cancelled)
468
{
469 470
	struct libinput *libinput = tp->device->base.seat->libinput;
	enum tp_gesture_2fg_state twofinger_state = tp->gesture.twofinger_state;
471

472 473
	tp->gesture.twofinger_state = GESTURE_2FG_STATE_NONE;

474 475 476 477 478
	if (!tp->gesture.started)
		return;

	switch (tp->gesture.finger_count) {
	case 2:
479 480 481 482 483 484 485 486 487 488 489
		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:
490
			gesture_notify_pinch_end(&tp->device->base, time,
491
						 tp->gesture.prev_scale,
492
						 cancelled);
493 494
			break;
		}
495
		break;
496 497
	case 3:
	case 4:
498 499
		gesture_notify_swipe_end(&tp->device->base, time,
					 tp->gesture.finger_count, cancelled);
500
		break;
501 502 503 504
	}
	tp->gesture.started = false;
}

505 506 507 508 509 510 511 512 513 514 515 516
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);
}

517 518 519 520 521 522 523 524
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;

525
	tp_gesture_cancel(tp, now); /* End current gesture */
526 527 528 529 530 531 532 533 534
	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;
535
	int i = 0;
536

537
	tp_for_each_touch(tp, t) {
538 539 540
		if (tp_touch_active(tp, t))
			active_touches++;

541 542 543
		i++;
	}

544 545 546
	if (active_touches != tp->gesture.finger_count) {
		/* If all fingers are lifted immediately end the gesture */
		if (active_touches == 0) {
547
			tp_gesture_stop(tp, time);
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
			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)
{
568 569 570 571 572
	if (tp->device->model_flags & EVDEV_MODEL_JUMPING_SEMI_MT)
		tp->gesture.enabled = false;
	else
		tp->gesture.enabled = true;

573 574
	tp->gesture.twofinger_state = GESTURE_2FG_STATE_NONE;

575 576 577 578 579 580 581 582 583 584 585
	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);
}