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
34 #define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 500 /* ms */
37 tp_hysteresis(int in, int center, int margin)
39 int diff = in - center;
40 if (abs(diff) <= margin)
44 return center + diff - margin;
46 return center + diff + margin;
49 static inline struct tp_motion *
50 tp_motion_history_offset(struct tp_touch *t, int offset)
53 (t->history.index - offset + TOUCHPAD_HISTORY_LENGTH) %
54 TOUCHPAD_HISTORY_LENGTH;
56 return &t->history.samples[offset_index];
60 tp_filter_motion(struct tp_dispatch *tp,
61 double *dx, double *dy,
62 double *dx_unaccel, double *dy_unaccel,
65 struct motion_params motion;
67 motion.dx = *dx * tp->accel.x_scale_coeff;
68 motion.dy = *dy * tp->accel.y_scale_coeff;
71 *dx_unaccel = motion.dx;
73 *dy_unaccel = motion.dy;
75 if (motion.dx != 0.0 || motion.dy != 0.0)
76 filter_dispatch(tp->device->pointer.filter, &motion, tp, time);
83 tp_motion_history_push(struct tp_touch *t)
85 int motion_index = (t->history.index + 1) % TOUCHPAD_HISTORY_LENGTH;
87 if (t->history.count < TOUCHPAD_HISTORY_LENGTH)
90 t->history.samples[motion_index].x = t->x;
91 t->history.samples[motion_index].y = t->y;
92 t->history.index = motion_index;
96 tp_motion_hysteresis(struct tp_dispatch *tp,
102 if (t->history.count == 0) {
103 t->hysteresis.center_x = t->x;
104 t->hysteresis.center_y = t->y;
107 t->hysteresis.center_x,
108 tp->hysteresis.margin_x);
110 t->hysteresis.center_y,
111 tp->hysteresis.margin_y);
112 t->hysteresis.center_x = x;
113 t->hysteresis.center_y = y;
120 tp_motion_history_reset(struct tp_touch *t)
122 t->history.count = 0;
125 static inline struct tp_touch *
126 tp_current_touch(struct tp_dispatch *tp)
128 return &tp->touches[min(tp->slot, tp->ntouches - 1)];
131 static inline struct tp_touch *
132 tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
134 assert(slot < tp->ntouches);
135 return &tp->touches[slot];
138 static inline unsigned int
139 tp_fake_finger_count(struct tp_dispatch *tp)
141 /* don't count BTN_TOUCH */
142 return ffs(tp->fake_touches >> 1);
146 tp_fake_finger_is_touching(struct tp_dispatch *tp)
148 return tp->fake_touches & 0x1;
152 tp_fake_finger_set(struct tp_dispatch *tp,
162 case BTN_TOOL_FINGER:
165 case BTN_TOOL_DOUBLETAP:
166 case BTN_TOOL_TRIPLETAP:
167 case BTN_TOOL_QUADTAP:
168 shift = code - BTN_TOOL_DOUBLETAP + 2;
175 tp->fake_touches |= 1 << shift;
177 tp->fake_touches &= ~(0x1 << shift);
181 tp_new_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
183 if (t->state == TOUCH_BEGIN ||
184 t->state == TOUCH_UPDATE ||
185 t->state == TOUCH_HOVERING)
188 /* we begin the touch as hovering because until BTN_TOUCH happens we
189 * don't know if it's a touch down or not. And BTN_TOUCH may happen
190 * after ABS_MT_TRACKING_ID */
191 tp_motion_history_reset(t);
193 t->has_ended = false;
194 t->state = TOUCH_HOVERING;
195 t->pinned.is_pinned = false;
197 tp->queued |= TOUCHPAD_EVENT_MOTION;
201 tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
204 t->state = TOUCH_BEGIN;
207 assert(tp->nfingers_down >= 1);
211 * End a touch, even if the touch sequence is still active.
214 tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
218 t->state = TOUCH_NONE;
230 t->is_pointer = false;
231 t->palm.is_palm = false;
232 t->state = TOUCH_END;
233 t->pinned.is_pinned = false;
235 assert(tp->nfingers_down >= 1);
237 tp->queued |= TOUCHPAD_EVENT_MOTION;
241 * End the touch sequence on ABS_MT_TRACKING_ID -1 or when the BTN_TOOL_* 0 is received.
244 tp_end_sequence(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
247 tp_end_touch(tp, t, time);
251 tp_estimate_delta(int x0, int x1, int x2, int x3)
253 return (x0 + x1 - x2 - x3) / 4.0;
257 tp_get_delta(struct tp_touch *t, double *dx, double *dy)
259 if (t->history.count < TOUCHPAD_MIN_SAMPLES) {
265 *dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x,
266 tp_motion_history_offset(t, 1)->x,
267 tp_motion_history_offset(t, 2)->x,
268 tp_motion_history_offset(t, 3)->x);
269 *dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y,
270 tp_motion_history_offset(t, 1)->y,
271 tp_motion_history_offset(t, 2)->y,
272 tp_motion_history_offset(t, 3)->y);
276 tp_process_absolute(struct tp_dispatch *tp,
277 const struct input_event *e,
280 struct tp_touch *t = tp_current_touch(tp);
283 case ABS_MT_POSITION_X:
287 tp->queued |= TOUCHPAD_EVENT_MOTION;
289 case ABS_MT_POSITION_Y:
293 tp->queued |= TOUCHPAD_EVENT_MOTION;
298 case ABS_MT_TRACKING_ID:
300 tp_new_touch(tp, t, time);
302 tp_end_sequence(tp, t, time);
307 tp_process_absolute_st(struct tp_dispatch *tp,
308 const struct input_event *e,
311 struct tp_touch *t = tp_current_touch(tp);
318 tp->queued |= TOUCHPAD_EVENT_MOTION;
324 tp->queued |= TOUCHPAD_EVENT_MOTION;
330 tp_process_fake_touch(struct tp_dispatch *tp,
331 const struct input_event *e,
335 unsigned int nfake_touches;
336 unsigned int i, start;
338 tp_fake_finger_set(tp, e->code, e->value != 0);
340 nfake_touches = tp_fake_finger_count(tp);
342 start = tp->has_mt ? tp->real_touches : 0;
343 for (i = start; i < tp->ntouches; i++) {
344 t = tp_get_touch(tp, i);
345 if (i < nfake_touches)
346 tp_new_touch(tp, t, time);
348 tp_end_sequence(tp, t, time);
353 tp_process_key(struct tp_dispatch *tp,
354 const struct input_event *e,
361 tp_process_button(tp, e, time);
364 case BTN_TOOL_FINGER:
365 case BTN_TOOL_DOUBLETAP:
366 case BTN_TOOL_TRIPLETAP:
367 case BTN_TOOL_QUADTAP:
368 tp_process_fake_touch(tp, e, time);
374 tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
376 unsigned int xdist, ydist;
378 if (!t->pinned.is_pinned)
381 xdist = abs(t->x - t->pinned.center_x);
382 ydist = abs(t->y - t->pinned.center_y);
384 if (xdist * xdist + ydist * ydist >=
385 tp->buttons.motion_dist * tp->buttons.motion_dist) {
386 t->pinned.is_pinned = false;
387 tp_set_pointer(tp, t);
391 /* The finger may slowly drift, adjust the center */
392 t->pinned.center_x = t->x + t->pinned.center_x / 2;
393 t->pinned.center_y = t->y + t->pinned.center_y / 2;
397 tp_pin_fingers(struct tp_dispatch *tp)
401 tp_for_each_touch(tp, t) {
402 t->is_pointer = false;
403 t->pinned.is_pinned = true;
404 t->pinned.center_x = t->x;
405 t->pinned.center_y = t->y;
410 tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
412 return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
414 !t->pinned.is_pinned &&
415 tp_button_touch_active(tp, t) &&
416 tp_edge_scroll_touch_active(tp, t);
420 tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
422 struct tp_touch *tmp = NULL;
424 /* Only set the touch as pointer if we don't have one yet */
425 tp_for_each_touch(tp, tmp) {
430 if (tp_touch_active(tp, t))
431 t->is_pointer = true;
435 tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
437 const int PALM_TIMEOUT = 200; /* ms */
438 const int DIRECTIONS = NE|E|SE|SW|W|NW;
440 /* If labelled a touch as palm, we unlabel as palm when
441 we move out of the palm edge zone within the timeout, provided
442 the direction is within 45 degrees of the horizontal.
444 if (t->palm.is_palm) {
445 if (time < t->palm.time + PALM_TIMEOUT &&
446 (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge)) {
447 int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y);
448 if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
449 t->palm.is_palm = false;
450 tp_set_pointer(tp, t);
456 /* palm must start in exclusion zone, it's ok to move into
457 the zone without being a palm */
458 if (t->state != TOUCH_BEGIN ||
459 (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge))
462 /* don't detect palm in software button areas, it's
463 likely that legitimate touches start in the area
464 covered by the exclusion zone */
465 if (tp->buttons.is_clickpad &&
466 tp_button_is_inside_softbutton_area(tp, t))
469 t->palm.is_palm = true;
476 tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
480 double dx = 0, dy =0;
483 tp_for_each_touch(tp, t) {
484 if (tp_touch_active(tp, t) && t->dirty) {
486 tp_get_delta(t, &tmpx, &tmpy);
491 /* Stop spurious MOTION events at the end of scrolling */
492 t->is_pointer = false;
501 tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
503 evdev_post_scroll(tp->device,
505 LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
507 tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_ACTIVE;
511 tp_twofinger_stop_scroll(struct tp_dispatch *tp, uint64_t time)
513 struct tp_touch *t, *ptr = NULL;
514 int nfingers_down = 0;
516 evdev_stop_scroll(tp->device,
518 LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
520 /* If we were scrolling and now there's exactly 1 active finger,
521 switch back to pointer movement */
522 if (tp->scroll.twofinger_state == TWOFINGER_SCROLL_STATE_ACTIVE) {
523 tp_for_each_touch(tp, t) {
524 if (tp_touch_active(tp, t)) {
531 if (nfingers_down == 1)
532 tp_set_pointer(tp, ptr);
535 tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_NONE;
539 tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
542 int nfingers_down = 0;
544 /* No 2fg scrolling during tap-n-drag */
545 if (tp_tap_dragging(tp))
548 /* No 2fg scrolling while a clickpad is clicked */
549 if (tp->buttons.is_clickpad && tp->buttons.state)
552 /* Only count active touches for 2 finger scrolling */
553 tp_for_each_touch(tp, t) {
554 if (tp_touch_active(tp, t))
558 if (nfingers_down == 2) {
559 tp_post_twofinger_scroll(tp, time);
563 tp_twofinger_stop_scroll(tp, time);
569 tp_scroll_handle_state(struct tp_dispatch *tp, uint64_t time)
571 /* Note this must be always called, so that it knows the state of
572 * touches when the scroll-mode changes.
574 tp_edge_scroll_handle_state(tp, time);
578 tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
580 struct libinput *libinput = tp->device->base.seat->libinput;
582 switch (tp->scroll.method) {
583 case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
585 case LIBINPUT_CONFIG_SCROLL_2FG:
586 return tp_twofinger_scroll_post_events(tp, time);
587 case LIBINPUT_CONFIG_SCROLL_EDGE:
588 return tp_edge_scroll_post_events(tp, time);
589 case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN:
590 log_bug_libinput(libinput, "Unexpected scroll mode\n");
597 tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time)
599 struct libinput *libinput = tp->device->base.seat->libinput;
601 switch (tp->scroll.method) {
602 case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
604 case LIBINPUT_CONFIG_SCROLL_2FG:
605 tp_twofinger_stop_scroll(tp, time);
607 case LIBINPUT_CONFIG_SCROLL_EDGE:
608 tp_edge_scroll_stop_events(tp, time);
610 case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN:
611 log_bug_libinput(libinput, "Unexpected scroll mode\n");
617 tp_remove_scroll(struct tp_dispatch *tp)
619 tp_remove_edge_scroll(tp);
623 tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
626 unsigned int nfake_touches;
629 if (!tp->fake_touches && !tp->nfingers_down)
632 nfake_touches = tp_fake_finger_count(tp);
633 if (tp->nfingers_down == nfake_touches &&
634 ((tp->nfingers_down == 0 && !tp_fake_finger_is_touching(tp)) ||
635 (tp->nfingers_down > 0 && tp_fake_finger_is_touching(tp))))
638 /* if BTN_TOUCH is set and we have less fingers down than fake
639 * touches, switch each hovering touch to BEGIN
640 * until nfingers_down matches nfake_touches
642 if (tp_fake_finger_is_touching(tp) &&
643 tp->nfingers_down < nfake_touches) {
644 for (i = 0; i < (int)tp->ntouches; i++) {
645 t = tp_get_touch(tp, i);
647 if (t->state == TOUCH_HOVERING) {
648 tp_begin_touch(tp, t, time);
650 if (tp->nfingers_down >= nfake_touches)
656 /* if BTN_TOUCH is unset end all touches, we're hovering now. If we
657 * have too many touches also end some of them. This is done in
660 if (tp->nfingers_down > nfake_touches ||
661 !tp_fake_finger_is_touching(tp)) {
662 for (i = tp->ntouches - 1; i >= 0; i--) {
663 t = tp_get_touch(tp, i);
665 if (t->state == TOUCH_HOVERING)
668 tp_end_touch(tp, t, time);
670 if (tp_fake_finger_is_touching(tp) &&
671 tp->nfingers_down == nfake_touches)
678 tp_process_state(struct tp_dispatch *tp, uint64_t time)
681 struct tp_touch *first = tp_get_touch(tp, 0);
684 tp_unhover_touches(tp, time);
686 for (i = 0; i < tp->ntouches; i++) {
687 t = tp_get_touch(tp, i);
689 /* semi-mt finger postions may "jump" when nfingers changes */
690 if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
691 tp_motion_history_reset(t);
693 if (i >= tp->real_touches && t->state != TOUCH_NONE) {
697 t->dirty = first->dirty;
703 tp_palm_detect(tp, t, time);
705 tp_motion_hysteresis(tp, t);
706 tp_motion_history_push(t);
708 tp_unpin_finger(tp, t);
711 tp_button_handle_state(tp, time);
712 tp_scroll_handle_state(tp, time);
715 * We have a physical button down event on a clickpad. To avoid
716 * spurious pointer moves by the clicking finger we pin all fingers.
717 * We unpin fingers when they move more then a certain threshold to
718 * to allow drag and drop.
720 if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) &&
721 tp->buttons.is_clickpad)
726 tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
730 tp_for_each_touch(tp, t) {
735 if (t->state == TOUCH_END) {
737 t->state = TOUCH_NONE;
739 t->state = TOUCH_HOVERING;
740 } else if (t->state == TOUCH_BEGIN) {
741 t->state = TOUCH_UPDATE;
747 tp->old_nfingers_down = tp->nfingers_down;
748 tp->buttons.old_state = tp->buttons.state;
750 tp->queued = TOUCHPAD_EVENT_NONE;
754 tp_get_pointer_delta(struct tp_dispatch *tp, double *dx, double *dy)
756 struct tp_touch *t = tp_current_touch(tp);
758 if (!t->is_pointer) {
759 tp_for_each_touch(tp, t) {
765 if (!t->is_pointer || !t->dirty)
768 tp_get_delta(t, dx, dy);
772 tp_get_active_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
778 for (i = 0; i < tp->real_touches; i++) {
779 t = tp_get_touch(tp, i);
781 if (!tp_touch_active(tp, t) || !t->dirty)
784 tp_get_delta(t, &tdx, &tdy);
791 tp_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
793 double dx = 0.0, dy = 0.0;
794 double dx_unaccel, dy_unaccel;
796 /* When a clickpad is clicked, combine motion of all active touches */
797 if (tp->buttons.is_clickpad && tp->buttons.state)
798 tp_get_active_touches_delta(tp, &dx, &dy);
800 tp_get_pointer_delta(tp, &dx, &dy);
802 tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time);
804 if (dx != 0.0 || dy != 0.0 || dx_unaccel != 0.0 || dy_unaccel != 0.0) {
805 pointer_notify_motion(&tp->device->base, time,
806 dx, dy, dx_unaccel, dy_unaccel);
811 tp_post_events(struct tp_dispatch *tp, uint64_t time)
813 int filter_motion = 0;
815 /* Only post (top) button events while suspended */
816 if (tp->device->suspended) {
817 tp_post_button_events(tp, time);
821 filter_motion |= tp_tap_handle_state(tp, time);
822 filter_motion |= tp_post_button_events(tp, time);
824 if (filter_motion || tp->sendevents.trackpoint_active) {
825 tp_stop_scroll_events(tp, time);
829 if (tp_post_scroll_events(tp, time) != 0)
832 tp_post_pointer_motion(tp, time);
836 tp_handle_state(struct tp_dispatch *tp,
839 tp_process_state(tp, time);
840 tp_post_events(tp, time);
841 tp_post_process_state(tp, time);
845 tp_process(struct evdev_dispatch *dispatch,
846 struct evdev_device *device,
847 struct input_event *e,
850 struct tp_dispatch *tp =
851 (struct tp_dispatch *)dispatch;
856 tp_process_absolute(tp, e, time);
858 tp_process_absolute_st(tp, e, time);
861 tp_process_key(tp, e, time);
864 tp_handle_state(tp, time);
870 tp_remove_sendevents(struct tp_dispatch *tp)
872 libinput_timer_cancel(&tp->sendevents.trackpoint_timer);
874 if (tp->buttons.trackpoint)
875 libinput_device_remove_event_listener(
876 &tp->sendevents.trackpoint_listener);
880 tp_remove(struct evdev_dispatch *dispatch)
882 struct tp_dispatch *tp =
883 (struct tp_dispatch*)dispatch;
886 tp_remove_buttons(tp);
887 tp_remove_sendevents(tp);
888 tp_remove_scroll(tp);
892 tp_destroy(struct evdev_dispatch *dispatch)
894 struct tp_dispatch *tp =
895 (struct tp_dispatch*)dispatch;
903 tp_clear_state(struct tp_dispatch *tp)
905 uint64_t now = libinput_now(tp->device->base.seat->libinput);
908 /* Unroll the touchpad state.
909 * Release buttons first. If tp is a clickpad, the button event
910 * must come before the touch up. If it isn't, the order doesn't
913 * Then cancel all timeouts on the taps, triggering the last set
916 * Then lift all touches so the touchpad is in a neutral state.
919 tp_release_all_buttons(tp, now);
920 tp_release_all_taps(tp, now);
922 tp_for_each_touch(tp, t) {
923 tp_end_sequence(tp, t, now);
926 tp_handle_state(tp, now);
930 tp_suspend(struct tp_dispatch *tp, struct evdev_device *device)
934 /* On devices with top softwarebuttons we don't actually suspend the
935 * device, to keep the "trackpoint" buttons working. tp_post_events()
936 * will only send events for the trackpoint while suspended.
938 if (tp->buttons.has_topbuttons) {
939 evdev_notify_suspended_device(device);
940 /* Enlarge topbutton area while suspended */
941 tp_init_top_softbuttons(tp, device, 1.5);
943 evdev_device_suspend(device);
948 tp_resume(struct tp_dispatch *tp, struct evdev_device *device)
950 if (tp->buttons.has_topbuttons) {
951 /* tap state-machine is offline while suspended, reset state */
953 /* restore original topbutton area size */
954 tp_init_top_softbuttons(tp, device, 1.0);
955 evdev_notify_resumed_device(device);
957 evdev_device_resume(device);
962 tp_trackpoint_timeout(uint64_t now, void *data)
964 struct tp_dispatch *tp = data;
966 tp_tap_resume(tp, now);
967 tp->sendevents.trackpoint_active = false;
971 tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
973 struct tp_dispatch *tp = data;
975 /* Buttons do not count as trackpad activity, as people may use
976 the trackpoint buttons in combination with the touchpad. */
977 if (event->type == LIBINPUT_EVENT_POINTER_BUTTON)
980 if (!tp->sendevents.trackpoint_active) {
981 evdev_stop_scroll(tp->device,
983 LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
984 tp_tap_suspend(tp, time);
985 tp->sendevents.trackpoint_active = true;
988 libinput_timer_set(&tp->sendevents.trackpoint_timer,
989 time + DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT);
993 tp_device_added(struct evdev_device *device,
994 struct evdev_device *added_device)
996 struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
998 if (tp->buttons.trackpoint == NULL &&
999 (added_device->tags & EVDEV_TAG_TRACKPOINT)) {
1000 /* Don't send any pending releases to the new trackpoint */
1001 tp->buttons.active_is_topbutton = false;
1002 tp->buttons.trackpoint = added_device;
1003 libinput_device_add_event_listener(&added_device->base,
1004 &tp->sendevents.trackpoint_listener,
1005 tp_trackpoint_event, tp);
1008 if (tp->sendevents.current_mode !=
1009 LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
1012 if (added_device->tags & EVDEV_TAG_EXTERNAL_MOUSE)
1013 tp_suspend(tp, device);
1017 tp_device_removed(struct evdev_device *device,
1018 struct evdev_device *removed_device)
1020 struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
1021 struct libinput_device *dev;
1023 if (removed_device == tp->buttons.trackpoint) {
1024 /* Clear any pending releases for the trackpoint */
1025 if (tp->buttons.active && tp->buttons.active_is_topbutton) {
1026 tp->buttons.active = 0;
1027 tp->buttons.active_is_topbutton = false;
1029 libinput_device_remove_event_listener(
1030 &tp->sendevents.trackpoint_listener);
1031 tp->buttons.trackpoint = NULL;
1034 if (tp->sendevents.current_mode !=
1035 LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
1038 list_for_each(dev, &device->base.seat->devices_list, link) {
1039 struct evdev_device *d = (struct evdev_device*)dev;
1040 if (d != removed_device &&
1041 (d->tags & EVDEV_TAG_EXTERNAL_MOUSE)) {
1046 tp_resume(tp, device);
1050 tp_tag_device(struct evdev_device *device,
1051 struct udev_device *udev_device)
1055 /* simple approach: touchpads on USB or Bluetooth are considered
1056 * external, anything else is internal. Exception is Apple -
1057 * internal touchpads are connected over USB and it doesn't have
1058 * external USB touchpads anyway.
1060 bustype = libevdev_get_id_bustype(device->evdev);
1061 if (bustype == BUS_USB) {
1062 if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_APPLE)
1063 device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
1064 } else if (bustype != BUS_BLUETOOTH)
1065 device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
1068 static struct evdev_dispatch_interface tp_interface = {
1074 tp_device_removed, /* device_suspended, treat as remove */
1075 tp_device_added, /* device_resumed, treat as add */
1080 tp_init_touch(struct tp_dispatch *tp,
1084 t->has_ended = true;
1088 tp_init_slots(struct tp_dispatch *tp,
1089 struct evdev_device *device)
1091 const struct input_absinfo *absinfo;
1096 { BTN_TOOL_QUINTTAP, 5 },
1097 { BTN_TOOL_QUADTAP, 4 },
1098 { BTN_TOOL_TRIPLETAP, 3 },
1099 { BTN_TOOL_DOUBLETAP, 2 },
1102 unsigned int i, n_btn_tool_touches = 1;
1104 absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
1106 tp->real_touches = absinfo->maximum + 1;
1107 tp->slot = absinfo->value;
1110 tp->real_touches = 1;
1115 tp->semi_mt = libevdev_has_property(device->evdev, INPUT_PROP_SEMI_MT);
1117 ARRAY_FOR_EACH(max_touches, m) {
1118 if (libevdev_has_event_code(device->evdev,
1121 n_btn_tool_touches = m->ntouches;
1126 tp->ntouches = max(tp->real_touches, n_btn_tool_touches);
1127 tp->touches = calloc(tp->ntouches, sizeof(struct tp_touch));
1131 for (i = 0; i < tp->ntouches; i++)
1132 tp_init_touch(tp, &tp->touches[i]);
1138 tp_init_accel(struct tp_dispatch *tp, double diagonal)
1143 res_x = libevdev_get_abs_resolution(tp->device->evdev,
1145 res_y = libevdev_get_abs_resolution(tp->device->evdev,
1148 res_x = libevdev_get_abs_resolution(tp->device->evdev,
1150 res_y = libevdev_get_abs_resolution(tp->device->evdev,
1155 * Not all touchpads report the same amount of units/mm (resolution).
1156 * Normalize motion events to the default mouse DPI as base
1157 * (unaccelerated) speed. This also evens out any differences in x
1158 * and y resolution, so that a circle on the
1159 * touchpad does not turn into an elipse on the screen.
1161 if (res_x > 1 && res_y > 1) {
1162 tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x;
1163 tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y;
1165 /* FIXME: once normalized, touchpads see the same
1166 acceleration as mice. that is technically correct but
1167 subjectively wrong, we expect a touchpad to be a lot
1168 slower than a mouse.
1169 For now, apply a magic factor here until this is
1170 fixed in the actual filter code.
1173 const double MAGIC = 0.4;
1174 tp->accel.x_scale_coeff *= MAGIC;
1175 tp->accel.y_scale_coeff *= MAGIC;
1179 * For touchpads where the driver does not provide resolution, fall
1180 * back to scaling motion events based on the diagonal size in units.
1182 tp->accel.x_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
1183 tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
1186 if (evdev_device_init_pointer_acceleration(tp->device) == -1)
1193 tp_scroll_config_scroll_method_get_methods(struct libinput_device *device)
1195 struct evdev_device *evdev = (struct evdev_device*)device;
1196 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
1197 uint32_t methods = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
1199 if (tp->ntouches >= 2)
1200 methods |= LIBINPUT_CONFIG_SCROLL_2FG;
1202 if (!tp->buttons.is_clickpad)
1203 methods |= LIBINPUT_CONFIG_SCROLL_EDGE;
1208 static enum libinput_config_status
1209 tp_scroll_config_scroll_method_set_method(struct libinput_device *device,
1210 enum libinput_config_scroll_method method)
1212 struct evdev_device *evdev = (struct evdev_device*)device;
1213 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
1215 if (method == tp->scroll.method)
1216 return LIBINPUT_CONFIG_STATUS_SUCCESS;
1218 tp_stop_scroll_events(tp, libinput_now(device->seat->libinput));
1219 tp->scroll.method = method;
1221 return LIBINPUT_CONFIG_STATUS_SUCCESS;
1224 static enum libinput_config_scroll_method
1225 tp_scroll_config_scroll_method_get_method(struct libinput_device *device)
1227 struct evdev_device *evdev = (struct evdev_device*)device;
1228 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
1230 return tp->scroll.method;
1233 static enum libinput_config_scroll_method
1234 tp_scroll_get_default_method(struct tp_dispatch *tp)
1236 if (tp->ntouches >= 2)
1237 return LIBINPUT_CONFIG_SCROLL_2FG;
1239 return LIBINPUT_CONFIG_SCROLL_EDGE;
1242 static enum libinput_config_scroll_method
1243 tp_scroll_config_scroll_method_get_default_method(struct libinput_device *device)
1245 struct evdev_device *evdev = (struct evdev_device*)device;
1246 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
1248 return tp_scroll_get_default_method(tp);
1252 tp_init_scroll(struct tp_dispatch *tp, struct evdev_device *device)
1254 if (tp_edge_scroll_init(tp, device) != 0)
1257 evdev_init_natural_scroll(device);
1259 tp->scroll.config_method.get_methods = tp_scroll_config_scroll_method_get_methods;
1260 tp->scroll.config_method.set_method = tp_scroll_config_scroll_method_set_method;
1261 tp->scroll.config_method.get_method = tp_scroll_config_scroll_method_get_method;
1262 tp->scroll.config_method.get_default_method = tp_scroll_config_scroll_method_get_default_method;
1263 tp->scroll.method = tp_scroll_get_default_method(tp);
1264 tp->device->base.config.scroll_method = &tp->scroll.config_method;
1266 /* In mm for touchpads with valid resolution, see tp_init_accel() */
1267 tp->device->scroll.threshold = 5.0;
1273 tp_init_palmdetect(struct tp_dispatch *tp,
1274 struct evdev_device *device)
1278 tp->palm.right_edge = INT_MAX;
1279 tp->palm.left_edge = INT_MIN;
1281 width = abs(device->abs.absinfo_x->maximum -
1282 device->abs.absinfo_x->minimum);
1284 /* Apple touchpads are always big enough to warrant palm detection */
1285 if (evdev_device_get_id_vendor(device) != VENDOR_ID_APPLE) {
1286 /* We don't know how big the touchpad is */
1287 if (device->abs.absinfo_x->resolution == 1)
1290 /* Enable palm detection on touchpads >= 80 mm. Anything smaller
1291 probably won't need it, until we find out it does */
1292 if (width/device->abs.absinfo_x->resolution < 80)
1296 /* palm edges are 5% of the width on each side */
1297 tp->palm.right_edge = device->abs.absinfo_x->maximum - width * 0.05;
1298 tp->palm.left_edge = device->abs.absinfo_x->minimum + width * 0.05;
1304 tp_init_sendevents(struct tp_dispatch *tp,
1305 struct evdev_device *device)
1307 libinput_timer_init(&tp->sendevents.trackpoint_timer,
1308 tp->device->base.seat->libinput,
1309 tp_trackpoint_timeout, tp);
1314 tp_init(struct tp_dispatch *tp,
1315 struct evdev_device *device)
1320 tp->base.interface = &tp_interface;
1321 tp->device = device;
1323 if (tp_init_slots(tp, device) != 0)
1326 width = abs(device->abs.absinfo_x->maximum -
1327 device->abs.absinfo_x->minimum);
1328 height = abs(device->abs.absinfo_y->maximum -
1329 device->abs.absinfo_y->minimum);
1330 diagonal = sqrt(width*width + height*height);
1332 tp->hysteresis.margin_x =
1333 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
1334 tp->hysteresis.margin_y =
1335 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
1337 if (tp_init_accel(tp, diagonal) != 0)
1340 if (tp_init_tap(tp) != 0)
1343 if (tp_init_buttons(tp, device) != 0)
1346 if (tp_init_palmdetect(tp, device) != 0)
1349 if (tp_init_sendevents(tp, device) != 0)
1352 if (tp_init_scroll(tp, device) != 0)
1355 device->seat_caps |= EVDEV_DEVICE_POINTER;
1361 tp_sendevents_get_modes(struct libinput_device *device)
1363 struct evdev_device *evdev = (struct evdev_device*)device;
1364 uint32_t modes = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
1366 if (evdev->tags & EVDEV_TAG_INTERNAL_TOUCHPAD)
1367 modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
1373 tp_suspend_conditional(struct tp_dispatch *tp,
1374 struct evdev_device *device)
1376 struct libinput_device *dev;
1378 list_for_each(dev, &device->base.seat->devices_list, link) {
1379 struct evdev_device *d = (struct evdev_device*)dev;
1380 if (d->tags & EVDEV_TAG_EXTERNAL_MOUSE) {
1381 tp_suspend(tp, device);
1387 static enum libinput_config_status
1388 tp_sendevents_set_mode(struct libinput_device *device,
1389 enum libinput_config_send_events_mode mode)
1391 struct evdev_device *evdev = (struct evdev_device*)device;
1392 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
1394 /* DISABLED overrides any DISABLED_ON_ */
1395 if ((mode & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED) &&
1396 (mode & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE))
1397 mode &= ~LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
1399 if (mode == tp->sendevents.current_mode)
1400 return LIBINPUT_CONFIG_STATUS_SUCCESS;
1403 case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED:
1404 tp_resume(tp, evdev);
1406 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
1407 tp_suspend(tp, evdev);
1409 case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
1410 tp_suspend_conditional(tp, evdev);
1413 return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
1416 tp->sendevents.current_mode = mode;
1418 return LIBINPUT_CONFIG_STATUS_SUCCESS;
1421 static enum libinput_config_send_events_mode
1422 tp_sendevents_get_mode(struct libinput_device *device)
1424 struct evdev_device *evdev = (struct evdev_device*)device;
1425 struct tp_dispatch *dispatch = (struct tp_dispatch*)evdev->dispatch;
1427 return dispatch->sendevents.current_mode;
1430 static enum libinput_config_send_events_mode
1431 tp_sendevents_get_default_mode(struct libinput_device *device)
1433 return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
1437 tp_change_to_left_handed(struct evdev_device *device)
1439 struct tp_dispatch *tp = (struct tp_dispatch *)device->dispatch;
1441 if (device->left_handed.want_enabled == device->left_handed.enabled)
1444 if (tp->buttons.state & 0x3) /* BTN_LEFT|BTN_RIGHT */
1447 /* tapping and clickfinger aren't affected by left-handed config,
1448 * so checking physical buttons is enough */
1450 device->left_handed.enabled = device->left_handed.want_enabled;
1453 struct model_lookup_t {
1455 uint16_t product_start;
1456 uint16_t product_end;
1457 enum touchpad_model model;
1460 static struct model_lookup_t model_lookup_table[] = {
1461 { 0x0002, 0x0007, 0x0007, MODEL_SYNAPTICS },
1462 { 0x0002, 0x0008, 0x0008, MODEL_ALPS },
1463 { 0x0002, 0x000e, 0x000e, MODEL_ELANTECH },
1464 { 0x05ac, 0, 0x0222, MODEL_APPLETOUCH },
1465 { 0x05ac, 0x0223, 0x0228, MODEL_UNIBODY_MACBOOK },
1466 { 0x05ac, 0x0229, 0x022b, MODEL_APPLETOUCH },
1467 { 0x05ac, 0x022c, 0xffff, MODEL_UNIBODY_MACBOOK },
1471 static enum touchpad_model
1472 tp_get_model(struct evdev_device *device)
1474 struct model_lookup_t *lookup;
1475 uint16_t vendor = libevdev_get_id_vendor(device->evdev);
1476 uint16_t product = libevdev_get_id_product(device->evdev);
1478 for (lookup = model_lookup_table; lookup->vendor; lookup++) {
1479 if (lookup->vendor == vendor &&
1480 lookup->product_start <= product &&
1481 product <= lookup->product_end)
1482 return lookup->model;
1484 return MODEL_UNKNOWN;
1487 struct evdev_dispatch *
1488 evdev_mt_touchpad_create(struct evdev_device *device)
1490 struct tp_dispatch *tp;
1492 tp = zalloc(sizeof *tp);
1496 tp->model = tp_get_model(device);
1498 if (tp_init(tp, device) != 0) {
1499 tp_destroy(&tp->base);
1503 device->base.config.sendevents = &tp->sendevents.config;
1505 tp->sendevents.current_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
1506 tp->sendevents.config.get_modes = tp_sendevents_get_modes;
1507 tp->sendevents.config.set_mode = tp_sendevents_set_mode;
1508 tp->sendevents.config.get_mode = tp_sendevents_get_mode;
1509 tp->sendevents.config.get_default_mode = tp_sendevents_get_default_mode;
1511 evdev_init_left_handed(device, tp_change_to_left_handed);