evdev-mt-touchpad.c 79.8 KB
Newer Older
1
/*
Peter Hutterer's avatar
Peter Hutterer committed
2
 * Copyright © 2014-2015 Red Hat, Inc.
3
 *
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
 */

#include "config.h"

26
#include <assert.h>
27
#include <math.h>
28
#include <stdbool.h>
29
#include <limits.h>
30

31
#include "evdev-mt-touchpad.h"
32

33 34 35
#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT ms2us(300)
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 ms2us(200)
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 ms2us(500)
36
#define THUMB_MOVE_TIMEOUT ms2us(300)
37
#define FAKE_FINGER_OVERFLOW (1 << 7)
38
#define THUMB_IGNORE_SPEED_THRESHOLD 20 /* mm/s */
39

40
static inline struct tp_history_point*
41 42 43 44 45 46 47 48 49
tp_motion_history_offset(struct tp_touch *t, int offset)
{
	int offset_index =
		(t->history.index - offset + TOUCHPAD_HISTORY_LENGTH) %
		TOUCHPAD_HISTORY_LENGTH;

	return &t->history.samples[offset_index];
}

50
struct normalized_coords
51
tp_filter_motion(struct tp_dispatch *tp,
52
		 const struct normalized_coords *unaccelerated,
53
		 uint64_t time)
54
{
55 56
	struct device_float_coords raw;

57 58
	if (normalized_is_zero(*unaccelerated))
		return *unaccelerated;
59

60 61 62 63
	/* Temporary solution only: convert back to raw coordinates, but
	 * make sure we're on the same resolution for both axes */
	raw = tp_unnormalize_for_xaxis(tp, *unaccelerated);

64
	return filter_dispatch(tp->device->pointer.filter,
65
			       &raw, tp, time);
66 67
}

68 69 70 71 72
struct normalized_coords
tp_filter_motion_unaccelerated(struct tp_dispatch *tp,
			       const struct normalized_coords *unaccelerated,
			       uint64_t time)
{
73 74
	struct device_float_coords raw;

75 76 77
	if (normalized_is_zero(*unaccelerated))
		return *unaccelerated;

78 79 80 81
	/* Temporary solution only: convert back to raw coordinates, but
	 * make sure we're on the same resolution for both axes */
	raw = tp_unnormalize_for_xaxis(tp, *unaccelerated);

82
	return filter_dispatch_constant(tp->device->pointer.filter,
83
					&raw, tp, time);
84 85
}

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
static inline void
tp_calculate_motion_speed(struct tp_dispatch *tp, struct tp_touch *t)
{
	const struct tp_history_point *last;
	struct device_coords delta;
	struct phys_coords mm;
	double distance;
	double speed;

	/* This doesn't kick in until we have at least 4 events in the
	 * motion history. As a side-effect, this automatically handles the
	 * 2fg scroll where a finger is down and moving fast before the
	 * other finger comes down for the scroll.
	 *
	 * We do *not* reset the speed to 0 here though. The motion history
	 * is reset whenever a new finger is down, so we'd be resetting the
	 * speed and failing.
	 */
	if (t->history.count < 4)
		return;

	/* TODO: we probably need a speed history here so we can average
	 * across a few events */
	last = tp_motion_history_offset(t, 1);
	delta.x = abs(t->point.x - last->point.x);
	delta.y = abs(t->point.y - last->point.y);
	mm = evdev_device_unit_delta_to_mm(tp->device, &delta);

	distance = length_in_mm(mm);
	speed = distance/(t->time - last->time); /* mm/us */
	speed *= 1000000; /* mm/s */

	t->speed.last_speed = speed;
}

121 122 123 124 125 126 127 128
static inline void
tp_motion_history_push(struct tp_touch *t)
{
	int motion_index = (t->history.index + 1) % TOUCHPAD_HISTORY_LENGTH;

	if (t->history.count < TOUCHPAD_HISTORY_LENGTH)
		t->history.count++;

129 130
	t->history.samples[motion_index].point = t->point;
	t->history.samples[motion_index].time = t->time;
131 132 133
	t->history.index = motion_index;
}

