2 * Copyright © 2014 Red Hat, Inc.
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.
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.
30 #include "evdev-mt-touchpad.h"
32 #define DEFAULT_ACCEL_NUMERATOR 1200.0
33 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
36 tp_hysteresis(int in, int center, int margin)
38 int diff = in - center;
39 if (abs(diff) <= margin)
43 return center + diff - margin;
45 return center + diff + margin;
48 static inline struct tp_motion *
49 tp_motion_history_offset(struct tp_touch *t, int offset)
52 (t->history.index - offset + TOUCHPAD_HISTORY_LENGTH) %
53 TOUCHPAD_HISTORY_LENGTH;
55 return &t->history.samples[offset_index];
59 tp_filter_motion(struct tp_dispatch *tp,
60 double *dx, double *dy, uint64_t time)
62 struct motion_params motion;
64 motion.dx = *dx * tp->accel.x_scale_coeff;
65 motion.dy = *dy * tp->accel.y_scale_coeff;
67 if (motion.dx != 0.0 || motion.dy != 0.0)
68 filter_dispatch(tp->filter, &motion, tp, time);
75 tp_motion_history_push(struct tp_touch *t)
77 int motion_index = (t->history.index + 1) % TOUCHPAD_HISTORY_LENGTH;
79 if (t->history.count < TOUCHPAD_HISTORY_LENGTH)
82 t->history.samples[motion_index].x = t->x;
83 t->history.samples[motion_index].y = t->y;
84 t->history.index = motion_index;
88 tp_motion_hysteresis(struct tp_dispatch *tp,
94 if (t->history.count == 0) {
95 t->hysteresis.center_x = t->x;
96 t->hysteresis.center_y = t->y;
99 t->hysteresis.center_x,
100 tp->hysteresis.margin_x);
102 t->hysteresis.center_y,
103 tp->hysteresis.margin_y);
104 t->hysteresis.center_x = x;
105 t->hysteresis.center_y = y;
112 tp_motion_history_reset(struct tp_touch *t)
114 t->history.count = 0;
117 static inline struct tp_touch *
118 tp_current_touch(struct tp_dispatch *tp)
120 return &tp->touches[min(tp->slot, tp->ntouches - 1)];
123 static inline struct tp_touch *
124 tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
126 assert(slot < tp->ntouches);
127 return &tp->touches[slot];
131 tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
133 if (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE)
136 tp_motion_history_reset(t);
138 t->state = TOUCH_BEGIN;
139 t->pinned.is_pinned = false;
142 assert(tp->nfingers_down >= 1);
143 tp->queued |= TOUCHPAD_EVENT_MOTION;
147 tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
149 if (t->state == TOUCH_END || t->state == TOUCH_NONE)
153 t->is_pointer = false;
154 t->palm.is_palm = false;
155 t->state = TOUCH_END;
156 t->pinned.is_pinned = false;
158 assert(tp->nfingers_down >= 1);
160 tp->queued |= TOUCHPAD_EVENT_MOTION;
164 tp_estimate_delta(int x0, int x1, int x2, int x3)
166 return (x0 + x1 - x2 - x3) / 4;
170 tp_get_delta(struct tp_touch *t, double *dx, double *dy)
172 if (t->history.count < 4) {
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);
189 tp_process_absolute(struct tp_dispatch *tp,
190 const struct input_event *e,
193 struct tp_touch *t = tp_current_touch(tp);
196 case ABS_MT_POSITION_X:
200 tp->queued |= TOUCHPAD_EVENT_MOTION;
202 case ABS_MT_POSITION_Y:
206 tp->queued |= TOUCHPAD_EVENT_MOTION;
211 case ABS_MT_TRACKING_ID:
213 tp_begin_touch(tp, t, time);
215 tp_end_touch(tp, t, time);
220 tp_process_absolute_st(struct tp_dispatch *tp,
221 const struct input_event *e,
224 struct tp_touch *t = tp_current_touch(tp);
231 tp->queued |= TOUCHPAD_EVENT_MOTION;
237 tp->queued |= TOUCHPAD_EVENT_MOTION;
243 tp_process_fake_touch(struct tp_dispatch *tp,
244 const struct input_event *e,
248 unsigned int fake_touches;
249 unsigned int nfake_touches;
253 if (e->code != BTN_TOUCH &&
254 (e->code < BTN_TOOL_DOUBLETAP || e->code > BTN_TOOL_QUADTAP))
257 shift = e->code == BTN_TOUCH ? 0 : (e->code - BTN_TOOL_DOUBLETAP + 1);
260 tp->fake_touches |= 1 << shift;
262 tp->fake_touches &= ~(0x1 << shift);
264 fake_touches = tp->fake_touches;
266 while (fake_touches) {
271 for (i = 0; i < tp->ntouches; i++) {
272 t = tp_get_touch(tp, i);
273 if (i < nfake_touches) {
274 tp_begin_touch(tp, t, time);
277 tp_end_touch(tp, t, time);
280 assert(tp->nfingers_down == nfake_touches);
284 tp_process_key(struct tp_dispatch *tp,
285 const struct input_event *e,
292 tp_process_button(tp, e, time);
295 case BTN_TOOL_DOUBLETAP:
296 case BTN_TOOL_TRIPLETAP:
297 case BTN_TOOL_QUADTAP:
299 tp_process_fake_touch(tp, e, time);
305 tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
307 unsigned int xdist, ydist;
309 if (!t->pinned.is_pinned)
312 xdist = abs(t->x - t->pinned.center_x);
313 ydist = abs(t->y - t->pinned.center_y);
315 if (xdist * xdist + ydist * ydist >=
316 tp->buttons.motion_dist * tp->buttons.motion_dist) {
317 t->pinned.is_pinned = false;
318 tp_set_pointer(tp, t);
323 tp_pin_fingers(struct tp_dispatch *tp)
327 tp_for_each_touch(tp, t) {
328 t->is_pointer = false;
329 t->pinned.is_pinned = true;
330 t->pinned.center_x = t->x;
331 t->pinned.center_y = t->y;
336 tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
338 return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
340 !t->pinned.is_pinned && tp_button_touch_active(tp, t);
344 tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
346 struct tp_touch *tmp = NULL;
348 /* Only set the touch as pointer if we don't have one yet */
349 tp_for_each_touch(tp, tmp) {
354 if (tp_touch_active(tp, t))
355 t->is_pointer = true;
359 tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
361 const int PALM_TIMEOUT = 200; /* ms */
362 const int DIRECTIONS = NE|E|SE|SW|W|NW;
364 /* If labelled a touch as palm, we unlabel as palm when
365 we move out of the palm edge zone within the timeout, provided
366 the direction is within 45 degrees of the horizontal.
368 if (t->palm.is_palm) {
369 if (time < t->palm.time + PALM_TIMEOUT &&
370 (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge)) {
371 int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y);
372 if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
373 t->palm.is_palm = false;
374 tp_set_pointer(tp, t);
380 /* palm must start in exclusion zone, it's ok to move into
381 the zone without being a palm */
382 if (t->state != TOUCH_BEGIN ||
383 (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge))
386 /* don't detect palm in software button areas, it's
387 likely that legitimate touches start in the area
388 covered by the exclusion zone */
389 if (tp->buttons.is_clickpad &&
390 tp_button_is_inside_softbutton_area(tp, t))
393 t->palm.is_palm = true;
400 tp_process_state(struct tp_dispatch *tp, uint64_t time)
403 struct tp_touch *first = tp_get_touch(tp, 0);
405 tp_for_each_touch(tp, t) {
406 if (!tp->has_mt && t != first && first->fake) {
410 t->dirty = first->dirty;
411 } else if (!t->dirty) {
415 tp_palm_detect(tp, t, time);
417 tp_motion_hysteresis(tp, t);
418 tp_motion_history_push(t);
420 tp_unpin_finger(tp, t);
423 tp_button_handle_state(tp, time);
426 * We have a physical button down event on a clickpad. To avoid
427 * spurious pointer moves by the clicking finger we pin all fingers.
428 * We unpin fingers when they move more then a certain threshold to
429 * to allow drag and drop.
431 if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) &&
432 tp->buttons.is_clickpad)
437 tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
441 tp_for_each_touch(tp, t) {
445 if (t->state == TOUCH_END) {
446 t->state = TOUCH_NONE;
448 } else if (t->state == TOUCH_BEGIN)
449 t->state = TOUCH_UPDATE;
454 tp->buttons.old_state = tp->buttons.state;
456 tp->queued = TOUCHPAD_EVENT_NONE;
460 tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
464 double dx = 0, dy =0;
467 tp_for_each_touch(tp, t) {
468 if (tp_touch_active(tp, t) && t->dirty) {
470 tp_get_delta(t, &tmpx, &tmpy);
475 /* Stop spurious MOTION events at the end of scrolling */
476 t->is_pointer = false;
485 tp_filter_motion(tp, &dx, &dy, time);
487 /* Require at least five px scrolling to start */
488 if (dy <= -5.0 || dy >= 5.0)
489 tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
491 if (dx <= -5.0 || dx >= 5.0)
492 tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
495 (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))) {
496 pointer_notify_axis(&tp->device->base,
498 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
503 (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))) {
504 pointer_notify_axis(&tp->device->base,
506 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
512 tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time)
514 /* terminate scrolling with a zero scroll event */
515 if (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
516 pointer_notify_axis(&tp->device->base,
518 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
520 if (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
521 pointer_notify_axis(&tp->device->base,
523 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
526 tp->scroll.direction = 0;
530 tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
533 int nfingers_down = 0;
535 /* Only count active touches for 2 finger scrolling */
536 tp_for_each_touch(tp, t) {
537 if (tp_touch_active(tp, t))
541 if (nfingers_down != 2) {
542 tp_stop_scroll_events(tp, time);
546 tp_post_twofinger_scroll(tp, time);
551 tp_post_events(struct tp_dispatch *tp, uint64_t time)
553 struct tp_touch *t = tp_current_touch(tp);
557 consumed |= tp_tap_handle_state(tp, time);
558 consumed |= tp_post_button_events(tp, time);
561 tp_stop_scroll_events(tp, time);
565 if (tp_post_scroll_events(tp, time) != 0)
568 if (!t->is_pointer) {
569 tp_for_each_touch(tp, t) {
575 if (!t->is_pointer ||
577 t->history.count < TOUCHPAD_MIN_SAMPLES)
580 tp_get_delta(t, &dx, &dy);
581 tp_filter_motion(tp, &dx, &dy, time);
583 if (dx != 0.0 || dy != 0.0)
584 pointer_notify_motion(&tp->device->base, time, dx, dy);
588 tp_process(struct evdev_dispatch *dispatch,
589 struct evdev_device *device,
590 struct input_event *e,
593 struct tp_dispatch *tp =
594 (struct tp_dispatch *)dispatch;
599 tp_process_absolute(tp, e, time);
601 tp_process_absolute_st(tp, e, time);
604 tp_process_key(tp, e, time);
607 tp_process_state(tp, time);
608 tp_post_events(tp, time);
609 tp_post_process_state(tp, time);
615 tp_destroy(struct evdev_dispatch *dispatch)
617 struct tp_dispatch *tp =
618 (struct tp_dispatch*)dispatch;
621 tp_destroy_buttons(tp);
623 filter_destroy(tp->filter);
628 static struct evdev_dispatch_interface tp_interface = {
634 tp_init_touch(struct tp_dispatch *tp,
641 tp_init_slots(struct tp_dispatch *tp,
642 struct evdev_device *device)
645 const struct input_absinfo *absinfo;
647 absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
649 tp->ntouches = absinfo->maximum + 1;
650 tp->slot = absinfo->value;
657 { BTN_TOOL_QUINTTAP, 5 },
658 { BTN_TOOL_QUADTAP, 4 },
659 { BTN_TOOL_TRIPLETAP, 3 },
660 { BTN_TOOL_DOUBLETAP, 2 },
668 ARRAY_FOR_EACH(max_touches, m) {
669 if (libevdev_has_event_code(device->evdev,
672 tp->ntouches = m->ntouches;
677 tp->touches = calloc(tp->ntouches,
678 sizeof(struct tp_touch));
682 for (i = 0; i < tp->ntouches; i++)
683 tp_init_touch(tp, &tp->touches[i]);
689 tp_init_accel(struct tp_dispatch *tp, double diagonal)
691 struct motion_filter *accel;
695 res_x = libevdev_get_abs_resolution(tp->device->evdev,
697 res_y = libevdev_get_abs_resolution(tp->device->evdev,
700 res_x = libevdev_get_abs_resolution(tp->device->evdev,
702 res_y = libevdev_get_abs_resolution(tp->device->evdev,
707 * Not all touchpads report the same amount of units/mm (resolution).
708 * Normalize motion events to a resolution of 15.74 units/mm
709 * (== 400 dpi) as base (unaccelerated) speed. This also evens out any
710 * differences in x and y resolution, so that a circle on the
711 * touchpad does not turn into an elipse on the screen.
713 * We pick 400dpi as thats one of the many default resolutions
714 * for USB mice, so we end up with a similar base speed on the device.
716 if (res_x > 1 && res_y > 1) {
717 tp->accel.x_scale_coeff = (400/25.4) / res_x;
718 tp->accel.y_scale_coeff = (400/25.4) / res_y;
721 * For touchpads where the driver does not provide resolution, fall
722 * back to scaling motion events based on the diagonal size in units.
724 tp->accel.x_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
725 tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
728 accel = create_pointer_accelator_filter(
729 pointer_accel_profile_smooth_simple);
739 tp_init_scroll(struct tp_dispatch *tp)
741 tp->scroll.direction = 0;
747 tp_init_palmdetect(struct tp_dispatch *tp,
748 struct evdev_device *device)
752 tp->palm.right_edge = INT_MAX;
753 tp->palm.left_edge = INT_MIN;
755 width = abs(device->abs.absinfo_x->maximum -
756 device->abs.absinfo_x->minimum);
758 /* Apple touchpads are always big enough to warrant palm detection */
759 if (evdev_device_get_id_vendor(device) != VENDOR_ID_APPLE) {
760 /* We don't know how big the touchpad is */
761 if (device->abs.absinfo_x->resolution == 1)
764 /* Enable palm detection on touchpads >= 80 mm. Anything smaller
765 probably won't need it, until we find out it does */
766 if (width/device->abs.absinfo_x->resolution < 80)
770 /* palm edges are 5% of the width on each side */
771 tp->palm.right_edge = device->abs.absinfo_x->maximum - width * 0.05;
772 tp->palm.left_edge = device->abs.absinfo_x->minimum + width * 0.05;
779 tp_init(struct tp_dispatch *tp,
780 struct evdev_device *device)
785 tp->base.interface = &tp_interface;
788 if (tp_init_slots(tp, device) != 0)
791 width = abs(device->abs.absinfo_x->maximum -
792 device->abs.absinfo_x->minimum);
793 height = abs(device->abs.absinfo_y->maximum -
794 device->abs.absinfo_y->minimum);
795 diagonal = sqrt(width*width + height*height);
797 tp->hysteresis.margin_x =
798 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
799 tp->hysteresis.margin_y =
800 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
802 if (tp_init_scroll(tp) != 0)
805 if (tp_init_accel(tp, diagonal) != 0)
808 if (tp_init_tap(tp) != 0)
811 if (tp_init_buttons(tp, device) != 0)
814 if (tp_init_palmdetect(tp, device) != 0)
820 struct evdev_dispatch *
821 evdev_mt_touchpad_create(struct evdev_device *device)
823 struct tp_dispatch *tp;
825 tp = zalloc(sizeof *tp);
829 if (tp_init(tp, device) != 0) {
830 tp_destroy(&tp->base);