Fix documentation for libinput_log_set_handler
[platform/upstream/libinput.git] / src / evdev-mt-touchpad-buttons.c
1 /*
2  * Copyright © 2014 Red Hat, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include <errno.h>
24 #include <limits.h>
25 #include <math.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include "linux/input.h"
29
30 #include "evdev-mt-touchpad.h"
31
32 #define DEFAULT_BUTTON_MOTION_THRESHOLD 0.02 /* 2% of size */
33 #define DEFAULT_BUTTON_ENTER_TIMEOUT 100 /* ms */
34 #define DEFAULT_BUTTON_LEAVE_TIMEOUT 300 /* ms */
35
36 /*****************************************
37  * BEFORE YOU EDIT THIS FILE, look at the state diagram in
38  * doc/touchpad-softbutton-state-machine.svg, or online at
39  * https://drive.google.com/file/d/0B1NwWmji69nocUs1cVJTbkdwMFk/edit?usp=sharing
40  * (it's a http://draw.io diagram)
41  *
42  * Any changes in this file must be represented in the diagram.
43  *
44  * The state machine only affects the soft button area code.
45  */
46
47 #define CASE_RETURN_STRING(a) case a: return #a;
48
49 static inline const char*
50 button_state_to_str(enum button_state state) {
51         switch(state) {
52         CASE_RETURN_STRING(BUTTON_STATE_NONE);
53         CASE_RETURN_STRING(BUTTON_STATE_AREA);
54         CASE_RETURN_STRING(BUTTON_STATE_BOTTOM);
55         CASE_RETURN_STRING(BUTTON_STATE_TOP);
56         CASE_RETURN_STRING(BUTTON_STATE_TOP_NEW);
57         CASE_RETURN_STRING(BUTTON_STATE_TOP_TO_IGNORE);
58         CASE_RETURN_STRING(BUTTON_STATE_IGNORE);
59         }
60         return NULL;
61 }
62
63 static inline const char*
64 button_event_to_str(enum button_event event) {
65         switch(event) {
66         CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_R);
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
81 is_inside_bottom_button_area(struct tp_dispatch *tp, struct tp_touch *t)
82 {
83         return t->y >= tp->buttons.bottom_area.top_edge;
84 }
85
86 static inline bool
87 is_inside_bottom_right_area(struct tp_dispatch *tp, struct tp_touch *t)
88 {
89         return is_inside_bottom_button_area(tp, t) &&
90                t->x > tp->buttons.bottom_area.rightbutton_left_edge;
91 }
92
93 static inline bool
94 is_inside_bottom_left_area(struct tp_dispatch *tp, struct tp_touch *t)
95 {
96         return is_inside_bottom_button_area(tp, t) &&
97                !is_inside_bottom_right_area(tp, t);
98 }
99
100 static inline bool
101 is_inside_top_button_area(struct tp_dispatch *tp, struct tp_touch *t)
102 {
103         return t->y <= tp->buttons.top_area.bottom_edge;
104 }
105
106 static inline bool
107 is_inside_top_right_area(struct tp_dispatch *tp, struct tp_touch *t)
108 {
109         return is_inside_top_button_area(tp, t) &&
110                t->x > tp->buttons.top_area.rightbutton_left_edge;
111 }
112
113 static inline bool
114 is_inside_top_left_area(struct tp_dispatch *tp, struct tp_touch *t)
115 {
116         return is_inside_top_button_area(tp, t) &&
117                t->x < tp->buttons.top_area.leftbutton_right_edge;
118 }
119
120 static inline bool
121 is_inside_top_middle_area(struct tp_dispatch *tp, struct tp_touch *t)
122 {
123         return is_inside_top_button_area(tp, t) &&
124                t->x >= tp->buttons.top_area.leftbutton_right_edge &&
125                t->x <= tp->buttons.top_area.rightbutton_left_edge;
126 }
127
128 static void
129 tp_button_set_enter_timer(struct tp_dispatch *tp, struct tp_touch *t)
130 {
131         libinput_timer_set(&t->button.timer,
132                            t->millis + DEFAULT_BUTTON_ENTER_TIMEOUT);
133 }
134
135 static void
136 tp_button_set_leave_timer(struct tp_dispatch *tp, struct tp_touch *t)
137 {
138         libinput_timer_set(&t->button.timer,
139                            t->millis + DEFAULT_BUTTON_LEAVE_TIMEOUT);
140 }
141
142 /*
143  * tp_button_set_state, change state and implement on-entry behavior
144  * as described in the state machine diagram.
145  */
146 static void
147 tp_button_set_state(struct tp_dispatch *tp, struct tp_touch *t,
148                     enum button_state new_state, enum button_event event)
149 {
150         libinput_timer_cancel(&t->button.timer);
151
152         t->button.state = new_state;
153         switch (t->button.state) {
154         case BUTTON_STATE_NONE:
155                 t->button.curr = 0;
156                 break;
157         case BUTTON_STATE_AREA:
158                 t->button.curr = BUTTON_EVENT_IN_AREA;
159                 tp_set_pointer(tp, t);
160                 break;
161         case BUTTON_STATE_BOTTOM:
162                 t->button.curr = event;
163                 break;
164         case BUTTON_STATE_TOP:
165                 break;
166         case BUTTON_STATE_TOP_NEW:
167                 t->button.curr = event;
168                 tp_button_set_enter_timer(tp, t);
169                 break;
170         case BUTTON_STATE_TOP_TO_IGNORE:
171                 tp_button_set_leave_timer(tp, t);
172                 break;
173         case BUTTON_STATE_IGNORE:
174                 t->button.curr = 0;
175                 break;
176         }
177 }
178
179 static void
180 tp_button_none_handle_event(struct tp_dispatch *tp,
181                             struct tp_touch *t,
182                             enum button_event event)
183 {
184         switch (event) {
185         case BUTTON_EVENT_IN_BOTTOM_R:
186         case BUTTON_EVENT_IN_BOTTOM_L:
187                 tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM, event);
188                 break;
189         case BUTTON_EVENT_IN_TOP_R:
190         case BUTTON_EVENT_IN_TOP_M:
191         case BUTTON_EVENT_IN_TOP_L:
192                 tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW, event);
193                 break;
194         case BUTTON_EVENT_IN_AREA:
195                 tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
196                 break;
197         case BUTTON_EVENT_UP:
198                 tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
199                 break;
200         case BUTTON_EVENT_PRESS:
201         case BUTTON_EVENT_RELEASE:
202         case BUTTON_EVENT_TIMEOUT:
203                 break;
204         }
205 }
206
207 static void
208 tp_button_area_handle_event(struct tp_dispatch *tp,
209                             struct tp_touch *t,
210                             enum button_event event)
211 {
212         switch (event) {
213         case BUTTON_EVENT_IN_BOTTOM_R:
214         case BUTTON_EVENT_IN_BOTTOM_L:
215         case BUTTON_EVENT_IN_TOP_R:
216         case BUTTON_EVENT_IN_TOP_M:
217         case BUTTON_EVENT_IN_TOP_L:
218         case BUTTON_EVENT_IN_AREA:
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
231 tp_button_bottom_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_L:
238                 if (event != t->button.curr)
239                         tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM,
240                                             event);
241                 break;
242         case BUTTON_EVENT_IN_TOP_R:
243         case BUTTON_EVENT_IN_TOP_M:
244         case BUTTON_EVENT_IN_TOP_L:
245         case BUTTON_EVENT_IN_AREA:
246                 tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
247                 break;
248         case BUTTON_EVENT_UP:
249                 tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
250                 break;
251         case BUTTON_EVENT_PRESS:
252         case BUTTON_EVENT_RELEASE:
253         case BUTTON_EVENT_TIMEOUT:
254                 break;
255         }
256 }
257
258 static void
259 tp_button_top_handle_event(struct tp_dispatch *tp,
260                             struct tp_touch *t,
261                             enum button_event event)
262 {
263         switch (event) {
264         case BUTTON_EVENT_IN_BOTTOM_R:
265         case BUTTON_EVENT_IN_BOTTOM_L:
266                 tp_button_set_state(tp, t, BUTTON_STATE_TOP_TO_IGNORE, event);
267                 break;
268         case BUTTON_EVENT_IN_TOP_R:
269         case BUTTON_EVENT_IN_TOP_M:
270         case BUTTON_EVENT_IN_TOP_L:
271                 if (event != t->button.curr)
272                         tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW,
273                                             event);
274                 break;
275         case BUTTON_EVENT_IN_AREA:
276                 tp_button_set_state(tp, t, BUTTON_STATE_TOP_TO_IGNORE, event);
277                 break;
278         case BUTTON_EVENT_UP:
279                 tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
280                 break;
281         case BUTTON_EVENT_PRESS:
282         case BUTTON_EVENT_RELEASE:
283         case BUTTON_EVENT_TIMEOUT:
284                 break;
285         }
286 }
287
288 static void
289 tp_button_top_new_handle_event(struct tp_dispatch *tp,
290                                 struct tp_touch *t,
291                                 enum button_event event)
292 {
293         switch(event) {
294         case BUTTON_EVENT_IN_BOTTOM_R:
295         case BUTTON_EVENT_IN_BOTTOM_L:
296                 tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
297                 break;
298         case BUTTON_EVENT_IN_TOP_R:
299         case BUTTON_EVENT_IN_TOP_M:
300         case BUTTON_EVENT_IN_TOP_L:
301                 if (event != t->button.curr)
302                         tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW,
303                                             event);
304                 break;
305         case BUTTON_EVENT_IN_AREA:
306                 tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
307                 break;
308         case BUTTON_EVENT_UP:
309                 tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
310                 break;
311         case BUTTON_EVENT_PRESS:
312                 tp_button_set_state(tp, t, BUTTON_STATE_TOP, event);
313                 break;
314         case BUTTON_EVENT_RELEASE:
315                 break;
316         case BUTTON_EVENT_TIMEOUT:
317                 tp_button_set_state(tp, t, BUTTON_STATE_TOP, event);
318                 break;
319         }
320 }
321
322 static void
323 tp_button_top_to_ignore_handle_event(struct tp_dispatch *tp,
324                                       struct tp_touch *t,
325                                       enum button_event event)
326 {
327         switch(event) {
328         case BUTTON_EVENT_IN_TOP_R:
329         case BUTTON_EVENT_IN_TOP_M:
330         case BUTTON_EVENT_IN_TOP_L:
331                 if (event == t->button.curr)
332                         tp_button_set_state(tp, t, BUTTON_STATE_TOP,
333                                             event);
334                 else
335                         tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW,
336                                             event);
337                 break;
338         case BUTTON_EVENT_IN_BOTTOM_R:
339         case BUTTON_EVENT_IN_BOTTOM_L:
340         case BUTTON_EVENT_IN_AREA:
341                 break;
342         case BUTTON_EVENT_UP:
343                 tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
344                 break;
345         case BUTTON_EVENT_PRESS:
346         case BUTTON_EVENT_RELEASE:
347                 break;
348         case BUTTON_EVENT_TIMEOUT:
349                 tp_button_set_state(tp, t, BUTTON_STATE_IGNORE, event);
350                 break;
351         }
352 }
353
354 static void
355 tp_button_ignore_handle_event(struct tp_dispatch *tp,
356                             struct tp_touch *t,
357                             enum button_event event)
358 {
359         switch (event) {
360         case BUTTON_EVENT_IN_BOTTOM_R:
361         case BUTTON_EVENT_IN_BOTTOM_L:
362         case BUTTON_EVENT_IN_TOP_R:
363         case BUTTON_EVENT_IN_TOP_M:
364         case BUTTON_EVENT_IN_TOP_L:
365         case BUTTON_EVENT_IN_AREA:
366                 break;
367         case BUTTON_EVENT_UP:
368                 tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
369                 break;
370         case BUTTON_EVENT_PRESS:
371         case BUTTON_EVENT_RELEASE:
372         case BUTTON_EVENT_TIMEOUT:
373                 break;
374         }
375 }
376
377 static void
378 tp_button_handle_event(struct tp_dispatch *tp,
379                        struct tp_touch *t,
380                        enum button_event event,
381                        uint64_t time)
382 {
383         struct libinput *libinput = tp->device->base.seat->libinput;
384         enum button_state current = t->button.state;
385
386         switch(t->button.state) {
387         case BUTTON_STATE_NONE:
388                 tp_button_none_handle_event(tp, t, event);
389                 break;
390         case BUTTON_STATE_AREA:
391                 tp_button_area_handle_event(tp, t, event);
392                 break;
393         case BUTTON_STATE_BOTTOM:
394                 tp_button_bottom_handle_event(tp, t, event);
395                 break;
396         case BUTTON_STATE_TOP:
397                 tp_button_top_handle_event(tp, t, event);
398                 break;
399         case BUTTON_STATE_TOP_NEW:
400                 tp_button_top_new_handle_event(tp, t, event);
401                 break;
402         case BUTTON_STATE_TOP_TO_IGNORE:
403                 tp_button_top_to_ignore_handle_event(tp, t, event);
404                 break;
405         case BUTTON_STATE_IGNORE:
406                 tp_button_ignore_handle_event(tp, t, event);
407                 break;
408         }
409
410         if (current != t->button.state)
411                 log_debug(libinput,
412                           "button state: from %s, event %s to %s\n",
413                           button_state_to_str(current),
414                           button_event_to_str(event),
415                           button_state_to_str(t->button.state));
416 }
417
418 int
419 tp_button_handle_state(struct tp_dispatch *tp, uint64_t time)
420 {
421         struct tp_touch *t;
422
423         tp_for_each_touch(tp, t) {
424                 if (t->state == TOUCH_NONE)
425                         continue;
426
427                 if (t->state == TOUCH_END) {
428                         tp_button_handle_event(tp, t, BUTTON_EVENT_UP, time);
429                 } else if (t->dirty) {
430                         if (is_inside_bottom_right_area(tp, t))
431                                 tp_button_handle_event(tp, t, BUTTON_EVENT_IN_BOTTOM_R, time);
432                         else if (is_inside_bottom_left_area(tp, t))
433                                 tp_button_handle_event(tp, t, BUTTON_EVENT_IN_BOTTOM_L, time);
434                         else if (is_inside_top_right_area(tp, t))
435                                 tp_button_handle_event(tp, t, BUTTON_EVENT_IN_TOP_R, time);
436                         else if (is_inside_top_middle_area(tp, t))
437                                 tp_button_handle_event(tp, t, BUTTON_EVENT_IN_TOP_M, time);
438                         else if (is_inside_top_left_area(tp, t))
439                                 tp_button_handle_event(tp, t, BUTTON_EVENT_IN_TOP_L, time);
440                         else
441                                 tp_button_handle_event(tp, t, BUTTON_EVENT_IN_AREA, time);
442                 }
443                 if (tp->queued & TOUCHPAD_EVENT_BUTTON_RELEASE)
444                         tp_button_handle_event(tp, t, BUTTON_EVENT_RELEASE, time);
445                 if (tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS)
446                         tp_button_handle_event(tp, t, BUTTON_EVENT_PRESS, time);
447         }
448
449         return 0;
450 }
451
452 static void
453 tp_button_handle_timeout(uint64_t now, void *data)
454 {
455         struct tp_touch *t = data;
456
457         tp_button_handle_event(t->tp, t, BUTTON_EVENT_TIMEOUT, now);
458 }
459
460 int
461 tp_process_button(struct tp_dispatch *tp,
462                   const struct input_event *e,
463                   uint64_t time)
464 {
465         struct libinput *libinput = tp->device->base.seat->libinput;
466         uint32_t mask = 1 << (e->code - BTN_LEFT);
467
468         /* Ignore other buttons on clickpads */
469         if (tp->buttons.is_clickpad && e->code != BTN_LEFT) {
470                 log_bug_kernel(libinput,
471                                "received %s button event on a clickpad\n",
472                                libevdev_event_code_get_name(EV_KEY, e->code));
473                 return 0;
474         }
475
476         if (e->value) {
477                 tp->buttons.state |= mask;
478                 tp->queued |= TOUCHPAD_EVENT_BUTTON_PRESS;
479         } else {
480                 tp->buttons.state &= ~mask;
481                 tp->queued |= TOUCHPAD_EVENT_BUTTON_RELEASE;
482         }
483
484         return 0;
485 }
486
487 void
488 tp_release_all_buttons(struct tp_dispatch *tp,
489                        uint64_t time)
490 {
491         if (tp->buttons.state) {
492                 tp->buttons.state = 0;
493                 tp->queued |= TOUCHPAD_EVENT_BUTTON_RELEASE;
494         }
495 }
496
497 void
498 tp_init_softbuttons(struct tp_dispatch *tp,
499                     struct evdev_device *device,
500                     double topbutton_size_mult)
501 {
502         int width, height;
503         const struct input_absinfo *absinfo_x, *absinfo_y;
504         int xoffset, yoffset;
505         int yres;
506
507         absinfo_x = device->abs.absinfo_x;
508         absinfo_y = device->abs.absinfo_y;
509
510         xoffset = absinfo_x->minimum,
511         yoffset = absinfo_y->minimum;
512         yres = absinfo_y->resolution;
513         width = abs(absinfo_x->maximum - absinfo_x->minimum);
514         height = abs(absinfo_y->maximum - absinfo_y->minimum);
515
516         /* button height: 10mm or 15% of the touchpad height,
517            whichever is smaller */
518         if (yres > 1 && (height * 0.15/yres) > 10) {
519                 tp->buttons.bottom_area.top_edge =
520                 absinfo_y->maximum - 10 * yres;
521         } else {
522                 tp->buttons.bottom_area.top_edge = height * .85 + yoffset;
523         }
524
525         tp->buttons.bottom_area.rightbutton_left_edge = width/2 + xoffset;
526
527         if (tp->buttons.has_topbuttons) {
528                 /* T440s has the top button line 5mm from the top, event
529                    analysis has shown events to start down to ~10mm from the
530                    top - which maps to 15%.  We allow the caller to enlarge the
531                    area using a multiplier for the touchpad disabled case. */
532                 double topsize_mm = 10 * topbutton_size_mult;
533                 double topsize_pct = .15 * topbutton_size_mult;
534
535                 if (yres > 1) {
536                         tp->buttons.top_area.bottom_edge =
537                         yoffset + topsize_mm * yres;
538                 } else {
539                         tp->buttons.top_area.bottom_edge = height * topsize_pct + yoffset;
540                 }
541                 tp->buttons.top_area.rightbutton_left_edge = width * .58 + xoffset;
542                 tp->buttons.top_area.leftbutton_right_edge = width * .42 + xoffset;
543         } else {
544                 tp->buttons.top_area.bottom_edge = INT_MIN;
545         }
546 }
547
548 int
549 tp_init_buttons(struct tp_dispatch *tp,
550                 struct evdev_device *device)
551 {
552         struct libinput *libinput = tp->device->base.seat->libinput;
553         struct tp_touch *t;
554         int width, height;
555         double diagonal;
556         const struct input_absinfo *absinfo_x, *absinfo_y;
557
558         tp->buttons.is_clickpad = libevdev_has_property(device->evdev,
559                                                         INPUT_PROP_BUTTONPAD);
560         tp->buttons.has_topbuttons = libevdev_has_property(device->evdev,
561                                                         INPUT_PROP_TOPBUTTONPAD);
562
563         if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE) ||
564             libevdev_has_event_code(device->evdev, EV_KEY, BTN_RIGHT)) {
565                 if (tp->buttons.is_clickpad)
566                         log_bug_kernel(libinput,
567                                        "%s: clickpad advertising right button\n",
568                                        device->sysname);
569         } else {
570                 if (!tp->buttons.is_clickpad)
571                         log_bug_kernel(libinput,
572                                        "%s: non clickpad without right button?\n",
573                                        device->sysname);
574         }
575
576         absinfo_x = device->abs.absinfo_x;
577         absinfo_y = device->abs.absinfo_y;
578
579         width = abs(absinfo_x->maximum - absinfo_x->minimum);
580         height = abs(absinfo_y->maximum - absinfo_y->minimum);
581         diagonal = sqrt(width*width + height*height);
582
583         tp->buttons.motion_dist = diagonal * DEFAULT_BUTTON_MOTION_THRESHOLD;
584
585         if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_APPLE)
586                 tp->buttons.use_clickfinger = true;
587
588         if (tp->buttons.is_clickpad && !tp->buttons.use_clickfinger) {
589                 tp_init_softbuttons(tp, device, 1.0);
590         } else {
591                 tp->buttons.bottom_area.top_edge = INT_MAX;
592                 tp->buttons.top_area.bottom_edge = INT_MIN;
593         }
594
595         tp_for_each_touch(tp, t) {
596                 t->button.state = BUTTON_STATE_NONE;
597                 libinput_timer_init(&t->button.timer,
598                                     tp->device->base.seat->libinput,
599                                     tp_button_handle_timeout, t);
600         }
601
602         return 0;
603 }
604
605 void
606 tp_destroy_buttons(struct tp_dispatch *tp)
607 {
608         struct tp_touch *t;
609
610         tp_for_each_touch(tp, t)
611                 libinput_timer_cancel(&t->button.timer);
612 }
613
614 static int
615 tp_post_clickfinger_buttons(struct tp_dispatch *tp, uint64_t time)
616 {
617         uint32_t current, old, button;
618         enum libinput_button_state state;
619
620         current = tp->buttons.state;
621         old = tp->buttons.old_state;
622
623         if (current == old)
624                 return 0;
625
626         if (current) {
627                 switch (tp->nfingers_down) {
628                 case 1: button = BTN_LEFT; break;
629                 case 2: button = BTN_RIGHT; break;
630                 case 3: button = BTN_MIDDLE; break;
631                 default:
632                         return 0;
633                 }
634                 tp->buttons.active = button;
635                 state = LIBINPUT_BUTTON_STATE_PRESSED;
636         } else {
637                 button = tp->buttons.active;
638                 tp->buttons.active = 0;
639                 state = LIBINPUT_BUTTON_STATE_RELEASED;
640         }
641
642         if (button) {
643                 evdev_pointer_notify_button(tp->device,
644                                             time,
645                                             button,
646                                             state);
647         }
648         return 1;
649 }
650
651 static int
652 tp_post_physical_buttons(struct tp_dispatch *tp, uint64_t time)
653 {
654         uint32_t current, old, button;
655
656         current = tp->buttons.state;
657         old = tp->buttons.old_state;
658         button = BTN_LEFT;
659
660         while (current || old) {
661                 enum libinput_button_state state;
662
663                 if ((current & 0x1) ^ (old & 0x1)) {
664                         uint32_t b;
665
666                         if (!!(current & 0x1))
667                                 state = LIBINPUT_BUTTON_STATE_PRESSED;
668                         else
669                                 state = LIBINPUT_BUTTON_STATE_RELEASED;
670
671                         b = evdev_to_left_handed(tp->device, button);
672                         evdev_pointer_notify_button(tp->device,
673                                                     time,
674                                                     b,
675                                                     state);
676                 }
677
678                 button++;
679                 current >>= 1;
680                 old >>= 1;
681         }
682
683         return 0;
684 }
685
686 static void
687 tp_notify_softbutton(struct tp_dispatch *tp,
688                      uint64_t time,
689                      uint32_t button,
690                      uint32_t is_topbutton,
691                      enum libinput_button_state state)
692 {
693         /* If we've a trackpoint, send top buttons through the trackpoint */
694         if (is_topbutton && tp->buttons.trackpoint) {
695                 struct evdev_dispatch *dispatch = tp->buttons.trackpoint->dispatch;
696                 struct input_event event;
697
698                 event.time.tv_sec = time/1000;
699                 event.time.tv_usec = (time % 1000) * 1000;
700                 event.type = EV_KEY;
701                 event.code = button;
702                 event.value = (state == LIBINPUT_BUTTON_STATE_PRESSED) ? 1 : 0;
703                 dispatch->interface->process(dispatch, tp->buttons.trackpoint,
704                                              &event, time);
705                 return;
706         }
707
708         /* Ignore button events not for the trackpoint while suspended */
709         if (tp->device->suspended)
710                 return;
711
712         evdev_pointer_notify_button(tp->device, time, button, state);
713 }
714
715 static int
716 tp_post_softbutton_buttons(struct tp_dispatch *tp, uint64_t time)
717 {
718         uint32_t current, old, button, is_top;
719         enum libinput_button_state state;
720         enum { AREA = 0x01, LEFT = 0x02, MIDDLE = 0x04, RIGHT = 0x08 };
721
722         current = tp->buttons.state;
723         old = tp->buttons.old_state;
724         button = 0;
725         is_top = 0;
726
727         if (!tp->buttons.click_pending && current == old)
728                 return 0;
729
730         if (current) {
731                 struct tp_touch *t;
732
733                 tp_for_each_touch(tp, t) {
734                         switch (t->button.curr) {
735                         case BUTTON_EVENT_IN_AREA:
736                                 button |= AREA;
737                                 break;
738                         case BUTTON_EVENT_IN_TOP_L:
739                                 is_top = 1;
740                         case BUTTON_EVENT_IN_BOTTOM_L:
741                                 button |= LEFT;
742                                 break;
743                         case BUTTON_EVENT_IN_TOP_M:
744                                 is_top = 1;
745                                 button |= MIDDLE;
746                                 break;
747                         case BUTTON_EVENT_IN_TOP_R:
748                                 is_top = 1;
749                         case BUTTON_EVENT_IN_BOTTOM_R:
750                                 button |= RIGHT;
751                                 break;
752                         default:
753                                 break;
754                         }
755                 }
756
757                 if (button == 0) {
758                         /* No touches, wait for a touch before processing */
759                         tp->buttons.click_pending = true;
760                         return 0;
761                 }
762
763                 if ((button & MIDDLE) || ((button & LEFT) && (button & RIGHT)))
764                         button = evdev_to_left_handed(tp->device, BTN_MIDDLE);
765                 else if (button & RIGHT)
766                         button = evdev_to_left_handed(tp->device, BTN_RIGHT);
767                 else if (button & LEFT)
768                         button = evdev_to_left_handed(tp->device, BTN_LEFT);
769                 else /* main area is always BTN_LEFT */
770                         button = BTN_LEFT;
771
772                 tp->buttons.active = button;
773                 tp->buttons.active_is_topbutton = is_top;
774                 state = LIBINPUT_BUTTON_STATE_PRESSED;
775         } else {
776                 button = tp->buttons.active;
777                 is_top = tp->buttons.active_is_topbutton;
778                 tp->buttons.active = 0;
779                 tp->buttons.active_is_topbutton = 0;
780                 state = LIBINPUT_BUTTON_STATE_RELEASED;
781         }
782
783         tp->buttons.click_pending = false;
784
785         if (button)
786                 tp_notify_softbutton(tp, time, button, is_top, state);
787
788         return 1;
789 }
790
791 int
792 tp_post_button_events(struct tp_dispatch *tp, uint64_t time)
793 {
794         if (tp->buttons.is_clickpad) {
795                 if (tp->buttons.use_clickfinger)
796                         return tp_post_clickfinger_buttons(tp, time);
797                 else
798                         return tp_post_softbutton_buttons(tp, time);
799         }
800
801         return tp_post_physical_buttons(tp, time);
802 }
803
804 int
805 tp_button_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
806 {
807         return t->button.state == BUTTON_STATE_AREA;
808 }
809
810 bool
811 tp_button_is_inside_softbutton_area(struct tp_dispatch *tp, struct tp_touch *t)
812 {
813         return is_inside_top_button_area(tp, t) || is_inside_bottom_button_area(tp, t);
814 }