134 135 136 137
static inline void
tp_motion_hysteresis(struct tp_dispatch *tp,
		     struct tp_touch *t)
{
138 139
	int x = t->point.x,
	    y = t->point.y;
140

141 142 143
	if (!tp->hysteresis.enabled)
		return;

144
	if (t->history.count == 0) {
145
		t->hysteresis_center = t->point;
146
	} else {
147 148
		x = evdev_hysteresis(x,
				     t->hysteresis_center.x,
149
				     tp->hysteresis.margin.x);
150 151
		y = evdev_hysteresis(y,
				     t->hysteresis_center.y,
152
				     tp->hysteresis.margin.y);
153 154 155 156
		t->hysteresis_center.x = x;
		t->hysteresis_center.y = y;
		t->point.x = x;
		t->point.y = y;
157 158 159
	}
}

160 161 162 163 164 165 166 167 168
static inline void
tp_motion_history_reset(struct tp_touch *t)
{
	t->history.count = 0;
}

static inline struct tp_touch *
tp_current_touch(struct tp_dispatch *tp)
{
169
	return &tp->touches[min(tp->slot, tp->ntouches - 1)];
170 171
}

172 173 174 175 176 177 178
static inline struct tp_touch *
tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
{
	assert(slot < tp->ntouches);
	return &tp->touches[slot];
}

179 180 181
static inline unsigned int
tp_fake_finger_count(struct tp_dispatch *tp)
{
182 183 184 185
	/* Only one of BTN_TOOL_DOUBLETAP/TRIPLETAP/... may be set at any
	 * time */
	if (__builtin_popcount(
		       tp->fake_touches & ~(FAKE_FINGER_OVERFLOW|0x1)) > 1)
186 187 188
		evdev_log_bug_kernel(tp->device,
				     "Invalid fake finger state %#x\n",
				     tp->fake_touches);
189

190 191 192 193
	if (tp->fake_touches & FAKE_FINGER_OVERFLOW)
		return FAKE_FINGER_OVERFLOW;
	else /* don't count BTN_TOUCH */
		return ffs(tp->fake_touches >> 1);
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
}

static inline bool
tp_fake_finger_is_touching(struct tp_dispatch *tp)
{
	return tp->fake_touches & 0x1;
}

static inline void
tp_fake_finger_set(struct tp_dispatch *tp,
		   unsigned int code,
		   bool is_press)
{
	unsigned int shift;

	switch (code) {
	case BTN_TOUCH:
211 212
		if (!is_press)
			tp->fake_touches &= ~FAKE_FINGER_OVERFLOW;
213 214 215 216 217 218 219 220 221 222
		shift = 0;
		break;
	case BTN_TOOL_FINGER:
		shift = 1;
		break;
	case BTN_TOOL_DOUBLETAP:
	case BTN_TOOL_TRIPLETAP:
	case BTN_TOOL_QUADTAP:
		shift = code - BTN_TOOL_DOUBLETAP + 2;
		break;
223 224 225 226 227 228 229
	/* when QUINTTAP is released we're either switching to 6 fingers
	   (flag stays in place until BTN_TOUCH is released) or
	   one of DOUBLE/TRIPLE/QUADTAP (will clear the flag on press) */
	case BTN_TOOL_QUINTTAP:
		if (is_press)
			tp->fake_touches |= FAKE_FINGER_OVERFLOW;
		return;
230 231 232 233
	default:
		return;
	}

234 235
	if (is_press) {
		tp->fake_touches &= ~FAKE_FINGER_OVERFLOW;
236
		tp->fake_touches |= 1 << shift;
237 238

	} else {
239
		tp->fake_touches &= ~(0x1 << shift);
240
	}
241 242
}

243
static inline void
244
tp_new_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
245
{
246 247 248
	if (t->state == TOUCH_BEGIN ||
	    t->state == TOUCH_UPDATE ||
	    t->state == TOUCH_HOVERING)
249 250
		return;

251 252 253
	/* we begin the touch as hovering because until BTN_TOUCH happens we
	 * don't know if it's a touch down or not. And BTN_TOUCH may happen
	 * after ABS_MT_TRACKING_ID */
254 255
	tp_motion_history_reset(t);
	t->dirty = true;
256
	t->has_ended = false;
257
	t->was_down = false;
258
	t->state = TOUCH_HOVERING;
259
	t->pinned.is_pinned = false;
260
	t->time = time;
261 262
	t->speed.last_speed = 0;
	t->speed.exceeded_count = 0;
263 264 265 266 267 268 269 270
	tp->queued |= TOUCHPAD_EVENT_MOTION;
}

