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)
133 if (t->state != TOUCH_UPDATE) {
134 tp_motion_history_reset(t);
136 t->state = TOUCH_BEGIN;
137 t->pinned.is_pinned = false;
139 assert(tp->nfingers_down >= 1);
140 tp->queued |= TOUCHPAD_EVENT_MOTION;
145 tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t)
147 if (t->state == TOUCH_NONE)
151 t->is_pointer = false;
152 t->palm.is_palm = false;
153 t->state = TOUCH_END;
154 t->pinned.is_pinned = false;
155 assert(tp->nfingers_down >= 1);
157 tp->queued |= TOUCHPAD_EVENT_MOTION;
161 tp_estimate_delta(int x0, int x1, int x2, int x3)
163 return (x0 + x1 - x2 - x3) / 4;
167 tp_get_delta(struct tp_touch *t, double *dx, double *dy)
169 if (t->history.count < 4) {
175 *dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x,
176 tp_motion_history_offset(t, 1)->x,
177 tp_motion_history_offset(t, 2)->x,
178 tp_motion_history_offset(t, 3)->x);
179 *dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y,
180 tp_motion_history_offset(t, 1)->y,
181 tp_motion_history_offset(t, 2)->y,
182 tp_motion_history_offset(t, 3)->y);
186 tp_process_absolute(struct tp_dispatch *tp,
187 const struct input_event *e,
190 struct tp_touch *t = tp_current_touch(tp);
193 case ABS_MT_POSITION_X:
197 tp->queued |= TOUCHPAD_EVENT_MOTION;
199 case ABS_MT_POSITION_Y:
203 tp->queued |= TOUCHPAD_EVENT_MOTION;
208 case ABS_MT_TRACKING_ID:
211 tp_begin_touch(tp, t);
218 tp_process_absolute_st(struct tp_dispatch *tp,
219 const struct input_event *e,
222 struct tp_touch *t = tp_current_touch(tp);
229 tp->queued |= TOUCHPAD_EVENT_MOTION;
235 tp->queued |= TOUCHPAD_EVENT_MOTION;
241 tp_process_fake_touch(struct tp_dispatch *tp,
242 const struct input_event *e,
246 unsigned int fake_touches;
247 unsigned int nfake_touches;
251 if (e->code != BTN_TOUCH &&
252 (e->code < BTN_TOOL_DOUBLETAP || e->code > BTN_TOOL_QUADTAP))
255 shift = e->code == BTN_TOUCH ? 0 : (e->code - BTN_TOOL_DOUBLETAP + 1);
258 tp->fake_touches |= 1 << shift;
260 tp->fake_touches &= ~(0x1 << shift);
262 fake_touches = tp->fake_touches;
264 while (fake_touches) {
269 for (i = 0; i < tp->ntouches; i++) {
270 t = tp_get_touch(tp, i);
271 if (i >= nfake_touches) {
272 if (t->state != TOUCH_NONE) {
276 } else if (t->state != TOUCH_UPDATE &&
277 t->state != TOUCH_BEGIN) {
278 t->state = TOUCH_NONE;
279 tp_begin_touch(tp, t);
285 assert(tp->nfingers_down == nfake_touches);
289 tp_process_key(struct tp_dispatch *tp,
290 const struct input_event *e,
297 tp_process_button(tp, e, time);
300 case BTN_TOOL_DOUBLETAP:
301 case BTN_TOOL_TRIPLETAP:
302 case BTN_TOOL_QUADTAP:
304 tp_process_fake_touch(tp, e, time);
310 tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
312 unsigned int xdist, ydist;
314 if (!t->pinned.is_pinned)
317 xdist = abs(t->x - t->pinned.center_x);
318 ydist = abs(t->y - t->pinned.center_y);
320 if (xdist * xdist + ydist * ydist >=
321 tp->buttons.motion_dist * tp->buttons.motion_dist) {
322 t->pinned.is_pinned = false;
323 tp_set_pointer(tp, t);
328 tp_pin_fingers(struct tp_dispatch *tp)
332 tp_for_each_touch(tp, t) {
333 t->is_pointer = false;
334 t->pinned.is_pinned = true;
335 t->pinned.center_x = t->x;
336 t->pinned.center_y = t->y;
341 tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
343 return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
345 !t->pinned.is_pinned && tp_button_touch_active(tp, t);
349 tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
351 struct tp_touch *tmp = NULL;
353 /* Only set the touch as pointer if we don't have one yet */
354 tp_for_each_touch(tp, tmp) {
359 if (tp_touch_active(tp, t))
360 t->is_pointer = true;
364 tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
366 const int PALM_TIMEOUT = 200; /* ms */
367 const int DIRECTIONS = NE|E|SE|SW|W|NW;
369 /* If labelled a touch as palm, we unlabel as palm when
370 we move out of the palm edge zone within the timeout, provided
371 the direction is within 45 degrees of the horizontal.
373 if (t->palm.is_palm) {
374 if (time < t->palm.time + PALM_TIMEOUT &&
375 (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge)) {
376 int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y);
377 if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
378 t->palm.is_palm = false;
379 tp_set_pointer(tp, t);
385 /* palm must start in exclusion zone, it's ok to move into
386 the zone without being a palm */
387 if (t->state != TOUCH_BEGIN ||
388 (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge))
391 /* don't detect palm in software button areas, it's
392 likely that legitimate touches start in the area
393 covered by the exclusion zone */
394 if (tp->buttons.is_clickpad &&
395 tp_button_is_inside_softbutton_area(tp, t))
398 t->palm.is_palm = true;
405 tp_process_state(struct tp_dispatch *tp, uint64_t time)
408 struct tp_touch *first = tp_get_touch(tp, 0);
410 tp_for_each_touch(tp, t) {
411 if (!tp->has_mt && t != first && first->fake) {
415 t->dirty = first->dirty;
416 } else if (!t->dirty) {
420 tp_palm_detect(tp, t, time);
422 tp_motion_hysteresis(tp, t);
423 tp_motion_history_push(t);
425 tp_unpin_finger(tp, t);
428 tp_button_handle_state(tp, time);
431 * We have a physical button down event on a clickpad. To avoid
432 * spurious pointer moves by the clicking finger we pin all fingers.
433 * We unpin fingers when they move more then a certain threshold to
434 * to allow drag and drop.
436 if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) &&
437 tp->buttons.is_clickpad)
442 tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
446 tp_for_each_touch(tp, t) {
450 if (t->state == TOUCH_END) {
451 t->state = TOUCH_NONE;
453 } else if (t->state == TOUCH_BEGIN)
454 t->state = TOUCH_UPDATE;
459 tp->buttons.old_state = tp->buttons.state;
461 tp->queued = TOUCHPAD_EVENT_NONE;
465 tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
469 double dx = 0, dy =0;
472 tp_for_each_touch(tp, t) {
473 if (tp_touch_active(tp, t) && t->dirty) {
475 tp_get_delta(t, &tmpx, &tmpy);
480 /* Stop spurious MOTION events at the end of scrolling */
481 t->is_pointer = false;
490 tp_filter_motion(tp, &dx, &dy, time);
492 /* Require at least five px scrolling to start */
493 if (dy <= -5.0 || dy >= 5.0)
494 tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
496 if (dx <= -5.0 || dx >= 5.0)
497 tp->scroll.direction |= (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
500 (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))) {
501 pointer_notify_axis(&tp->device->base,
503 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
508 (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))) {
509 pointer_notify_axis(&tp->device->base,
511 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
517 tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time)
519 /* terminate scrolling with a zero scroll event */
520 if (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
521 pointer_notify_axis(&tp->device->base,
523 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
525 if (tp->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
526 pointer_notify_axis(&tp->device->base,
528 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
531 tp->scroll.direction = 0;
535 tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
538 int nfingers_down = 0;
540 /* Only count active touches for 2 finger scrolling */
541 tp_for_each_touch(tp, t) {
542 if (tp_touch_active(tp, t))
546 if (nfingers_down != 2) {
547 tp_stop_scroll_events(tp, time);
551 tp_post_twofinger_scroll(tp, time);
556 tp_post_events(struct tp_dispatch *tp, uint64_t time)
558 struct tp_touch *t = tp_current_touch(tp);
562 consumed |= tp_tap_handle_state(tp, time);
563 consumed |= tp_post_button_events(tp, time);
566 tp_stop_scroll_events(tp, time);
570 if (tp_post_scroll_events(tp, time) != 0)
573 if (!t->is_pointer) {
574 tp_for_each_touch(tp, t) {
580 if (!t->is_pointer ||
582 t->history.count < TOUCHPAD_MIN_SAMPLES)
585 tp_get_delta(t, &dx, &dy);
586 tp_filter_motion(tp, &dx, &dy, time);
588 if (dx != 0.0 || dy != 0.0)
589 pointer_notify_motion(&tp->device->base, time, dx, dy);
593 tp_process(struct evdev_dispatch *dispatch,
594 struct evdev_device *device,
595 struct input_event *e,
598 struct tp_dispatch *tp =
599 (struct tp_dispatch *)dispatch;
604 tp_process_absolute(tp, e, time);
606 tp_process_absolute_st(tp, e, time);
609 tp_process_key(tp, e, time);
612 tp_process_state(tp, time);
613 tp_post_events(tp, time);
614 tp_post_process_state(tp, time);
620 tp_destroy(struct evdev_dispatch *dispatch)
622 struct tp_dispatch *tp =
623 (struct tp_dispatch*)dispatch;
626 tp_destroy_buttons(tp);
628 filter_destroy(tp->filter);
633 static struct evdev_dispatch_interface tp_interface = {
639 tp_init_touch(struct tp_dispatch *tp,
646 tp_init_slots(struct tp_dispatch *tp,
647 struct evdev_device *device)
650 const struct input_absinfo *absinfo;
652 absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
654 tp->ntouches = absinfo->maximum + 1;
655 tp->slot = absinfo->value;
662 { BTN_TOOL_QUINTTAP, 5 },
663 { BTN_TOOL_QUADTAP, 4 },
664 { BTN_TOOL_TRIPLETAP, 3 },
665 { BTN_TOOL_DOUBLETAP, 2 },
673 ARRAY_FOR_EACH(max_touches, m) {
674 if (libevdev_has_event_code(device->evdev,
677 tp->ntouches = m->ntouches;
682 tp->touches = calloc(tp->ntouches,
683 sizeof(struct tp_touch));
687 for (i = 0; i < tp->ntouches; i++)
688 tp_init_touch(tp, &tp->touches[i]);
694 tp_init_accel(struct tp_dispatch *tp, double diagonal)
696 struct motion_filter *accel;
700 res_x = libevdev_get_abs_resolution(tp->device->evdev,
702 res_y = libevdev_get_abs_resolution(tp->device->evdev,
705 res_x = libevdev_get_abs_resolution(tp->device->evdev,
707 res_y = libevdev_get_abs_resolution(tp->device->evdev,
712 * Not all touchpads report the same amount of units/mm (resolution).
713 * Normalize motion events to a resolution of 15.74 units/mm
714 * (== 400 dpi) as base (unaccelerated) speed. This also evens out any
715 * differences in x and y resolution, so that a circle on the
716 * touchpad does not turn into an elipse on the screen.
718 * We pick 400dpi as thats one of the many default resolutions
719 * for USB mice, so we end up with a similar base speed on the device.
721 if (res_x > 1 && res_y > 1) {
722 tp->accel.x_scale_coeff = (400/25.4) / res_x;
723 tp->accel.y_scale_coeff = (400/25.4) / res_y;
726 * For touchpads where the driver does not provide resolution, fall
727 * back to scaling motion events based on the diagonal size in units.
729 tp->accel.x_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
730 tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
733 accel = create_pointer_accelator_filter(
734 pointer_accel_profile_smooth_simple);
744 tp_init_scroll(struct tp_dispatch *tp)
746 tp->scroll.direction = 0;
752 tp_init_palmdetect(struct tp_dispatch *tp,
753 struct evdev_device *device)
757 tp->palm.right_edge = INT_MAX;
758 tp->palm.left_edge = INT_MIN;
760 width = abs(device->abs.absinfo_x->maximum -
761 device->abs.absinfo_x->minimum);
763 /* Apple touchpads are always big enough to warrant palm detection */
764 if (evdev_device_get_id_vendor(device) != VENDOR_ID_APPLE) {
765 /* We don't know how big the touchpad is */
766 if (device->abs.absinfo_x->resolution == 1)
769 /* Enable palm detection on touchpads >= 80 mm. Anything smaller
770 probably won't need it, until we find out it does */
771 if (width/device->abs.absinfo_x->resolution < 80)
775 /* palm edges are 5% of the width on each side */
776 tp->palm.right_edge = device->abs.absinfo_x->maximum - width * 0.05;
777 tp->palm.left_edge = device->abs.absinfo_x->minimum + width * 0.05;
784 tp_init(struct tp_dispatch *tp,
785 struct evdev_device *device)
790 tp->base.interface = &tp_interface;
793 if (tp_init_slots(tp, device) != 0)
796 width = abs(device->abs.absinfo_x->maximum -
797 device->abs.absinfo_x->minimum);
798 height = abs(device->abs.absinfo_y->maximum -
799 device->abs.absinfo_y->minimum);
800 diagonal = sqrt(width*width + height*height);
802 tp->hysteresis.margin_x =
803 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
804 tp->hysteresis.margin_y =
805 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
807 if (tp_init_scroll(tp) != 0)
810 if (tp_init_accel(tp, diagonal) != 0)
813 if (tp_init_tap(tp) != 0)
816 if (tp_init_buttons(tp, device) != 0)
819 if (tp_init_palmdetect(tp, device) != 0)
825 struct evdev_dispatch *
826 evdev_mt_touchpad_create(struct evdev_device *device)
828 struct tp_dispatch *tp;
830 tp = zalloc(sizeof *tp);
834 if (tp_init(tp, device) != 0) {
835 tp_destroy(&tp->base);