evdev: Add an internal device suspend / resume notification system
[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->sendevents.current_mode !=
646             LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
647                 return;
648
649         if (added_device->tags & EVDEV_TAG_EXTERNAL_MOUSE)
650                 tp_suspend(tp, device);
651 }
652
653 static void
654 tp_device_removed(struct evdev_device *device,
655                   struct evdev_device *removed_device)
656 {
657         struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
658         struct libinput_device *dev;
659
660         if (tp->sendevents.current_mode !=
661             LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
662                 return;
663
664         list_for_each(dev, &device->base.seat->devices_list, link) {
665                 struct evdev_device *d = (struct evdev_device*)dev;
666                 if (d != removed_device &&
667                     (d->tags & EVDEV_TAG_EXTERNAL_MOUSE)) {
668                         return;
669                 }
670         }
671
672         tp_resume(tp, device);
673 }
674
675 static void
676 tp_tag_device(struct evdev_device *device,
677               struct udev_device *udev_device)
678 {
679         int bustype;
680
681         /* simple approach: touchpads on USB or Bluetooth are considered
682          * external, anything else is internal. Exception is Apple -
683          * internal touchpads are connected over USB and it doesn't have
684          * external USB touchpads anyway.
685          */
686         bustype = libevdev_get_id_bustype(device->evdev);
687         if (bustype == BUS_USB) {
688                  if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_APPLE)
689                          device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
690         } else if (bustype != BUS_BLUETOOTH)
691                 device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
692 }
693
694 static struct evdev_dispatch_interface tp_interface = {
695         tp_process,
696         tp_destroy,
697         tp_device_added,
698         tp_device_removed,
699         NULL, /* device_suspended */
700         NULL, /* device_resumed */
701         tp_tag_device,
702 };
703
704 static void
705 tp_init_touch(struct tp_dispatch *tp,
706               struct tp_touch *t)
707 {
708         t->tp = tp;
709 }
710
711 static int
712 tp_init_slots(struct tp_dispatch *tp,
713               struct evdev_device *device)
714 {
715         const struct input_absinfo *absinfo;
716         struct map {
717                 unsigned int code;
718                 int ntouches;
719         } max_touches[] = {
720                 { BTN_TOOL_QUINTTAP, 5 },
721                 { BTN_TOOL_QUADTAP, 4 },
722                 { BTN_TOOL_TRIPLETAP, 3 },
723                 { BTN_TOOL_DOUBLETAP, 2 },
724         };
725         struct map *m;
726         unsigned int i, n_btn_tool_touches = 1;
727
728         absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
729         if (absinfo) {
730                 tp->real_touches = absinfo->maximum + 1;
731                 tp->slot = absinfo->value;
732                 tp->has_mt = true;
733         } else {
734                 tp->real_touches = 1;
735                 tp->slot = 0;
736                 tp->has_mt = false;
737         }
738
739         tp->semi_mt = libevdev_has_property(device->evdev, INPUT_PROP_SEMI_MT);
740
741         ARRAY_FOR_EACH(max_touches, m) {
742                 if (libevdev_has_event_code(device->evdev,
743                                             EV_KEY,
744                                             m->code)) {
745                         n_btn_tool_touches = m->ntouches;
746                         break;
747                 }
748         }
749
750         tp->ntouches = max(tp->real_touches, n_btn_tool_touches);
751         tp->touches = calloc(tp->ntouches, sizeof(struct tp_touch));
752         if (!tp->touches)
753                 return -1;
754
755         for (i = 0; i < tp->ntouches; i++)
756                 tp_init_touch(tp, &tp->touches[i]);
757
758         return 0;
759 }
760
761 static int
762 tp_init_accel(struct tp_dispatch *tp, double diagonal)
763 {
764         struct motion_filter *accel;
765         int res_x, res_y;
766
767         if (tp->has_mt) {
768                 res_x = libevdev_get_abs_resolution(tp->device->evdev,
769                                                     ABS_MT_POSITION_X);
770                 res_y = libevdev_get_abs_resolution(tp->device->evdev,
771                                                     ABS_MT_POSITION_Y);
772         } else {
773                 res_x = libevdev_get_abs_resolution(tp->device->evdev,
774                                                     ABS_X);
775                 res_y = libevdev_get_abs_resolution(tp->device->evdev,
776                                                     ABS_Y);
777         }
778
779         /*
780          * Not all touchpads report the same amount of units/mm (resolution).
781          * Normalize motion events to a resolution of 15.74 units/mm
782          * (== 400 dpi) as base (unaccelerated) speed. This also evens out any
783          * differences in x and y resolution, so that a circle on the
784          * touchpad does not turn into an elipse on the screen.
785          *
786          * We pick 400dpi as thats one of the many default resolutions
787          * for USB mice, so we end up with a similar base speed on the device.
788          */
789         if (res_x > 1 && res_y > 1) {
790                 tp->accel.x_scale_coeff = (400/25.4) / res_x;
791                 tp->accel.y_scale_coeff = (400/25.4) / res_y;
792         } else {
793         /*
794          * For touchpads where the driver does not provide resolution, fall
795          * back to scaling motion events based on the diagonal size in units.
796          */
797                 tp->accel.x_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
798                 tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
799         }
800
801         accel = create_pointer_accelator_filter(
802                         pointer_accel_profile_smooth_simple);
803         if (accel == NULL)
804                 return -1;
805
806         tp->filter = accel;
807
808         return 0;
809 }
810
811 static int
812 tp_init_palmdetect(struct tp_dispatch *tp,
813                    struct evdev_device *device)
814 {
815         int width;
816
817         tp->palm.right_edge = INT_MAX;
818         tp->palm.left_edge = INT_MIN;
819
820         width = abs(device->abs.absinfo_x->maximum -
821                     device->abs.absinfo_x->minimum);
822
823         /* Apple touchpads are always big enough to warrant palm detection */
824         if (evdev_device_get_id_vendor(device) != VENDOR_ID_APPLE) {
825                 /* We don't know how big the touchpad is */
826                 if (device->abs.absinfo_x->resolution == 1)
827                         return 0;
828
829                 /* Enable palm detection on touchpads >= 80 mm. Anything smaller
830                    probably won't need it, until we find out it does */
831                 if (width/device->abs.absinfo_x->resolution < 80)
832                         return 0;
833         }
834
835         /* palm edges are 5% of the width on each side */
836         tp->palm.right_edge = device->abs.absinfo_x->maximum - width * 0.05;
837         tp->palm.left_edge = device->abs.absinfo_x->minimum + width * 0.05;
838
839         return 0;
840 }
841
842 static int
843 tp_init(struct tp_dispatch *tp,
844         struct evdev_device *device)
845 {
846         int width, height;
847         double diagonal;
848
849         tp->base.interface = &tp_interface;
850         tp->device = device;
851
852         if (tp_init_slots(tp, device) != 0)
853                 return -1;
854
855         width = abs(device->abs.absinfo_x->maximum -
856                     device->abs.absinfo_x->minimum);
857         height = abs(device->abs.absinfo_y->maximum -
858                      device->abs.absinfo_y->minimum);
859         diagonal = sqrt(width*width + height*height);
860
861         tp->hysteresis.margin_x =
862                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
863         tp->hysteresis.margin_y =
864                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
865
866         if (tp_init_accel(tp, diagonal) != 0)
867                 return -1;
868
869         if (tp_init_tap(tp) != 0)
870                 return -1;
871
872         if (tp_init_buttons(tp, device) != 0)
873                 return -1;
874
875         if (tp_init_palmdetect(tp, device) != 0)
876                 return -1;
877
878         device->seat_caps |= EVDEV_DEVICE_POINTER;
879
880         return 0;
881 }
882
883 static uint32_t
884 tp_sendevents_get_modes(struct libinput_device *device)
885 {
886         struct evdev_device *evdev = (struct evdev_device*)device;
887         uint32_t modes = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED |
888                          LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
889
890         if (evdev->tags & EVDEV_TAG_INTERNAL_TOUCHPAD)
891                 modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
892
893         return modes;
894 }
895
896 static void
897 tp_suspend_conditional(struct tp_dispatch *tp,
898                        struct evdev_device *device)
899 {
900         struct libinput_device *dev;
901
902         list_for_each(dev, &device->base.seat->devices_list, link) {
903                 struct evdev_device *d = (struct evdev_device*)dev;
904                 if (d->tags & EVDEV_TAG_EXTERNAL_MOUSE) {
905                         tp_suspend(tp, device);
906                         return;
907                 }
908         }
909 }
910
911 static enum libinput_config_status
912 tp_sendevents_set_mode(struct libinput_device *device,
913                        enum libinput_config_send_events_mode mode)
914 {
915         struct evdev_device *evdev = (struct evdev_device*)device;
916         struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
917
918         if (mode == tp->sendevents.current_mode)
919                 return LIBINPUT_CONFIG_STATUS_SUCCESS;
920
921         switch(mode) {
922         case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED:
923                 tp_resume(tp, evdev);
924                 break;
925         case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
926                 tp_suspend(tp, evdev);
927                 break;
928         case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
929                 tp_suspend_conditional(tp, evdev);
930                 break;
931         default:
932                 return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
933         }
934
935         tp->sendevents.current_mode = mode;
936
937         return LIBINPUT_CONFIG_STATUS_SUCCESS;
938 }
939
940 static enum libinput_config_send_events_mode
941 tp_sendevents_get_mode(struct libinput_device *device)
942 {
943         struct evdev_device *evdev = (struct evdev_device*)device;
944         struct tp_dispatch *dispatch = (struct tp_dispatch*)evdev->dispatch;
945
946         return dispatch->sendevents.current_mode;
947 }
948
949 static enum libinput_config_send_events_mode
950 tp_sendevents_get_default_mode(struct libinput_device *device)
951 {
952         return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
953 }
954
955 struct evdev_dispatch *
956 evdev_mt_touchpad_create(struct evdev_device *device)
957 {
958         struct tp_dispatch *tp;
959
960         tp = zalloc(sizeof *tp);
961         if (!tp)
962                 return NULL;
963
964         if (tp_init(tp, device) != 0) {
965                 tp_destroy(&tp->base);
966                 return NULL;
967         }
968
969         device->base.config.sendevents = &tp->sendevents.config;
970
971         tp->sendevents.current_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
972         tp->sendevents.config.get_modes = tp_sendevents_get_modes;
973         tp->sendevents.config.set_mode = tp_sendevents_set_mode;
974         tp->sendevents.config.get_mode = tp_sendevents_get_mode;
975         tp->sendevents.config.get_default_mode = tp_sendevents_get_default_mode;
976
977         return  &tp->base;
978 }