touchpad: mark a intentional switch case fallthrough as such
[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                 tp_tap_clear_timer(tp);
225                 break;
226         case TAP_EVENT_TIMEOUT:
227                 tp->tap.state = TAP_STATE_IDLE;
228                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
229                 break;
230         case TAP_EVENT_BUTTON:
231                 tp->tap.state = TAP_STATE_DEAD;
232                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
233                 break;
234         }
235 }
236
237 static void
238 tp_tap_touch2_handle_event(struct tp_dispatch *tp,
239                            struct tp_touch *t,
240                            enum tap_event event, uint64_t time)
241 {
242
243         switch (event) {
244         case TAP_EVENT_TOUCH:
245                 tp->tap.state = TAP_STATE_TOUCH_3;
246                 tp_tap_set_timer(tp, time);
247                 break;
248         case TAP_EVENT_RELEASE:
249                 tp->tap.state = TAP_STATE_HOLD;
250                 tp_tap_notify(tp, t, time, 2, LIBINPUT_BUTTON_STATE_PRESSED);
251                 tp_tap_notify(tp, t, time, 2, LIBINPUT_BUTTON_STATE_RELEASED);
252                 tp_tap_clear_timer(tp);
253                 break;
254         case TAP_EVENT_MOTION:
255                 tp_tap_clear_timer(tp);
256                 /* fallthrough */
257         case TAP_EVENT_TIMEOUT:
258                 tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
259                 break;
260         case TAP_EVENT_BUTTON:
261                 tp->tap.state = TAP_STATE_DEAD;
262                 break;
263         }
264 }
265
266 static void
267 tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp,
268                                 struct tp_touch *t,
269                                 enum tap_event event, uint64_t time)
270 {
271
272         switch (event) {
273         case TAP_EVENT_TOUCH:
274                 tp->tap.state = TAP_STATE_TOUCH_3;
275                 tp_tap_set_timer(tp, time);
276                 break;
277         case TAP_EVENT_RELEASE:
278                 tp->tap.state = TAP_STATE_HOLD;
279                 break;
280         case TAP_EVENT_MOTION:
281         case TAP_EVENT_TIMEOUT:
282                 tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
283                 break;
284         case TAP_EVENT_BUTTON:
285                 tp->tap.state = TAP_STATE_DEAD;
286                 break;
287         }
288 }
289
290 static void
291 tp_tap_touch3_handle_event(struct tp_dispatch *tp,
292                            struct tp_touch *t,
293                            enum tap_event event, uint64_t time)
294 {
295
296         switch (event) {
297         case TAP_EVENT_TOUCH:
298                 tp->tap.state = TAP_STATE_DEAD;
299                 tp_tap_clear_timer(tp);
300                 break;
301         case TAP_EVENT_MOTION:
302         case TAP_EVENT_TIMEOUT:
303                 tp->tap.state = TAP_STATE_TOUCH_3_HOLD;
304                 tp_tap_clear_timer(tp);
305                 break;
306         case TAP_EVENT_RELEASE:
307                 tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
308                 tp_tap_notify(tp, t, time, 3, LIBINPUT_BUTTON_STATE_PRESSED);
309                 tp_tap_notify(tp, t, time, 3, LIBINPUT_BUTTON_STATE_RELEASED);
310                 break;
311         case TAP_EVENT_BUTTON:
312                 tp->tap.state = TAP_STATE_DEAD;
313                 break;
314         }
315 }
316
317 static void
318 tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp,
319                                 struct tp_touch *t,
320                                 enum tap_event event, uint64_t time)
321 {
322
323         switch (event) {
324         case TAP_EVENT_TOUCH:
325                 tp->tap.state = TAP_STATE_DEAD;
326                 tp_tap_set_timer(tp, time);
327                 break;
328         case TAP_EVENT_RELEASE:
329                 tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
330                 break;
331         case TAP_EVENT_MOTION:
332         case TAP_EVENT_TIMEOUT:
333                 break;
334         case TAP_EVENT_BUTTON:
335                 tp->tap.state = TAP_STATE_DEAD;
336                 break;
337         }
338 }
339
340 static void
341 tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
342                                           struct tp_touch *t,
343                                           enum tap_event event, uint64_t time)
344 {
345         switch (event) {
346         case TAP_EVENT_TOUCH:
347                 tp->tap.state = TAP_STATE_DRAGGING_2;
348                 break;
349         case TAP_EVENT_RELEASE:
350                 tp->tap.state = TAP_STATE_IDLE;
351                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
352                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
353                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
354                 tp_tap_clear_timer(tp);
355                 break;
356         case TAP_EVENT_MOTION:
357         case TAP_EVENT_TIMEOUT:
358                 tp->tap.state = TAP_STATE_DRAGGING;
359                 break;
360         case TAP_EVENT_BUTTON:
361                 tp->tap.state = TAP_STATE_DEAD;
362                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
363                 break;
364         }
365 }
366
367 static void
368 tp_tap_dragging_handle_event(struct tp_dispatch *tp,
369                              struct tp_touch *t,
370                              enum tap_event event, uint64_t time)
371 {
372
373         switch (event) {
374         case TAP_EVENT_TOUCH:
375                 tp->tap.state = TAP_STATE_DRAGGING_2;
376                 break;
377         case TAP_EVENT_RELEASE:
378                 tp->tap.state = TAP_STATE_DRAGGING_WAIT;
379                 tp_tap_set_timer(tp, time);
380                 break;
381         case TAP_EVENT_MOTION:
382         case TAP_EVENT_TIMEOUT:
383                 /* noop */
384                 break;
385         case TAP_EVENT_BUTTON:
386                 tp->tap.state = TAP_STATE_DEAD;
387                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
388                 break;
389         }
390 }
391
392 static void
393 tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
394                                   struct tp_touch *t,
395                                   enum tap_event event, uint64_t time)
396 {
397
398         switch (event) {
399         case TAP_EVENT_TOUCH:
400                 tp->tap.state = TAP_STATE_DRAGGING;
401                 tp_tap_clear_timer(tp);
402                 break;
403         case TAP_EVENT_RELEASE:
404         case TAP_EVENT_MOTION:
405                 break;
406         case TAP_EVENT_TIMEOUT:
407                 tp->tap.state = TAP_STATE_IDLE;
408                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
409                 break;
410         case TAP_EVENT_BUTTON:
411                 tp->tap.state = TAP_STATE_DEAD;
412                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
413                 break;
414         }
415 }
416
417 static void
418 tp_tap_dragging2_handle_event(struct tp_dispatch *tp,
419                               struct tp_touch *t,
420                               enum tap_event event, uint64_t time)
421 {
422
423         switch (event) {
424         case TAP_EVENT_RELEASE:
425                 tp->tap.state = TAP_STATE_DRAGGING;
426                 break;
427         case TAP_EVENT_TOUCH:
428                 tp->tap.state = TAP_STATE_DEAD;
429                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
430                 break;
431         case TAP_EVENT_MOTION:
432         case TAP_EVENT_TIMEOUT:
433                 /* noop */
434                 break;
435         case TAP_EVENT_BUTTON:
436                 tp->tap.state = TAP_STATE_DEAD;
437                 tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
438                 break;
439         }
440 }
441
442 static void
443 tp_tap_dead_handle_event(struct tp_dispatch *tp,
444                          struct tp_touch *t,
445                          enum tap_event event,
446                          uint64_t time)
447 {
448
449         switch (event) {
450         case TAP_EVENT_RELEASE:
451                 if (tp->nfingers_down == 0)
452                         tp->tap.state = TAP_STATE_IDLE;
453                 break;
454         case TAP_EVENT_TOUCH:
455         case TAP_EVENT_MOTION:
456         case TAP_EVENT_TIMEOUT:
457         case TAP_EVENT_BUTTON:
458                 break;
459         }
460 }
461
462 static void
463 tp_tap_handle_event(struct tp_dispatch *tp,
464                     struct tp_touch *t,
465                     enum tap_event event,
466                     uint64_t time)
467 {
468         struct libinput *libinput = tp->device->base.seat->libinput;
469         enum tp_tap_state current;
470
471         current = tp->tap.state;
472
473         switch(tp->tap.state) {
474         case TAP_STATE_IDLE:
475                 if (!tp->tap.enabled)
476                         break;
477
478                 tp_tap_idle_handle_event(tp, t, event, time);
479                 break;
480         case TAP_STATE_TOUCH:
481                 tp_tap_touch_handle_event(tp, t, event, time);
482                 break;
483         case TAP_STATE_HOLD:
484                 tp_tap_hold_handle_event(tp, t, event, time);
485                 break;
486         case TAP_STATE_TAPPED:
487                 tp_tap_tapped_handle_event(tp, t, event, time);
488                 break;
489         case TAP_STATE_TOUCH_2:
490                 tp_tap_touch2_handle_event(tp, t, event, time);
491                 break;
492         case TAP_STATE_TOUCH_2_HOLD:
493                 tp_tap_touch2_hold_handle_event(tp, t, event, time);
494                 break;
495         case TAP_STATE_TOUCH_3:
496                 tp_tap_touch3_handle_event(tp, t, event, time);
497                 break;
498         case TAP_STATE_TOUCH_3_HOLD:
499                 tp_tap_touch3_hold_handle_event(tp, t, event, time);
500                 break;
501         case TAP_STATE_DRAGGING_OR_DOUBLETAP:
502                 tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time);
503                 break;
504         case TAP_STATE_DRAGGING:
505                 tp_tap_dragging_handle_event(tp, t, event, time);
506                 break;
507         case TAP_STATE_DRAGGING_WAIT:
508                 tp_tap_dragging_wait_handle_event(tp, t, event, time);
509                 break;
510         case TAP_STATE_DRAGGING_2:
511                 tp_tap_dragging2_handle_event(tp, t, event, time);
512                 break;
513         case TAP_STATE_DEAD:
514                 tp_tap_dead_handle_event(tp, t, event, time);
515                 break;
516         }
517
518         if (tp->tap.state == TAP_STATE_IDLE || tp->tap.state == TAP_STATE_DEAD)
519                 tp_tap_clear_timer(tp);
520
521         log_debug(libinput,
522                   "tap state: %s → %s → %s\n",
523                   tap_state_to_str(current),
524                   tap_event_to_str(event),
525                   tap_state_to_str(tp->tap.state));
526 }
527
528 static bool
529 tp_tap_exceeds_motion_threshold(struct tp_dispatch *tp, struct tp_touch *t)
530 {
531         int threshold = DEFAULT_TAP_MOVE_THRESHOLD;
532         double dx, dy;
533
534         tp_get_delta(t, &dx, &dy);
535
536         return dx * dx + dy * dy > threshold * threshold;
537 }
538
539 int
540 tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
541 {
542         struct tp_touch *t;
543         int filter_motion = 0;
544
545         if (tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS)
546                 tp_tap_handle_event(tp, NULL, TAP_EVENT_BUTTON, time);
547
548         tp_for_each_touch(tp, t) {
549                 if (!t->dirty || t->state == TOUCH_NONE)
550                         continue;
551
552                 if (tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS)
553                         t->tap.state = TAP_TOUCH_STATE_DEAD;
554
555                 if (t->state == TOUCH_BEGIN) {
556                         t->tap.state = TAP_TOUCH_STATE_TOUCH;
557                         tp_tap_handle_event(tp, t, TAP_EVENT_TOUCH, time);
558                 } else if (t->state == TOUCH_END) {
559                         tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time);
560                         t->tap.state = TAP_TOUCH_STATE_DEAD;
561                 } else if (tp->tap.state != TAP_STATE_IDLE &&
562                          tp_tap_exceeds_motion_threshold(tp, t)) {
563                         struct tp_touch *tmp;
564
565                         /* Any touch exceeding the threshold turns all
566                          * touches into DEAD */
567                         tp_for_each_touch(tp, tmp) {
568                                 if (tmp->tap.state == TAP_TOUCH_STATE_TOUCH)
569                                         tmp->tap.state = TAP_TOUCH_STATE_DEAD;
570                         }
571
572                         tp_tap_handle_event(tp, t, TAP_EVENT_MOTION, time);
573                 }
574         }
575
576         /**
577          * In any state where motion exceeding the move threshold would
578          * move to the next state, filter that motion until we actually
579          * exceed it. This prevents small motion events while we're waiting
580          * on a decision if a tap is a tap.
581          */
582         switch (tp->tap.state) {
583         case TAP_STATE_TOUCH:
584         case TAP_STATE_TAPPED:
585         case TAP_STATE_DRAGGING_OR_DOUBLETAP:
586         case TAP_STATE_TOUCH_2:
587         case TAP_STATE_TOUCH_3:
588                 filter_motion = 1;
589                 break;
590
591         default:
592                 break;
593
594         }
595
596         return filter_motion;
597 }
598
599 static void
600 tp_tap_handle_timeout(uint64_t time, void *data)
601 {
602         struct tp_dispatch *tp = data;
603         struct tp_touch *t;
604
605         tp_tap_handle_event(tp, NULL, TAP_EVENT_TIMEOUT, time);
606
607         tp_for_each_touch(tp, t) {
608                 if (t->state == TOUCH_NONE ||
609                     t->tap.state == TAP_TOUCH_STATE_IDLE)
610                         continue;
611
612                 t->tap.state = TAP_TOUCH_STATE_DEAD;
613         }
614 }
615
616 static int
617 tp_tap_config_count(struct libinput_device *device)
618 {
619         struct evdev_dispatch *dispatch;
620         struct tp_dispatch *tp;
621
622         dispatch = ((struct evdev_device *) device)->dispatch;
623         tp = container_of(dispatch, tp, base);
624
625         return min(tp->ntouches, 3); /* we only do up to 3 finger tap */
626 }
627
628 static enum libinput_config_status
629 tp_tap_config_set_enabled(struct libinput_device *device,
630                           enum libinput_config_tap_state enabled)
631 {
632         struct evdev_dispatch *dispatch;
633         struct tp_dispatch *tp;
634
635         dispatch = ((struct evdev_device *) device)->dispatch;
636         tp = container_of(dispatch, tp, base);
637
638         tp->tap.enabled = (enabled == LIBINPUT_CONFIG_TAP_ENABLED);
639
640         return LIBINPUT_CONFIG_STATUS_SUCCESS;
641 }
642
643 static enum libinput_config_tap_state
644 tp_tap_config_is_enabled(struct libinput_device *device)
645 {
646         struct evdev_dispatch *dispatch;
647         struct tp_dispatch *tp;
648
649         dispatch = ((struct evdev_device *) device)->dispatch;
650         tp = container_of(dispatch, tp, base);
651
652         return tp->tap.enabled ? LIBINPUT_CONFIG_TAP_ENABLED :
653                                  LIBINPUT_CONFIG_TAP_DISABLED;
654 }
655
656 static enum libinput_config_tap_state
657 tp_tap_config_get_default(struct libinput_device *device)
658 {
659         /**
660          * Tapping is disabled by default for two reasons:
661          * * if you don't know that tapping is a thing (or enabled by
662          *   default), you get spurious mouse events that make the desktop
663          *   feel buggy.
664          * * if you do know what tapping is and you want it, you
665          *   usually know where to enable it, or at least you can search for
666          *   it.
667          */
668         return LIBINPUT_CONFIG_TAP_DISABLED;
669 }
670
671 int
672 tp_init_tap(struct tp_dispatch *tp)
673 {
674         tp->tap.config.count = tp_tap_config_count;
675         tp->tap.config.set_enabled = tp_tap_config_set_enabled;
676         tp->tap.config.get_enabled = tp_tap_config_is_enabled;
677         tp->tap.config.get_default = tp_tap_config_get_default;
678         tp->device->base.config.tap = &tp->tap.config;
679
680         tp->tap.state = TAP_STATE_IDLE;
681
682         libinput_timer_init(&tp->tap.timer,
683                             tp->device->base.seat->libinput,
684                             tp_tap_handle_timeout, tp);
685
686         return 0;
687 }
688
689 void
690 tp_destroy_tap(struct tp_dispatch *tp)
691 {
692         libinput_timer_cancel(&tp->tap.timer);
693 }