evdev: Log evdev event queue overflows
[platform/upstream/libinput.git] / src / evdev-mt-touchpad-tap.c
1 /*
2  * Copyright © 2013 Red Hat, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software
5  * and its documentation for any purpose is hereby granted without
6  * fee, provided that the above copyright notice appear in all copies
7  * and that both that copyright notice and this permission notice
8  * appear in supporting documentation, and that the name of Red Hat
9  * not be used in advertising or publicity pertaining to distribution
10  * of the software without specific, written prior permission.  Red
11  * Hat makes no representations about the suitability of this software
12  * for any purpose.  It is provided "as is" without express or implied
13  * warranty.
14  *
15  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17  * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <assert.h>
29 #include <errno.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <unistd.h>
34
35 #include "evdev-mt-touchpad.h"
36
37 #define CASE_RETURN_STRING(a) case a: return #a;
38
39 #define DEFAULT_TAP_TIMEOUT_PERIOD 180
40 #define DEFAULT_TAP_MOVE_THRESHOLD 30
41
42 enum tap_event {
43         TAP_EVENT_TOUCH = 12,
44         TAP_EVENT_MOTION,
45         TAP_EVENT_RELEASE,
46         TAP_EVENT_BUTTON,
47         TAP_EVENT_TIMEOUT,
48 };
49
50 /*****************************************
51  * DO NOT EDIT THIS FILE!
52  *
53  * Look at the state diagram in doc/touchpad-tap-state-machine.svg, or
54  * online at
55  * https://drive.google.com/file/d/0B1NwWmji69noYTdMcU1kTUZuUVE/edit?usp=sharing
56  * (it's a http://draw.io diagram)
57  *
58  * Any changes in this file must be represented in the diagram.
59  */
60
61 static inline const char*
62 tap_state_to_str(enum tp_tap_state state) {
63
64         switch(state) {
65         CASE_RETURN_STRING(TAP_STATE_IDLE);
66         CASE_RETURN_STRING(TAP_STATE_HOLD);
67         CASE_RETURN_STRING(TAP_STATE_TOUCH);
68         CASE_RETURN_STRING(TAP_STATE_TAPPED);
69         CASE_RETURN_STRING(TAP_STATE_TOUCH_2);
70         CASE_RETURN_STRING(TAP_STATE_TOUCH_2_HOLD);
71         CASE_RETURN_STRING(TAP_STATE_TOUCH_3);
72         CASE_RETURN_STRING(TAP_STATE_TOUCH_3_HOLD);
73         CASE_RETURN_STRING(TAP_STATE_DRAGGING);
74         CASE_RETURN_STRING(TAP_STATE_DRAGGING_WAIT);
75         CASE_RETURN_STRING(TAP_STATE_DRAGGING_OR_DOUBLETAP);
76         CASE_RETURN_STRING(TAP_STATE_DRAGGING_2);
77         CASE_RETURN_STRING(TAP_STATE_DEAD);
78         }
79         return NULL;
80 }
81
82 static inline const char*
83 tap_event_to_str(enum tap_event event) {
84
85         switch(event) {
86         CASE_RETURN_STRING(TAP_EVENT_TOUCH);
87         CASE_RETURN_STRING(TAP_EVENT_MOTION);
88         CASE_RETURN_STRING(TAP_EVENT_RELEASE);
89         CASE_RETURN_STRING(TAP_EVENT_TIMEOUT);
90         CASE_RETURN_STRING(TAP_EVENT_BUTTON);
91         }
92         return NULL;
93 }
94 #undef CASE_RETURN_STRING
95
96 static void
97 tp_tap_notify(struct tp_dispatch *tp,
98               struct tp_touch *t,
99               uint64_t time,
100               int nfingers,
101               enum libinput_button_state state)
102 {
103         int32_t button;
104
105         if (t && t->tap.state == TAP_TOUCH_STATE_DEAD)
106                 return;
107
108         switch (nfingers) {
109         case 1: button = BTN_LEFT; break;
110         case 2: button = BTN_RIGHT; break;
111         case 3: button = BTN_MIDDLE; break;
112         default:
113                 return;
114         }
115
116         evdev_pointer_notify_button(tp->device,
117                                     time,
118                                     button,
119                                     state);
120 }
121
122 static void
123 tp_tap_set_timer(struct tp_dispatch *tp, uint64_t time)
124 {
125         libinput_timer_set(&tp->tap.timer, time + DEFAULT_TAP_TIMEOUT_PERIOD);
126 }
127
128 static void
129 tp_tap_clear_timer(struct tp_dispatch *tp)
130 {
131         libinput_timer_cancel(&tp->tap.timer);
132 }
133
134 static void
135 tp_tap_idle_handle_event(struct tp_dispatch *tp,
136                          struct tp_touch *t,
137                          enum tap_event event, uint64_t time)
138 {
139         struct libinput *libinput = tp->device->base.seat->libinput;
140
141         switch (event) {
142         case TAP_EVENT_TOUCH:
143                 tp->tap.state = TAP_STATE_TOUCH;
144                 tp_tap_set_timer(tp, time);
145                 break;
146         case TAP_EVENT_RELEASE:
147         case TAP_EVENT_MOTION:
148                 log_bug_libinput(libinput,
149                                  "invalid event, no fingers are down\n");
150                 break;
151         case TAP_EVENT_TIMEOUT:
152                 break;
153         case TAP_EVENT_BUTTON:
154                 tp->tap.state = TAP_STATE_DEAD;
155                 break;
156         }
157 }
158
159 static void
160 tp_tap_touch_handle_event(struct tp_dispatch *tp,
161                           struct tp_touch *t,
162                           enum tap_event event, uint64_t time)
163 {
164
165         switch (event) {
166         case TAP_EVENT_TOUCH:
167                 tp->tap.state = TAP_STATE_TOUCH_2;
168                 tp_tap_set_timer(tp, time);
169                 break;
170         case TAP_EVENT_RELEASE:
171                 tp->tap.state = TAP_STATE_TAPPED;
172                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
173                 tp_tap_set_timer(tp, time);
174                 break;
175         case TAP_EVENT_TIMEOUT:
176         case TAP_EVENT_MOTION:
177                 tp->tap.state = TAP_STATE_HOLD;
178                 tp_tap_clear_timer(tp);
179                 break;
180         case TAP_EVENT_BUTTON:
181                 tp->tap.state = TAP_STATE_DEAD;
182                 break;
183         }
184 }
185
186 static void
187 tp_tap_hold_handle_event(struct tp_dispatch *tp,
188                          struct tp_touch *t,
189                          enum tap_event event, uint64_t time)
190 {
191
192         switch (event) {
193         case TAP_EVENT_TOUCH:
194                 tp->tap.state = TAP_STATE_TOUCH_2;
195                 tp_tap_set_timer(tp, time);
196                 break;
197         case TAP_EVENT_RELEASE:
198                 tp->tap.state = TAP_STATE_IDLE;
199                 break;
200         case TAP_EVENT_MOTION:
201         case TAP_EVENT_TIMEOUT:
202                 break;
203         case TAP_EVENT_BUTTON:
204                 tp->tap.state = TAP_STATE_DEAD;
205                 break;
206         }
207 }
208
209 static void
210 tp_tap_tapped_handle_event(struct tp_dispatch *tp,
211                            struct tp_touch *t,
212                            enum tap_event event, uint64_t time)
213 {
214         struct libinput *libinput = tp->device->base.seat->libinput;
215
216         switch (event) {
217         case TAP_EVENT_MOTION:
218         case TAP_EVENT_RELEASE:
219                 log_bug_libinput(libinput,
220                                  "invalid event when fingers are up\n");
221                 break;
222         case TAP_EVENT_TOUCH:
223                 tp->tap.state = TAP_STATE_DRAGGING_OR_DOUBLETAP;
224                 break;
225         case TAP_EVENT_TIMEOUT:
226                 tp->tap.state = TAP_STATE_IDLE;
227                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
228                 break;
229         case TAP_EVENT_BUTTON:
230                 tp->tap.state = TAP_STATE_DEAD;
231                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
232                 break;
233         }
234 }
235
236 static void
237 tp_tap_touch2_handle_event(struct tp_dispatch *tp,
238                            struct tp_touch *t,
239                            enum tap_event event, uint64_t time)
240 {
241
242         switch (event) {
243         case TAP_EVENT_TOUCH:
244                 tp->tap.state = TAP_STATE_TOUCH_3;
245                 tp_tap_set_timer(tp, time);
246                 break;
247         case TAP_EVENT_RELEASE:
248                 tp->tap.state = TAP_STATE_HOLD;
249                 tp_tap_notify(tp, t, time, 2, LIBINPUT_BUTTON_STATE_PRESSED);
250                 tp_tap_notify(tp, t, time, 2, LIBINPUT_BUTTON_STATE_RELEASED);
251                 tp_tap_clear_timer(tp);
252                 break;
253         case TAP_EVENT_MOTION:
254                 tp_tap_clear_timer(tp);
255                 /* fallthrough */
256         case TAP_EVENT_TIMEOUT:
257                 tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
258                 break;
259         case TAP_EVENT_BUTTON:
260                 tp->tap.state = TAP_STATE_DEAD;
261                 break;
262         }
263 }
264
265 static void
266 tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp,
267                                 struct tp_touch *t,
268                                 enum tap_event event, uint64_t time)
269 {
270
271         switch (event) {
272         case TAP_EVENT_TOUCH:
273                 tp->tap.state = TAP_STATE_TOUCH_3;
274                 tp_tap_set_timer(tp, time);
275                 break;
276         case TAP_EVENT_RELEASE:
277                 tp->tap.state = TAP_STATE_HOLD;
278                 break;
279         case TAP_EVENT_MOTION:
280         case TAP_EVENT_TIMEOUT:
281                 tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
282                 break;
283         case TAP_EVENT_BUTTON:
284                 tp->tap.state = TAP_STATE_DEAD;
285                 break;
286         }
287 }
288
289 static void
290 tp_tap_touch3_handle_event(struct tp_dispatch *tp,
291                            struct tp_touch *t,
292                            enum tap_event event, uint64_t time)
293 {
294
295         switch (event) {
296         case TAP_EVENT_TOUCH:
297                 tp->tap.state = TAP_STATE_DEAD;
298                 tp_tap_clear_timer(tp);
299                 break;
300         case TAP_EVENT_MOTION:
301         case TAP_EVENT_TIMEOUT:
302                 tp->tap.state = TAP_STATE_TOUCH_3_HOLD;
303                 tp_tap_clear_timer(tp);
304                 break;
305         case TAP_EVENT_RELEASE:
306                 tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
307                 tp_tap_notify(tp, t, time, 3, LIBINPUT_BUTTON_STATE_PRESSED);
308                 tp_tap_notify(tp, t, time, 3, LIBINPUT_BUTTON_STATE_RELEASED);
309                 break;
310         case TAP_EVENT_BUTTON:
311                 tp->tap.state = TAP_STATE_DEAD;
312                 break;
313         }
314 }
315
316 static void
317 tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp,
318                                 struct tp_touch *t,
319                                 enum tap_event event, uint64_t time)
320 {
321
322         switch (event) {
323         case TAP_EVENT_TOUCH:
324                 tp->tap.state = TAP_STATE_DEAD;
325                 tp_tap_set_timer(tp, time);
326                 break;
327         case TAP_EVENT_RELEASE:
328                 tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
329                 break;
330         case TAP_EVENT_MOTION:
331         case TAP_EVENT_TIMEOUT:
332                 break;
333         case TAP_EVENT_BUTTON:
334                 tp->tap.state = TAP_STATE_DEAD;
335                 break;
336         }
337 }
338
339 static void
340 tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
341                                           struct tp_touch *t,
342                                           enum tap_event event, uint64_t time)
343 {
344         switch (event) {
345         case TAP_EVENT_TOUCH:
346                 tp->tap.state = TAP_STATE_DRAGGING_2;
347                 break;
348         case TAP_EVENT_RELEASE:
349                 tp->tap.state = TAP_STATE_IDLE;
350                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
351                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
352                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
353                 tp_tap_clear_timer(tp);
354                 break;
355         case TAP_EVENT_MOTION:
356         case TAP_EVENT_TIMEOUT:
357                 tp->tap.state = TAP_STATE_DRAGGING;
358                 break;
359         case TAP_EVENT_BUTTON:
360                 tp->tap.state = TAP_STATE_DEAD;
361                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
362                 break;
363         }
364 }
365
366 static void
367 tp_tap_dragging_handle_event(struct tp_dispatch *tp,
368                              struct tp_touch *t,
369                              enum tap_event event, uint64_t time)
370 {
371
372         switch (event) {
373         case TAP_EVENT_TOUCH:
374                 tp->tap.state = TAP_STATE_DRAGGING_2;
375                 break;
376         case TAP_EVENT_RELEASE:
377                 tp->tap.state = TAP_STATE_DRAGGING_WAIT;
378                 tp_tap_set_timer(tp, time);
379                 break;
380         case TAP_EVENT_MOTION:
381         case TAP_EVENT_TIMEOUT:
382                 /* noop */
383                 break;
384         case TAP_EVENT_BUTTON:
385                 tp->tap.state = TAP_STATE_DEAD;
386                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
387                 break;
388         }
389 }
390
391 static void
392 tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
393                                   struct tp_touch *t,
394                                   enum tap_event event, uint64_t time)
395 {
396
397         switch (event) {
398         case TAP_EVENT_TOUCH:
399                 tp->tap.state = TAP_STATE_DRAGGING;
400                 tp_tap_clear_timer(tp);
401                 break;
402         case TAP_EVENT_RELEASE:
403         case TAP_EVENT_MOTION:
404                 break;
405         case TAP_EVENT_TIMEOUT:
406                 tp->tap.state = TAP_STATE_IDLE;
407                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
408                 break;
409         case TAP_EVENT_BUTTON:
410                 tp->tap.state = TAP_STATE_DEAD;
411                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
412                 break;
413         }
414 }
415
416 static void
417 tp_tap_dragging2_handle_event(struct tp_dispatch *tp,
418                               struct tp_touch *t,
419                               enum tap_event event, uint64_t time)
420 {
421
422         switch (event) {
423         case TAP_EVENT_RELEASE:
424                 tp->tap.state = TAP_STATE_DRAGGING;
425                 break;
426         case TAP_EVENT_TOUCH:
427                 tp->tap.state = TAP_STATE_DEAD;
428                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
429                 break;
430         case TAP_EVENT_MOTION:
431         case TAP_EVENT_TIMEOUT:
432                 /* noop */
433                 break;
434         case TAP_EVENT_BUTTON:
435                 tp->tap.state = TAP_STATE_DEAD;
436                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
437                 break;
438         }
439 }
440
441 static void
442 tp_tap_dead_handle_event(struct tp_dispatch *tp,
443                          struct tp_touch *t,
444                          enum tap_event event,
445                          uint64_t time)
446 {
447
448         switch (event) {
449         case TAP_EVENT_RELEASE:
450                 if (tp->nfingers_down == 0)
451                         tp->tap.state = TAP_STATE_IDLE;
452                 break;
453         case TAP_EVENT_TOUCH:
454         case TAP_EVENT_MOTION:
455         case TAP_EVENT_TIMEOUT:
456         case TAP_EVENT_BUTTON:
457                 break;
458         }
459 }
460
461 static void
462 tp_tap_handle_event(struct tp_dispatch *tp,
463                     struct tp_touch *t,
464                     enum tap_event event,
465                     uint64_t time)
466 {
467         struct libinput *libinput = tp->device->base.seat->libinput;
468         enum tp_tap_state current;
469
470         current = tp->tap.state;
471
472         switch(tp->tap.state) {
473         case TAP_STATE_IDLE:
474                 if (!tp->tap.enabled)
475                         break;
476
477                 tp_tap_idle_handle_event(tp, t, event, time);
478                 break;
479         case TAP_STATE_TOUCH:
480                 tp_tap_touch_handle_event(tp, t, event, time);
481                 break;
482         case TAP_STATE_HOLD:
483                 tp_tap_hold_handle_event(tp, t, event, time);
484                 break;
485         case TAP_STATE_TAPPED:
486                 tp_tap_tapped_handle_event(tp, t, event, time);
487                 break;
488         case TAP_STATE_TOUCH_2:
489                 tp_tap_touch2_handle_event(tp, t, event, time);
490                 break;
491         case TAP_STATE_TOUCH_2_HOLD:
492                 tp_tap_touch2_hold_handle_event(tp, t, event, time);
493                 break;
494         case TAP_STATE_TOUCH_3:
495                 tp_tap_touch3_handle_event(tp, t, event, time);
496                 break;
497         case TAP_STATE_TOUCH_3_HOLD:
498                 tp_tap_touch3_hold_handle_event(tp, t, event, time);
499                 break;
500         case TAP_STATE_DRAGGING_OR_DOUBLETAP:
501                 tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time);
502                 break;
503         case TAP_STATE_DRAGGING:
504                 tp_tap_dragging_handle_event(tp, t, event, time);
505                 break;
506         case TAP_STATE_DRAGGING_WAIT:
507                 tp_tap_dragging_wait_handle_event(tp, t, event, time);
508                 break;
509         case TAP_STATE_DRAGGING_2:
510                 tp_tap_dragging2_handle_event(tp, t, event, time);
511                 break;
512         case TAP_STATE_DEAD:
513                 tp_tap_dead_handle_event(tp, t, event, time);
514                 break;
515         }
516
517         if (tp->tap.state == TAP_STATE_IDLE || tp->tap.state == TAP_STATE_DEAD)
518                 tp_tap_clear_timer(tp);
519
520         log_debug(libinput,
521                   "tap state: %s → %s → %s\n",
522                   tap_state_to_str(current),
523                   tap_event_to_str(event),
524                   tap_state_to_str(tp->tap.state));
525 }
526
527 static bool
528 tp_tap_exceeds_motion_threshold(struct tp_dispatch *tp, struct tp_touch *t)
529 {
530         int threshold = DEFAULT_TAP_MOVE_THRESHOLD;
531         double dx, dy;
532
533         tp_get_delta(t, &dx, &dy);
534
535         return dx * dx + dy * dy > threshold * threshold;
536 }
537
538 int
539 tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
540 {
541         struct tp_touch *t;
542         int filter_motion = 0;
543
544         /* Handle queued button pressed events from clickpads. For touchpads
545          * with separate physical buttons, ignore button pressed events so they
546          * don't interfere with tapping. */
547         if (tp->buttons.is_clickpad && tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS)
548                 tp_tap_handle_event(tp, NULL, TAP_EVENT_BUTTON, time);
549
550         tp_for_each_touch(tp, t) {
551                 if (!t->dirty || t->state == TOUCH_NONE)
552                         continue;
553
554                 if (tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS)
555                         t->tap.state = TAP_TOUCH_STATE_DEAD;
556
557                 if (t->state == TOUCH_BEGIN) {
558                         t->tap.state = TAP_TOUCH_STATE_TOUCH;
559                         tp_tap_handle_event(tp, t, TAP_EVENT_TOUCH, time);
560                 } else if (t->state == TOUCH_END) {
561                         tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time);
562                         t->tap.state = TAP_TOUCH_STATE_DEAD;
563                 } else if (tp->tap.state != TAP_STATE_IDLE &&
564                          tp_tap_exceeds_motion_threshold(tp, t)) {
565                         struct tp_touch *tmp;
566
567                         /* Any touch exceeding the threshold turns all
568                          * touches into DEAD */
569                         tp_for_each_touch(tp, tmp) {
570                                 if (tmp->tap.state == TAP_TOUCH_STATE_TOUCH)
571                                         tmp->tap.state = TAP_TOUCH_STATE_DEAD;
572                         }
573
574                         tp_tap_handle_event(tp, t, TAP_EVENT_MOTION, time);
575                 }
576         }
577
578         /**
579          * In any state where motion exceeding the move threshold would
580          * move to the next state, filter that motion until we actually
581          * exceed it. This prevents small motion events while we're waiting
582          * on a decision if a tap is a tap.
583          */
584         switch (tp->tap.state) {
585         case TAP_STATE_TOUCH:
586         case TAP_STATE_TAPPED:
587         case TAP_STATE_DRAGGING_OR_DOUBLETAP:
588         case TAP_STATE_TOUCH_2:
589         case TAP_STATE_TOUCH_3:
590                 filter_motion = 1;
591                 break;
592
593         default:
594                 break;
595
596         }
597
598         return filter_motion;
599 }
600
601 static void
602 tp_tap_handle_timeout(uint64_t time, void *data)
603 {
604         struct tp_dispatch *tp = data;
605         struct tp_touch *t;
606
607         tp_tap_handle_event(tp, NULL, TAP_EVENT_TIMEOUT, time);
608
609         tp_for_each_touch(tp, t) {
610                 if (t->state == TOUCH_NONE ||
611                     t->tap.state == TAP_TOUCH_STATE_IDLE)
612                         continue;
613
614                 t->tap.state = TAP_TOUCH_STATE_DEAD;
615         }
616 }
617
618 static int
619 tp_tap_config_count(struct libinput_device *device)
620 {
621         struct evdev_dispatch *dispatch;
622         struct tp_dispatch *tp = NULL;
623
624         dispatch = ((struct evdev_device *) device)->dispatch;
625         tp = container_of(dispatch, tp, base);
626
627         return min(tp->ntouches, 3); /* we only do up to 3 finger tap */
628 }
629
630 static enum libinput_config_status
631 tp_tap_config_set_enabled(struct libinput_device *device,
632                           enum libinput_config_tap_state enabled)
633 {
634         struct evdev_dispatch *dispatch;
635         struct tp_dispatch *tp = NULL;
636
637         dispatch = ((struct evdev_device *) device)->dispatch;
638         tp = container_of(dispatch, tp, base);
639
640         tp->tap.enabled = (enabled == LIBINPUT_CONFIG_TAP_ENABLED);
641
642         return LIBINPUT_CONFIG_STATUS_SUCCESS;
643 }
644
645 static enum libinput_config_tap_state
646 tp_tap_config_is_enabled(struct libinput_device *device)
647 {
648         struct evdev_dispatch *dispatch;
649         struct tp_dispatch *tp = NULL;
650
651         dispatch = ((struct evdev_device *) device)->dispatch;
652         tp = container_of(dispatch, tp, base);
653
654         return tp->tap.enabled ? LIBINPUT_CONFIG_TAP_ENABLED :
655                                  LIBINPUT_CONFIG_TAP_DISABLED;
656 }
657
658 static enum libinput_config_tap_state
659 tp_tap_config_get_default(struct libinput_device *device)
660 {
661         /**
662          * Tapping is disabled by default for two reasons:
663          * * if you don't know that tapping is a thing (or enabled by
664          *   default), you get spurious mouse events that make the desktop
665          *   feel buggy.
666          * * if you do know what tapping is and you want it, you
667          *   usually know where to enable it, or at least you can search for
668          *   it.
669          */
670         return LIBINPUT_CONFIG_TAP_DISABLED;
671 }
672
673 int
674 tp_init_tap(struct tp_dispatch *tp)
675 {
676         tp->tap.config.count = tp_tap_config_count;
677         tp->tap.config.set_enabled = tp_tap_config_set_enabled;
678         tp->tap.config.get_enabled = tp_tap_config_is_enabled;
679         tp->tap.config.get_default = tp_tap_config_get_default;
680         tp->device->base.config.tap = &tp->tap.config;
681
682         tp->tap.state = TAP_STATE_IDLE;
683
684         libinput_timer_init(&tp->tap.timer,
685                             tp->device->base.seat->libinput,
686                             tp_tap_handle_timeout, tp);
687
688         return 0;
689 }
690
691 void
692 tp_destroy_tap(struct tp_dispatch *tp)
693 {
694         libinput_timer_cancel(&tp->tap.timer);
695 }
696
697 void
698 tp_release_all_taps(struct tp_dispatch *tp, uint64_t now)
699 {
700         tp_tap_handle_timeout(now, tp);
701 }