1 /*
2  * Copyright © 2014-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 <errno.h>
27 #include <limits.h>
28 #include <math.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include "linux/input.h"
32 
33 #include "evdev-mt-touchpad.h"
34 
35 #define DEFAULT_BUTTON_ENTER_TIMEOUT ms2us(100)
36 #define DEFAULT_BUTTON_LEAVE_TIMEOUT ms2us(300)
37 
38 /*****************************************
39  * BEFORE YOU EDIT THIS FILE, look at the state diagram in
40  * doc/touchpad-softbutton-state-machine.svg, or online at
41  * https://drive.google.com/file/d/0B1NwWmji69nocUs1cVJTbkdwMFk/edit?usp=sharing
42  * (it's a http://draw.io diagram)
43  *
44  * Any changes in this file must be represented in the diagram.
45  *
46  * The state machine only affects the soft button area code.
47  */
48 
49 static inline const char*
button_state_to_str(enum button_state state)50 button_state_to_str(enum button_state state)
51 {
52 	switch(state) {
53 	CASE_RETURN_STRING(BUTTON_STATE_NONE);
54 	CASE_RETURN_STRING(BUTTON_STATE_AREA);
55 	CASE_RETURN_STRING(BUTTON_STATE_BOTTOM);
56 	CASE_RETURN_STRING(BUTTON_STATE_TOP);
57 	CASE_RETURN_STRING(BUTTON_STATE_TOP_NEW);
58 	CASE_RETURN_STRING(BUTTON_STATE_TOP_TO_IGNORE);
59 	CASE_RETURN_STRING(BUTTON_STATE_IGNORE);
60 	}
61 	return NULL;
62 }
63 
64 static inline const char*
button_event_to_str(enum button_event event)65 button_event_to_str(enum button_event event)
66 {
67 	switch(event) {
68 	CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_R);
69 	CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_M);
70 	CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_L);
71 	CASE_RETURN_STRING(BUTTON_EVENT_IN_TOP_R);
72 	CASE_RETURN_STRING(BUTTON_EVENT_IN_TOP_M);
73 	CASE_RETURN_STRING(BUTTON_EVENT_IN_TOP_L);
74 	CASE_RETURN_STRING(BUTTON_EVENT_IN_AREA);
75 	CASE_RETURN_STRING(BUTTON_EVENT_UP);
76 	CASE_RETURN_STRING(BUTTON_EVENT_PRESS);
77 	CASE_RETURN_STRING(BUTTON_EVENT_RELEASE);
78 	CASE_RETURN_STRING(BUTTON_EVENT_TIMEOUT);
79 	}
80 	return NULL;
81 }
82 
83 static inline bool
is_inside_bottom_button_area(const struct tp_dispatch * tp,const struct tp_touch * t)84 is_inside_bottom_button_area(const struct tp_dispatch *tp,
85 			     const struct tp_touch *t)
86 {
87 	return t->point.y >= tp->buttons.bottom_area.top_edge;
88 }
89 
90 static inline bool
is_inside_bottom_right_area(const struct tp_dispatch * tp,const struct tp_touch * t)91 is_inside_bottom_right_area(const struct tp_dispatch *tp,
92 			    const struct tp_touch *t)
93 {
94 	return is_inside_bottom_button_area(tp, t) &&
95 	       t->point.x > tp->buttons.bottom_area.rightbutton_left_edge;
96 }
97 
98 static inline bool
is_inside_bottom_middle_area(const struct tp_dispatch * tp,const struct tp_touch * t)99 is_inside_bottom_middle_area(const struct tp_dispatch *tp,
100 			   const struct tp_touch *t)
101 {
102 	return is_inside_bottom_button_area(tp, t) &&
103 	       !is_inside_bottom_right_area(tp, t) &&
104 	       t->point.x > tp->buttons.bottom_area.middlebutton_left_edge;
105 }
106 
107 static inline bool
is_inside_bottom_left_area(const struct tp_dispatch * tp,const struct tp_touch * t)108 is_inside_bottom_left_area(const struct tp_dispatch *tp,
109 			   const struct tp_touch *t)
110 {
111 	return is_inside_bottom_button_area(tp, t) &&
112 	       !is_inside_bottom_middle_area(tp, t) &&
113 	       !is_inside_bottom_right_area(tp, t);
114 }
115 
116 static inline bool
is_inside_top_button_area(const struct tp_dispatch * tp,const struct tp_touch * t)117 is_inside_top_button_area(const struct tp_dispatch *tp,
118 			  const struct tp_touch *t)
119 {
120 	return t->point.y <= tp->buttons.top_area.bottom_edge;
121 }
122 
123 static inline bool
is_inside_top_right_area(const struct tp_dispatch * tp,const struct tp_touch * t)124 is_inside_top_right_area(const struct tp_dispatch *tp,
125 			 const struct tp_touch *t)
126 {
127 	return is_inside_top_button_area(tp, t) &&
128 	       t->point.x > tp->buttons.top_area.rightbutton_left_edge;
129 }
130 
131 static inline bool
is_inside_top_left_area(const struct tp_dispatch * tp,const struct tp_touch * t)132 is_inside_top_left_area(const struct tp_dispatch *tp,
133 			const struct tp_touch *t)
134 {
135 	return is_inside_top_button_area(tp, t) &&
136 	       t->point.x < tp->buttons.top_area.leftbutton_right_edge;
137 }
138 
139 static inline bool
is_inside_top_middle_area(const struct tp_dispatch * tp,const struct tp_touch * t)140 is_inside_top_middle_area(const struct tp_dispatch *tp,
141 			  const struct tp_touch *t)
142 {
143 	return is_inside_top_button_area(tp, t) &&
144 	       t->point.x >= tp->buttons.top_area.leftbutton_right_edge &&
145 	       t->point.x <= tp->buttons.top_area.rightbutton_left_edge;
146 }
147 
148 static void
tp_button_set_enter_timer(struct tp_dispatch * tp,struct tp_touch * t)149 tp_button_set_enter_timer(struct tp_dispatch *tp, struct tp_touch *t)
150 {
151 	libinput_timer_set(&t->button.timer,
152 			   t->time + DEFAULT_BUTTON_ENTER_TIMEOUT);
153 }
154 
155 static void
tp_button_set_leave_timer(struct tp_dispatch * tp,struct tp_touch * t)156 tp_button_set_leave_timer(struct tp_dispatch *tp, struct tp_touch *t)
157 {
158 	libinput_timer_set(&t->button.timer,
159 			   t->time + DEFAULT_BUTTON_LEAVE_TIMEOUT);
160 }
161 
162 /*
163  * tp_button_set_state, change state and implement on-entry behavior
164  * as described in the state machine diagram.
165  */
166 static void
tp_button_set_state(struct tp_dispatch * tp,struct tp_touch * t,enum button_state new_state,enum button_event event)167 tp_button_set_state(struct tp_dispatch *tp,
168 		    struct tp_touch *t,
169 		    enum button_state new_state,
170 		    enum button_event event)
171 {
172 	libinput_timer_cancel(&t->button.timer);
173 
174 	t->button.state = new_state;
175 
176 	switch (t->button.state) {
177 	case BUTTON_STATE_NONE:
178 		t->button.current = 0;
179 		break;
180 	case BUTTON_STATE_AREA:
181 		t->button.current = BUTTON_EVENT_IN_AREA;
182 		break;
183 	case BUTTON_STATE_BOTTOM:
184 		t->button.current = event;
185 		break;
186 	case BUTTON_STATE_TOP:
187 		break;
188 	case BUTTON_STATE_TOP_NEW:
189 		t->button.current = event;
190 		tp_button_set_enter_timer(tp, t);
191 		break;
192 	case BUTTON_STATE_TOP_TO_IGNORE:
193 		tp_button_set_leave_timer(tp, t);
194 		break;
195 	case BUTTON_STATE_IGNORE:
196 		t->button.current = 0;
197 		break;
198 	}
199 }
200 
201 static void
tp_button_none_handle_event(struct tp_dispatch * tp,struct tp_touch * t,enum button_event event)202 tp_button_none_handle_event(struct tp_dispatch *tp,
203 			    struct tp_touch *t,
204 			    enum button_event event)
205 {
206 	switch (event) {
207 	case BUTTON_EVENT_IN_BOTTOM_R:
208 	case BUTTON_EVENT_IN_BOTTOM_M:
209 	case BUTTON_EVENT_IN_BOTTOM_L:
210 		tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM, event);
211 		break;
212 	case BUTTON_EVENT_IN_TOP_R:
213 	case BUTTON_EVENT_IN_TOP_M:
214 	case BUTTON_EVENT_IN_TOP_L:
215 		tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW, event);
216 		break;
217 	case BUTTON_EVENT_IN_AREA:
218 		tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
219 		break;
220 	case BUTTON_EVENT_UP:
221 		tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
222 		break;
223 	case BUTTON_EVENT_PRESS:
224 	case BUTTON_EVENT_RELEASE:
225 	case BUTTON_EVENT_TIMEOUT:
226 		break;
227 	}
228 }
229 
230 static void
tp_button_area_handle_event(struct tp_dispatch * tp,struct tp_touch * t,enum button_event event)231 tp_button_area_handle_event(struct tp_dispatch *tp,
232 			    struct tp_touch *t,
233 			    enum button_event event)
234 {
235 	switch (event) {
236 	case BUTTON_EVENT_IN_BOTTOM_R:
237 	case BUTTON_EVENT_IN_BOTTOM_M:
238 	case BUTTON_EVENT_IN_BOTTOM_L:
239 	case BUTTON_EVENT_IN_TOP_R:
240 	case BUTTON_EVENT_IN_TOP_M:
241 	case BUTTON_EVENT_IN_TOP_L:
242 	case BUTTON_EVENT_IN_AREA:
243 		break;
244 	case BUTTON_EVENT_UP:
245 		tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
246 		break;
247 	case BUTTON_EVENT_PRESS:
248 	case BUTTON_EVENT_RELEASE:
249 	case BUTTON_EVENT_TIMEOUT:
250 		break;
251 	}
252 }
253 
254 /**
255  * Release any button in the bottom area, provided it started within a
256  * threshold around start_time (i.e. simultaneously with the other touch
257  * that triggered this call).
258  */
259 static inline void
tp_button_release_other_bottom_touches(struct tp_dispatch * tp,uint64_t other_start_time)260 tp_button_release_other_bottom_touches(struct tp_dispatch *tp,
261 				       uint64_t other_start_time)
262 {
263 	struct tp_touch *t;
264 
265 	tp_for_each_touch(tp, t) {
266 		uint64_t tdelta;
267 
268 		if (t->button.state != BUTTON_STATE_BOTTOM ||
269 		    t->button.has_moved)
270 			continue;
271 
272 		if (other_start_time > t->button.initial_time)
273 			tdelta = other_start_time - t->button.initial_time;
274 		else
275 			tdelta = t->button.initial_time - other_start_time;
276 
277 		if (tdelta > ms2us(80))
278 			continue;
279 
280 		t->button.has_moved = true;
281 	}
282 }
283 
284 static void
tp_button_bottom_handle_event(struct tp_dispatch * tp,struct tp_touch * t,enum button_event event)285 tp_button_bottom_handle_event(struct tp_dispatch *tp,
286 			      struct tp_touch *t,
287 			      enum button_event event)
288 {
289 	switch (event) {
290 	case BUTTON_EVENT_IN_BOTTOM_R:
291 	case BUTTON_EVENT_IN_BOTTOM_M:
292 	case BUTTON_EVENT_IN_BOTTOM_L:
293 		if (event != t->button.current)
294 			tp_button_set_state(tp,
295 					    t,
296 					    BUTTON_STATE_BOTTOM,
297 					    event);
298 		break;
299 	case BUTTON_EVENT_IN_TOP_R:
300 	case BUTTON_EVENT_IN_TOP_M:
301 	case BUTTON_EVENT_IN_TOP_L:
302 	case BUTTON_EVENT_IN_AREA:
303 		tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
304 
305 		/* We just transitioned one finger from BOTTOM to AREA,
306 		 * if there are other fingers in BOTTOM that started
307 		 * simultaneously with this finger, release those fingers
308 		 * because they're part of a gesture.
309 		 */
310 		tp_button_release_other_bottom_touches(tp,
311 						       t->button.initial_time);
312 		break;
313 	case BUTTON_EVENT_UP:
314 		tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
315 		break;
316 	case BUTTON_EVENT_PRESS:
317 	case BUTTON_EVENT_RELEASE:
318 	case BUTTON_EVENT_TIMEOUT:
319 		break;
320 	}
321 }
322 
323 static void
tp_button_top_handle_event(struct tp_dispatch * tp,struct tp_touch * t,enum button_event event)324 tp_button_top_handle_event(struct tp_dispatch *tp,
325 			   struct tp_touch *t,
326 			   enum button_event event)
327 {
328 	switch (event) {
329 	case BUTTON_EVENT_IN_BOTTOM_R:
330 	case BUTTON_EVENT_IN_BOTTOM_M:
331 	case BUTTON_EVENT_IN_BOTTOM_L:
332 		tp_button_set_state(tp, t, BUTTON_STATE_TOP_TO_IGNORE, event);
333 		break;
334 	case BUTTON_EVENT_IN_TOP_R:
335 	case BUTTON_EVENT_IN_TOP_M:
336 	case BUTTON_EVENT_IN_TOP_L:
337 		if (event != t->button.current)
338 			tp_button_set_state(tp,
339 					    t,
340 					    BUTTON_STATE_TOP_NEW,
341 					    event);
342 		break;
343 	case BUTTON_EVENT_IN_AREA:
344 		tp_button_set_state(tp, t, BUTTON_STATE_TOP_TO_IGNORE, event);
345 		break;
346 	case BUTTON_EVENT_UP:
347 		tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
348 		break;
349 	case BUTTON_EVENT_PRESS:
350 	case BUTTON_EVENT_RELEASE:
351 	case BUTTON_EVENT_TIMEOUT:
352 		break;
353 	}
354 }
355 
356 static void
tp_button_top_new_handle_event(struct tp_dispatch * tp,struct tp_touch * t,enum button_event event)357 tp_button_top_new_handle_event(struct tp_dispatch *tp,
358 			       struct tp_touch *t,
359 			       enum button_event event)
360 {
361 	switch(event) {
362 	case BUTTON_EVENT_IN_BOTTOM_R:
363 	case BUTTON_EVENT_IN_BOTTOM_M:
364 	case BUTTON_EVENT_IN_BOTTOM_L:
365 		tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
366 		break;
367 	case BUTTON_EVENT_IN_TOP_R:
368 	case BUTTON_EVENT_IN_TOP_M:
369 	case BUTTON_EVENT_IN_TOP_L:
370 		if (event != t->button.current)
371 			tp_button_set_state(tp,
372 					    t,
373 					    BUTTON_STATE_TOP_NEW,
374 					    event);
375 		break;
376 	case BUTTON_EVENT_IN_AREA:
377 		tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
378 		break;
379 	case BUTTON_EVENT_UP:
380 		tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
381 		break;
382 	case BUTTON_EVENT_PRESS:
383 		tp_button_set_state(tp, t, BUTTON_STATE_TOP, event);
384 		break;
385 	case BUTTON_EVENT_RELEASE:
386 		break;
387 	case BUTTON_EVENT_TIMEOUT:
388 		tp_button_set_state(tp, t, BUTTON_STATE_TOP, event);
389 		break;
390 	}
391 }
392 
393 static void
tp_button_top_to_ignore_handle_event(struct tp_dispatch * tp,struct tp_touch * t,enum button_event event)394 tp_button_top_to_ignore_handle_event(struct tp_dispatch *tp,
395 				     struct tp_touch *t,
396 				     enum button_event event)
397 {
398 	switch(event) {
399 	case BUTTON_EVENT_IN_TOP_R:
400 	case BUTTON_EVENT_IN_TOP_M:
401 	case BUTTON_EVENT_IN_TOP_L:
402 		if (event == t->button.current)
403 			tp_button_set_state(tp,
404 					    t,
405 					    BUTTON_STATE_TOP,
406 					    event);
407 		else
408 			tp_button_set_state(tp,
409 					    t,
410 					    BUTTON_STATE_TOP_NEW,
411 					    event);
412 		break;
413 	case BUTTON_EVENT_IN_BOTTOM_R:
414 	case BUTTON_EVENT_IN_BOTTOM_M:
415 	case BUTTON_EVENT_IN_BOTTOM_L:
416 	case BUTTON_EVENT_IN_AREA:
417 		break;
418 	case BUTTON_EVENT_UP:
419 		tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
420 		break;
421 	case BUTTON_EVENT_PRESS:
422 	case BUTTON_EVENT_RELEASE:
423 		break;
424 	case BUTTON_EVENT_TIMEOUT:
425 		tp_button_set_state(tp, t, BUTTON_STATE_IGNORE, event);
426 		break;
427 	}
428 }
429 
430 static void
tp_button_ignore_handle_event(struct tp_dispatch * tp,struct tp_touch * t,enum button_event event)431 tp_button_ignore_handle_event(struct tp_dispatch *tp,
432 			      struct tp_touch *t,
433 			      enum button_event event)
434 {
435 	switch (event) {
436 	case BUTTON_EVENT_IN_BOTTOM_R:
437 	case BUTTON_EVENT_IN_BOTTOM_M:
438 	case BUTTON_EVENT_IN_BOTTOM_L:
439 	case BUTTON_EVENT_IN_TOP_R:
440 	case BUTTON_EVENT_IN_TOP_M:
441 	case BUTTON_EVENT_IN_TOP_L:
442 	case BUTTON_EVENT_IN_AREA:
443 		break;
444 	case BUTTON_EVENT_UP:
445 		tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
446 		break;
447 	case BUTTON_EVENT_PRESS:
448 		t->button.current = BUTTON_EVENT_IN_AREA;
449 		break;
450 	case BUTTON_EVENT_RELEASE:
451 		break;
452 	case BUTTON_EVENT_TIMEOUT:
453 		break;
454 	}
455 }
456 
457 static void
tp_button_handle_event(struct tp_dispatch * tp,struct tp_touch * t,enum button_event event,uint64_t time)458 tp_button_handle_event(struct tp_dispatch *tp,
459 		       struct tp_touch *t,
460 		       enum button_event event,
461 		       uint64_t time)
462 {
463 	enum button_state current = t->button.state;
464 
465 	switch(t->button.state) {
466 	case BUTTON_STATE_NONE:
467 		tp_button_none_handle_event(tp, t, event);
468 		break;
469 	case BUTTON_STATE_AREA:
470 		tp_button_area_handle_event(tp, t, event);
471 		break;
472 	case BUTTON_STATE_BOTTOM:
473 		tp_button_bottom_handle_event(tp, t, event);
474 		break;
475 	case BUTTON_STATE_TOP:
476 		tp_button_top_handle_event(tp, t, event);
477 		break;
478 	case BUTTON_STATE_TOP_NEW:
479 		tp_button_top_new_handle_event(tp, t, event);
480 		break;
481 	case BUTTON_STATE_TOP_TO_IGNORE:
482 		tp_button_top_to_ignore_handle_event(tp, t, event);
483 		break;
484 	case BUTTON_STATE_IGNORE:
485 		tp_button_ignore_handle_event(tp, t, event);
486 		break;
487 	}
488 
489 	if (current != t->button.state)
490 		evdev_log_debug(tp->device,
491 				"button state: touch %d from %-20s event %-24s to %-20s\n",
492 				t->index,
493 				button_state_to_str(current),
494 				button_event_to_str(event),
495 				button_state_to_str(t->button.state));
496 }
497 
498 static inline void
tp_button_check_for_movement(struct tp_dispatch * tp,struct tp_touch * t)499 tp_button_check_for_movement(struct tp_dispatch *tp, struct tp_touch *t)
500 {
501 	struct device_coords delta;
502 	struct phys_coords mm;
503 	double vector_length;
504 
505 	if (t->button.has_moved)
506 		return;
507 
508 	switch (t->button.state) {
509 	case BUTTON_STATE_NONE:
510 	case BUTTON_STATE_AREA:
511 	case BUTTON_STATE_TOP:
512 	case BUTTON_STATE_TOP_NEW:
513 	case BUTTON_STATE_TOP_TO_IGNORE:
514 	case BUTTON_STATE_IGNORE:
515 		/* No point calculating if we're not going to use it */
516 		return;
517 	case BUTTON_STATE_BOTTOM:
518 		break;
519 	}
520 
521 	delta.x = t->point.x - t->button.initial.x;
522 	delta.y = t->point.y - t->button.initial.y;
523 	mm = evdev_device_unit_delta_to_mm(tp->device, &delta);
524 	vector_length = hypot(mm.x, mm.y);
525 
526 	if (vector_length > 5.0 /* mm */) {
527 		t->button.has_moved = true;
528 
529 		tp_button_release_other_bottom_touches(tp,
530 						       t->button.initial_time);
531 	}
532 }
533 
534 void
tp_button_handle_state(struct tp_dispatch * tp,uint64_t time)535 tp_button_handle_state(struct tp_dispatch *tp, uint64_t time)
536 {
537 	struct tp_touch *t;
538 
539 	tp_for_each_touch(tp, t) {
540 		if (t->state == TOUCH_NONE || t->state == TOUCH_HOVERING)
541 			continue;
542 
543 		if (t->state == TOUCH_BEGIN) {
544 			t->button.initial = t->point;
545 			t->button.initial_time = time;
546 			t->button.has_moved = false;
547 		}
548 
549 		if (t->state == TOUCH_END) {
550 			tp_button_handle_event(tp, t, BUTTON_EVENT_UP, time);
551 		} else if (t->dirty) {
552 			enum button_event event;
553 
554 			if (is_inside_bottom_button_area(tp, t)) {
555 				if (is_inside_bottom_right_area(tp, t))
556 					event = BUTTON_EVENT_IN_BOTTOM_R;
557 				else if (is_inside_bottom_middle_area(tp, t))
558 					event = BUTTON_EVENT_IN_BOTTOM_M;
559 				else
560 					event = BUTTON_EVENT_IN_BOTTOM_L;
561 
562 				/* In the bottom area we check for movement
563 				 * within the area. Top area - meh */
564 				tp_button_check_for_movement(tp, t);
565 			} else if (is_inside_top_button_area(tp, t)) {
566 				if (is_inside_top_right_area(tp, t))
567 					event = BUTTON_EVENT_IN_TOP_R;
568 				else if (is_inside_top_middle_area(tp, t))
569 					event = BUTTON_EVENT_IN_TOP_M;
570 				else
571 					event = BUTTON_EVENT_IN_TOP_L;
572 			} else {
573 				event = BUTTON_EVENT_IN_AREA;
574 			}
575 
576 			tp_button_handle_event(tp, t, event, time);
577 		}
578 		if (tp->queued & TOUCHPAD_EVENT_BUTTON_RELEASE)
579 			tp_button_handle_event(tp, t, BUTTON_EVENT_RELEASE, time);
580 		if (tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS)
581 			tp_button_handle_event(tp, t, BUTTON_EVENT_PRESS, time);
582 	}
583 }
584 
585 static void
tp_button_handle_timeout(uint64_t now,void * data)586 tp_button_handle_timeout(uint64_t now, void *data)
587 {
588 	struct tp_touch *t = data;
589 
590 	tp_button_handle_event(t->tp, t, BUTTON_EVENT_TIMEOUT, now);
591 }
592 
593 void
tp_process_button(struct tp_dispatch * tp,const struct input_event * e,uint64_t time)594 tp_process_button(struct tp_dispatch *tp,
595 		  const struct input_event *e,
596 		  uint64_t time)
597 {
598 	uint32_t mask = 1 << (e->code - BTN_LEFT);
599 
600 	/* Ignore other buttons on clickpads */
601 	if (tp->buttons.is_clickpad && e->code != BTN_LEFT) {
602 		evdev_log_bug_kernel(tp->device,
603 				     "received %s button event on a clickpad\n",
604 				     libevdev_event_code_get_name(EV_KEY, e->code));
605 		return;
606 	}
607 
608 	if (e->value) {
609 		tp->buttons.state |= mask;
610 		tp->queued |= TOUCHPAD_EVENT_BUTTON_PRESS;
611 	} else {
612 		tp->buttons.state &= ~mask;
613 		tp->queued |= TOUCHPAD_EVENT_BUTTON_RELEASE;
614 	}
615 }
616 
617 void
tp_release_all_buttons(struct tp_dispatch * tp,uint64_t time)618 tp_release_all_buttons(struct tp_dispatch *tp,
619 		       uint64_t time)
620 {
621 	if (tp->buttons.state) {
622 		tp->buttons.state = 0;
623 		tp->queued |= TOUCHPAD_EVENT_BUTTON_RELEASE;
624 	}
625 }
626 
627 static void
tp_init_softbuttons(struct tp_dispatch * tp,struct evdev_device * device)628 tp_init_softbuttons(struct tp_dispatch *tp,
629 		    struct evdev_device *device)
630 {
631 	double width, height;
632 	struct device_coords edges;
633 	int mb_le, mb_re; /* middle button left/right edge */
634 	struct phys_coords mm = { 0.0, 0.0 };
635 
636 	evdev_device_get_size(device, &width, &height);
637 
638 	/* button height: 10mm or 15% or the touchpad height,
639 	   whichever is smaller */
640 	if (height * 0.15 > 10)
641 		mm.y = height - 10;
642 	else
643 		mm.y = height * 0.85;
644 
645 	mm.x = width * 0.5;
646 	edges = evdev_device_mm_to_units(device, &mm);
647 	tp->buttons.bottom_area.top_edge = edges.y;
648 	tp->buttons.bottom_area.rightbutton_left_edge = edges.x;
649 
650 	tp->buttons.bottom_area.middlebutton_left_edge = INT_MAX;
651 
652 	/* if middlebutton emulation is enabled, don't init a software area */
653 	if (device->middlebutton.want_enabled)
654 		return;
655 
656 	/* The middle button is 25% of the touchpad and centered. Many
657 	 * touchpads don't have markings for the middle button at all so we
658 	 * need to make it big enough to reliably hit it but not too big so
659 	 * it takes away all the space.
660 	 *
661 	 * On touchpads with visible markings we reduce the size of the
662 	 * middle button since users have a visual guide.
663 	 */
664 	if (evdev_device_has_model_quirk(device,
665 					 QUIRK_MODEL_TOUCHPAD_VISIBLE_MARKER)) {
666 		mm.x = width/2 - 5; /* 10mm wide */
667 		edges = evdev_device_mm_to_units(device, &mm);
668 		mb_le = edges.x;
669 
670 		mm.x = width/2 + 5; /* 10mm wide */
671 		edges = evdev_device_mm_to_units(device, &mm);
672 		mb_re = edges.x;
673 	} else {
674 		mm.x = width * 0.375;
675 		edges = evdev_device_mm_to_units(device, &mm);
676 		mb_le = edges.x;
677 
678 		mm.x = width * 0.625;
679 		edges = evdev_device_mm_to_units(device, &mm);
680 		mb_re = edges.x;
681 	}
682 
683 	tp->buttons.bottom_area.middlebutton_left_edge = mb_le;
684 	tp->buttons.bottom_area.rightbutton_left_edge = mb_re;
685 }
686 
687 void
tp_init_top_softbuttons(struct tp_dispatch * tp,struct evdev_device * device,double topbutton_size_mult)688 tp_init_top_softbuttons(struct tp_dispatch *tp,
689 			struct evdev_device *device,
690 			double topbutton_size_mult)
691 {
692 	struct device_coords edges;
693 
694 	if (tp->buttons.has_topbuttons) {
695 		/* T440s has the top button line 5mm from the top, event
696 		   analysis has shown events to start down to ~10mm from the
697 		   top - which maps to 15%.  We allow the caller to enlarge the
698 		   area using a multiplier for the touchpad disabled case. */
699 		double topsize_mm = 10 * topbutton_size_mult;
700 		struct phys_coords mm;
701 		double width, height;
702 
703 		evdev_device_get_size(device, &width, &height);
704 
705 		mm.x = width * 0.60;
706 		mm.y = topsize_mm;
707 		edges = evdev_device_mm_to_units(device, &mm);
708 		tp->buttons.top_area.bottom_edge = edges.y;
709 		tp->buttons.top_area.rightbutton_left_edge = edges.x;
710 
711 		mm.x = width * 0.40;
712 		edges = evdev_device_mm_to_units(device, &mm);
713 		tp->buttons.top_area.leftbutton_right_edge = edges.x;
714 	} else {
715 		tp->buttons.top_area.bottom_edge = INT_MIN;
716 	}
717 }
718 
719 static inline uint32_t
tp_button_config_click_get_methods(struct libinput_device * device)720 tp_button_config_click_get_methods(struct libinput_device *device)
721 {
722 	struct evdev_device *evdev = evdev_device(device);
723 	struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
724 	uint32_t methods = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
725 
726 	if (tp->buttons.is_clickpad) {
727 		methods |= LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
728 		if (tp->has_mt)
729 			methods |= LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
730 	}
731 
732 	if (evdev->model_flags & EVDEV_MODEL_APPLE_TOUCHPAD_ONEBUTTON)
733 		methods |= LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
734 
735 	return methods;
736 }
737 
738 static void
tp_switch_click_method(struct tp_dispatch * tp)739 tp_switch_click_method(struct tp_dispatch *tp)
740 {
741 	/*
742 	 * All we need to do when switching click methods is to change the
743 	 * bottom_area.top_edge so that when in clickfinger mode the bottom
744 	 * touchpad area is not dead wrt finger movement starting there.
745 	 *
746 	 * We do not need to take any state into account, fingers which are
747 	 * already down will simply keep the state / area they have assigned
748 	 * until they are released, and the post_button_events path is state
749 	 * agnostic.
750 	 */
751 
752 	switch (tp->buttons.click_method) {
753 	case LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS:
754 		tp_init_softbuttons(tp, tp->device);
755 		break;
756 	case LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER:
757 	case LIBINPUT_CONFIG_CLICK_METHOD_NONE:
758 		tp->buttons.bottom_area.top_edge = INT_MAX;
759 		break;
760 	}
761 }
762 
763 static enum libinput_config_status
tp_button_config_click_set_method(struct libinput_device * device,enum libinput_config_click_method method)764 tp_button_config_click_set_method(struct libinput_device *device,
765 				  enum libinput_config_click_method method)
766 {
767 	struct evdev_device *evdev = evdev_device(device);
768 	struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
769 
770 	tp->buttons.click_method = method;
771 	tp_switch_click_method(tp);
772 
773 	return LIBINPUT_CONFIG_STATUS_SUCCESS;
774 }
775 
776 static enum libinput_config_click_method
tp_button_config_click_get_method(struct libinput_device * device)777 tp_button_config_click_get_method(struct libinput_device *device)
778 {
779 	struct evdev_device *evdev = evdev_device(device);
780 	struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
781 
782 	return tp->buttons.click_method;
783 }
784 
785 static enum libinput_config_click_method
tp_click_get_default_method(struct tp_dispatch * tp)786 tp_click_get_default_method(struct tp_dispatch *tp)
787 {
788 	struct evdev_device *device = tp->device;
789 
790 	if (evdev_device_has_model_quirk(device, QUIRK_MODEL_CHROMEBOOK) ||
791 	    evdev_device_has_model_quirk(device, QUIRK_MODEL_SYSTEM76_BONOBO) ||
792 	    evdev_device_has_model_quirk(device, QUIRK_MODEL_SYSTEM76_GALAGO) ||
793 	    evdev_device_has_model_quirk(device, QUIRK_MODEL_SYSTEM76_KUDU) ||
794 	    evdev_device_has_model_quirk(device, QUIRK_MODEL_CLEVO_W740SU) ||
795 	    evdev_device_has_model_quirk(device, QUIRK_MODEL_APPLE_TOUCHPAD_ONEBUTTON))
796 		return LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
797 
798 	if (!tp->buttons.is_clickpad)
799 		return LIBINPUT_CONFIG_CLICK_METHOD_NONE;
800 	else if (libevdev_get_id_vendor(tp->device->evdev) == VENDOR_ID_APPLE)
801 		return LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
802 
803 	return LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
804 }
805 
806 static enum libinput_config_click_method
tp_button_config_click_get_default_method(struct libinput_device * device)807 tp_button_config_click_get_default_method(struct libinput_device *device)
808 {
809 	struct evdev_device *evdev = evdev_device(device);
810 	struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
811 
812 	return tp_click_get_default_method(tp);
813 }
814 
815 void
tp_clickpad_middlebutton_apply_config(struct evdev_device * device)816 tp_clickpad_middlebutton_apply_config(struct evdev_device *device)
817 {
818 	struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
819 
820 	if (!tp->buttons.is_clickpad ||
821 	    tp->buttons.state != 0)
822 		return;
823 
824 	if (device->middlebutton.want_enabled ==
825 	    device->middlebutton.enabled)
826 		return;
827 
828 	device->middlebutton.enabled = device->middlebutton.want_enabled;
829 	if (tp->buttons.click_method ==
830 	    LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS)
831 		tp_init_softbuttons(tp, device);
832 }
833 
834 static int
tp_clickpad_middlebutton_is_available(struct libinput_device * device)835 tp_clickpad_middlebutton_is_available(struct libinput_device *device)
836 {
837 	return evdev_middlebutton_is_available(device);
838 }
839 
840 static enum libinput_config_status
tp_clickpad_middlebutton_set(struct libinput_device * device,enum libinput_config_middle_emulation_state enable)841 tp_clickpad_middlebutton_set(struct libinput_device *device,
842 		     enum libinput_config_middle_emulation_state enable)
843 {
844 	struct evdev_device *evdev = evdev_device(device);
845 
846 	switch (enable) {
847 	case LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED:
848 		evdev->middlebutton.want_enabled = true;
849 		break;
850 	case LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED:
851 		evdev->middlebutton.want_enabled = false;
852 		break;
853 	default:
854 		return LIBINPUT_CONFIG_STATUS_INVALID;
855 	}
856 
857 	tp_clickpad_middlebutton_apply_config(evdev);
858 
859 	return LIBINPUT_CONFIG_STATUS_SUCCESS;
860 }
861 
862 static enum libinput_config_middle_emulation_state
tp_clickpad_middlebutton_get(struct libinput_device * device)863 tp_clickpad_middlebutton_get(struct libinput_device *device)
864 {
865 	return evdev_middlebutton_get(device);
866 }
867 
868 static enum libinput_config_middle_emulation_state
tp_clickpad_middlebutton_get_default(struct libinput_device * device)869 tp_clickpad_middlebutton_get_default(struct libinput_device *device)
870 {
871 	return evdev_middlebutton_get_default(device);
872 }
873 
874 static inline void
tp_init_clickpad_middlebutton_emulation(struct tp_dispatch * tp,struct evdev_device * device)875 tp_init_clickpad_middlebutton_emulation(struct tp_dispatch *tp,
876 					struct evdev_device *device)
877 {
878 	device->middlebutton.enabled_default = false;
879 	device->middlebutton.want_enabled = false;
880 	device->middlebutton.enabled = false;
881 
882 	device->middlebutton.config.available = tp_clickpad_middlebutton_is_available;
883 	device->middlebutton.config.set = tp_clickpad_middlebutton_set;
884 	device->middlebutton.config.get = tp_clickpad_middlebutton_get;
885 	device->middlebutton.config.get_default = tp_clickpad_middlebutton_get_default;
886 	device->base.config.middle_emulation = &device->middlebutton.config;
887 }
888 
889 static inline void
tp_init_middlebutton_emulation(struct tp_dispatch * tp,struct evdev_device * device)890 tp_init_middlebutton_emulation(struct tp_dispatch *tp,
891 			       struct evdev_device *device)
892 {
893 	bool enable_by_default,
894 	     want_config_option;
895 
896 	/* On clickpads we provide the config option but disable by default.
897 	   When enabled, the middle software button disappears */
898 	if (tp->buttons.is_clickpad) {
899 		tp_init_clickpad_middlebutton_emulation(tp, device);
900 		return;
901 	}
902 
903 	/* init middle button emulation on non-clickpads, but only if we
904 	 * don't have a middle button. Exception: ALPS touchpads don't know
905 	 * if they have a middle button, so we always want the option there
906 	 * and enabled by default.
907 	 */
908 	if (!libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE)) {
909 		enable_by_default = true;
910 		want_config_option = false;
911 	} else if (evdev_device_has_model_quirk(device,
912 						QUIRK_MODEL_ALPS_TOUCHPAD)) {
913 		enable_by_default = true;
914 		want_config_option = true;
915 	} else
916 		return;
917 
918 	evdev_init_middlebutton(tp->device,
919 				enable_by_default,
920 				want_config_option);
921 }
922 
923 void
tp_init_buttons(struct tp_dispatch * tp,struct evdev_device * device)924 tp_init_buttons(struct tp_dispatch *tp,
925 		struct evdev_device *device)
926 {
927 	struct tp_touch *t;
928 	const struct input_absinfo *absinfo_x, *absinfo_y;
929 	int i;
930 
931 	tp->buttons.is_clickpad = libevdev_has_property(device->evdev,
932 							INPUT_PROP_BUTTONPAD);
933 	tp->buttons.has_topbuttons = libevdev_has_property(device->evdev,
934 						        INPUT_PROP_TOPBUTTONPAD);
935 
936 	if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE) ||
937 	    libevdev_has_event_code(device->evdev, EV_KEY, BTN_RIGHT)) {
938 		if (tp->buttons.is_clickpad)
939 			evdev_log_bug_kernel(device,
940 					     "clickpad advertising right button\n");
941 	} else if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_LEFT) &&
942 		   !tp->buttons.is_clickpad &&
943 		   libevdev_get_id_vendor(device->evdev) != VENDOR_ID_APPLE) {
944 			evdev_log_bug_kernel(device,
945 					     "non clickpad without right button?\n");
946 	}
947 
948 	absinfo_x = device->abs.absinfo_x;
949 	absinfo_y = device->abs.absinfo_y;
950 
951 	/* pinned-finger motion threshold, see tp_unpin_finger. */
952 	tp->buttons.motion_dist.x_scale_coeff = 1.0/absinfo_x->resolution;
953 	tp->buttons.motion_dist.y_scale_coeff = 1.0/absinfo_y->resolution;
954 
955 	tp->buttons.config_method.get_methods = tp_button_config_click_get_methods;
956 	tp->buttons.config_method.set_method = tp_button_config_click_set_method;
957 	tp->buttons.config_method.get_method = tp_button_config_click_get_method;
958 	tp->buttons.config_method.get_default_method = tp_button_config_click_get_default_method;
959 	tp->device->base.config.click_method = &tp->buttons.config_method;
960 
961 	tp->buttons.click_method = tp_click_get_default_method(tp);
962 	tp_switch_click_method(tp);
963 
964 	tp_init_top_softbuttons(tp, device, 1.0);
965 
966 	tp_init_middlebutton_emulation(tp, device);
967 
968 	i = 0;
969 	tp_for_each_touch(tp, t) {
970 		char timer_name[64];
971 		i++;
972 
973 		snprintf(timer_name,
974 			 sizeof(timer_name),
975 			 "%s (%d) button",
976 			 evdev_device_get_sysname(device),
977 			 i);
978 		t->button.state = BUTTON_STATE_NONE;
979 		libinput_timer_init(&t->button.timer,
980 				    tp_libinput_context(tp),
981 				    timer_name,
982 				    tp_button_handle_timeout, t);
983 	}
984 }
985 
986 void
tp_remove_buttons(struct tp_dispatch * tp)987 tp_remove_buttons(struct tp_dispatch *tp)
988 {
989 	struct tp_touch *t;
990 
991 	tp_for_each_touch(tp, t) {
992 		libinput_timer_cancel(&t->button.timer);
993 		libinput_timer_destroy(&t->button.timer);
994 	}
995 }
996 
997 static int
tp_post_physical_buttons(struct tp_dispatch * tp,uint64_t time)998 tp_post_physical_buttons(struct tp_dispatch *tp, uint64_t time)
999 {
1000 	uint32_t current, old, button;
1001 
1002 	current = tp->buttons.state;
1003 	old = tp->buttons.old_state;
1004 	button = BTN_LEFT;
1005 
1006 	while (current || old) {
1007 		enum libinput_button_state state;
1008 
1009 		if ((current & 0x1) ^ (old & 0x1)) {
1010 			uint32_t b;
1011 
1012 			if (!!(current & 0x1))
1013 				state = LIBINPUT_BUTTON_STATE_PRESSED;
1014 			else
1015 				state = LIBINPUT_BUTTON_STATE_RELEASED;
1016 
1017 			b = evdev_to_left_handed(tp->device, button);
1018 			evdev_pointer_notify_physical_button(tp->device,
1019 							     time,
1020 							     b,
1021 							     state);
1022 		}
1023 
1024 		button++;
1025 		current >>= 1;
1026 		old >>= 1;
1027 	}
1028 
1029 	return 0;
1030 }
1031 
1032 static inline bool
tp_clickfinger_within_distance(struct tp_dispatch * tp,struct tp_touch * t1,struct tp_touch * t2)1033 tp_clickfinger_within_distance(struct tp_dispatch *tp,
1034 			       struct tp_touch *t1,
1035 			       struct tp_touch *t2)
1036 {
1037 	double x, y;
1038 	bool within_distance = false;
1039 	int xres, yres;
1040 	int bottom_threshold;
1041 
1042 	if (!t1 || !t2)
1043 		return 0;
1044 
1045 	if (t1->thumb.state == THUMB_STATE_YES ||
1046 	    t2->thumb.state == THUMB_STATE_YES)
1047 		return 0;
1048 
1049 	x = abs(t1->point.x - t2->point.x);
1050 	y = abs(t1->point.y - t2->point.y);
1051 
1052 	xres = tp->device->abs.absinfo_x->resolution;
1053 	yres = tp->device->abs.absinfo_y->resolution;
1054 	x /= xres;
1055 	y /= yres;
1056 
1057 	/* maximum horiz spread is 40mm horiz, 30mm vert, anything wider
1058 	 * than that is probably a gesture. */
1059 	if (x > 40 || y > 30)
1060 		goto out;
1061 
1062 	within_distance = true;
1063 
1064 	/* if y spread is <= 20mm, they're definitely together. */
1065 	if (y <= 20)
1066 		goto out;
1067 
1068 	/* if they're vertically spread between 20-40mm, they're not
1069 	 * together if:
1070 	 * - the touchpad's vertical size is >50mm, anything smaller is
1071 	 *   unlikely to have a thumb resting on it
1072 	 * - and one of the touches is in the bottom 20mm of the touchpad
1073 	 *   and the other one isn't
1074 	 */
1075 
1076 	if (tp->device->abs.dimensions.y/yres < 50)
1077 		goto out;
1078 
1079 	bottom_threshold = tp->device->abs.absinfo_y->maximum - 20 * yres;
1080 	if ((t1->point.y > bottom_threshold) !=
1081 		    (t2->point.y > bottom_threshold))
1082 		within_distance = 0;
1083 
1084 out:
1085 	return within_distance;
1086 }
1087 
1088 static uint32_t
tp_clickfinger_set_button(struct tp_dispatch * tp)1089 tp_clickfinger_set_button(struct tp_dispatch *tp)
1090 {
1091 	uint32_t button;
1092 	unsigned int nfingers = 0;
1093 	struct tp_touch *t;
1094 	struct tp_touch *first = NULL,
1095 			*second = NULL;
1096 
1097 	tp_for_each_touch(tp, t) {
1098 		if (t->state != TOUCH_BEGIN && t->state != TOUCH_UPDATE)
1099 			continue;
1100 
1101 		if (t->thumb.state == THUMB_STATE_YES)
1102 			continue;
1103 
1104 		if (t->palm.state != PALM_NONE)
1105 			continue;
1106 
1107 		nfingers++;
1108 
1109 		if (!first)
1110 			first = t;
1111 		else if (!second)
1112 			second = t;
1113 	}
1114 
1115 	/* Only check for finger distance when there are 2 fingers on the
1116 	 * touchpad */
1117 	if (nfingers != 2)
1118 		goto out;
1119 
1120 	if (tp_clickfinger_within_distance(tp, first, second))
1121 		nfingers = 2;
1122 	else
1123 		nfingers = 1;
1124 
1125 out:
1126 	switch (nfingers) {
1127 	case 0:
1128 	case 1: button = BTN_LEFT; break;
1129 	case 2: button = BTN_RIGHT; break;
1130 	default:
1131 		button = BTN_MIDDLE; break;
1132 		break;
1133 	}
1134 
1135 	return button;
1136 }
1137 
1138 static int
tp_notify_clickpadbutton(struct tp_dispatch * tp,uint64_t time,uint32_t button,uint32_t is_topbutton,enum libinput_button_state state)1139 tp_notify_clickpadbutton(struct tp_dispatch *tp,
1140 			 uint64_t time,
1141 			 uint32_t button,
1142 			 uint32_t is_topbutton,
1143 			 enum libinput_button_state state)
1144 {
1145 	/* If we've a trackpoint, send top buttons through the trackpoint */
1146 	if (is_topbutton && tp->buttons.trackpoint) {
1147 		struct evdev_dispatch *dispatch = tp->buttons.trackpoint->dispatch;
1148 		struct input_event event;
1149 		struct input_event syn_report = {{ 0, 0 }, EV_SYN, SYN_REPORT, 0 };
1150 
1151 		event.time = us2tv(time);
1152 		event.type = EV_KEY;
1153 		event.code = button;
1154 		event.value = (state == LIBINPUT_BUTTON_STATE_PRESSED) ? 1 : 0;
1155 		syn_report.time = event.time;
1156 		dispatch->interface->process(dispatch,
1157 					     tp->buttons.trackpoint,
1158 					     &event,
1159 					     time);
1160 		dispatch->interface->process(dispatch,
1161 					     tp->buttons.trackpoint,
1162 					     &syn_report,
1163 					     time);
1164 		return 1;
1165 	}
1166 
1167 	/* Ignore button events not for the trackpoint while suspended */
1168 	if (tp->device->is_suspended)
1169 		return 0;
1170 
1171 	/* A button click always terminates edge scrolling, even if we
1172 	 * don't end up sending a button event. */
1173 	tp_edge_scroll_stop_events(tp, time);
1174 
1175 	/*
1176 	 * If the user has requested clickfinger replace the button chosen
1177 	 * by the softbutton code with one based on the number of fingers.
1178 	 */
1179 	if (tp->buttons.click_method == LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER &&
1180 	    state == LIBINPUT_BUTTON_STATE_PRESSED) {
1181 		button = tp_clickfinger_set_button(tp);
1182 		tp->buttons.active = button;
1183 
1184 		if (!button)
1185 			return 0;
1186 	}
1187 
1188 	evdev_pointer_notify_button(tp->device, time, button, state);
1189 	return 1;
1190 }
1191 
1192 static int
tp_post_clickpadbutton_buttons(struct tp_dispatch * tp,uint64_t time)1193 tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
1194 {
1195 	uint32_t current, old, button, is_top;
1196 	enum libinput_button_state state;
1197 	enum { AREA = 0x01, LEFT = 0x02, MIDDLE = 0x04, RIGHT = 0x08 };
1198 	bool want_left_handed = true;
1199 
1200 	current = tp->buttons.state;
1201 	old = tp->buttons.old_state;
1202 	is_top = 0;
1203 
1204 	if (!tp->buttons.click_pending && current == old)
1205 		return 0;
1206 
1207 	if (current) {
1208 		struct tp_touch *t;
1209 		uint32_t area = 0;
1210 
1211 		tp_for_each_touch(tp, t) {
1212 			switch (t->button.current) {
1213 			case BUTTON_EVENT_IN_AREA:
1214 				area |= AREA;
1215 				break;
1216 			case BUTTON_EVENT_IN_TOP_L:
1217 				is_top = 1;
1218 				/* fallthrough */
1219 			case BUTTON_EVENT_IN_BOTTOM_L:
1220 				area |= LEFT;
1221 				break;
1222 			case BUTTON_EVENT_IN_TOP_M:
1223 				is_top = 1;
1224 				/* fallthrough */
1225 			case BUTTON_EVENT_IN_BOTTOM_M:
1226 				area |= MIDDLE;
1227 				break;
1228 			case BUTTON_EVENT_IN_TOP_R:
1229 				is_top = 1;
1230 				/* fallthrough */
1231 			case BUTTON_EVENT_IN_BOTTOM_R:
1232 				area |= RIGHT;
1233 				break;
1234 			default:
1235 				break;
1236 			}
1237 		}
1238 
1239 		if (area == 0 &&
1240 		    tp->buttons.click_method != LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) {
1241 			/* No touches, wait for a touch before processing */
1242 			tp->buttons.click_pending = true;
1243 			return 0;
1244 		}
1245 
1246 		if ((tp->device->middlebutton.enabled || is_top) &&
1247 		    (area & LEFT) && (area & RIGHT)) {
1248 			button = BTN_MIDDLE;
1249 		} else if (area & MIDDLE) {
1250 			button = BTN_MIDDLE;
1251 		} else if (area & RIGHT) {
1252 			button = BTN_RIGHT;
1253 		} else if (area & LEFT) {
1254 			button = BTN_LEFT;
1255 		} else { /* main or no area (for clickfinger) is always BTN_LEFT */
1256 			button = BTN_LEFT;
1257 			want_left_handed = false;
1258 		}
1259 
1260 		if (is_top)
1261 			want_left_handed = false;
1262 
1263 		if (want_left_handed)
1264 			button = evdev_to_left_handed(tp->device, button);
1265 
1266 		tp->buttons.active = button;
1267 		tp->buttons.active_is_topbutton = is_top;
1268 		state = LIBINPUT_BUTTON_STATE_PRESSED;
1269 	} else {
1270 		button = tp->buttons.active;
1271 		is_top = tp->buttons.active_is_topbutton;
1272 		tp->buttons.active = 0;
1273 		tp->buttons.active_is_topbutton = 0;
1274 		state = LIBINPUT_BUTTON_STATE_RELEASED;
1275 	}
1276 
1277 	tp->buttons.click_pending = false;
1278 
1279 	if (button)
1280 		return tp_notify_clickpadbutton(tp,
1281 						time,
1282 						button,
1283 						is_top,
1284 						state);
1285 	return 0;
1286 }
1287 
1288 int
tp_post_button_events(struct tp_dispatch * tp,uint64_t time)1289 tp_post_button_events(struct tp_dispatch *tp, uint64_t time)
1290 {
1291 	if (tp->buttons.is_clickpad ||
1292 	    tp->device->model_flags & EVDEV_MODEL_APPLE_TOUCHPAD_ONEBUTTON)
1293 		return tp_post_clickpadbutton_buttons(tp, time);
1294 	else
1295 		return tp_post_physical_buttons(tp, time);
1296 }
1297 
1298 bool
tp_button_touch_active(const struct tp_dispatch * tp,const struct tp_touch * t)1299 tp_button_touch_active(const struct tp_dispatch *tp,
1300 		       const struct tp_touch *t)
1301 {
1302 	return t->button.state == BUTTON_STATE_AREA || t->button.has_moved;
1303 }
1304 
1305 bool
tp_button_is_inside_softbutton_area(const struct tp_dispatch * tp,const struct tp_touch * t)1306 tp_button_is_inside_softbutton_area(const struct tp_dispatch *tp,
1307 				    const struct tp_touch *t)
1308 {
1309 	return is_inside_top_button_area(tp, t) ||
1310 	       is_inside_bottom_button_area(tp, t);
1311 }
1312