static inline void
tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
{
	t->dirty = true;
	t->state = TOUCH_BEGIN;
271
	t->time = time;
272
	t->was_down = true;
273
	tp->nfingers_down++;
274
	t->palm.time = time;
275 276
	t->thumb.state = THUMB_STATE_MAYBE;
	t->thumb.first_touch_time = time;
277
	t->tap.is_thumb = false;
278
	assert(tp->nfingers_down >= 1);
279 280
}

281 282 283
/**
 * End a touch, even if the touch sequence is still active.
 */
284
static inline void
285
tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
286
{
287 288 289 290 291 292
	switch (t->state) {
	case TOUCH_HOVERING:
		t->state = TOUCH_NONE;
		/* fallthough */
	case TOUCH_NONE:
	case TOUCH_END:
293
		return;
294 295 296 297 298
	case TOUCH_BEGIN:
	case TOUCH_UPDATE:
		break;

	}
299 300

	t->dirty = true;
301
	t->palm.state = PALM_NONE;
302
	t->state = TOUCH_END;
303
	t->pinned.is_pinned = false;
304
	t->time = time;
305
	t->palm.time = 0;
306 307
	assert(tp->nfingers_down >= 1);
	tp->nfingers_down--;
308
	tp->queued |= TOUCHPAD_EVENT_MOTION;
309 310
}

311 312 313 314 315 316 317 318 319 320
/**
 * End the touch sequence on ABS_MT_TRACKING_ID -1 or when the BTN_TOOL_* 0 is received.
 */
