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