Change internal timestamps to uint64_t to properly deal with wrapping
[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
29 #include "evdev-mt-touchpad.h"
30
31 #define DEFAULT_CONSTANT_ACCEL_NUMERATOR 50
32 #define DEFAULT_MIN_ACCEL_FACTOR 0.16
33 #define DEFAULT_MAX_ACCEL_FACTOR 1.0
34 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
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 if (diff < -margin)
46                 return center + diff + margin;
47         return center + diff;
48 }
49
50 static double
51 tp_accel_profile(struct motion_filter *filter,
52                  void *data,
53                  double velocity,
54                  uint64_t time)
55 {
56         struct tp_dispatch *tp =
57                 (struct tp_dispatch *) data;
58
59         double accel_factor;
60
61         accel_factor = velocity * tp->accel.constant_factor;
62
63         if (accel_factor > tp->accel.max_factor)
64                 accel_factor = tp->accel.max_factor;
65         else if (accel_factor < tp->accel.min_factor)
66                 accel_factor = tp->accel.min_factor;
67
68         return accel_factor;
69 }
70
71 static inline struct tp_motion *
72 tp_motion_history_offset(struct tp_touch *t, int offset)
73 {
74         int offset_index =
75                 (t->history.index - offset + TOUCHPAD_HISTORY_LENGTH) %
76                 TOUCHPAD_HISTORY_LENGTH;
77
78         return &t->history.samples[offset_index];
79 }
80
81 static void
82 tp_filter_motion(struct tp_dispatch *tp,
83                  double *dx, double *dy, uint64_t time)
84 {
85         struct motion_params motion;
86
87         motion.dx = *dx;
88         motion.dy = *dy;
89
90         filter_dispatch(tp->filter, &motion, tp, time);
91
92         *dx = motion.dx;
93         *dy = motion.dy;
94 }
95
96 static inline void
97 tp_motion_history_push(struct tp_touch *t)
98 {
99         int motion_index = (t->history.index + 1) % TOUCHPAD_HISTORY_LENGTH;
100
101         if (t->history.count < TOUCHPAD_HISTORY_LENGTH)
102                 t->history.count++;
103
104         t->history.samples[motion_index].x = t->x;
105         t->history.samples[motion_index].y = t->y;
106         t->history.index = motion_index;
107 }
108
109 static inline void
110 tp_motion_hysteresis(struct tp_dispatch *tp,
111                      struct tp_touch *t)
112 {
113         int x = t->x,
114             y = t->y;
115
116         if (t->history.count == 0) {
117                 t->hysteresis.center_x = t->x;
118                 t->hysteresis.center_y = t->y;
119         } else {
120                 x = tp_hysteresis(x,
121                                   t->hysteresis.center_x,
122                                   tp->hysteresis.margin_x);
123                 y = tp_hysteresis(y,
124                                   t->hysteresis.center_y,
125                                   tp->hysteresis.margin_y);
126                 t->hysteresis.center_x = x;
127                 t->hysteresis.center_y = y;
128                 t->x = x;
129                 t->y = y;
130         }
131 }
132
133 static inline void
134 tp_motion_history_reset(struct tp_touch *t)
135 {
136         t->history.count = 0;
137 }
138
139 static inline struct tp_touch *
140 tp_current_touch(struct tp_dispatch *tp)
141 {
142         return &tp->touches[min(tp->slot, tp->ntouches)];
143 }
144
145 static inline struct tp_touch *
146 tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
147 {
148         assert(slot < tp->ntouches);
149         return &tp->touches[slot];
150 }
151
152 static inline void
153 tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t)
154 {
155         if (t->state != TOUCH_UPDATE) {
156                 tp_motion_history_reset(t);
157                 t->dirty = true;
158                 t->state = TOUCH_BEGIN;
159                 t->pinned.is_pinned = false;
160                 tp->nfingers_down++;
161                 assert(tp->nfingers_down >= 1);
162                 tp->queued |= TOUCHPAD_EVENT_MOTION;
163         }
164 }
165
166 static inline void
167 tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t)
168 {
169         if (t->state == TOUCH_NONE)
170                 return;
171
172         t->dirty = true;
173         t->is_pointer = false;
174         t->state = TOUCH_END;
175         t->pinned.is_pinned = false;
176         assert(tp->nfingers_down >= 1);
177         tp->nfingers_down--;
178         tp->queued |= TOUCHPAD_EVENT_MOTION;
179 }
180
181 static double
182 tp_estimate_delta(int x0, int x1, int x2, int x3)
183 {
184         return (x0 + x1 - x2 - x3) / 4;
185 }
186
187 void
188 tp_get_delta(struct tp_touch *t, double *dx, double *dy)
189 {
190         if (t->history.count < 4) {
191                 *dx = 0;
192                 *dy = 0;
193                 return;
194         }
195
196         *dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x,
197                                 tp_motion_history_offset(t, 1)->x,
198                                 tp_motion_history_offset(t, 2)->x,
199                                 tp_motion_history_offset(t, 3)->x);
200         *dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y,
201                                 tp_motion_history_offset(t, 1)->y,
202                                 tp_motion_history_offset(t, 2)->y,
203                                 tp_motion_history_offset(t, 3)->y);
204 }
205
206 static void
207 tp_process_absolute(struct tp_dispatch *tp,
208                     const struct input_event *e,
209                     uint64_t time)
210 {
211         struct tp_touch *t = tp_current_touch(tp);
212
213         switch(e->code) {
214         case ABS_MT_POSITION_X:
215                 t->x = e->value;
216                 t->millis = time;
217                 t->dirty = true;
218                 tp->queued |= TOUCHPAD_EVENT_MOTION;
219                 break;
220         case ABS_MT_POSITION_Y:
221                 t->y = e->value;
222                 t->millis = time;
223                 t->dirty = true;
224                 tp->queued |= TOUCHPAD_EVENT_MOTION;
225                 break;
226         case ABS_MT_SLOT:
227                 tp->slot = e->value;
228                 break;
229         case ABS_MT_TRACKING_ID:
230                 t->millis = time;
231                 if (e->value != -1)
232                         tp_begin_touch(tp, t);
233                 else
234                         tp_end_touch(tp, t);
235         }
236 }
237
238 static void
239 tp_process_absolute_st(struct tp_dispatch *tp,
240                        const struct input_event *e,
241                        uint64_t time)
242 {
243         struct tp_touch *t = tp_current_touch(tp);
244
245         switch(e->code) {
246         case ABS_X:
247                 t->x = e->value;
248                 t->millis = time;
249                 t->dirty = true;
250                 tp->queued |= TOUCHPAD_EVENT_MOTION;
251                 break;
252         case ABS_Y:
253                 t->y = e->value;
254                 t->millis = time;
255                 t->dirty = true;
256                 tp->queued |= TOUCHPAD_EVENT_MOTION;
257                 break;
258         }
259 }
260
261 static void
262 tp_process_fake_touch(struct tp_dispatch *tp,
263                       const struct input_event *e,
264                       uint64_t time)
265 {
266         struct tp_touch *t;
267         unsigned int fake_touches;
268         unsigned int nfake_touches;
269         unsigned int i;
270         unsigned int shift;
271
272         if (e->code != BTN_TOUCH &&
273             (e->code < BTN_TOOL_DOUBLETAP || e->code > BTN_TOOL_QUADTAP))
274                 return;
275
276         shift = e->code == BTN_TOUCH ? 0 : (e->code - BTN_TOOL_DOUBLETAP + 1);
277
278         if (e->value)
279                 tp->fake_touches |= 1 << shift;
280         else
281                 tp->fake_touches &= ~(0x1 << shift);
282
283         fake_touches = tp->fake_touches;
284         nfake_touches = 0;
285         while (fake_touches) {
286                 nfake_touches++;
287                 fake_touches >>= 1;
288         }
289
290         for (i = 0; i < tp->ntouches; i++) {
291                 t = tp_get_touch(tp, i);
292                 if (i >= nfake_touches) {
293                         if (t->state != TOUCH_NONE) {
294                                 tp_end_touch(tp, t);
295                                 t->millis = time;
296                         }
297                 } else if (t->state != TOUCH_UPDATE &&
298                            t->state != TOUCH_BEGIN) {
299                         t->state = TOUCH_NONE;
300                         tp_begin_touch(tp, t);
301                         t->millis = time;
302                         t->fake =true;
303                 }
304         }
305
306         assert(tp->nfingers_down == nfake_touches);
307 }
308
309 static void
310 tp_process_key(struct tp_dispatch *tp,
311                const struct input_event *e,
312                uint64_t time)
313 {
314         switch (e->code) {
315                 case BTN_LEFT:
316                 case BTN_MIDDLE:
317                 case BTN_RIGHT:
318                         tp_process_button(tp, e, time);
319                         break;
320                 case BTN_TOUCH:
321                 case BTN_TOOL_DOUBLETAP:
322                 case BTN_TOOL_TRIPLETAP:
323                 case BTN_TOOL_QUADTAP:
324                         if (!tp->has_mt)
325                                 tp_process_fake_touch(tp, e, time);
326                         break;
327         }
328 }
329
330 static void
331 tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
332 {
333         unsigned int xdist, ydist;
334
335         if (!t->pinned.is_pinned)
336                 return;
337
338         xdist = abs(t->x - t->pinned.center_x);
339         ydist = abs(t->y - t->pinned.center_y);
340
341         if (xdist * xdist + ydist * ydist >=
342                         tp->buttons.motion_dist * tp->buttons.motion_dist) {
343                 t->pinned.is_pinned = false;
344                 tp_set_pointer(tp, t);
345         }
346 }
347
348 static void
349 tp_pin_fingers(struct tp_dispatch *tp)
350 {
351         struct tp_touch *t;
352
353         tp_for_each_touch(tp, t) {
354                 t->is_pointer = false;
355                 t->pinned.is_pinned = true;
356                 t->pinned.center_x = t->x;
357                 t->pinned.center_y = t->y;
358         }
359 }
360
361 static int
362 tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
363 {
364         return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
365                 !t->pinned.is_pinned && tp_button_touch_active(tp, t);
366 }
367
368 void
369 tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
370 {
371         struct tp_touch *tmp = NULL;
372
373         /* Only set the touch as pointer if we don't have one yet */
374         tp_for_each_touch(tp, tmp) {
375                 if (tmp->is_pointer)
376                         return;
377         }
378
379         if (tp_touch_active(tp, t))
380                 t->is_pointer = true;
381 }
382
383 static void
384 tp_process_state(struct tp_dispatch *tp, uint64_t time)
385 {
386         struct tp_touch *t;
387         struct tp_touch *first = tp_get_touch(tp, 0);
388
389         tp_for_each_touch(tp, t) {
390                 if (!tp->has_mt && t != first && first->fake) {
391                         t->x = first->x;
392                         t->y = first->y;
393                         if (!t->dirty)
394                                 t->dirty = first->dirty;
395                 } else if (!t->dirty)
396                         continue;
397
398                 tp_motion_hysteresis(tp, t);
399                 tp_motion_history_push(t);
400
401                 tp_unpin_finger(tp, t);
402         }
403
404         tp_button_handle_state(tp, time);
405
406         /*
407          * We have a physical button down event on a clickpad. To avoid
408          * spurious pointer moves by the clicking finger we pin all fingers.
409          * We unpin fingers when they move more then a certain threshold to
410          * to allow drag and drop.
411          */
412         if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) &&
413             tp->buttons.is_clickpad)
414                 tp_pin_fingers(tp);
415 }
416
417 static void
418 tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
419 {
420         struct tp_touch *t;
421
422         tp_for_each_touch(tp, t) {
423                 if (!t->dirty)
424                         continue;
425
426                 if (t->state == TOUCH_END) {
427                         t->state = TOUCH_NONE;
428                         t->fake = false;
429                 } else if (t->state == TOUCH_BEGIN)
430                         t->state = TOUCH_UPDATE;
431
432                 t->dirty = false;
433         }
434
435         tp->buttons.old_state = tp->buttons.state;
436
437         tp->queued = TOUCHPAD_EVENT_NONE;
438 }
439
440 static void
441 tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
442 {
443         struct tp_touch *t;
444         int nchanged = 0;
445         double dx = 0, dy =0;
446         double tmpx, tmpy;
447
448         tp_for_each_touch(tp, t) {
449                 if (tp_touch_active(tp, t) && t->dirty) {
450                         nchanged++;
451                         tp_get_delta(t, &tmpx, &tmpy);
452
453                         dx += tmpx;
454                         dy += tmpy;
455                 }
456         }
457
458         if (nchanged == 0)
459                 return;
460
461         dx /= nchanged;
462         dy /= nchanged;
463
464         tp_filter_motion(tp, &dx, &dy, time);
465
466         if (tp->scroll.state == SCROLL_STATE_NONE) {
467                 /* Require at least one px scrolling to start */
468                 if (dx <= -1.0 || dx >= 1.0) {
469                         tp->scroll.state = SCROLL_STATE_SCROLLING;
470                         tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL);
471                 }
472
473                 if (dy <= -1.0 || dy >= 1.0) {
474                         tp->scroll.state = SCROLL_STATE_SCROLLING;
475                         tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL);
476                 }
477
478                 if (tp->scroll.state == SCROLL_STATE_NONE)
479                         return;
480         }
481
482         if (dy != 0.0 &&
483             (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL))) {
484                 pointer_notify_axis(&tp->device->base,
485                                     time,
486                                     LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
487                                     li_fixed_from_double(dy));
488         }
489
490         if (dx != 0.0 &&
491             (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL))) {
492                 pointer_notify_axis(&tp->device->base,
493                                     time,
494                                     LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
495                                     li_fixed_from_double(dx));
496         }
497 }
498
499 static int
500 tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
501 {
502         struct tp_touch *t;
503         int nfingers_down = 0;
504
505         /* Only count active touches for 2 finger scrolling */
506         tp_for_each_touch(tp, t) {
507                 if (tp_touch_active(tp, t))
508                         nfingers_down++;
509         }
510
511         if (nfingers_down != 2) {
512                 /* terminate scrolling with a zero scroll event to notify
513                  * caller that it really ended now */
514                 if (tp->scroll.state != SCROLL_STATE_NONE) {
515                         tp->scroll.state = SCROLL_STATE_NONE;
516                         tp->scroll.direction = 0;
517                         if (tp->scroll.direction & LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL)
518                                 pointer_notify_axis(&tp->device->base,
519                                                     time,
520                                                     LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
521                                                     0);
522                         if (tp->scroll.direction & LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL)
523                                 pointer_notify_axis(&tp->device->base,
524                                                     time,
525                                                     LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
526                                                     0);
527                 }
528         } else {
529                 tp_post_twofinger_scroll(tp, time);
530                 return 1;
531         }
532         return 0;
533 }
534
535 static void
536 tp_post_events(struct tp_dispatch *tp, uint64_t time)
537 {
538         struct tp_touch *t = tp_current_touch(tp);
539         double dx, dy;
540
541         if (tp_post_button_events(tp, time) != 0)
542                 return;
543
544         if (tp_tap_handle_state(tp, time) != 0)
545                 return;
546
547         if (tp_post_scroll_events(tp, time) != 0)
548                 return;
549
550         if (t->history.count >= TOUCHPAD_MIN_SAMPLES) {
551                 if (!t->is_pointer) {
552                         tp_for_each_touch(tp, t) {
553                                 if (t->is_pointer)
554                                         break;
555                         }
556                 }
557
558                 if (!t->is_pointer)
559                         return;
560
561                 tp_get_delta(t, &dx, &dy);
562                 tp_filter_motion(tp, &dx, &dy, time);
563
564                 if (dx != 0 || dy != 0)
565                         pointer_notify_motion(
566                                 &tp->device->base,
567                                 time,
568                                 li_fixed_from_double(dx),
569                                 li_fixed_from_double(dy));
570         }
571 }
572
573 static void
574 tp_process(struct evdev_dispatch *dispatch,
575            struct evdev_device *device,
576            struct input_event *e,
577            uint64_t time)
578 {
579         struct tp_dispatch *tp =
580                 (struct tp_dispatch *)dispatch;
581
582         switch (e->type) {
583         case EV_ABS:
584                 if (tp->has_mt)
585                         tp_process_absolute(tp, e, time);
586                 else
587                         tp_process_absolute_st(tp, e, time);
588                 break;
589         case EV_KEY:
590                 tp_process_key(tp, e, time);
591                 break;
592         case EV_SYN:
593                 tp_process_state(tp, time);
594                 tp_post_events(tp, time);
595                 tp_post_process_state(tp, time);
596                 break;
597         }
598 }
599
600 static void
601 tp_destroy(struct evdev_dispatch *dispatch)
602 {
603         struct tp_dispatch *tp =
604                 (struct tp_dispatch*)dispatch;
605
606         tp_destroy_tap(tp);
607         tp_destroy_buttons(tp);
608
609         if (tp->filter)
610                 tp->filter->interface->destroy(tp->filter);
611         free(tp->touches);
612         free(tp);
613 }
614
615 static struct evdev_dispatch_interface tp_interface = {
616         tp_process,
617         tp_destroy
618 };
619
620 static void
621 tp_init_touch(struct tp_dispatch *tp,
622               struct tp_touch *t)
623 {
624         t->button.state = BUTTON_STATE_NONE;
625 }
626
627 static int
628 tp_init_slots(struct tp_dispatch *tp,
629               struct evdev_device *device)
630 {
631         size_t i;
632         const struct input_absinfo *absinfo;
633
634         absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
635         if (absinfo) {
636                 tp->ntouches = absinfo->maximum + 1;
637                 tp->slot = absinfo->value;
638                 tp->has_mt = true;
639         } else {
640                 struct map {
641                         unsigned int code;
642                         int ntouches;
643                 } max_touches[] = {
644                         { BTN_TOOL_QUINTTAP, 5 },
645                         { BTN_TOOL_QUADTAP, 4 },
646                         { BTN_TOOL_TRIPLETAP, 3 },
647                         { BTN_TOOL_DOUBLETAP, 2 },
648                 };
649                 struct map *m;
650
651                 tp->slot = 0;
652                 tp->has_mt = false;
653                 tp->ntouches = 1;
654
655                 ARRAY_FOR_EACH(max_touches, m) {
656                         if (libevdev_has_event_code(device->evdev,
657                                                     EV_KEY,
658                                                     m->code)) {
659                                 tp->ntouches = m->ntouches;
660                                 break;
661                         }
662                 }
663         }
664         tp->touches = calloc(tp->ntouches,
665                              sizeof(struct tp_touch));
666         if (!tp->touches)
667                 return -1;
668
669         for (i = 0; i < tp->ntouches; i++)
670                 tp_init_touch(tp, &tp->touches[i]);
671
672         return 0;
673 }
674
675 static int
676 tp_init_accel(struct tp_dispatch *touchpad, double diagonal)
677 {
678         struct motion_filter *accel;
679
680         touchpad->accel.constant_factor =
681                 DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal;
682         touchpad->accel.min_factor = DEFAULT_MIN_ACCEL_FACTOR;
683         touchpad->accel.max_factor = DEFAULT_MAX_ACCEL_FACTOR;
684
685         accel = create_pointer_accelator_filter(tp_accel_profile);
686         if (accel == NULL)
687                 return -1;
688
689         touchpad->filter = accel;
690
691         return 0;
692 }
693
694 static int
695 tp_init_scroll(struct tp_dispatch *tp)
696 {
697         tp->scroll.direction = 0;
698         tp->scroll.state = SCROLL_STATE_NONE;
699
700         return 0;
701 }
702
703 static int
704 tp_init(struct tp_dispatch *tp,
705         struct evdev_device *device)
706 {
707         int width, height;
708         double diagonal;
709
710         tp->base.interface = &tp_interface;
711         tp->device = device;
712         tp->tap.timer_fd = -1;
713         tp->buttons.timer_fd = -1;
714
715         if (tp_init_slots(tp, device) != 0)
716                 return -1;
717
718         width = abs(device->abs.max_x - device->abs.min_x);
719         height = abs(device->abs.max_y - device->abs.min_y);
720         diagonal = sqrt(width*width + height*height);
721
722         tp->hysteresis.margin_x =
723                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
724         tp->hysteresis.margin_y =
725                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
726
727         if (tp_init_scroll(tp) != 0)
728                 return -1;
729
730         if (tp_init_accel(tp, diagonal) != 0)
731                 return -1;
732
733         if (tp_init_tap(tp) != 0)
734                 return -1;
735
736         if (tp_init_buttons(tp, device) != 0)
737                 return -1;
738
739         return 0;
740 }
741
742 struct evdev_dispatch *
743 evdev_mt_touchpad_create(struct evdev_device *device)
744 {
745         struct tp_dispatch *tp;
746
747         tp = zalloc(sizeof *tp);
748         if (!tp)
749                 return NULL;
750
751         if (tp_init(tp, device) != 0) {
752                 tp_destroy(&tp->base);
753                 return NULL;
754         }
755
756         return  &tp->base;
757 }