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