touchpad: Keep track of associated trackpoint device
[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
35 static inline int
36 tp_hysteresis(int in, int center, int margin)
37 {
38         int diff = in - center;
39         if (abs(diff) <= margin)
40                 return center;
41
42         if (diff > margin)
43                 return center + diff - margin;
44         else
45                 return center + diff + margin;
46 }
47
48 static inline struct tp_motion *
49 tp_motion_history_offset(struct tp_touch *t, int offset)
50 {
51         int offset_index =
52                 (t->history.index - offset + TOUCHPAD_HISTORY_LENGTH) %
53                 TOUCHPAD_HISTORY_LENGTH;
54
55         return &t->history.samples[offset_index];
56 }
57
58 static void
59 tp_filter_motion(struct tp_dispatch *tp,
60                  double *dx, double *dy, uint64_t time)
61 {
62         struct motion_params motion;
63
64         motion.dx = *dx * tp->accel.x_scale_coeff;
65         motion.dy = *dy * tp->accel.y_scale_coeff;
66
67         if (motion.dx != 0.0 || motion.dy != 0.0)
68                 filter_dispatch(tp->filter, &motion, tp, time);
69
70         *dx = motion.dx;
71         *dy = motion.dy;
72 }
73
74 static inline void
75 tp_motion_history_push(struct tp_touch *t)
76 {
77         int motion_index = (t->history.index + 1) % TOUCHPAD_HISTORY_LENGTH;
78
79         if (t->history.count < TOUCHPAD_HISTORY_LENGTH)
80                 t->history.count++;
81
82         t->history.samples[motion_index].x = t->x;
83         t->history.samples[motion_index].y = t->y;
84         t->history.index = motion_index;
85 }
86
87 static inline void
88 tp_motion_hysteresis(struct tp_dispatch *tp,
89                      struct tp_touch *t)
90 {
91         int x = t->x,
92             y = t->y;
93
94         if (t->history.count == 0) {
95                 t->hysteresis.center_x = t->x;
96                 t->hysteresis.center_y = t->y;
97         } else {
98                 x = tp_hysteresis(x,
99                                   t->hysteresis.center_x,
100                                   tp->hysteresis.margin_x);
101                 y = tp_hysteresis(y,
102                                   t->hysteresis.center_y,
103                                   tp->hysteresis.margin_y);
104                 t->hysteresis.center_x = x;
105                 t->hysteresis.center_y = y;
106                 t->x = x;
107                 t->y = y;
108         }
109 }
110
111 static inline void
112 tp_motion_history_reset(struct tp_touch *t)
113 {
114         t->history.count = 0;
115 }
116
117 static inline struct tp_touch *
118 tp_current_touch(struct tp_dispatch *tp)
119 {
120         return &tp->touches[min(tp->slot, tp->ntouches - 1)];
121 }
122
123 static inline struct tp_touch *
124 tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
125 {
126         assert(slot < tp->ntouches);
127         return &tp->touches[slot];
128 }
129
130 static inline void
131 tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
132 {
133         if (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE)
134                 return;
135
136         tp_motion_history_reset(t);
137         t->dirty = true;
138         t->state = TOUCH_BEGIN;
139         t->pinned.is_pinned = false;
140         t->millis = time;
141         tp->nfingers_down++;
142         assert(tp->nfingers_down >= 1);
143         tp->queued |= TOUCHPAD_EVENT_MOTION;
144 }
145
146 static inline void
147 tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
148 {
149         if (t->state == TOUCH_END || t->state == TOUCH_NONE)
150                 return;
151
152         t->dirty = true;
153         t->is_pointer = false;
154         t->palm.is_palm = false;
155         t->state = TOUCH_END;
156         t->pinned.is_pinned = false;
157         t->millis = time;
158         assert(tp->nfingers_down >= 1);
159         tp->nfingers_down--;
160         tp->queued |= TOUCHPAD_EVENT_MOTION;
161 }
162
163 static double
164 tp_estimate_delta(int x0, int x1, int x2, int x3)
165 {
166         return (x0 + x1 - x2 - x3) / 4.0;
167 }
168
169 void
170 tp_get_delta(struct tp_touch *t, double *dx, double *dy)
171 {
172         if (t->history.count < 4) {
173                 *dx = 0;
174                 *dy = 0;
175                 return;
176         }
177
178         *dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x,
179                                 tp_motion_history_offset(t, 1)->x,
180                                 tp_motion_history_offset(t, 2)->x,
181                                 tp_motion_history_offset(t, 3)->x);
182         *dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y,
183                                 tp_motion_history_offset(t, 1)->y,
184                                 tp_motion_history_offset(t, 2)->y,
185                                 tp_motion_history_offset(t, 3)->y);
186 }
187
188 static void
189 tp_process_absolute(struct tp_dispatch *tp,
190                     const struct input_event *e,
191                     uint64_t time)
192 {
193         struct tp_touch *t = tp_current_touch(tp);
194
195         switch(e->code) {
196         case ABS_MT_POSITION_X:
197                 t->x = e->value;
198                 t->millis = time;
199                 t->dirty = true;
200                 tp->queued |= TOUCHPAD_EVENT_MOTION;
201                 break;
202         case ABS_MT_POSITION_Y:
203                 t->y = e->value;
204                 t->millis = time;
205                 t->dirty = true;
206                 tp->queued |= TOUCHPAD_EVENT_MOTION;
207                 break;
208         case ABS_MT_SLOT:
209                 tp->slot = e->value;
210                 break;
211         case ABS_MT_TRACKING_ID:
212                 if (e->value != -1)
213                         tp_begin_touch(tp, t, time);
214                 else
215                         tp_end_touch(tp, t, time);
216         }
217 }
218
219 static void
220 tp_process_absolute_st(struct tp_dispatch *tp,
221                        const struct input_event *e,
222                        uint64_t time)
223 {
224         struct tp_touch *t = tp_current_touch(tp);
225
226         switch(e->code) {
227         case ABS_X:
228                 t->x = e->value;
229                 t->millis = time;
230                 t->dirty = true;
231                 tp->queued |= TOUCHPAD_EVENT_MOTION;
232                 break;
233         case ABS_Y:
234                 t->y = e->value;
235                 t->millis = time;
236                 t->dirty = true;
237                 tp->queued |= TOUCHPAD_EVENT_MOTION;
238                 break;
239         }
240 }
241
242 static void
243 tp_process_fake_touch(struct tp_dispatch *tp,
244                       const struct input_event *e,
245                       uint64_t time)
246 {
247         struct tp_touch *t;
248         unsigned int fake_touches;
249         unsigned int nfake_touches;
250         unsigned int i, start;
251         unsigned int shift;
252
253         if (e->code != BTN_TOUCH &&
254             (e->code < BTN_TOOL_DOUBLETAP || e->code > BTN_TOOL_QUADTAP))
255                 return;
256
257         shift = e->code == BTN_TOUCH ? 0 : (e->code - BTN_TOOL_DOUBLETAP + 1);
258
259         if (e->value)
260                 tp->fake_touches |= 1 << shift;
261         else
262                 tp->fake_touches &= ~(0x1 << shift);
263
264         fake_touches = tp->fake_touches;
265         nfake_touches = 0;
266         while (fake_touches) {
267                 nfake_touches++;
268                 fake_touches >>= 1;
269         }
270
271         /* For single touch tps we use BTN_TOUCH for begin / end of touch 0 */
272         start = tp->has_mt ? tp->real_touches : 0;
273         for (i = start; i < tp->ntouches; i++) {
274                 t = tp_get_touch(tp, i);
275                 if (i < nfake_touches)
276                         tp_begin_touch(tp, t, time);
277                 else
278                         tp_end_touch(tp, t, time);
279         }
280
281         /* On mt the actual touch info may arrive after BTN_TOOL_FOO */
282         assert(tp->has_mt || tp->nfingers_down == nfake_touches);
283 }
284
285 static void
286 tp_process_key(struct tp_dispatch *tp,
287                const struct input_event *e,
288                uint64_t time)
289 {
290         switch (e->code) {
291                 case BTN_LEFT:
292                 case BTN_MIDDLE:
293                 case BTN_RIGHT:
294                         tp_process_button(tp, e, time);
295                         break;
296                 case BTN_TOUCH:
297                 case BTN_TOOL_DOUBLETAP:
298                 case BTN_TOOL_TRIPLETAP:
299                 case BTN_TOOL_QUADTAP:
300                         tp_process_fake_touch(tp, e, time);
301                         break;
302         }
303 }
304
305 static void
306 tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
307 {
308         unsigned int xdist, ydist;
309
310         if (!t->pinned.is_pinned)
311                 return;
312
313         xdist = abs(t->x - t->pinned.center_x);
314         ydist = abs(t->y - t->pinned.center_y);
315
316         if (xdist * xdist + ydist * ydist >=
317                         tp->buttons.motion_dist * tp->buttons.motion_dist) {
318                 t->pinned.is_pinned = false;
319                 tp_set_pointer(tp, t);
320         }
321 }
322
323 static void
324 tp_pin_fingers(struct tp_dispatch *tp)
325 {
326         struct tp_touch *t;
327
328         tp_for_each_touch(tp, t) {
329                 t->is_pointer = false;
330                 t->pinned.is_pinned = true;
331                 t->pinned.center_x = t->x;
332                 t->pinned.center_y = t->y;
333         }
334 }
335
336 static int
337 tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
338 {
339         return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
340                 !t->palm.is_palm &&
341                 !t->pinned.is_pinned && tp_button_touch_active(tp, t);
342 }
343
344 void
345 tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
346 {
347         struct tp_touch *tmp = NULL;
348
349         /* Only set the touch as pointer if we don't have one yet */
350         tp_for_each_touch(tp, tmp) {
351                 if (tmp->is_pointer)
352                         return;
353         }
354
355         if (tp_touch_active(tp, t))
356                 t->is_pointer = true;
357 }
358
359 static void
360 tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
361 {
362         const int PALM_TIMEOUT = 200; /* ms */
363         const int DIRECTIONS = NE|E|SE|SW|W|NW;
364
365         /* If labelled a touch as palm, we unlabel as palm when
366            we move out of the palm edge zone within the timeout, provided
367            the direction is within 45 degrees of the horizontal.
368          */
369         if (t->palm.is_palm) {
370                 if (time < t->palm.time + PALM_TIMEOUT &&
371                     (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge)) {
372                         int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y);
373                         if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
374                                 t->palm.is_palm = false;
375                                 tp_set_pointer(tp, t);
376                         }
377                 }
378                 return;
379         }
380
381         /* palm must start in exclusion zone, it's ok to move into
382            the zone without being a palm */
383         if (t->state != TOUCH_BEGIN ||
384             (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge))
385                 return;
386
387         /* don't detect palm in software button areas, it's
388            likely that legitimate touches start in the area
389            covered by the exclusion zone */
390         if (tp->buttons.is_clickpad &&
391             tp_button_is_inside_softbutton_area(tp, t))
392                 return;
393
394         t->palm.is_palm = true;
395         t->palm.time = time;
396         t->palm.x = t->x;
397         t->palm.y = t->y;
398 }
399
400 static void
401 tp_process_state(struct tp_dispatch *tp, uint64_t time)
402 {
403         struct tp_touch *t;
404         struct tp_touch *first = tp_get_touch(tp, 0);
405         unsigned int i;
406
407         for (i = 0; i < tp->ntouches; i++) {
408                 t = tp_get_touch(tp, i);
409
410                 /* semi-mt finger postions may "jump" when nfingers changes */
411                 if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
412                         tp_motion_history_reset(t);
413
414                 if (i >= tp->real_touches && t->state != TOUCH_NONE) {
415                         t->x = first->x;
416                         t->y = first->y;
417                         if (!t->dirty)
418                                 t->dirty = first->dirty;
419                 }
420
421                 if (!t->dirty)
422                         continue;
423
424                 tp_palm_detect(tp, t, time);
425
426                 tp_motion_hysteresis(tp, t);
427                 tp_motion_history_push(t);
428
429                 tp_unpin_finger(tp, t);
430         }
431
432         tp_button_handle_state(tp, time);
433
434         /*
435          * We have a physical button down event on a clickpad. To avoid
436          * spurious pointer moves by the clicking finger we pin all fingers.
437          * We unpin fingers when they move more then a certain threshold to
438          * to allow drag and drop.
439          */
440         if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) &&
441             tp->buttons.is_clickpad)
442                 tp_pin_fingers(tp);
443 }
444
445 static void
446 tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
447 {
448         struct tp_touch *t;
449
450         tp_for_each_touch(tp, t) {
451                 if (!t->dirty)
452                         continue;
453
454                 if (t->state == TOUCH_END)
455                         t->state = TOUCH_NONE;
456                 else if (t->state == TOUCH_BEGIN)
457                         t->state = TOUCH_UPDATE;
458
459                 t->dirty = false;
460         }
461
462         tp->old_nfingers_down = tp->nfingers_down;
463         tp->buttons.old_state = tp->buttons.state;
464
465         tp->queued = TOUCHPAD_EVENT_NONE;
466 }
467
468 static void
469 tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
470 {
471         struct tp_touch *t;
472         int nchanged = 0;
473         double dx = 0, dy =0;
474         double tmpx, tmpy;
475
476         tp_for_each_touch(tp, t) {
477                 if (tp_touch_active(tp, t) && t->dirty) {
478                         nchanged++;
479                         tp_get_delta(t, &tmpx, &tmpy);
480
481                         dx += tmpx;
482                         dy += tmpy;
483                 }
484                 /* Stop spurious MOTION events at the end of scrolling */
485                 t->is_pointer = false;
486         }
487
488         if (nchanged == 0)
489                 return;
490
491         dx /= nchanged;
492         dy /= nchanged;
493
494         tp_filter_motion(tp, &dx, &dy, time);
495         evdev_post_scroll(tp->device, time, dx, dy);
496 }
497
498 static int
499 tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
500 {
501         struct tp_touch *t;
502         int nfingers_down = 0;
503
504         /* Only count active touches for 2 finger scrolling */
505         tp_for_each_touch(tp, t) {
506                 if (tp_touch_active(tp, t))
507                         nfingers_down++;
508         }
509
510         if (nfingers_down != 2) {
511                 evdev_stop_scroll(tp->device, time);
512                 return 0;
513         }
514
515         tp_post_twofinger_scroll(tp, time);
516         return 1;
517 }
518
519 static void
520 tp_post_events(struct tp_dispatch *tp, uint64_t time)
521 {
522         struct tp_touch *t = tp_current_touch(tp);
523         double dx, dy;
524         int consumed = 0;
525
526         consumed |= tp_tap_handle_state(tp, time);
527         consumed |= tp_post_button_events(tp, time);
528
529         if (consumed) {
530                 evdev_stop_scroll(tp->device, time);
531                 return;
532         }
533
534         if (tp_post_scroll_events(tp, time) != 0)
535                 return;
536
537         if (!t->is_pointer) {
538                 tp_for_each_touch(tp, t) {
539                         if (t->is_pointer)
540                                 break;
541                 }
542         }
543
544         if (!t->is_pointer ||
545             !t->dirty ||
546             t->history.count < TOUCHPAD_MIN_SAMPLES)
547                 return;
548
549         tp_get_delta(t, &dx, &dy);
550         tp_filter_motion(tp, &dx, &dy, time);
551
552         if (dx != 0.0 || dy != 0.0)
553                 pointer_notify_motion(&tp->device->base, time, dx, dy);
554 }
555
556 static void
557 tp_handle_state(struct tp_dispatch *tp,
558                 uint64_t time)
559 {
560         tp_process_state(tp, time);
561         tp_post_events(tp, time);
562         tp_post_process_state(tp, time);
563 }
564
565 static void
566 tp_process(struct evdev_dispatch *dispatch,
567            struct evdev_device *device,
568            struct input_event *e,
569            uint64_t time)
570 {
571         struct tp_dispatch *tp =
572                 (struct tp_dispatch *)dispatch;
573
574         switch (e->type) {
575         case EV_ABS:
576                 if (tp->has_mt)
577                         tp_process_absolute(tp, e, time);
578                 else
579                         tp_process_absolute_st(tp, e, time);
580                 break;
581         case EV_KEY:
582                 tp_process_key(tp, e, time);
583                 break;
584         case EV_SYN:
585                 tp_handle_state(tp, time);
586                 break;
587         }
588 }
589
590 static void
591 tp_destroy(struct evdev_dispatch *dispatch)
592 {
593         struct tp_dispatch *tp =
594                 (struct tp_dispatch*)dispatch;
595
596         tp_destroy_tap(tp);
597         tp_destroy_buttons(tp);
598
599         filter_destroy(tp->filter);
600         free(tp->touches);
601         free(tp);
602 }
603
604 static void
605 tp_suspend(struct tp_dispatch *tp, struct evdev_device *device)
606 {
607         uint64_t now = libinput_now(tp->device->base.seat->libinput);
608         struct tp_touch *t;
609
610         /* Unroll the touchpad state.
611          * Release buttons first. If tp is a clickpad, the button event
612          * must come before the touch up. If it isn't, the order doesn't
613          * matter anyway
614          *
615          * Then cancel all timeouts on the taps, triggering the last set
616          * of events.
617          *
618          * Then lift all touches so the touchpad is in a neutral state.
619          *
620          */
621         tp_release_all_buttons(tp, now);
622         tp_release_all_taps(tp, now);
623
624         tp_for_each_touch(tp, t) {
625                 tp_end_touch(tp, t, now);
626         }
627
628         tp_handle_state(tp, now);
629
630         evdev_device_suspend(device);
631 }
632
633 static void
634 tp_resume(struct tp_dispatch *tp, struct evdev_device *device)
635 {
636         evdev_device_resume(device);
637 }
638
639 static void
640 tp_device_added(struct evdev_device *device,
641                 struct evdev_device *added_device)
642 {
643         struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
644
645         if (tp->buttons.trackpoint == NULL &&
646             (added_device->tags & EVDEV_TAG_TRACKPOINT))
647                 tp->buttons.trackpoint = added_device;
648
649         if (tp->sendevents.current_mode !=
650             LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
651                 return;
652
653         if (added_device->tags & EVDEV_TAG_EXTERNAL_MOUSE)
654                 tp_suspend(tp, device);
655 }
656
657 static void
658 tp_device_removed(struct evdev_device *device,
659                   struct evdev_device *removed_device)
660 {
661         struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
662         struct libinput_device *dev;
663
664         if (removed_device == tp->buttons.trackpoint)
665                 tp->buttons.trackpoint = NULL;
666
667         if (tp->sendevents.current_mode !=
668             LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
669                 return;
670
671         list_for_each(dev, &device->base.seat->devices_list, link) {
672                 struct evdev_device *d = (struct evdev_device*)dev;
673                 if (d != removed_device &&
674                     (d->tags & EVDEV_TAG_EXTERNAL_MOUSE)) {
675                         return;
676                 }
677         }
678
679         tp_resume(tp, device);
680 }
681
682 static void
683 tp_tag_device(struct evdev_device *device,
684               struct udev_device *udev_device)
685 {
686         int bustype;
687
688         /* simple approach: touchpads on USB or Bluetooth are considered
689          * external, anything else is internal. Exception is Apple -
690          * internal touchpads are connected over USB and it doesn't have
691          * external USB touchpads anyway.
692          */
693         bustype = libevdev_get_id_bustype(device->evdev);
694         if (bustype == BUS_USB) {
695                  if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_APPLE)
696                          device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
697         } else if (bustype != BUS_BLUETOOTH)
698                 device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
699 }
700
701 static struct evdev_dispatch_interface tp_interface = {
702         tp_process,
703         tp_destroy,
704         tp_device_added,
705         tp_device_removed,
706         NULL, /* device_suspended */
707         NULL, /* device_resumed */
708         tp_tag_device,
709 };
710
711 static void
712 tp_init_touch(struct tp_dispatch *tp,
713               struct tp_touch *t)
714 {
715         t->tp = tp;
716 }
717
718 static int
719 tp_init_slots(struct tp_dispatch *tp,
720               struct evdev_device *device)
721 {
722         const struct input_absinfo *absinfo;
723         struct map {
724                 unsigned int code;
725                 int ntouches;
726         } max_touches[] = {
727                 { BTN_TOOL_QUINTTAP, 5 },
728                 { BTN_TOOL_QUADTAP, 4 },
729                 { BTN_TOOL_TRIPLETAP, 3 },
730                 { BTN_TOOL_DOUBLETAP, 2 },
731         };
732         struct map *m;
733         unsigned int i, n_btn_tool_touches = 1;
734
735         absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
736         if (absinfo) {
737                 tp->real_touches = absinfo->maximum + 1;
738                 tp->slot = absinfo->value;
739                 tp->has_mt = true;
740         } else {
741                 tp->real_touches = 1;
742                 tp->slot = 0;
743                 tp->has_mt = false;
744         }
745
746         tp->semi_mt = libevdev_has_property(device->evdev, INPUT_PROP_SEMI_MT);
747
748         ARRAY_FOR_EACH(max_touches, m) {
749                 if (libevdev_has_event_code(device->evdev,
750                                             EV_KEY,
751                                             m->code)) {
752                         n_btn_tool_touches = m->ntouches;
753                         break;
754                 }
755         }
756
757         tp->ntouches = max(tp->real_touches, n_btn_tool_touches);
758         tp->touches = calloc(tp->ntouches, sizeof(struct tp_touch));
759         if (!tp->touches)
760                 return -1;
761
762         for (i = 0; i < tp->ntouches; i++)
763                 tp_init_touch(tp, &tp->touches[i]);
764
765         return 0;
766 }
767
768 static int
769 tp_init_accel(struct tp_dispatch *tp, double diagonal)
770 {
771         struct motion_filter *accel;
772         int res_x, res_y;
773
774         if (tp->has_mt) {
775                 res_x = libevdev_get_abs_resolution(tp->device->evdev,
776                                                     ABS_MT_POSITION_X);
777                 res_y = libevdev_get_abs_resolution(tp->device->evdev,
778                                                     ABS_MT_POSITION_Y);
779         } else {
780                 res_x = libevdev_get_abs_resolution(tp->device->evdev,
781                                                     ABS_X);
782                 res_y = libevdev_get_abs_resolution(tp->device->evdev,
783                                                     ABS_Y);
784         }
785
786         /*
787          * Not all touchpads report the same amount of units/mm (resolution).
788          * Normalize motion events to a resolution of 15.74 units/mm
789          * (== 400 dpi) as base (unaccelerated) speed. This also evens out any
790          * differences in x and y resolution, so that a circle on the
791          * touchpad does not turn into an elipse on the screen.
792          *
793          * We pick 400dpi as thats one of the many default resolutions
794          * for USB mice, so we end up with a similar base speed on the device.
795          */
796         if (res_x > 1 && res_y > 1) {
797                 tp->accel.x_scale_coeff = (400/25.4) / res_x;
798                 tp->accel.y_scale_coeff = (400/25.4) / res_y;
799         } else {
800         /*
801          * For touchpads where the driver does not provide resolution, fall
802          * back to scaling motion events based on the diagonal size in units.
803          */
804                 tp->accel.x_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
805                 tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
806         }
807
808         accel = create_pointer_accelator_filter(
809                         pointer_accel_profile_smooth_simple);
810         if (accel == NULL)
811                 return -1;
812
813         tp->filter = accel;
814
815         return 0;
816 }
817
818 static int
819 tp_init_palmdetect(struct tp_dispatch *tp,
820                    struct evdev_device *device)
821 {
822         int width;
823
824         tp->palm.right_edge = INT_MAX;
825         tp->palm.left_edge = INT_MIN;
826
827         width = abs(device->abs.absinfo_x->maximum -
828                     device->abs.absinfo_x->minimum);
829
830         /* Apple touchpads are always big enough to warrant palm detection */
831         if (evdev_device_get_id_vendor(device) != VENDOR_ID_APPLE) {
832                 /* We don't know how big the touchpad is */
833                 if (device->abs.absinfo_x->resolution == 1)
834                         return 0;
835
836                 /* Enable palm detection on touchpads >= 80 mm. Anything smaller
837                    probably won't need it, until we find out it does */
838                 if (width/device->abs.absinfo_x->resolution < 80)
839                         return 0;
840         }
841
842         /* palm edges are 5% of the width on each side */
843         tp->palm.right_edge = device->abs.absinfo_x->maximum - width * 0.05;
844         tp->palm.left_edge = device->abs.absinfo_x->minimum + width * 0.05;
845
846         return 0;
847 }
848
849 static int
850 tp_init(struct tp_dispatch *tp,
851         struct evdev_device *device)
852 {
853         int width, height;
854         double diagonal;
855
856         tp->base.interface = &tp_interface;
857         tp->device = device;
858
859         if (tp_init_slots(tp, device) != 0)
860                 return -1;
861
862         width = abs(device->abs.absinfo_x->maximum -
863                     device->abs.absinfo_x->minimum);
864         height = abs(device->abs.absinfo_y->maximum -
865                      device->abs.absinfo_y->minimum);
866         diagonal = sqrt(width*width + height*height);
867
868         tp->hysteresis.margin_x =
869                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
870         tp->hysteresis.margin_y =
871                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
872
873         if (tp_init_accel(tp, diagonal) != 0)
874                 return -1;
875
876         if (tp_init_tap(tp) != 0)
877                 return -1;
878
879         if (tp_init_buttons(tp, device) != 0)
880                 return -1;
881
882         if (tp_init_palmdetect(tp, device) != 0)
883                 return -1;
884
885         device->seat_caps |= EVDEV_DEVICE_POINTER;
886
887         return 0;
888 }
889
890 static uint32_t
891 tp_sendevents_get_modes(struct libinput_device *device)
892 {
893         struct evdev_device *evdev = (struct evdev_device*)device;
894         uint32_t modes = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED |
895                          LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
896
897         if (evdev->tags & EVDEV_TAG_INTERNAL_TOUCHPAD)
898                 modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
899
900         return modes;
901 }
902
903 static void
904 tp_suspend_conditional(struct tp_dispatch *tp,
905                        struct evdev_device *device)
906 {
907         struct libinput_device *dev;
908
909         list_for_each(dev, &device->base.seat->devices_list, link) {
910                 struct evdev_device *d = (struct evdev_device*)dev;
911                 if (d->tags & EVDEV_TAG_EXTERNAL_MOUSE) {
912                         tp_suspend(tp, device);
913                         return;
914                 }
915         }
916 }
917
918 static enum libinput_config_status
919 tp_sendevents_set_mode(struct libinput_device *device,
920                        enum libinput_config_send_events_mode mode)
921 {
922         struct evdev_device *evdev = (struct evdev_device*)device;
923         struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
924
925         if (mode == tp->sendevents.current_mode)
926                 return LIBINPUT_CONFIG_STATUS_SUCCESS;
927
928         switch(mode) {
929         case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED:
930                 tp_resume(tp, evdev);
931                 break;
932         case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
933                 tp_suspend(tp, evdev);
934                 break;
935         case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
936                 tp_suspend_conditional(tp, evdev);
937                 break;
938         default:
939                 return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
940         }
941
942         tp->sendevents.current_mode = mode;
943
944         return LIBINPUT_CONFIG_STATUS_SUCCESS;
945 }
946
947 static enum libinput_config_send_events_mode
948 tp_sendevents_get_mode(struct libinput_device *device)
949 {
950         struct evdev_device *evdev = (struct evdev_device*)device;
951         struct tp_dispatch *dispatch = (struct tp_dispatch*)evdev->dispatch;
952
953         return dispatch->sendevents.current_mode;
954 }
955
956 static enum libinput_config_send_events_mode
957 tp_sendevents_get_default_mode(struct libinput_device *device)
958 {
959         return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
960 }
961
962 struct evdev_dispatch *
963 evdev_mt_touchpad_create(struct evdev_device *device)
964 {
965         struct tp_dispatch *tp;
966
967         tp = zalloc(sizeof *tp);
968         if (!tp)
969                 return NULL;
970
971         if (tp_init(tp, device) != 0) {
972                 tp_destroy(&tp->base);
973                 return NULL;
974         }
975
976         device->base.config.sendevents = &tp->sendevents.config;
977
978         tp->sendevents.current_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
979         tp->sendevents.config.get_modes = tp_sendevents_get_modes;
980         tp->sendevents.config.set_mode = tp_sendevents_set_mode;
981         tp->sendevents.config.get_mode = tp_sendevents_get_mode;
982         tp->sendevents.config.get_default_mode = tp_sendevents_get_default_mode;
983
984         return  &tp->base;
985 }