touchpad: hook up click method configuration
[platform/upstream/libinput.git] / src / evdev-mt-touchpad.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 "config.h"
24
25 #include <assert.h>
26 #include <math.h>
27 #include <stdbool.h>
28 #include <limits.h>
29
30 #include "evdev-mt-touchpad.h"
31
32 #define DEFAULT_ACCEL_NUMERATOR 1200.0
33 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
34 #define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 500 /* ms */
35
36 static inline int
37 tp_hysteresis(int in, int center, int margin)
38 {
39         int diff = in - center;
40         if (abs(diff) <= margin)
41                 return center;
42
43         if (diff > margin)
44                 return center + diff - margin;
45         else
46                 return center + diff + margin;
47 }
48
49 static inline struct tp_motion *
50 tp_motion_history_offset(struct tp_touch *t, int offset)
51 {
52         int offset_index =
53                 (t->history.index - offset + TOUCHPAD_HISTORY_LENGTH) %
54                 TOUCHPAD_HISTORY_LENGTH;
55
56         return &t->history.samples[offset_index];
57 }
58
59 void
60 tp_filter_motion(struct tp_dispatch *tp,
61                  double *dx, double *dy,
62                  double *dx_unaccel, double *dy_unaccel,
63                  uint64_t time)
64 {
65         struct motion_params motion;
66
67         motion.dx = *dx * tp->accel.x_scale_coeff;
68         motion.dy = *dy * tp->accel.y_scale_coeff;
69
70         if (dx_unaccel)
71                 *dx_unaccel = motion.dx;
72         if (dy_unaccel)
73                 *dy_unaccel = motion.dy;
74
75         if (motion.dx != 0.0 || motion.dy != 0.0)
76                 filter_dispatch(tp->device->pointer.filter, &motion, tp, time);
77
78         *dx = motion.dx;
79         *dy = motion.dy;
80 }
81
82 static inline void
83 tp_motion_history_push(struct tp_touch *t)
84 {
85         int motion_index = (t->history.index + 1) % TOUCHPAD_HISTORY_LENGTH;
86
87         if (t->history.count < TOUCHPAD_HISTORY_LENGTH)
88                 t->history.count++;
89
90         t->history.samples[motion_index].x = t->x;
91         t->history.samples[motion_index].y = t->y;
92         t->history.index = motion_index;
93 }
94
95 static inline void
96 tp_motion_hysteresis(struct tp_dispatch *tp,
97                      struct tp_touch *t)
98 {
99         int x = t->x,
100             y = t->y;
101
102         if (t->history.count == 0) {
103                 t->hysteresis.center_x = t->x;
104                 t->hysteresis.center_y = t->y;
105         } else {
106                 x = tp_hysteresis(x,
107                                   t->hysteresis.center_x,
108                                   tp->hysteresis.margin_x);
109                 y = tp_hysteresis(y,
110                                   t->hysteresis.center_y,
111                                   tp->hysteresis.margin_y);
112                 t->hysteresis.center_x = x;
113                 t->hysteresis.center_y = y;
114                 t->x = x;
115                 t->y = y;
116         }
117 }
118
119 static inline void
120 tp_motion_history_reset(struct tp_touch *t)
121 {
122         t->history.count = 0;
123 }
124
125 static inline struct tp_touch *
126 tp_current_touch(struct tp_dispatch *tp)
127 {
128         return &tp->touches[min(tp->slot, tp->ntouches - 1)];
129 }
130
131 static inline struct tp_touch *
132 tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
133 {
134         assert(slot < tp->ntouches);
135         return &tp->touches[slot];
136 }
137
138 static inline unsigned int
139 tp_fake_finger_count(struct tp_dispatch *tp)
140 {
141         /* don't count BTN_TOUCH */
142         return ffs(tp->fake_touches >> 1);
143 }
144
145 static inline bool
146 tp_fake_finger_is_touching(struct tp_dispatch *tp)
147 {
148         return tp->fake_touches & 0x1;
149 }
150
151 static inline void
152 tp_fake_finger_set(struct tp_dispatch *tp,
153                    unsigned int code,
154                    bool is_press)
155 {
156         unsigned int shift;
157
158         switch (code) {
159         case BTN_TOUCH:
160                 shift = 0;
161                 break;
162         case BTN_TOOL_FINGER:
163                 shift = 1;
164                 break;
165         case BTN_TOOL_DOUBLETAP:
166         case BTN_TOOL_TRIPLETAP:
167         case BTN_TOOL_QUADTAP:
168                 shift = code - BTN_TOOL_DOUBLETAP + 2;
169                 break;
170         default:
171                 return;
172         }
173
174         if (is_press)
175                 tp->fake_touches |= 1 << shift;
176         else
177                 tp->fake_touches &= ~(0x1 << shift);
178 }
179
180 static inline void
181 tp_new_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
182 {
183         if (t->state == TOUCH_BEGIN ||
184             t->state == TOUCH_UPDATE ||
185             t->state == TOUCH_HOVERING)
186                 return;
187
188         /* we begin the touch as hovering because until BTN_TOUCH happens we
189          * don't know if it's a touch down or not. And BTN_TOUCH may happen
190          * after ABS_MT_TRACKING_ID */
191         tp_motion_history_reset(t);
192         t->dirty = true;
193         t->has_ended = false;
194         t->state = TOUCH_HOVERING;
195         t->pinned.is_pinned = false;
196         t->millis = time;
197         tp->queued |= TOUCHPAD_EVENT_MOTION;
198 }
199
200 static inline void
201 tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
202 {
203         t->dirty = true;
204         t->state = TOUCH_BEGIN;
205         t->millis = time;
206         tp->nfingers_down++;
207         assert(tp->nfingers_down >= 1);
208 }
209
210 /**
211  * End a touch, even if the touch sequence is still active.
212  */
213 static inline void
214 tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
215 {
216         switch (t->state) {
217         case TOUCH_HOVERING:
218                 t->state = TOUCH_NONE;
219                 /* fallthough */
220         case TOUCH_NONE:
221         case TOUCH_END:
222                 return;
223         case TOUCH_BEGIN:
224         case TOUCH_UPDATE:
225                 break;
226
227         }
228
229         t->dirty = true;
230         t->is_pointer = false;
231         t->palm.is_palm = false;
232         t->state = TOUCH_END;
233         t->pinned.is_pinned = false;
234         t->millis = time;
235         assert(tp->nfingers_down >= 1);
236         tp->nfingers_down--;
237         tp->queued |= TOUCHPAD_EVENT_MOTION;
238 }
239
240 /**
241  * End the touch sequence on ABS_MT_TRACKING_ID -1 or when the BTN_TOOL_* 0 is received.
242  */
243 static inline void
244 tp_end_sequence(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
245 {
246         t->has_ended = true;
247         tp_end_touch(tp, t, time);
248 }
249
250 static double
251 tp_estimate_delta(int x0, int x1, int x2, int x3)
252 {
253         return (x0 + x1 - x2 - x3) / 4.0;
254 }
255
256 void
257 tp_get_delta(struct tp_touch *t, double *dx, double *dy)
258 {
259         if (t->history.count < TOUCHPAD_MIN_SAMPLES) {
260                 *dx = 0;
261                 *dy = 0;
262                 return;
263         }
264
265         *dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x,
266                                 tp_motion_history_offset(t, 1)->x,
267                                 tp_motion_history_offset(t, 2)->x,
268                                 tp_motion_history_offset(t, 3)->x);
269         *dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y,
270                                 tp_motion_history_offset(t, 1)->y,
271                                 tp_motion_history_offset(t, 2)->y,
272                                 tp_motion_history_offset(t, 3)->y);
273 }
274
275 static void
276 tp_process_absolute(struct tp_dispatch *tp,
277                     const struct input_event *e,
278                     uint64_t time)
279 {
280         struct tp_touch *t = tp_current_touch(tp);
281
282         switch(e->code) {
283         case ABS_MT_POSITION_X:
284                 t->x = e->value;
285                 t->millis = time;
286                 t->dirty = true;
287                 tp->queued |= TOUCHPAD_EVENT_MOTION;
288                 break;
289         case ABS_MT_POSITION_Y:
290                 t->y = e->value;
291                 t->millis = time;
292                 t->dirty = true;
293                 tp->queued |= TOUCHPAD_EVENT_MOTION;
294                 break;
295         case ABS_MT_SLOT:
296                 tp->slot = e->value;
297                 break;
298         case ABS_MT_TRACKING_ID:
299                 if (e->value != -1)
300                         tp_new_touch(tp, t, time);
301                 else
302                         tp_end_sequence(tp, t, time);
303         }
304 }
305
306 static void
307 tp_process_absolute_st(struct tp_dispatch *tp,
308                        const struct input_event *e,
309                        uint64_t time)
310 {
311         struct tp_touch *t = tp_current_touch(tp);
312
313         switch(e->code) {
314         case ABS_X:
315                 t->x = e->value;
316                 t->millis = time;
317                 t->dirty = true;
318                 tp->queued |= TOUCHPAD_EVENT_MOTION;
319                 break;
320         case ABS_Y:
321                 t->y = e->value;
322                 t->millis = time;
323                 t->dirty = true;
324                 tp->queued |= TOUCHPAD_EVENT_MOTION;
325                 break;
326         }
327 }
328
329 static void
330 tp_process_fake_touch(struct tp_dispatch *tp,
331                       const struct input_event *e,
332                       uint64_t time)
333 {
334         struct tp_touch *t;
335         unsigned int nfake_touches;
336         unsigned int i, start;
337
338         tp_fake_finger_set(tp, e->code, e->value != 0);
339
340         nfake_touches = tp_fake_finger_count(tp);
341
342         start = tp->has_mt ? tp->real_touches : 0;
343         for (i = start; i < tp->ntouches; i++) {
344                 t = tp_get_touch(tp, i);
345                 if (i < nfake_touches)
346                         tp_new_touch(tp, t, time);
347                 else
348                         tp_end_sequence(tp, t, time);
349         }
350 }
351
352 static void
353 tp_process_key(struct tp_dispatch *tp,
354                const struct input_event *e,
355                uint64_t time)
356 {
357         switch (e->code) {
358                 case BTN_LEFT:
359                 case BTN_MIDDLE:
360                 case BTN_RIGHT:
361                         tp_process_button(tp, e, time);
362                         break;
363                 case BTN_TOUCH:
364                 case BTN_TOOL_FINGER:
365                 case BTN_TOOL_DOUBLETAP:
366                 case BTN_TOOL_TRIPLETAP:
367                 case BTN_TOOL_QUADTAP:
368                         tp_process_fake_touch(tp, e, time);
369                         break;
370         }
371 }
372
373 static void
374 tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
375 {
376         unsigned int xdist, ydist;
377
378         if (!t->pinned.is_pinned)
379                 return;
380
381         xdist = abs(t->x - t->pinned.center_x);
382         ydist = abs(t->y - t->pinned.center_y);
383
384         if (xdist * xdist + ydist * ydist >=
385                         tp->buttons.motion_dist * tp->buttons.motion_dist) {
386                 t->pinned.is_pinned = false;
387                 tp_set_pointer(tp, t);
388                 return;
389         }
390
391         /* The finger may slowly drift, adjust the center */
392         t->pinned.center_x = t->x + t->pinned.center_x / 2;
393         t->pinned.center_y = t->y + t->pinned.center_y / 2;
394 }
395
396 static void
397 tp_pin_fingers(struct tp_dispatch *tp)
398 {
399         struct tp_touch *t;
400
401         tp_for_each_touch(tp, t) {
402                 t->is_pointer = false;
403                 t->pinned.is_pinned = true;
404                 t->pinned.center_x = t->x;
405                 t->pinned.center_y = t->y;
406         }
407 }
408
409 static int
410 tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
411 {
412         return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
413                 !t->palm.is_palm &&
414                 !t->pinned.is_pinned &&
415                 tp_button_touch_active(tp, t) &&
416                 tp_edge_scroll_touch_active(tp, t);
417 }
418
419 void
420 tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
421 {
422         struct tp_touch *tmp = NULL;
423
424         /* Only set the touch as pointer if we don't have one yet */
425         tp_for_each_touch(tp, tmp) {
426                 if (tmp->is_pointer)
427                         return;
428         }
429
430         if (tp_touch_active(tp, t))
431                 t->is_pointer = true;
432 }
433
434 static void
435 tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
436 {
437         const int PALM_TIMEOUT = 200; /* ms */
438         const int DIRECTIONS = NE|E|SE|SW|W|NW;
439
440         /* If labelled a touch as palm, we unlabel as palm when
441            we move out of the palm edge zone within the timeout, provided
442            the direction is within 45 degrees of the horizontal.
443          */
444         if (t->palm.is_palm) {
445                 if (time < t->palm.time + PALM_TIMEOUT &&
446                     (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge)) {
447                         int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y);
448                         if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
449                                 t->palm.is_palm = false;
450                                 tp_set_pointer(tp, t);
451                         }
452                 }
453                 return;
454         }
455
456         /* palm must start in exclusion zone, it's ok to move into
457            the zone without being a palm */
458         if (t->state != TOUCH_BEGIN ||
459             (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge))
460                 return;
461
462         /* don't detect palm in software button areas, it's
463            likely that legitimate touches start in the area
464            covered by the exclusion zone */
465         if (tp->buttons.is_clickpad &&
466             tp_button_is_inside_softbutton_area(tp, t))
467                 return;
468
469         t->palm.is_palm = true;
470         t->palm.time = time;
471         t->palm.x = t->x;
472         t->palm.y = t->y;
473 }
474
475 static void
476 tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
477 {
478         struct tp_touch *t;
479         int nchanged = 0;
480         double dx = 0, dy =0;
481         double tmpx, tmpy;
482
483         tp_for_each_touch(tp, t) {
484                 if (tp_touch_active(tp, t) && t->dirty) {
485                         nchanged++;
486                         tp_get_delta(t, &tmpx, &tmpy);
487
488                         dx += tmpx;
489                         dy += tmpy;
490                 }
491                 /* Stop spurious MOTION events at the end of scrolling */
492                 t->is_pointer = false;
493         }
494
495         if (nchanged == 0)
496                 return;
497
498         dx /= nchanged;
499         dy /= nchanged;
500
501         tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
502
503         evdev_post_scroll(tp->device,
504                           time,
505                           LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
506                           dx, dy);
507         tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_ACTIVE;
508 }
509
510 static void
511 tp_twofinger_stop_scroll(struct tp_dispatch *tp, uint64_t time)
512 {
513         struct tp_touch *t, *ptr = NULL;
514         int nfingers_down = 0;
515
516         evdev_stop_scroll(tp->device,
517                           time,
518                           LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
519
520         /* If we were scrolling and now there's exactly 1 active finger,
521            switch back to pointer movement */
522         if (tp->scroll.twofinger_state == TWOFINGER_SCROLL_STATE_ACTIVE) {
523                 tp_for_each_touch(tp, t) {
524                         if (tp_touch_active(tp, t)) {
525                                 nfingers_down++;
526                                 if (ptr == NULL)
527                                         ptr = t;
528                         }
529                 }
530
531                 if (nfingers_down == 1)
532                         tp_set_pointer(tp, ptr);
533         }
534
535         tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_NONE;
536 }
537
538 static int
539 tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
540 {
541         struct tp_touch *t;
542         int nfingers_down = 0;
543
544         /* No 2fg scrolling during tap-n-drag */
545         if (tp_tap_dragging(tp))
546                 return 0;
547
548         /* No 2fg scrolling while a clickpad is clicked */
549         if (tp->buttons.is_clickpad && tp->buttons.state)
550                 return 0;
551
552         /* Only count active touches for 2 finger scrolling */
553         tp_for_each_touch(tp, t) {
554                 if (tp_touch_active(tp, t))
555                         nfingers_down++;
556         }
557
558         if (nfingers_down == 2) {
559                 tp_post_twofinger_scroll(tp, time);
560                 return 1;
561         }
562
563         tp_twofinger_stop_scroll(tp, time);
564
565         return 0;
566 }
567
568 static void
569 tp_scroll_handle_state(struct tp_dispatch *tp, uint64_t time)
570 {
571         /* Note this must be always called, so that it knows the state of
572          * touches when the scroll-mode changes.
573          */
574         tp_edge_scroll_handle_state(tp, time);
575 }
576
577 static int
578 tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
579 {
580         struct libinput *libinput = tp->device->base.seat->libinput;
581
582         switch (tp->scroll.method) {
583         case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
584                 break;
585         case LIBINPUT_CONFIG_SCROLL_2FG:
586                 return tp_twofinger_scroll_post_events(tp, time);
587         case LIBINPUT_CONFIG_SCROLL_EDGE:
588                 return tp_edge_scroll_post_events(tp, time);
589         case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN:
590                 log_bug_libinput(libinput, "Unexpected scroll mode\n");
591                 break;
592         }
593         return 0;
594 }
595
596 static void
597 tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time)
598 {
599         struct libinput *libinput = tp->device->base.seat->libinput;
600
601         switch (tp->scroll.method) {
602         case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
603                 break;
604         case LIBINPUT_CONFIG_SCROLL_2FG:
605                 tp_twofinger_stop_scroll(tp, time);
606                 break;
607         case LIBINPUT_CONFIG_SCROLL_EDGE:
608                 tp_edge_scroll_stop_events(tp, time);
609                 break;
610         case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN:
611                 log_bug_libinput(libinput, "Unexpected scroll mode\n");
612                 break;
613         }
614 }
615
616 static void
617 tp_remove_scroll(struct tp_dispatch *tp)
618 {
619         tp_remove_edge_scroll(tp);
620 }
621
622 static void
623 tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
624 {
625         struct tp_touch *t;
626         unsigned int nfake_touches;
627         int i;
628
629         if (!tp->fake_touches && !tp->nfingers_down)
630                 return;
631
632         nfake_touches = tp_fake_finger_count(tp);
633         if (tp->nfingers_down == nfake_touches &&
634             ((tp->nfingers_down == 0 && !tp_fake_finger_is_touching(tp)) ||
635              (tp->nfingers_down > 0 && tp_fake_finger_is_touching(tp))))
636                 return;
637
638         /* if BTN_TOUCH is set and we have less fingers down than fake
639          * touches, switch each hovering touch to BEGIN
640          * until nfingers_down matches nfake_touches
641          */
642         if (tp_fake_finger_is_touching(tp) &&
643             tp->nfingers_down < nfake_touches) {
644                 for (i = 0; i < (int)tp->ntouches; i++) {
645                         t = tp_get_touch(tp, i);
646
647                         if (t->state == TOUCH_HOVERING) {
648                                 tp_begin_touch(tp, t, time);
649
650                                 if (tp->nfingers_down >= nfake_touches)
651                                         break;
652                         }
653                 }
654         }
655
656         /* if BTN_TOUCH is unset end all touches, we're hovering now. If we
657          * have too many touches also end some of them. This is done in
658          * reverse order.
659          */
660         if (tp->nfingers_down > nfake_touches ||
661             !tp_fake_finger_is_touching(tp)) {
662                 for (i = tp->ntouches - 1; i >= 0; i--) {
663                         t = tp_get_touch(tp, i);
664
665                         if (t->state == TOUCH_HOVERING)
666                                 continue;
667
668                         tp_end_touch(tp, t, time);
669
670                         if (tp_fake_finger_is_touching(tp) &&
671                             tp->nfingers_down == nfake_touches)
672                                 break;
673                 }
674         }
675 }
676
677 static void
678 tp_process_state(struct tp_dispatch *tp, uint64_t time)
679 {
680         struct tp_touch *t;
681         struct tp_touch *first = tp_get_touch(tp, 0);
682         unsigned int i;
683
684         tp_unhover_touches(tp, time);
685
686         for (i = 0; i < tp->ntouches; i++) {
687                 t = tp_get_touch(tp, i);
688
689                 /* semi-mt finger postions may "jump" when nfingers changes */
690                 if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
691                         tp_motion_history_reset(t);
692
693                 if (i >= tp->real_touches && t->state != TOUCH_NONE) {
694                         t->x = first->x;
695                         t->y = first->y;
696                         if (!t->dirty)
697                                 t->dirty = first->dirty;
698                 }
699
700                 if (!t->dirty)
701                         continue;
702
703                 tp_palm_detect(tp, t, time);
704
705                 tp_motion_hysteresis(tp, t);
706                 tp_motion_history_push(t);
707
708                 tp_unpin_finger(tp, t);
709         }
710
711         tp_button_handle_state(tp, time);
712         tp_scroll_handle_state(tp, time);
713
714         /*
715          * We have a physical button down event on a clickpad. To avoid
716          * spurious pointer moves by the clicking finger we pin all fingers.
717          * We unpin fingers when they move more then a certain threshold to
718          * to allow drag and drop.
719          */
720         if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) &&
721             tp->buttons.is_clickpad)
722                 tp_pin_fingers(tp);
723 }
724
725 static void
726 tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
727 {
728         struct tp_touch *t;
729
730         tp_for_each_touch(tp, t) {
731
732                 if (!t->dirty)
733                         continue;
734
735                 if (t->state == TOUCH_END) {
736                         if (t->has_ended)
737                                 t->state = TOUCH_NONE;
738                         else
739                                 t->state = TOUCH_HOVERING;
740                 } else if (t->state == TOUCH_BEGIN) {
741                         t->state = TOUCH_UPDATE;
742                 }
743
744                 t->dirty = false;
745         }
746
747         tp->old_nfingers_down = tp->nfingers_down;
748         tp->buttons.old_state = tp->buttons.state;
749
750         tp->queued = TOUCHPAD_EVENT_NONE;
751 }
752
753 static void
754 tp_get_pointer_delta(struct tp_dispatch *tp, double *dx, double *dy)
755 {
756         struct tp_touch *t = tp_current_touch(tp);
757
758         if (!t->is_pointer) {
759                 tp_for_each_touch(tp, t) {
760                         if (t->is_pointer)
761                                 break;
762                 }
763         }
764
765         if (!t->is_pointer || !t->dirty)
766                 return;
767
768         tp_get_delta(t, dx, dy);
769 }
770
771 static void
772 tp_get_active_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
773 {
774         struct tp_touch *t;
775         double tdx, tdy;
776         unsigned int i;
777
778         for (i = 0; i < tp->real_touches; i++) {
779                 t = tp_get_touch(tp, i);
780
781                 if (!tp_touch_active(tp, t) || !t->dirty)
782                         continue;
783
784                 tp_get_delta(t, &tdx, &tdy);
785                 *dx += tdx;
786                 *dy += tdy;
787         }
788 }
789
790 static void
791 tp_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
792 {
793         double dx = 0.0, dy = 0.0;
794         double dx_unaccel, dy_unaccel;
795
796         /* When a clickpad is clicked, combine motion of all active touches */
797         if (tp->buttons.is_clickpad && tp->buttons.state)
798                 tp_get_active_touches_delta(tp, &dx, &dy);
799         else
800                 tp_get_pointer_delta(tp, &dx, &dy);
801
802         tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time);
803
804         if (dx != 0.0 || dy != 0.0 || dx_unaccel != 0.0 || dy_unaccel != 0.0) {
805                 pointer_notify_motion(&tp->device->base, time,
806                                       dx, dy, dx_unaccel, dy_unaccel);
807         }
808 }
809
810 static void
811 tp_post_events(struct tp_dispatch *tp, uint64_t time)
812 {
813         int filter_motion = 0;
814
815         /* Only post (top) button events while suspended */
816         if (tp->device->suspended) {
817                 tp_post_button_events(tp, time);
818                 return;
819         }
820
821         filter_motion |= tp_tap_handle_state(tp, time);
822         filter_motion |= tp_post_button_events(tp, time);
823
824         if (filter_motion || tp->sendevents.trackpoint_active) {
825                 tp_stop_scroll_events(tp, time);
826                 return;
827         }
828
829         if (tp_post_scroll_events(tp, time) != 0)
830                 return;
831
832         tp_post_pointer_motion(tp, time);
833 }
834
835 static void
836 tp_handle_state(struct tp_dispatch *tp,
837                 uint64_t time)
838 {
839         tp_process_state(tp, time);
840         tp_post_events(tp, time);
841         tp_post_process_state(tp, time);
842 }
843
844 static void
845 tp_process(struct evdev_dispatch *dispatch,
846            struct evdev_device *device,
847            struct input_event *e,
848            uint64_t time)
849 {
850         struct tp_dispatch *tp =
851                 (struct tp_dispatch *)dispatch;
852
853         switch (e->type) {
854         case EV_ABS:
855                 if (tp->has_mt)
856                         tp_process_absolute(tp, e, time);
857                 else
858                         tp_process_absolute_st(tp, e, time);
859                 break;
860         case EV_KEY:
861                 tp_process_key(tp, e, time);
862                 break;
863         case EV_SYN:
864                 tp_handle_state(tp, time);
865                 break;
866         }
867 }
868
869 static void
870 tp_remove_sendevents(struct tp_dispatch *tp)
871 {
872         libinput_timer_cancel(&tp->sendevents.trackpoint_timer);
873
874         if (tp->buttons.trackpoint)
875                 libinput_device_remove_event_listener(
876                                         &tp->sendevents.trackpoint_listener);
877 }
878
879 static void
880 tp_remove(struct evdev_dispatch *dispatch)
881 {
882         struct tp_dispatch *tp =
883                 (struct tp_dispatch*)dispatch;
884
885         tp_remove_tap(tp);
886         tp_remove_buttons(tp);
887         tp_remove_sendevents(tp);
888         tp_remove_scroll(tp);
889 }
890
891 static void
892 tp_destroy(struct evdev_dispatch *dispatch)
893 {
894         struct tp_dispatch *tp =
895                 (struct tp_dispatch*)dispatch;
896
897
898         free(tp->touches);
899         free(tp);
900 }
901
902 static void
903 tp_clear_state(struct tp_dispatch *tp)
904 {
905         uint64_t now = libinput_now(tp->device->base.seat->libinput);
906         struct tp_touch *t;
907
908         /* Unroll the touchpad state.
909          * Release buttons first. If tp is a clickpad, the button event
910          * must come before the touch up. If it isn't, the order doesn't
911          * matter anyway
912          *
913          * Then cancel all timeouts on the taps, triggering the last set
914          * of events.
915          *
916          * Then lift all touches so the touchpad is in a neutral state.
917          *
918          */
919         tp_release_all_buttons(tp, now);
920         tp_release_all_taps(tp, now);
921
922         tp_for_each_touch(tp, t) {
923                 tp_end_sequence(tp, t, now);
924         }
925
926         tp_handle_state(tp, now);
927 }
928
929 static void
930 tp_suspend(struct tp_dispatch *tp, struct evdev_device *device)
931 {
932         tp_clear_state(tp);
933
934         /* On devices with top softwarebuttons we don't actually suspend the
935          * device, to keep the "trackpoint" buttons working. tp_post_events()
936          * will only send events for the trackpoint while suspended.
937          */
938         if (tp->buttons.has_topbuttons) {
939                 evdev_notify_suspended_device(device);
940                 /* Enlarge topbutton area while suspended */
941                 tp_init_top_softbuttons(tp, device, 1.5);
942         } else {
943                 evdev_device_suspend(device);
944         }
945 }
946
947 static void
948 tp_resume(struct tp_dispatch *tp, struct evdev_device *device)
949 {
950         if (tp->buttons.has_topbuttons) {
951                 /* tap state-machine is offline while suspended, reset state */
952                 tp_clear_state(tp);
953                 /* restore original topbutton area size */
954                 tp_init_top_softbuttons(tp, device, 1.0);
955                 evdev_notify_resumed_device(device);
956         } else {
957                 evdev_device_resume(device);
958         }
959 }
960
961 static void
962 tp_trackpoint_timeout(uint64_t now, void *data)
963 {
964         struct tp_dispatch *tp = data;
965
966         tp_tap_resume(tp, now);
967         tp->sendevents.trackpoint_active = false;
968 }
969
970 static void
971 tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
972 {
973         struct tp_dispatch *tp = data;
974
975         /* Buttons do not count as trackpad activity, as people may use
976            the trackpoint buttons in combination with the touchpad. */
977         if (event->type == LIBINPUT_EVENT_POINTER_BUTTON)
978                 return;
979
980         if (!tp->sendevents.trackpoint_active) {
981                 evdev_stop_scroll(tp->device,
982                                   time,
983                                   LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
984                 tp_tap_suspend(tp, time);
985                 tp->sendevents.trackpoint_active = true;
986         }
987
988         libinput_timer_set(&tp->sendevents.trackpoint_timer,
989                            time + DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT);
990 }
991
992 static void
993 tp_device_added(struct evdev_device *device,
994                 struct evdev_device *added_device)
995 {
996         struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
997
998         if (tp->buttons.trackpoint == NULL &&
999             (added_device->tags & EVDEV_TAG_TRACKPOINT)) {
1000                 /* Don't send any pending releases to the new trackpoint */
1001                 tp->buttons.active_is_topbutton = false;
1002                 tp->buttons.trackpoint = added_device;
1003                 libinput_device_add_event_listener(&added_device->base,
1004                                         &tp->sendevents.trackpoint_listener,
1005                                         tp_trackpoint_event, tp);
1006         }
1007
1008         if (tp->sendevents.current_mode !=
1009             LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
1010                 return;
1011
1012         if (added_device->tags & EVDEV_TAG_EXTERNAL_MOUSE)
1013                 tp_suspend(tp, device);
1014 }
1015
1016 static void
1017 tp_device_removed(struct evdev_device *device,
1018                   struct evdev_device *removed_device)
1019 {
1020         struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
1021         struct libinput_device *dev;
1022
1023         if (removed_device == tp->buttons.trackpoint) {
1024                 /* Clear any pending releases for the trackpoint */
1025                 if (tp->buttons.active && tp->buttons.active_is_topbutton) {
1026                         tp->buttons.active = 0;
1027                         tp->buttons.active_is_topbutton = false;
1028                 }
1029                 libinput_device_remove_event_listener(
1030                                         &tp->sendevents.trackpoint_listener);
1031                 tp->buttons.trackpoint = NULL;
1032         }
1033
1034         if (tp->sendevents.current_mode !=
1035             LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
1036                 return;
1037
1038         list_for_each(dev, &device->base.seat->devices_list, link) {
1039                 struct evdev_device *d = (struct evdev_device*)dev;
1040                 if (d != removed_device &&
1041                     (d->tags & EVDEV_TAG_EXTERNAL_MOUSE)) {
1042                         return;
1043                 }
1044         }
1045
1046         tp_resume(tp, device);
1047 }
1048
1049 static void
1050 tp_tag_device(struct evdev_device *device,
1051               struct udev_device *udev_device)
1052 {
1053         int bustype;
1054
1055         /* simple approach: touchpads on USB or Bluetooth are considered
1056          * external, anything else is internal. Exception is Apple -
1057          * internal touchpads are connected over USB and it doesn't have
1058          * external USB touchpads anyway.
1059          */
1060         bustype = libevdev_get_id_bustype(device->evdev);
1061         if (bustype == BUS_USB) {
1062                  if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_APPLE)
1063                          device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
1064         } else if (bustype != BUS_BLUETOOTH)
1065                 device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
1066 }
1067
1068 static struct evdev_dispatch_interface tp_interface = {
1069         tp_process,
1070         tp_remove,
1071         tp_destroy,
1072         tp_device_added,
1073         tp_device_removed,
1074         tp_device_removed, /* device_suspended, treat as remove */
1075         tp_device_added,   /* device_resumed, treat as add */
1076         tp_tag_device,
1077 };
1078
1079 static void
1080 tp_init_touch(struct tp_dispatch *tp,
1081               struct tp_touch *t)
1082 {
1083         t->tp = tp;
1084         t->has_ended = true;
1085 }
1086
1087 static int
1088 tp_init_slots(struct tp_dispatch *tp,
1089               struct evdev_device *device)
1090 {
1091         const struct input_absinfo *absinfo;
1092         struct map {
1093                 unsigned int code;
1094                 int ntouches;
1095         } max_touches[] = {
1096                 { BTN_TOOL_QUINTTAP, 5 },
1097                 { BTN_TOOL_QUADTAP, 4 },
1098                 { BTN_TOOL_TRIPLETAP, 3 },
1099                 { BTN_TOOL_DOUBLETAP, 2 },
1100         };
1101         struct map *m;
1102         unsigned int i, n_btn_tool_touches = 1;
1103
1104         absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
1105         if (absinfo) {
1106                 tp->real_touches = absinfo->maximum + 1;
1107                 tp->slot = absinfo->value;
1108                 tp->has_mt = true;
1109         } else {
1110                 tp->real_touches = 1;
1111                 tp->slot = 0;
1112                 tp->has_mt = false;
1113         }
1114
1115         tp->semi_mt = libevdev_has_property(device->evdev, INPUT_PROP_SEMI_MT);
1116
1117         ARRAY_FOR_EACH(max_touches, m) {
1118                 if (libevdev_has_event_code(device->evdev,
1119                                             EV_KEY,
1120                                             m->code)) {
1121                         n_btn_tool_touches = m->ntouches;
1122                         break;
1123                 }
1124         }
1125
1126         tp->ntouches = max(tp->real_touches, n_btn_tool_touches);
1127         tp->touches = calloc(tp->ntouches, sizeof(struct tp_touch));
1128         if (!tp->touches)
1129                 return -1;
1130
1131         for (i = 0; i < tp->ntouches; i++)
1132                 tp_init_touch(tp, &tp->touches[i]);
1133
1134         return 0;
1135 }
1136
1137 static int
1138 tp_init_accel(struct tp_dispatch *tp, double diagonal)
1139 {
1140         int res_x, res_y;
1141
1142         if (tp->has_mt) {
1143                 res_x = libevdev_get_abs_resolution(tp->device->evdev,
1144                                                     ABS_MT_POSITION_X);
1145                 res_y = libevdev_get_abs_resolution(tp->device->evdev,
1146                                                     ABS_MT_POSITION_Y);
1147         } else {
1148                 res_x = libevdev_get_abs_resolution(tp->device->evdev,
1149                                                     ABS_X);
1150                 res_y = libevdev_get_abs_resolution(tp->device->evdev,
1151                                                     ABS_Y);
1152         }
1153
1154         /*
1155          * Not all touchpads report the same amount of units/mm (resolution).
1156          * Normalize motion events to the default mouse DPI as base
1157          * (unaccelerated) speed. This also evens out any differences in x
1158          * and y resolution, so that a circle on the
1159          * touchpad does not turn into an elipse on the screen.
1160          */
1161         if (res_x > 1 && res_y > 1) {
1162                 tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x;
1163                 tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y;
1164
1165                 /* FIXME: once normalized, touchpads see the same
1166                    acceleration as mice. that is technically correct but
1167                    subjectively wrong, we expect a touchpad to be a lot
1168                    slower than a mouse.
1169                    For now, apply a magic factor here until this is
1170                    fixed in the actual filter code.
1171                  */
1172                 {
1173                         const double MAGIC = 0.4;
1174                         tp->accel.x_scale_coeff *= MAGIC;
1175                         tp->accel.y_scale_coeff *= MAGIC;
1176                 }
1177         } else {
1178         /*
1179          * For touchpads where the driver does not provide resolution, fall
1180          * back to scaling motion events based on the diagonal size in units.
1181          */
1182                 tp->accel.x_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
1183                 tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
1184         }
1185
1186         if (evdev_device_init_pointer_acceleration(tp->device) == -1)
1187                 return -1;
1188
1189         return 0;
1190 }
1191
1192 static uint32_t
1193 tp_scroll_config_scroll_method_get_methods(struct libinput_device *device)
1194 {
1195         struct evdev_device *evdev = (struct evdev_device*)device;
1196         struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
1197         uint32_t methods = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
1198
1199         if (tp->ntouches >= 2)
1200                 methods |= LIBINPUT_CONFIG_SCROLL_2FG;
1201
1202         if (!tp->buttons.is_clickpad)
1203                 methods |= LIBINPUT_CONFIG_SCROLL_EDGE;
1204
1205         return methods;
1206 }
1207
1208 static enum libinput_config_status
1209 tp_scroll_config_scroll_method_set_method(struct libinput_device *device,
1210                         enum libinput_config_scroll_method method)
1211 {
1212         struct evdev_device *evdev = (struct evdev_device*)device;
1213         struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
1214
1215         if (method == tp->scroll.method)
1216                 return LIBINPUT_CONFIG_STATUS_SUCCESS;
1217
1218         tp_stop_scroll_events(tp, libinput_now(device->seat->libinput));
1219         tp->scroll.method = method;
1220
1221         return LIBINPUT_CONFIG_STATUS_SUCCESS;
1222 }
1223
1224 static enum libinput_config_scroll_method
1225 tp_scroll_config_scroll_method_get_method(struct libinput_device *device)
1226 {
1227         struct evdev_device *evdev = (struct evdev_device*)device;
1228         struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
1229
1230         return tp->scroll.method;
1231 }
1232
1233 static enum libinput_config_scroll_method
1234 tp_scroll_get_default_method(struct tp_dispatch *tp)
1235 {
1236         if (tp->ntouches >= 2)
1237                 return LIBINPUT_CONFIG_SCROLL_2FG;
1238         else
1239                 return LIBINPUT_CONFIG_SCROLL_EDGE;
1240 }
1241
1242 static enum libinput_config_scroll_method
1243 tp_scroll_config_scroll_method_get_default_method(struct libinput_device *device)
1244 {
1245         struct evdev_device *evdev = (struct evdev_device*)device;
1246         struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
1247
1248         return tp_scroll_get_default_method(tp);
1249 }
1250
1251 static int
1252 tp_init_scroll(struct tp_dispatch *tp, struct evdev_device *device)
1253 {
1254         if (tp_edge_scroll_init(tp, device) != 0)
1255                 return -1;
1256
1257         evdev_init_natural_scroll(device);
1258
1259         tp->scroll.config_method.get_methods = tp_scroll_config_scroll_method_get_methods;
1260         tp->scroll.config_method.set_method = tp_scroll_config_scroll_method_set_method;
1261         tp->scroll.config_method.get_method = tp_scroll_config_scroll_method_get_method;
1262         tp->scroll.config_method.get_default_method = tp_scroll_config_scroll_method_get_default_method;
1263         tp->scroll.method = tp_scroll_get_default_method(tp);
1264         tp->device->base.config.scroll_method = &tp->scroll.config_method;
1265
1266         /* In mm for touchpads with valid resolution, see tp_init_accel() */
1267         tp->device->scroll.threshold = 5.0;
1268
1269         return 0;
1270 }
1271
1272 static int
1273 tp_init_palmdetect(struct tp_dispatch *tp,
1274                    struct evdev_device *device)
1275 {
1276         int width;
1277
1278         tp->palm.right_edge = INT_MAX;
1279         tp->palm.left_edge = INT_MIN;
1280
1281         width = abs(device->abs.absinfo_x->maximum -
1282                     device->abs.absinfo_x->minimum);
1283
1284         /* Apple touchpads are always big enough to warrant palm detection */
1285         if (evdev_device_get_id_vendor(device) != VENDOR_ID_APPLE) {
1286                 /* We don't know how big the touchpad is */
1287                 if (device->abs.absinfo_x->resolution == 1)
1288                         return 0;
1289
1290                 /* Enable palm detection on touchpads >= 80 mm. Anything smaller
1291                    probably won't need it, until we find out it does */
1292                 if (width/device->abs.absinfo_x->resolution < 80)
1293                         return 0;
1294         }
1295
1296         /* palm edges are 5% of the width on each side */
1297         tp->palm.right_edge = device->abs.absinfo_x->maximum - width * 0.05;
1298         tp->palm.left_edge = device->abs.absinfo_x->minimum + width * 0.05;
1299
1300         return 0;
1301 }
1302
1303 static int
1304 tp_init_sendevents(struct tp_dispatch *tp,
1305                    struct evdev_device *device)
1306 {
1307         libinput_timer_init(&tp->sendevents.trackpoint_timer,
1308                             tp->device->base.seat->libinput,
1309                             tp_trackpoint_timeout, tp);
1310         return 0;
1311 }
1312
1313 static int
1314 tp_init(struct tp_dispatch *tp,
1315         struct evdev_device *device)
1316 {
1317         int width, height;
1318         double diagonal;
1319
1320         tp->base.interface = &tp_interface;
1321         tp->device = device;
1322
1323         if (tp_init_slots(tp, device) != 0)
1324                 return -1;
1325
1326         width = abs(device->abs.absinfo_x->maximum -
1327                     device->abs.absinfo_x->minimum);
1328         height = abs(device->abs.absinfo_y->maximum -
1329                      device->abs.absinfo_y->minimum);
1330         diagonal = sqrt(width*width + height*height);
1331
1332         tp->hysteresis.margin_x =
1333                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
1334         tp->hysteresis.margin_y =
1335                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
1336
1337         if (tp_init_accel(tp, diagonal) != 0)
1338                 return -1;
1339
1340         if (tp_init_tap(tp) != 0)
1341                 return -1;
1342
1343         if (tp_init_buttons(tp, device) != 0)
1344                 return -1;
1345
1346         if (tp_init_palmdetect(tp, device) != 0)
1347                 return -1;
1348
1349         if (tp_init_sendevents(tp, device) != 0)
1350                 return -1;
1351
1352         if (tp_init_scroll(tp, device) != 0)
1353                 return -1;
1354
1355         device->seat_caps |= EVDEV_DEVICE_POINTER;
1356
1357         return 0;
1358 }
1359
1360 static uint32_t
1361 tp_sendevents_get_modes(struct libinput_device *device)
1362 {
1363         struct evdev_device *evdev = (struct evdev_device*)device;
1364         uint32_t modes = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
1365
1366         if (evdev->tags & EVDEV_TAG_INTERNAL_TOUCHPAD)
1367                 modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
1368
1369         return modes;
1370 }
1371
1372 static void
1373 tp_suspend_conditional(struct tp_dispatch *tp,
1374                        struct evdev_device *device)
1375 {
1376         struct libinput_device *dev;
1377
1378         list_for_each(dev, &device->base.seat->devices_list, link) {
1379                 struct evdev_device *d = (struct evdev_device*)dev;
1380                 if (d->tags & EVDEV_TAG_EXTERNAL_MOUSE) {
1381                         tp_suspend(tp, device);
1382                         return;
1383                 }
1384         }
1385 }
1386
1387 static enum libinput_config_status
1388 tp_sendevents_set_mode(struct libinput_device *device,
1389                        enum libinput_config_send_events_mode mode)
1390 {
1391         struct evdev_device *evdev = (struct evdev_device*)device;
1392         struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
1393
1394         /* DISABLED overrides any DISABLED_ON_ */
1395         if ((mode & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED) &&
1396             (mode & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE))
1397             mode &= ~LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
1398
1399         if (mode == tp->sendevents.current_mode)
1400                 return LIBINPUT_CONFIG_STATUS_SUCCESS;
1401
1402         switch(mode) {
1403         case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED:
1404                 tp_resume(tp, evdev);
1405                 break;
1406         case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
1407                 tp_suspend(tp, evdev);
1408                 break;
1409         case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
1410                 tp_suspend_conditional(tp, evdev);
1411                 break;
1412         default:
1413                 return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
1414         }
1415
1416         tp->sendevents.current_mode = mode;
1417
1418         return LIBINPUT_CONFIG_STATUS_SUCCESS;
1419 }
1420
1421 static enum libinput_config_send_events_mode
1422 tp_sendevents_get_mode(struct libinput_device *device)
1423 {
1424         struct evdev_device *evdev = (struct evdev_device*)device;
1425         struct tp_dispatch *dispatch = (struct tp_dispatch*)evdev->dispatch;
1426
1427         return dispatch->sendevents.current_mode;
1428 }
1429
1430 static enum libinput_config_send_events_mode
1431 tp_sendevents_get_default_mode(struct libinput_device *device)
1432 {
1433         return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
1434 }
1435
1436 static void
1437 tp_change_to_left_handed(struct evdev_device *device)
1438 {
1439         struct tp_dispatch *tp = (struct tp_dispatch *)device->dispatch;
1440
1441         if (device->left_handed.want_enabled == device->left_handed.enabled)
1442                 return;
1443
1444         if (tp->buttons.state & 0x3) /* BTN_LEFT|BTN_RIGHT */
1445                 return;
1446
1447         /* tapping and clickfinger aren't affected by left-handed config,
1448          * so checking physical buttons is enough */
1449
1450         device->left_handed.enabled = device->left_handed.want_enabled;
1451 }
1452
1453 struct model_lookup_t {
1454         uint16_t vendor;
1455         uint16_t product_start;
1456         uint16_t product_end;
1457         enum touchpad_model model;
1458 };
1459
1460 static struct model_lookup_t model_lookup_table[] = {
1461         { 0x0002, 0x0007, 0x0007, MODEL_SYNAPTICS },
1462         { 0x0002, 0x0008, 0x0008, MODEL_ALPS },
1463         { 0x0002, 0x000e, 0x000e, MODEL_ELANTECH },
1464         { 0x05ac,      0, 0x0222, MODEL_APPLETOUCH },
1465         { 0x05ac, 0x0223, 0x0228, MODEL_UNIBODY_MACBOOK },
1466         { 0x05ac, 0x0229, 0x022b, MODEL_APPLETOUCH },
1467         { 0x05ac, 0x022c, 0xffff, MODEL_UNIBODY_MACBOOK },
1468         { 0, 0, 0, 0 }
1469 };
1470
1471 static enum touchpad_model
1472 tp_get_model(struct evdev_device *device)
1473 {
1474         struct model_lookup_t *lookup;
1475         uint16_t vendor  = libevdev_get_id_vendor(device->evdev);
1476         uint16_t product = libevdev_get_id_product(device->evdev);
1477
1478         for (lookup = model_lookup_table; lookup->vendor; lookup++) {
1479                 if (lookup->vendor == vendor &&
1480                     lookup->product_start <= product &&
1481                     product <= lookup->product_end)
1482                         return lookup->model;
1483         }
1484         return MODEL_UNKNOWN;
1485 }
1486
1487 struct evdev_dispatch *
1488 evdev_mt_touchpad_create(struct evdev_device *device)
1489 {
1490         struct tp_dispatch *tp;
1491
1492         tp = zalloc(sizeof *tp);
1493         if (!tp)
1494                 return NULL;
1495
1496         tp->model = tp_get_model(device);
1497
1498         if (tp_init(tp, device) != 0) {
1499                 tp_destroy(&tp->base);
1500                 return NULL;
1501         }
1502
1503         device->base.config.sendevents = &tp->sendevents.config;
1504
1505         tp->sendevents.current_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
1506         tp->sendevents.config.get_modes = tp_sendevents_get_modes;
1507         tp->sendevents.config.set_mode = tp_sendevents_set_mode;
1508         tp->sendevents.config.get_mode = tp_sendevents_get_mode;
1509         tp->sendevents.config.get_default_mode = tp_sendevents_get_default_mode;
1510
1511         evdev_init_left_handed(device, tp_change_to_left_handed);
1512
1513         return  &tp->base;
1514 }