static inline void
tp_end_sequence(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
{
	t->has_ended = true;
	tp_end_touch(tp, t, time);
}

321 322 323 324 325 326 327 328
static void
tp_stop_actions(struct tp_dispatch *tp, uint64_t time)
{
	tp_edge_scroll_stop_events(tp, time);
	tp_gesture_cancel(tp, time);
	tp_tap_suspend(tp, time);
}

329 330
struct normalized_coords
tp_get_delta(struct tp_touch *t)
331
{
332
	struct device_float_coords delta;
333
	const struct normalized_coords zero = { 0.0, 0.0 };
334

335
	if (t->history.count <= 1)
336 337
		return zero;

338 339 340 341
	delta.x = tp_motion_history_offset(t, 0)->point.x -
		  tp_motion_history_offset(t, 1)->point.x;
	delta.y = tp_motion_history_offset(t, 0)->point.y -
		  tp_motion_history_offset(t, 1)->point.y;
342 343

	return tp_normalize_delta(t->tp, delta);
344 345 346
}

static void
347 348
tp_process_absolute(struct tp_dispatch *tp,
		    const struct input_event *e,
349
		    uint64_t time)
350
{
351 352 353 354
	struct tp_touch *t = tp_current_touch(tp);

	switch(e->code) {
	case ABS_MT_POSITION_X:
355 356 357
		evdev_device_check_abs_axis_range(tp->device,
						  e->code,
						  e->value);
358
		t->point.x = e->value;
359
		t->time = time;
360
		t->dirty = true;
361
		tp->queued |= TOUCHPAD_EVENT_MOTION;
362 363
		break;
	case ABS_MT_POSITION_Y:
364 365 366
		evdev_device_check_abs_axis_range(tp->device,
						  e->code,
						  e->value);
367
		t->point.y = e->value;
368
		t->time = time;
369
		t->dirty = true;
370
		tp->queued |= TOUCHPAD_EVENT_MOTION;
371 372 373 374 375 376
		break;
	case ABS_MT_SLOT:
		tp->slot = e->value;
		break;
	case ABS_MT_TRACKING_ID:
		if (e->value != -1)
377
			tp_new_touch(tp, t, time);
378
		else
379
			tp_end_sequence(tp, t, time);
380
		break;
381 382
	case ABS_MT_PRESSURE:
		t->pressure = e->value;
383
		t->time = time;
384
		t->dirty = true;
385
		tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
386
		break;
387 388
	case ABS_MT_TOOL_TYPE:
		t->is_tool_palm = e->value == MT_TOOL_PALM;
389
		t->time = time;
390 391 392
		t->dirty = true;
		tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
		break;
393 394 395 396 397 398 399 400 401 402
	case ABS_MT_TOUCH_MAJOR:
		t->major = e->value;
		t->dirty = true;
		tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
		break;
	case ABS_MT_TOUCH_MINOR:
		t->minor = e->value;
		t->dirty = true;
		tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
		break;
403
	}
404 405
}

406 407 408
static void
tp_process_absolute_st(struct tp_dispatch *tp,
		       const struct input_event *e,
409
		       uint64_t time)
410 411 412 413 414
{
	struct tp_touch *t = tp_current_touch(tp);

	switch(e->code) {
	case ABS_X:
415 416 417
		evdev_device_check_abs_axis_range(tp->device,
						  e->code,
						  e->value);
418
		t->point.x = e->value;
419
		t->time = time;
420
		t->dirty = true;
421
		tp->queued |= TOUCHPAD_EVENT_MOTION;
422 423
		break;
	case ABS_Y:
424 425 426
		evdev_device_check_abs_axis_range(tp->device,
						  e->code,
						  e->value);
427
		t->point.y = e->value;
428
		t->time = time;
429 430 431
		t->dirty = true;
		tp->queued |= TOUCHPAD_EVENT_MOTION;
		break;
432 433
	case ABS_PRESSURE:
		t->pressure = e->value;
434
		t->time = time;
435 436 437
		t->dirty = true;
		tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
		break;
438 439 440
	}
}

441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
static inline void
tp_restore_synaptics_touches(struct tp_dispatch *tp,
			     uint64_t time)
{
	unsigned int i;
	unsigned int nfake_touches;

	nfake_touches = tp_fake_finger_count(tp);
	if (nfake_touches < 3)
		return;

	if (tp->nfingers_down >= nfake_touches ||
	    tp->nfingers_down == tp->num_slots)
		return;

	/* Synaptics devices may end touch 2 on BTN_TOOL_TRIPLETAP
	 * and start it again on the next frame with different coordinates
	 * (#91352). We search the touches we have, if there is one that has
	 * just ended despite us being on tripletap, we move it back to
	 * update.
	 */
	for (i = 0; i < tp->num_slots; i++) {
		struct tp_touch *t = tp_get_touch(tp, i);

		if (t->state != TOUCH_END)
			continue;

		/* new touch, move it through begin to update immediately */
		tp_new_touch(tp, t, time);
		tp_begin_touch(tp, t, time);
		t->state = TOUCH_UPDATE;
	}
}

475
static void
476 477
tp_process_fake_touches(struct tp_dispatch *tp,
			uint64_t time)
478 479 480
{
	struct tp_touch *t;
	unsigned int nfake_touches;
481
	unsigned int i, start;
482

483
	nfake_touches = tp_fake_finger_count(tp);
484 485
	if (nfake_touches == FAKE_FINGER_OVERFLOW)
		return;
486

487 488 489 490
	if (tp->device->model_flags &
	    EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD)
		tp_restore_synaptics_touches(tp, time);

491
	start = tp->has_mt ? tp->num_slots : 0;
492
	for (i = start; i < tp->ntouches; i++) {
493
		t = tp_get_touch(tp, i);
494
		if (i < nfake_touches)
495
			tp_new_touch(tp, t, time);
496
		else
497
			tp_end_sequence(tp, t, time);
498 499 500
	}
}

501 502 503 504 505 506 507 508
static void
tp_process_trackpoint_button(struct tp_dispatch *tp,
			     const struct input_event *e,
			     uint64_t time)
{
	struct evdev_dispatch *dispatch;
	struct input_event event;

509
	if (!tp->buttons.trackpoint)
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
		return;

	dispatch = tp->buttons.trackpoint->dispatch;

	event = *e;

	switch (event.code) {
	case BTN_0:
		event.code = BTN_LEFT;
		break;
	case BTN_1:
		event.code = BTN_RIGHT;
		break;
	case BTN_2:
		event.code = BTN_MIDDLE;
		break;
	default:
		return;
	}

	dispatch->interface->process(dispatch,
				     tp->buttons.trackpoint,
				     &event, time);
}

535 536 537
static void
tp_process_key(struct tp_dispatch *tp,
	       const struct input_event *e,
538
	       uint64_t time)
539 540 541 542 543
{
	switch (e->code) {
		case BTN_LEFT:
		case BTN_MIDDLE:
		case BTN_RIGHT:
544
			tp_process_button(tp, e, time);
545
			break;
546
		case BTN_TOUCH:
547
		case BTN_TOOL_FINGER:
548 549 550
		case BTN_TOOL_DOUBLETAP:
		case BTN_TOOL_TRIPLETAP:
		case BTN_TOOL_QUADTAP:
551
		case BTN_TOOL_QUINTTAP:
552
			tp_fake_finger_set(tp, e->code, !!e->value);
553
			break;
554 555 556 557 558
		case BTN_0:
		case BTN_1:
		case BTN_2:
			tp_process_trackpoint_button(tp, e, time);
			break;
559 560 561
	}
}

562
static void
563
tp_unpin_finger(const struct tp_dispatch *tp, struct tp_touch *t)
564
{
565 566
	struct phys_coords mm;
	struct device_coords delta;
567

568 569 570
	if (!t->pinned.is_pinned)
		return;

571 572 573 574
	delta.x = abs(t->point.x - t->pinned.center.x);
	delta.y = abs(t->point.y - t->pinned.center.y);

	mm = evdev_device_unit_delta_to_mm(tp->device, &delta);
575

576
	/* 1.5mm movement -> unpin */
577
	if (hypot(mm.x, mm.y) >= 1.5) {
578
		t->pinned.is_pinned = false;
579
		return;
580 581 582 583
	}
}

static void
584
tp_pin_fingers(struct tp_dispatch *tp)
585
{
586
	struct tp_touch *t;
587 588

	tp_for_each_touch(tp, t) {
589
		t->pinned.is_pinned = true;
590
		t->pinned.center = t->point;
591 592 593
	}
}

594
bool
595
tp_touch_active(const struct tp_dispatch *tp, const struct tp_touch *t)
596 597
{
	return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
598
		t->palm.state == PALM_NONE &&
599
		!t->pinned.is_pinned &&
600
		t->thumb.state != THUMB_STATE_YES &&
601 602
		tp_button_touch_active(tp, t) &&
		tp_edge_scroll_touch_active(tp, t);
603
}
604

605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
static inline bool
tp_palm_was_in_side_edge(const struct tp_dispatch *tp, const struct tp_touch *t)
{
	return t->palm.first.x < tp->palm.left_edge ||
	       t->palm.first.x > tp->palm.right_edge;
}

static inline bool
tp_palm_was_in_top_edge(const struct tp_dispatch *tp, const struct tp_touch *t)
{
	return t->palm.first.y < tp->palm.upper_edge;
}

static inline bool
tp_palm_in_side_edge(const struct tp_dispatch *tp, const struct tp_touch *t)
{
	return t->point.x < tp->palm.left_edge ||
	       t->point.x > tp->palm.right_edge;
}

static inline bool
tp_palm_in_top_edge(const struct tp_dispatch *tp, const struct tp_touch *t)
{
	return t->point.y < tp->palm.upper_edge;
}

static inline bool
tp_palm_in_edge(const struct tp_dispatch *tp, const struct tp_touch *t)
{
	return tp_palm_in_side_edge(tp, t) || tp_palm_in_top_edge(tp, t);
}

637
bool
638
tp_palm_tap_is_palm(const struct tp_dispatch *tp, const struct tp_touch *t)
639 640 641 642
{
	if (t->state != TOUCH_BEGIN)
		return false;

643
	if (!tp_palm_in_edge(tp, t))
644 645
		return false;

646 647
	evdev_log_debug(tp->device, "palm: palm-tap detected\n");
	return true;
648 649
}

650 651 652 653
static bool
tp_palm_detect_dwt_triggered(struct tp_dispatch *tp,
			     struct tp_touch *t,
			     uint64_t time)
654
{
655 656
	if (tp->dwt.dwt_enabled &&
	    tp->dwt.keyboard_active &&
657
	    t->state == TOUCH_BEGIN) {
658 659
		t->palm.state = PALM_TYPING;
		t->palm.first = t->point;
660
		return true;
661 662
	} else if (!tp->dwt.keyboard_active &&
		   t->state == TOUCH_UPDATE &&
Peter Hutterer's avatar
Peter Hutterer committed
663
		   t->palm.state == PALM_TYPING) {
664 665 666 667 668 669 670 671 672
		/* If a touch has started before the first or after the last
		   key press, release it on timeout. Benefit: a palm rested
		   while typing on the touchpad will be ignored, but a touch
		   started once we stop typing will be able to control the
		   pointer (alas not tap, etc.).
		   */
		if (t->palm.time == 0 ||
		    t->palm.time > tp->dwt.keyboard_last_press_time) {
			t->palm.state = PALM_NONE;
673 674
			evdev_log_debug(tp->device,
					"palm: touch released, timeout after typing\n");
675
		}
676 677
	}

678
	return false;
679 680
}

681 682 683 684
static bool
tp_palm_detect_trackpoint_triggered(struct tp_dispatch *tp,
				    struct tp_touch *t,
				    uint64_t time)
685
{
686
	if (!tp->palm.monitor_trackpoint)
687
		return false;
688

689 690 691 692
	if (t->palm.state == PALM_NONE &&
	    t->state == TOUCH_BEGIN &&
	    tp->palm.trackpoint_active) {
		t->palm.state = PALM_TRACKPOINT;
693
		return true;
694 695 696 697 698 699 700
	} else if (t->palm.state == PALM_TRACKPOINT &&
		   t->state == TOUCH_UPDATE &&
		   !tp->palm.trackpoint_active) {

		if (t->palm.time == 0 ||
		    t->palm.time > tp->palm.trackpoint_last_event_time) {
			t->palm.state = PALM_NONE;
701 702
			evdev_log_debug(tp->device,
				       "palm: touch released, timeout after trackpoint\n");
703 704 705
		}
	}

706
	return false;
707 708
}

709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
static bool
tp_palm_detect_tool_triggered(struct tp_dispatch *tp,
			      struct tp_touch *t,
			      uint64_t time)
{
	if (!tp->palm.use_mt_tool)
		return false;

	if (t->palm.state != PALM_NONE &&
	    t->palm.state != PALM_TOOL_PALM)
		return false;

	if (t->palm.state == PALM_NONE &&
	    t->is_tool_palm)
		t->palm.state = PALM_TOOL_PALM;
	else if (t->palm.state == PALM_TOOL_PALM &&
		 !t->is_tool_palm)
		t->palm.state = PALM_NONE;

	if (t->palm.state == PALM_TOOL_PALM)
		tp_stop_actions(tp, time);

	return t->palm.state == PALM_TOOL_PALM;
}

734 735 736 737
static inline bool
tp_palm_detect_move_out_of_edge(struct tp_dispatch *tp,
				struct tp_touch *t,
				uint64_t time)
738
{
739
	const int PALM_TIMEOUT = ms2us(200);
740
	int directions = 0;
741 742
	struct device_float_coords delta;
	int dirs;
743

744 745 746 747 748 749 750 751 752 753 754 755
	if (time < t->palm.time + PALM_TIMEOUT && !tp_palm_in_edge(tp, t)) {
		if (tp_palm_was_in_side_edge(tp, t))
			directions = NE|E|SE|SW|W|NW;
		else if (tp_palm_was_in_top_edge(tp, t))
			directions = S|SE|SW;

		if (directions) {
			delta = device_delta(t->point, t->palm.first);
			dirs = phys_get_direction(tp_phys_delta(tp, delta));
			if ((dirs & directions) && !(dirs & ~directions))
				return true;
		}
756 757 758 759 760
	}

	return false;
}

761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789
static inline bool
tp_palm_detect_multifinger(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
{
	struct tp_touch *other;

	if (tp->nfingers_down < 2)
		return false;

	/* If we have at least one other active non-palm touch make this
	 * touch non-palm too. This avoids palm detection during two-finger
	 * scrolling.
	 *
	 * Note: if both touches start in the palm zone within the same
	 * frame the second touch will still be PALM_NONE and thus detected
	 * here as non-palm touch. This is too niche to worry about for now.
	 */
	tp_for_each_touch(tp, other) {
		if (other == t)
			continue;

		if (tp_touch_active(tp, other) &&
		    other->palm.state == PALM_NONE) {
			return true;
		}
	}

	return false;
}

790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
static inline bool
tp_palm_detect_touch_size_triggered(struct tp_dispatch *tp,
				    struct tp_touch *t,
				    uint64_t time)
{
	if (!tp->palm.use_size)
		return false;

	/* If a finger size is large enough for palm, we stick with that and
	 * force the user to release and reset the finger */
	if (t->palm.state != PALM_NONE && t->palm.state != PALM_TOUCH_SIZE)
		return false;

	if (t->major > tp->palm.size_threshold ||
	    t->minor > tp->palm.size_threshold) {
805 806 807
		if (t->palm.state != PALM_TOUCH_SIZE)
			evdev_log_debug(tp->device,
					"palm: touch size exceeded\n");
808 809 810 811 812 813 814
		t->palm.state = PALM_TOUCH_SIZE;
		return true;
	}

	return false;
}

815 816 817 818
static inline bool
tp_palm_detect_edge(struct tp_dispatch *tp,
		    struct tp_touch *t,
		    uint64_t time)
819
{
820
	if (t->palm.state == PALM_EDGE) {
821 822
		if (tp_palm_detect_multifinger(tp, t, time)) {
			t->palm.state = PALM_NONE;
823
			evdev_log_debug(tp->device,
824 825 826 827 828 829 830
				  "palm: touch released, multiple fingers\n");

		/* If labelled a touch as palm, we unlabel as palm when
		   we move out of the palm edge zone within the timeout, provided
		   the direction is within 45 degrees of the horizontal.
		 */
		} else if (tp_palm_detect_move_out_of_edge(tp, t, time)) {
831
			t->palm.state = PALM_NONE;
832
			evdev_log_debug(tp->device,
833
				  "palm: touch released, out of edge zone\n");
834
		}
835
		return false;
836
	} else if (tp_palm_detect_multifinger(tp, t, time)) {
837
		return false;
838
	}
839 840 841

	/* palm must start in exclusion zone, it's ok to move into
	   the zone without being a palm */
842
	if (t->state != TOUCH_BEGIN || !tp_palm_in_edge(tp, t))
843
		return false;
844 845 846 847 848 849

	/* don't detect palm in software button areas, it's
	   likely that legitimate touches start in the area
	   covered by the exclusion zone */
	if (tp->buttons.is_clickpad &&
	    tp_button_is_inside_softbutton_area(tp, t))
850
		return false;
851

852
	if (tp_touch_get_edge(tp, t) & EDGE_RIGHT)
853
		return false;
854

855
	t->palm.state = PALM_EDGE;
856
	t->palm.time = time;
857
	t->palm.first = t->point;
858

859 860 861
	return true;
}

862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
static bool
tp_palm_detect_pressure_triggered(struct tp_dispatch *tp,
				  struct tp_touch *t,
				  uint64_t time)
{
	if (!tp->palm.use_pressure)
		return false;

	if (t->palm.state != PALM_NONE &&
	    t->palm.state != PALM_PRESSURE)
		return false;

	if (t->pressure > tp->palm.pressure_threshold)
		t->palm.state = PALM_PRESSURE;

	return t->palm.state == PALM_PRESSURE;
}

880 881 882
static void
tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
{
883 884
	const char *palm_state;
	enum touch_palm_state oldstate = t->palm.state;
885

886 887 888
	if (tp_palm_detect_pressure_triggered(tp, t, time))
		goto out;

889 890 891 892 893 894
	if (tp_palm_detect_dwt_triggered(tp, t, time))
		goto out;

	if (tp_palm_detect_trackpoint_triggered(tp, t, time))
		goto out;

895 896 897
	if (tp_palm_detect_tool_triggered(tp, t, time))
		goto out;

898 899 900
	if (tp_palm_detect_touch_size_triggered(tp, t, time))
		goto out;

901 902 903
	if (tp_palm_detect_edge(tp, t, time))
		goto out;

904 905 906 907 908 909 910 911 912
	/* Pressure is highest priority because it cannot be released and
	 * overrides all other checks. So we check once before anything else
	 * in case pressure triggers on a non-palm touch. And again after
	 * everything in case one of the others released but we have a
	 * pressure trigger now.
	 */
	if (tp_palm_detect_pressure_triggered(tp, t, time))
		goto out;

913
	return;
914
out:
915

916 917 918 919 920 921 922 923 924 925 926 927 928
	if (oldstate == t->palm.state)
		return;

	switch (t->palm.state) {
	case PALM_EDGE:
		palm_state = "edge";
		break;
	case PALM_TYPING:
		palm_state = "typing";
		break;
	case PALM_TRACKPOINT:
		palm_state = "trackpoint";
		break;
929 930 931
	case PALM_TOOL_PALM:
		palm_state = "tool-palm";
		break;
932 933 934
	case PALM_PRESSURE:
		palm_state = "pressure";
		break;
935 936 937
	case PALM_TOUCH_SIZE:
		palm_state = "touch size";
		break;
938 939 940 941 942
	case PALM_NONE:
	default:
		abort();
		break;
	}
943
	evdev_log_debug(tp->device,
944
		  "palm: palm detected (%s)\n",
945
		  palm_state);
946 947
}

948 949 950 951 952 953 954 955 956 957 958 959
static inline const char*
thumb_state_to_str(enum tp_thumb_state state)
{
	switch(state){
	CASE_RETURN_STRING(THUMB_STATE_NO);
	CASE_RETURN_STRING(THUMB_STATE_YES);
	CASE_RETURN_STRING(THUMB_STATE_MAYBE);
	}

	return NULL;
}

960
static void
961
tp_thumb_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
962
{
963 964 965 966 967
	enum tp_thumb_state state = t->thumb.state;

	/* once a thumb, always a thumb, once ruled out always ruled out */
	if (!tp->thumb.detect_thumbs ||
	    t->thumb.state != THUMB_STATE_MAYBE)
968 969
		return;

970 971 972 973 974 975 976
	if (t->point.y < tp->thumb.upper_thumb_line) {
		/* if a potential thumb is above the line, it won't ever
		 * label as thumb */
		t->thumb.state = THUMB_STATE_NO;
		goto out;
	}

977 978 979 980 981
	/* If the thumb moves by more than 7mm, it's not a resting thumb */
	if (t->state == TOUCH_BEGIN)
		t->thumb.initial = t->point;
	else if (t->state == TOUCH_UPDATE) {
		struct device_float_coords delta;
982
		struct phys_coords mm;
983 984

		delta = device_delta(t->point, t->thumb.initial);
985 986
		mm = tp_phys_delta(tp, delta);
		if (length_in_mm(mm) > 7) {
987 988 989 990 991
			t->thumb.state = THUMB_STATE_NO;
			goto out;
		}
	}

992
	/* Note: a thumb at the edge of the touchpad won't trigger the
993 994 995 996
	 * threshold, the surface area is usually too small. So we have a
	 * two-stage detection: pressure and time within the area.
	 * A finger that remains at the very bottom of the touchpad becomes
	 * a thumb.
997
	 */
998 999 1000 1001
	if (t->pressure > tp->thumb.threshold)
		t->thumb.state = THUMB_STATE_YES;
	else if (t->point.y > tp->thumb.lower_thumb_line &&
		 tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE &&
1002
		 t->thumb.first_touch_time + THUMB_MOVE_TIMEOUT < time)
1003
		t->thumb.state = THUMB_STATE_YES;
1004 1005 1006 1007 1008 1009 1010

	/* now what? we marked it as thumb, so:
	 *
	 * - pointer motion must ignore this touch
	 * - clickfinger must ignore this touch for finger count
	 * - software buttons are unaffected
	 * - edge scrolling unaffected
1011
	 * - gestures: unaffected
1012 1013 1014
	 * - tapping: honour thumb on begin, ignore it otherwise for now,
	 *   this gets a tad complicated otherwise
	 */
1015 1016
out:
	if (t->thumb.state != state)
1017
		evdev_log_debug(tp->device,
1018 1019 1020
			  "thumb state: %s → %s\n",
			  thumb_state_to_str(state),
			  thumb_state_to_str(t->thumb.state));
1021 1022
}

1023
static void
1024
tp_unhover_pressure(struct tp_dispatch *tp, uint64_t time)
1025 1026
{
	struct tp_touch *t;
1027 1028 1029
	int i;
	unsigned int nfake_touches;
	unsigned int real_fingers_down = 0;
1030

1031 1032 1033 1034 1035
	nfake_touches = tp_fake_finger_count(tp);
	if (nfake_touches == FAKE_FINGER_OVERFLOW)
		nfake_touches = 0;

	for (i = 0; i < (int)tp->num_slots; i++) {