Lines Matching +full:libinput +full:- +full:test +full:- +full:suite +full:- +full:touch
2 * Copyright © 2014-2015 Red Hat, Inc.
36 #include "evdev-mt-touchpad.h"
37 #include "util-input-event.h"
55 (t->history.index - offset + TOUCHPAD_HISTORY_LENGTH) % in tp_motion_history_offset()
58 return &t->history.samples[offset_index]; in tp_motion_history_offset()
75 return filter_dispatch(tp->device->pointer.filter, in tp_filter_motion()
93 return filter_dispatch_constant(tp->device->pointer.filter, in tp_filter_motion_unaccelerated()
111 return filter_dispatch_scroll(tp->device->pointer.filter, in tp_filter_scroll()
126 /* Don't do this on single-touch or semi-mt devices */ in tp_calculate_motion_speed()
127 if (!tp->has_mt || tp->semi_mt) in tp_calculate_motion_speed()
130 if (t->state != TOUCH_UPDATE) in tp_calculate_motion_speed()
134 * motion history. As a side-effect, this automatically handles the in tp_calculate_motion_speed()
142 if (t->history.count < 4) in tp_calculate_motion_speed()
148 delta.x = abs(t->point.x - last->point.x); in tp_calculate_motion_speed()
149 delta.y = abs(t->point.y - last->point.y); in tp_calculate_motion_speed()
150 mm = evdev_device_unit_delta_to_mm(tp->device, &delta); in tp_calculate_motion_speed()
153 speed = distance/(time - last->time); /* mm/us */ in tp_calculate_motion_speed()
156 t->speed.last_speed = speed; in tp_calculate_motion_speed()
162 int motion_index = (t->history.index + 1) % TOUCHPAD_HISTORY_LENGTH; in tp_motion_history_push()
164 if (t->history.count < TOUCHPAD_HISTORY_LENGTH) in tp_motion_history_push()
165 t->history.count++; in tp_motion_history_push()
167 t->history.samples[motion_index].point = t->point; in tp_motion_history_push()
168 t->history.samples[motion_index].time = time; in tp_motion_history_push()
169 t->history.index = motion_index; in tp_motion_history_push()
192 if (tp->nfingers_down != 1 || in tp_detect_wobbling()
193 tp->nfingers_down != tp->old_nfingers_down) in tp_detect_wobbling()
196 if (tp->hysteresis.enabled || t->history.count == 0) in tp_detect_wobbling()
199 if (!(tp->queued & TOUCHPAD_EVENT_MOTION)) { in tp_detect_wobbling()
200 t->hysteresis.x_motion_history = 0; in tp_detect_wobbling()
204 prev_point = &tp_motion_history_offset(t, 0)->point; in tp_detect_wobbling()
205 dx = prev_point->x - t->point.x; in tp_detect_wobbling()
206 dy = prev_point->y - t->point.y; in tp_detect_wobbling()
207 dtime = time - tp->hysteresis.last_motion_time; in tp_detect_wobbling()
209 tp->hysteresis.last_motion_time = time; in tp_detect_wobbling()
212 t->hysteresis.x_motion_history = 0; in tp_detect_wobbling()
216 t->hysteresis.x_motion_history >>= 1; in tp_detect_wobbling()
220 t->hysteresis.x_motion_history |= bit(2); in tp_detect_wobbling()
221 if (t->hysteresis.x_motion_history == r_l_r) { in tp_detect_wobbling()
222 tp->hysteresis.enabled = true; in tp_detect_wobbling()
223 evdev_log_debug(tp->device, in tp_detect_wobbling()
225 "See %s/touchpad-jitter.html for details\n", in tp_detect_wobbling()
235 if (!tp->hysteresis.enabled) in tp_motion_hysteresis()
238 if (t->history.count > 0) in tp_motion_hysteresis()
239 t->point = evdev_hysteresis(&t->point, in tp_motion_hysteresis()
240 &t->hysteresis.center, in tp_motion_hysteresis()
241 &tp->hysteresis.margin); in tp_motion_hysteresis()
243 t->hysteresis.center = t->point; in tp_motion_hysteresis()
249 t->history.count = 0; in tp_motion_history_reset()
255 return &tp->touches[min(tp->slot, tp->ntouches - 1)]; in tp_current_touch()
261 assert(slot < tp->ntouches); in tp_get_touch()
262 return &tp->touches[slot]; in tp_get_touch()
269 tp->fake_touches & ~(FAKE_FINGER_OVERFLOW|0x1); in tp_fake_finger_count()
273 if (fake_touches & (fake_touches - 1)) in tp_fake_finger_count()
274 evdev_log_bug_kernel(tp->device, in tp_fake_finger_count()
276 tp->fake_touches); in tp_fake_finger_count()
278 if (tp->fake_touches & FAKE_FINGER_OVERFLOW) in tp_fake_finger_count()
282 return ffs(tp->fake_touches >> 1); in tp_fake_finger_count()
288 return tp->fake_touches & 0x1; in tp_fake_finger_is_touching()
301 tp->fake_touches &= ~FAKE_FINGER_OVERFLOW; in tp_fake_finger_set()
310 shift = code - BTN_TOOL_DOUBLETAP + 2; in tp_fake_finger_set()
317 tp->fake_touches |= FAKE_FINGER_OVERFLOW; in tp_fake_finger_set()
324 tp->fake_touches &= ~FAKE_FINGER_OVERFLOW; in tp_fake_finger_set()
325 tp->fake_touches |= bit(shift); in tp_fake_finger_set()
328 tp->fake_touches &= ~bit(shift); in tp_fake_finger_set()
335 if (t->state == TOUCH_BEGIN || in tp_new_touch()
336 t->state == TOUCH_UPDATE || in tp_new_touch()
337 t->state == TOUCH_HOVERING) in tp_new_touch()
340 /* Bug #161: touch ends in the same event frame where it restarts in tp_new_touch()
342 if (t->state == TOUCH_MAYBE_END) { in tp_new_touch()
343 evdev_log_bug_kernel(tp->device, in tp_new_touch()
344 "touch %d ended and began in in same frame.\n", in tp_new_touch()
345 t->index); in tp_new_touch()
346 tp->nfingers_down++; in tp_new_touch()
347 t->state = TOUCH_UPDATE; in tp_new_touch()
348 t->has_ended = false; in tp_new_touch()
352 /* we begin the touch as hovering because until BTN_TOUCH happens we in tp_new_touch()
353 * don't know if it's a touch down or not. And BTN_TOUCH may happen in tp_new_touch()
356 t->dirty = true; in tp_new_touch()
357 t->has_ended = false; in tp_new_touch()
358 t->was_down = false; in tp_new_touch()
359 t->palm.state = PALM_NONE; in tp_new_touch()
360 t->state = TOUCH_HOVERING; in tp_new_touch()
361 t->pinned.is_pinned = false; in tp_new_touch()
362 t->speed.last_speed = 0; in tp_new_touch()
363 t->speed.exceeded_count = 0; in tp_new_touch()
364 t->hysteresis.x_motion_history = 0; in tp_new_touch()
365 tp->queued |= TOUCHPAD_EVENT_MOTION; in tp_new_touch()
371 t->dirty = true; in tp_begin_touch()
372 t->state = TOUCH_BEGIN; in tp_begin_touch()
373 t->initial_time = time; in tp_begin_touch()
374 t->was_down = true; in tp_begin_touch()
375 tp->nfingers_down++; in tp_begin_touch()
376 t->palm.time = time; in tp_begin_touch()
377 t->tap.is_thumb = false; in tp_begin_touch()
378 t->tap.is_palm = false; in tp_begin_touch()
379 t->speed.exceeded_count = 0; in tp_begin_touch()
380 assert(tp->nfingers_down >= 1); in tp_begin_touch()
381 tp->hysteresis.last_motion_time = time; in tp_begin_touch()
385 * Schedule a touch to be ended, based on either the events or some
386 * attributes of the touch (size, pressure). In some cases we need to
387 * resurrect a touch that has ended, so this doesn't actually end the touch
397 switch (t->state) { in tp_maybe_end_touch()
402 evdev_log_bug_libinput(tp->device, in tp_maybe_end_touch()
403 "touch %d: already in TOUCH_END\n", in tp_maybe_end_touch()
404 t->index); in tp_maybe_end_touch()
412 if (t->state != TOUCH_HOVERING) { in tp_maybe_end_touch()
413 assert(tp->nfingers_down >= 1); in tp_maybe_end_touch()
414 tp->nfingers_down--; in tp_maybe_end_touch()
415 t->state = TOUCH_MAYBE_END; in tp_maybe_end_touch()
417 t->state = TOUCH_NONE; in tp_maybe_end_touch()
420 t->dirty = true; in tp_maybe_end_touch()
424 * Inverse to tp_maybe_end_touch(), restores a touch back to its previous
431 t->dirty = true; in tp_recover_ended_touch()
432 t->state = TOUCH_UPDATE; in tp_recover_ended_touch()
433 tp->nfingers_down++; in tp_recover_ended_touch()
437 * End a touch, even if the touch sequence is still active.
443 if (t->state != TOUCH_MAYBE_END) { in tp_end_touch()
444 evdev_log_bug_libinput(tp->device, in tp_end_touch()
445 "touch %d should be MAYBE_END, is %d\n", in tp_end_touch()
446 t->index, in tp_end_touch()
447 t->state); in tp_end_touch()
451 t->dirty = true; in tp_end_touch()
452 t->palm.state = PALM_NONE; in tp_end_touch()
453 t->state = TOUCH_END; in tp_end_touch()
454 t->pinned.is_pinned = false; in tp_end_touch()
455 t->palm.time = 0; in tp_end_touch()
456 t->speed.exceeded_count = 0; in tp_end_touch()
457 tp->queued |= TOUCHPAD_EVENT_MOTION; in tp_end_touch()
461 * End the touch sequence on ABS_MT_TRACKING_ID -1 or when the BTN_TOOL_* 0 is received.
466 t->has_ended = true; in tp_end_sequence()
484 if (t->history.count <= 1) in tp_get_delta()
487 delta.x = tp_motion_history_offset(t, 0)->point.x - in tp_get_delta()
488 tp_motion_history_offset(t, 1)->point.x; in tp_get_delta()
489 delta.y = tp_motion_history_offset(t, 0)->point.y - in tp_get_delta()
490 tp_motion_history_offset(t, 1)->point.y; in tp_get_delta()
500 if (!tp->left_handed.rotate) in rotated()
506 absinfo = tp->device->abs.absinfo_x; in rotated()
510 absinfo = tp->device->abs.absinfo_y; in rotated()
515 return absinfo->maximum - (value - absinfo->minimum); in rotated()
525 switch(e->code) { in tp_process_absolute()
527 evdev_device_check_abs_axis_range(tp->device, in tp_process_absolute()
528 e->code, in tp_process_absolute()
529 e->value); in tp_process_absolute()
530 t->point.x = rotated(tp, e->code, e->value); in tp_process_absolute()
531 t->dirty = true; in tp_process_absolute()
532 tp->queued |= TOUCHPAD_EVENT_MOTION; in tp_process_absolute()
535 evdev_device_check_abs_axis_range(tp->device, in tp_process_absolute()
536 e->code, in tp_process_absolute()
537 e->value); in tp_process_absolute()
538 t->point.y = rotated(tp, e->code, e->value); in tp_process_absolute()
539 t->dirty = true; in tp_process_absolute()
540 tp->queued |= TOUCHPAD_EVENT_MOTION; in tp_process_absolute()
543 tp->slot = e->value; in tp_process_absolute()
546 if (e->value != -1) { in tp_process_absolute()
547 tp->nactive_slots += 1; in tp_process_absolute()
550 assert(tp->nactive_slots >= 1); in tp_process_absolute()
551 tp->nactive_slots -= 1; in tp_process_absolute()
556 t->pressure = e->value; in tp_process_absolute()
557 t->dirty = true; in tp_process_absolute()
558 tp->queued |= TOUCHPAD_EVENT_OTHERAXIS; in tp_process_absolute()
561 t->is_tool_palm = e->value == MT_TOOL_PALM; in tp_process_absolute()
562 t->dirty = true; in tp_process_absolute()
563 tp->queued |= TOUCHPAD_EVENT_OTHERAXIS; in tp_process_absolute()
566 t->major = e->value; in tp_process_absolute()
567 t->dirty = true; in tp_process_absolute()
568 tp->queued |= TOUCHPAD_EVENT_OTHERAXIS; in tp_process_absolute()
571 t->minor = e->value; in tp_process_absolute()
572 t->dirty = true; in tp_process_absolute()
573 tp->queued |= TOUCHPAD_EVENT_OTHERAXIS; in tp_process_absolute()
585 switch(e->code) { in tp_process_absolute_st()
587 evdev_device_check_abs_axis_range(tp->device, in tp_process_absolute_st()
588 e->code, in tp_process_absolute_st()
589 e->value); in tp_process_absolute_st()
590 t->point.x = rotated(tp, e->code, e->value); in tp_process_absolute_st()
591 t->dirty = true; in tp_process_absolute_st()
592 tp->queued |= TOUCHPAD_EVENT_MOTION; in tp_process_absolute_st()
595 evdev_device_check_abs_axis_range(tp->device, in tp_process_absolute_st()
596 e->code, in tp_process_absolute_st()
597 e->value); in tp_process_absolute_st()
598 t->point.y = rotated(tp, e->code, e->value); in tp_process_absolute_st()
599 t->dirty = true; in tp_process_absolute_st()
600 tp->queued |= TOUCHPAD_EVENT_MOTION; in tp_process_absolute_st()
603 t->pressure = e->value; in tp_process_absolute_st()
604 t->dirty = true; in tp_process_absolute_st()
605 tp->queued |= TOUCHPAD_EVENT_OTHERAXIS; in tp_process_absolute_st()
621 if (tp->nfingers_down >= nfake_touches || in tp_restore_synaptics_touches()
622 (tp->nfingers_down == tp->num_slots && nfake_touches == tp->num_slots)) in tp_restore_synaptics_touches()
625 /* Synaptics devices may end touch 2 on transition to/from in tp_restore_synaptics_touches()
634 for (i = 0; i < tp->num_slots; i++) { in tp_restore_synaptics_touches()
637 if (t->state != TOUCH_MAYBE_END) in tp_restore_synaptics_touches()
640 /* new touch, move it through begin to update immediately */ in tp_restore_synaptics_touches()
657 if (tp->device->model_flags & in tp_process_fake_touches()
664 * This also means that the third touch falls through the cracks and in tp_process_fake_touches()
667 * See https://gitlab.freedesktop.org/libinput/libinput/issues/408 in tp_process_fake_touches()
683 if (tp->device->model_flags & EVDEV_MODEL_ALPS_SERIAL_TOUCHPAD && in tp_process_fake_touches()
684 nfake_touches > 1 && tp->has_mt && in tp_process_fake_touches()
685 tp->nactive_slots > 0 && in tp_process_fake_touches()
686 nfake_touches > tp->nactive_slots && in tp_process_fake_touches()
687 tp->nactive_slots < tp->num_slots) { in tp_process_fake_touches()
688 evdev_log_bug_kernel(tp->device, in tp_process_fake_touches()
690 tp->num_slots, in tp_process_fake_touches()
691 tp->nactive_slots); in tp_process_fake_touches()
695 * actual touch point but that requires specially crafted in tp_process_fake_touches()
698 tp->num_slots = tp->nactive_slots; in tp_process_fake_touches()
701 start = tp->has_mt ? tp->num_slots : 0; in tp_process_fake_touches()
702 for (i = start; i < tp->ntouches; i++) { in tp_process_fake_touches()
726 if (!tp->buttons.trackpoint) in tp_process_trackpoint_button()
729 dispatch = tp->buttons.trackpoint->dispatch; in tp_process_trackpoint_button()
732 syn_report.input_event_sec = e->input_event_sec; in tp_process_trackpoint_button()
733 syn_report.input_event_usec = e->input_event_usec; in tp_process_trackpoint_button()
749 dispatch->interface->process(dispatch, in tp_process_trackpoint_button()
750 tp->buttons.trackpoint, in tp_process_trackpoint_button()
752 dispatch->interface->process(dispatch, in tp_process_trackpoint_button()
753 tp->buttons.trackpoint, in tp_process_trackpoint_button()
763 if (e->value == 2) in tp_process_key()
766 switch (e->code) { in tp_process_key()
778 tp_fake_finger_set(tp, e->code, !!e->value); in tp_process_key()
793 if (e->code != MSC_TIMESTAMP) in tp_process_msc()
796 tp->quirks.msc_timestamp.now = e->value; in tp_process_msc()
797 tp->queued |= TOUCHPAD_EVENT_TIMESTAMP; in tp_process_msc()
806 if (!t->pinned.is_pinned) in tp_unpin_finger()
809 delta.x = abs(t->point.x - t->pinned.center.x); in tp_unpin_finger()
810 delta.y = abs(t->point.y - t->pinned.center.y); in tp_unpin_finger()
812 mm = evdev_device_unit_delta_to_mm(tp->device, &delta); in tp_unpin_finger()
814 /* 1.5mm movement -> unpin */ in tp_unpin_finger()
816 t->pinned.is_pinned = false; in tp_unpin_finger()
827 t->pinned.is_pinned = true; in tp_pin_fingers()
828 t->pinned.center = t->point; in tp_pin_fingers()
835 return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) && in tp_touch_active()
836 t->palm.state == PALM_NONE && in tp_touch_active()
837 !t->pinned.is_pinned && in tp_touch_active()
846 return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) && in tp_touch_active_for_gesture()
847 t->palm.state == PALM_NONE && in tp_touch_active_for_gesture()
848 !t->pinned.is_pinned && in tp_touch_active_for_gesture()
857 return t->palm.first.x < tp->palm.left_edge || in tp_palm_was_in_side_edge()
858 t->palm.first.x > tp->palm.right_edge; in tp_palm_was_in_side_edge()
864 return t->palm.first.y < tp->palm.upper_edge; in tp_palm_was_in_top_edge()
870 return t->point.x < tp->palm.left_edge || in tp_palm_in_side_edge()
871 t->point.x > tp->palm.right_edge; in tp_palm_in_side_edge()
877 return t->point.y < tp->palm.upper_edge; in tp_palm_in_top_edge()
891 if (tp->dwt.dwt_enabled && in tp_palm_detect_dwt_triggered()
892 tp->dwt.keyboard_active && in tp_palm_detect_dwt_triggered()
893 t->state == TOUCH_BEGIN) { in tp_palm_detect_dwt_triggered()
894 t->palm.state = PALM_TYPING; in tp_palm_detect_dwt_triggered()
895 t->palm.first = t->point; in tp_palm_detect_dwt_triggered()
899 if (!tp->dwt.keyboard_active && in tp_palm_detect_dwt_triggered()
900 t->state == TOUCH_UPDATE && in tp_palm_detect_dwt_triggered()
901 t->palm.state == PALM_TYPING) { in tp_palm_detect_dwt_triggered()
902 /* If a touch has started before the first or after the last in tp_palm_detect_dwt_triggered()
904 while typing on the touchpad will be ignored, but a touch in tp_palm_detect_dwt_triggered()
908 if (t->palm.time == 0 || in tp_palm_detect_dwt_triggered()
909 t->palm.time > tp->dwt.keyboard_last_press_time) { in tp_palm_detect_dwt_triggered()
910 t->palm.state = PALM_NONE; in tp_palm_detect_dwt_triggered()
911 evdev_log_debug(tp->device, in tp_palm_detect_dwt_triggered()
912 "palm: touch %d released, timeout after typing\n", in tp_palm_detect_dwt_triggered()
913 t->index); in tp_palm_detect_dwt_triggered()
925 if (!tp->palm.monitor_trackpoint) in tp_palm_detect_trackpoint_triggered()
928 if (t->palm.state == PALM_NONE && in tp_palm_detect_trackpoint_triggered()
929 t->state == TOUCH_BEGIN && in tp_palm_detect_trackpoint_triggered()
930 tp->palm.trackpoint_active) { in tp_palm_detect_trackpoint_triggered()
931 t->palm.state = PALM_TRACKPOINT; in tp_palm_detect_trackpoint_triggered()
935 if (t->palm.state == PALM_TRACKPOINT && in tp_palm_detect_trackpoint_triggered()
936 t->state == TOUCH_UPDATE && in tp_palm_detect_trackpoint_triggered()
937 !tp->palm.trackpoint_active) { in tp_palm_detect_trackpoint_triggered()
939 if (t->palm.time == 0 || in tp_palm_detect_trackpoint_triggered()
940 t->palm.time > tp->palm.trackpoint_last_event_time) { in tp_palm_detect_trackpoint_triggered()
941 t->palm.state = PALM_NONE; in tp_palm_detect_trackpoint_triggered()
942 evdev_log_debug(tp->device, in tp_palm_detect_trackpoint_triggered()
943 "palm: touch %d released, timeout after trackpoint\n", t->index); in tp_palm_detect_trackpoint_triggered()
955 if (!tp->palm.use_mt_tool) in tp_palm_detect_tool_triggered()
958 if (t->palm.state != PALM_NONE && in tp_palm_detect_tool_triggered()
959 t->palm.state != PALM_TOOL_PALM) in tp_palm_detect_tool_triggered()
962 if (t->palm.state == PALM_NONE && in tp_palm_detect_tool_triggered()
963 t->is_tool_palm) in tp_palm_detect_tool_triggered()
964 t->palm.state = PALM_TOOL_PALM; in tp_palm_detect_tool_triggered()
965 else if (t->palm.state == PALM_TOOL_PALM && in tp_palm_detect_tool_triggered()
966 !t->is_tool_palm) in tp_palm_detect_tool_triggered()
967 t->palm.state = PALM_NONE; in tp_palm_detect_tool_triggered()
969 return t->palm.state == PALM_TOOL_PALM; in tp_palm_detect_tool_triggered()
982 if (time < t->palm.time + PALM_TIMEOUT && !tp_palm_in_edge(tp, t)) { in tp_palm_detect_move_out_of_edge()
989 delta = device_delta(t->point, t->palm.first); in tp_palm_detect_move_out_of_edge()
1004 if (tp->nfingers_down < 2) in tp_palm_detect_multifinger()
1007 /* If we have at least one other active non-palm touch make this in tp_palm_detect_multifinger()
1008 * touch non-palm too. This avoids palm detection during two-finger in tp_palm_detect_multifinger()
1012 * frame the second touch will still be PALM_NONE and thus detected in tp_palm_detect_multifinger()
1013 * here as non-palm touch. This is too niche to worry about for now. in tp_palm_detect_multifinger()
1020 other->palm.state == PALM_NONE) { in tp_palm_detect_multifinger()
1033 if (!tp->palm.use_size) in tp_palm_detect_touch_size_triggered()
1038 if (t->palm.state != PALM_NONE && t->palm.state != PALM_TOUCH_SIZE) in tp_palm_detect_touch_size_triggered()
1041 if (t->major > tp->palm.size_threshold || in tp_palm_detect_touch_size_triggered()
1042 t->minor > tp->palm.size_threshold) { in tp_palm_detect_touch_size_triggered()
1043 if (t->palm.state != PALM_TOUCH_SIZE) in tp_palm_detect_touch_size_triggered()
1044 evdev_log_debug(tp->device, in tp_palm_detect_touch_size_triggered()
1045 "palm: touch %d size exceeded\n", in tp_palm_detect_touch_size_triggered()
1046 t->index); in tp_palm_detect_touch_size_triggered()
1047 t->palm.state = PALM_TOUCH_SIZE; in tp_palm_detect_touch_size_triggered()
1059 if (t->palm.state == PALM_EDGE) { in tp_palm_detect_edge()
1061 t->palm.state = PALM_NONE; in tp_palm_detect_edge()
1062 evdev_log_debug(tp->device, in tp_palm_detect_edge()
1063 "palm: touch %d released, multiple fingers\n", in tp_palm_detect_edge()
1064 t->index); in tp_palm_detect_edge()
1066 /* If labelled a touch as palm, we unlabel as palm when in tp_palm_detect_edge()
1071 t->palm.state = PALM_NONE; in tp_palm_detect_edge()
1072 evdev_log_debug(tp->device, in tp_palm_detect_edge()
1073 "palm: touch %d released, out of edge zone\n", in tp_palm_detect_edge()
1074 t->index); in tp_palm_detect_edge()
1085 if (t->state != TOUCH_BEGIN || !tp_palm_in_edge(tp, t)) in tp_palm_detect_edge()
1091 t->palm.state = PALM_EDGE; in tp_palm_detect_edge()
1092 t->palm.time = time; in tp_palm_detect_edge()
1093 t->palm.first = t->point; in tp_palm_detect_edge()
1103 if (!tp->palm.use_pressure) in tp_palm_detect_pressure_triggered()
1106 if (t->palm.state != PALM_NONE && in tp_palm_detect_pressure_triggered()
1107 t->palm.state != PALM_PRESSURE) in tp_palm_detect_pressure_triggered()
1110 if (t->pressure > tp->palm.pressure_threshold) in tp_palm_detect_pressure_triggered()
1111 t->palm.state = PALM_PRESSURE; in tp_palm_detect_pressure_triggered()
1113 return t->palm.state == PALM_PRESSURE; in tp_palm_detect_pressure_triggered()
1121 if (tp->arbitration.state == ARBITRATION_NOT_ACTIVE) in tp_palm_detect_arbitration_triggered()
1124 t->palm.state = PALM_ARBITRATION; in tp_palm_detect_arbitration_triggered()
1133 enum touch_palm_state oldstate = t->palm.state; in tp_palm_detect()
1158 * in case pressure triggers on a non-palm touch. And again after in tp_palm_detect()
1168 if (oldstate == t->palm.state) in tp_palm_detect()
1171 switch (t->palm.state) { in tp_palm_detect()
1182 palm_state = "tool-palm"; in tp_palm_detect()
1188 palm_state = "touch size"; in tp_palm_detect()
1198 evdev_log_debug(tp->device, in tp_palm_detect()
1199 "palm: touch %d (%s), palm detected (%s)\n", in tp_palm_detect()
1200 t->index, in tp_palm_detect()
1201 touch_state_to_str(t->state), in tp_palm_detect()
1217 for (i = 0; i < (int)tp->num_slots; i++) { in tp_unhover_pressure()
1220 if (t->state == TOUCH_NONE) in tp_unhover_pressure()
1223 if (t->dirty) { in tp_unhover_pressure()
1224 if (t->state == TOUCH_HOVERING) { in tp_unhover_pressure()
1225 if (t->pressure >= tp->pressure.high) { in tp_unhover_pressure()
1226 evdev_log_debug(tp->device, in tp_unhover_pressure()
1227 "pressure: begin touch %d\n", in tp_unhover_pressure()
1228 t->index); in tp_unhover_pressure()
1235 * for single-finger touches where the real touch in tp_unhover_pressure()
1238 } else if (nfake_touches <= tp->num_slots || in tp_unhover_pressure()
1239 tp->num_slots == 1) { in tp_unhover_pressure()
1240 if (t->pressure < tp->pressure.low) { in tp_unhover_pressure()
1241 evdev_log_debug(tp->device, in tp_unhover_pressure()
1242 "pressure: end touch %d\n", in tp_unhover_pressure()
1243 t->index); in tp_unhover_pressure()
1249 if (t->state == TOUCH_BEGIN || in tp_unhover_pressure()
1250 t->state == TOUCH_UPDATE) in tp_unhover_pressure()
1254 if (nfake_touches <= tp->num_slots || in tp_unhover_pressure()
1255 tp->nfingers_down == 0) in tp_unhover_pressure()
1264 if (t->state == TOUCH_HOVERING) { in tp_unhover_pressure()
1269 if (tp->nfingers_down >= nfake_touches) in tp_unhover_pressure()
1275 if (tp->nfingers_down > nfake_touches || in tp_unhover_pressure()
1277 for (i = tp->ntouches - 1; i >= 0; i--) { in tp_unhover_pressure()
1280 if (t->state == TOUCH_HOVERING || in tp_unhover_pressure()
1281 t->state == TOUCH_NONE || in tp_unhover_pressure()
1282 t->state == TOUCH_MAYBE_END) in tp_unhover_pressure()
1288 tp->nfingers_down == nfake_touches) in tp_unhover_pressure()
1298 int low = tp->touch_size.low, in tp_unhover_size()
1299 high = tp->touch_size.high; in tp_unhover_size()
1305 for (i = 0; i < (int)tp->num_slots; i++) { in tp_unhover_size()
1308 if (t->state == TOUCH_NONE) in tp_unhover_size()
1311 if (!t->dirty) in tp_unhover_size()
1314 if (t->state == TOUCH_HOVERING) { in tp_unhover_size()
1315 if ((t->major > high && t->minor > low) || in tp_unhover_size()
1316 (t->major > low && t->minor > high)) { in tp_unhover_size()
1317 evdev_log_debug(tp->device, in tp_unhover_size()
1318 "touch-size: begin touch %d\n", in tp_unhover_size()
1319 t->index); in tp_unhover_size()
1325 if (t->major < low || t->minor < low) { in tp_unhover_size()
1326 evdev_log_debug(tp->device, in tp_unhover_size()
1327 "touch-size: end touch %d\n", in tp_unhover_size()
1328 t->index); in tp_unhover_size()
1342 if (!tp->fake_touches && !tp->nfingers_down) in tp_unhover_fake_touches()
1349 if (tp->nfingers_down == nfake_touches && in tp_unhover_fake_touches()
1350 ((tp->nfingers_down == 0 && !tp_fake_finger_is_touching(tp)) || in tp_unhover_fake_touches()
1351 (tp->nfingers_down > 0 && tp_fake_finger_is_touching(tp)))) in tp_unhover_fake_touches()
1355 * touches, switch each hovering touch to BEGIN in tp_unhover_fake_touches()
1359 tp->nfingers_down < nfake_touches) { in tp_unhover_fake_touches()
1361 if (t->state == TOUCH_HOVERING) { in tp_unhover_fake_touches()
1364 if (tp->nfingers_down >= nfake_touches) in tp_unhover_fake_touches()
1374 if (tp->nfingers_down > nfake_touches || in tp_unhover_fake_touches()
1376 for (i = tp->ntouches - 1; i >= 0; i--) { in tp_unhover_fake_touches()
1379 if (t->state == TOUCH_HOVERING || in tp_unhover_fake_touches()
1380 t->state == TOUCH_NONE) in tp_unhover_fake_touches()
1386 tp->nfingers_down == nfake_touches) in tp_unhover_fake_touches()
1395 if (tp->pressure.use_pressure) in tp_unhover_touches()
1397 else if (tp->touch_size.use_touch_size) in tp_unhover_touches()
1411 if (tp_fake_finger_count(tp) <= tp->num_slots || in tp_position_fake_touches()
1412 tp->nfingers_down == 0) in tp_position_fake_touches()
1415 /* We have at least one fake touch down. Find the top-most real in tp_position_fake_touches()
1416 * touch and copy its coordinates over to to all fake touches. in tp_position_fake_touches()
1417 * This is more reliable than just taking the first touch. in tp_position_fake_touches()
1419 for (i = 0; i < tp->num_slots; i++) { in tp_position_fake_touches()
1421 if (t->state == TOUCH_END || in tp_position_fake_touches()
1422 t->state == TOUCH_NONE) in tp_position_fake_touches()
1425 if (topmost == NULL || t->point.y < topmost->point.y) in tp_position_fake_touches()
1430 evdev_log_bug_libinput(tp->device, in tp_position_fake_touches()
1431 "Unable to find topmost touch\n"); in tp_position_fake_touches()
1435 start = tp->has_mt ? tp->num_slots : 1; in tp_position_fake_touches()
1436 for (i = start; i < tp->ntouches; i++) { in tp_position_fake_touches()
1438 if (t->state == TOUCH_NONE) in tp_position_fake_touches()
1441 t->point = topmost->point; in tp_position_fake_touches()
1442 t->pressure = topmost->pressure; in tp_position_fake_touches()
1443 if (!t->dirty) in tp_position_fake_touches()
1444 t->dirty = topmost->dirty; in tp_position_fake_touches()
1457 if (tp->nfingers_down != tp->old_nfingers_down) in tp_need_motion_history_reset()
1462 reset that touch to non-dirty effectively swallowing that event in tp_need_motion_history_reset()
1465 if (tp->device->model_flags & EVDEV_MODEL_LENOVO_T450_TOUCHPAD) { in tp_need_motion_history_reset()
1466 if (tp->queued & TOUCHPAD_EVENT_MOTION) { in tp_need_motion_history_reset()
1467 if (tp->quirks.nonmotion_event_count > 10) { in tp_need_motion_history_reset()
1468 tp->queued &= ~TOUCHPAD_EVENT_MOTION; in tp_need_motion_history_reset()
1471 tp->quirks.nonmotion_event_count = 0; in tp_need_motion_history_reset()
1474 if ((tp->queued & (TOUCHPAD_EVENT_OTHERAXIS|TOUCHPAD_EVENT_MOTION)) == in tp_need_motion_history_reset()
1476 tp->quirks.nonmotion_event_count++; in tp_need_motion_history_reset()
1501 if (tp->jump.detection_disabled) in tp_detect_jumps()
1507 if (tp->device->model_flags & EVDEV_MODEL_WACOM_TOUCHPAD) in tp_detect_jumps()
1510 if (t->history.count == 0) { in tp_detect_jumps()
1511 t->jumps.last_delta_mm = 0.0; in tp_detect_jumps()
1518 tdelta = time - last->time; in tp_detect_jumps()
1520 /* For test devices we always force the time delta to 12, at least in tp_detect_jumps()
1521 until the test suite actually does proper intervals. */ in tp_detect_jumps()
1522 if (tp->device->model_flags & EVDEV_MODEL_TEST_DEVICE) in tp_detect_jumps()
1534 delta.x = abs(t->point.x - last->point.x); in tp_detect_jumps()
1535 delta.y = abs(t->point.y - last->point.y); in tp_detect_jumps()
1536 mm = evdev_device_unit_delta_to_mm(tp->device, &delta); in tp_detect_jumps()
1538 rel_distance = abs_distance - t->jumps.last_delta_mm; in tp_detect_jumps()
1543 * https://gitlab.freedesktop.org/libinput/libinput/-/issues/492 in tp_detect_jumps()
1547 if (tp->device->model_flags & EVDEV_MODEL_ALPS_SERIAL_TOUCHPAD && in tp_detect_jumps()
1548 t->point.x == 4095 && t->point.y == 0) { in tp_detect_jumps()
1549 t->point = last->point; in tp_detect_jumps()
1554 * - current single-event delta is >20mm, or in tp_detect_jumps()
1555 * - we increased the delta by over 7mm within a 12ms frame. in tp_detect_jumps()
1559 t->jumps.last_delta_mm = abs_distance; in tp_detect_jumps()
1570 * @param t The touch point
1582 if (t->state != TOUCH_UPDATE) in tp_motion_history_fix_last()
1592 for (int i = 0; i < (int)t->history.count; i++) { in tp_motion_history_fix_last()
1596 p->time = time - jumping_interval - normal_interval * i; in tp_motion_history_fix_last()
1603 struct msc_timestamp *m = &tp->quirks.msc_timestamp; in tp_process_msc_timestamp()
1635 if (m->now == 0) { in tp_process_msc_timestamp()
1636 m->state = JUMP_STATE_EXPECT_FIRST; in tp_process_msc_timestamp()
1637 m->interval = 0; in tp_process_msc_timestamp()
1641 switch(m->state) { in tp_process_msc_timestamp()
1643 if (m->now > ms2us(20)) { in tp_process_msc_timestamp()
1644 m->state = JUMP_STATE_IGNORE; in tp_process_msc_timestamp()
1646 m->state = JUMP_STATE_EXPECT_DELAY; in tp_process_msc_timestamp()
1647 m->interval = m->now; in tp_process_msc_timestamp()
1651 if (m->now > m->interval * 2) { in tp_process_msc_timestamp()
1657 tdelta = m->now - m->interval; in tp_process_msc_timestamp()
1663 m->interval, in tp_process_msc_timestamp()
1666 m->state = JUMP_STATE_IGNORE; in tp_process_msc_timestamp()
1674 filter_restart(tp->device->pointer.filter, tp, time - tdelta); in tp_process_msc_timestamp()
1687 if (tp->queued & TOUCHPAD_EVENT_TIMESTAMP) in tp_pre_process_state()
1694 if (t->state == TOUCH_MAYBE_END) in tp_pre_process_state()
1697 /* Ignore motion when pressure/touch size fell below the in tp_pre_process_state()
1698 * threshold, thus ending the touch */ in tp_pre_process_state()
1699 if (t->state == TOUCH_END && t->history.count > 0) in tp_pre_process_state()
1700 t->point = tp_motion_history_offset(t, 0)->point; in tp_pre_process_state()
1719 if (t->state == TOUCH_NONE) in tp_process_state()
1724 t->quirks.reset_motion_history = true; in tp_process_state()
1725 } else if (t->quirks.reset_motion_history) { in tp_process_state()
1727 t->quirks.reset_motion_history = false; in tp_process_state()
1730 if (!t->dirty) { in tp_process_state()
1731 /* A non-dirty touch must be below the speed limit */ in tp_process_state()
1732 if (t->speed.exceeded_count > 0) in tp_process_state()
1733 t->speed.exceeded_count--; in tp_process_state()
1736 t->speed.exceeded_count); in tp_process_state()
1738 /* A touch that hasn't moved must be in the same in tp_process_state()
1747 if (!tp->semi_mt) in tp_process_state()
1748 evdev_log_bug_kernel_ratelimit(tp->device, in tp_process_state()
1749 &tp->jump.warning, in tp_process_state()
1750 "Touch jump detected and discarded.\n" in tp_process_state()
1751 "See %s/touchpad-jumping-cursors.html for details\n", in tp_process_state()
1762 /* Touch speed handling: if we'are above the threshold, in tp_process_state()
1766 * Take the touch with the highest speed excess, if it is in tp_process_state()
1774 if (t->speed.last_speed > THUMB_IGNORE_SPEED_THRESHOLD) { in tp_process_state()
1775 if (t->speed.exceeded_count < 15) in tp_process_state()
1776 t->speed.exceeded_count++; in tp_process_state()
1777 } else if (t->speed.exceeded_count > 0) { in tp_process_state()
1778 t->speed.exceeded_count--; in tp_process_state()
1782 t->speed.exceeded_count); in tp_process_state()
1788 if (t->state == TOUCH_BEGIN) { in tp_process_state()
1794 if (tp->thumb.detect_thumbs && in tp_process_state()
1796 tp->nfingers_down >= 2) in tp_process_state()
1800 filter_restart(tp->device->pointer.filter, tp, time); in tp_process_state()
1811 if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) && in tp_process_state()
1812 tp->buttons.is_clickpad) in tp_process_state()
1825 if (!t->dirty) in tp_post_process_state()
1828 if (t->state == TOUCH_END) { in tp_post_process_state()
1829 if (t->has_ended) in tp_post_process_state()
1830 t->state = TOUCH_NONE; in tp_post_process_state()
1832 t->state = TOUCH_HOVERING; in tp_post_process_state()
1833 } else if (t->state == TOUCH_BEGIN) { in tp_post_process_state()
1834 t->state = TOUCH_UPDATE; in tp_post_process_state()
1837 t->dirty = false; in tp_post_process_state()
1840 tp->old_nfingers_down = tp->nfingers_down; in tp_post_process_state()
1841 tp->buttons.old_state = tp->buttons.state; in tp_post_process_state()
1843 tp->queued = TOUCHPAD_EVENT_NONE; in tp_post_process_state()
1845 if (tp->nfingers_down == 0) in tp_post_process_state()
1857 if (tp->device->is_suspended) { in tp_post_events()
1865 if (tp->palm.trackpoint_active || tp->dwt.keyboard_active) { in tp_post_events()
1887 struct tp_dispatch *tp = (struct tp_dispatch *)device->dispatch; in tp_apply_rotation()
1889 if (tp->left_handed.want_rotate == tp->left_handed.rotate) in tp_apply_rotation()
1892 if (tp->nfingers_down) in tp_apply_rotation()
1895 tp->left_handed.rotate = tp->left_handed.want_rotate; in tp_apply_rotation()
1898 "touchpad-rotation: rotation is %s\n", in tp_apply_rotation()
1899 tp->left_handed.rotate ? "on" : "off"); in tp_apply_rotation()
1911 tp_clickpad_middlebutton_apply_config(tp->device); in tp_handle_state()
1912 tp_apply_rotation(tp->device); in tp_handle_state()
1925 if (i >= tp->nfingers_down) in tp_debug_touch_state()
1930 t->point.x, in tp_debug_touch_state()
1931 t->point.y, in tp_debug_touch_state()
1932 t->pressure, in tp_debug_touch_state()
1936 evdev_log_debug(device, "touch state: %s\n", buf); in tp_debug_touch_state()
1947 switch (e->type) { in tp_interface_process()
1949 if (tp->has_mt) in tp_interface_process()
1974 libinput_timer_cancel(&tp->palm.trackpoint_timer); in tp_remove_sendevents()
1975 libinput_timer_cancel(&tp->dwt.keyboard_timer); in tp_remove_sendevents()
1977 if (tp->buttons.trackpoint && in tp_remove_sendevents()
1978 tp->palm.monitor_trackpoint) in tp_remove_sendevents()
1980 &tp->palm.trackpoint_listener); in tp_remove_sendevents()
1982 list_for_each(kbd, &tp->dwt.paired_keyboard_list, link) { in tp_remove_sendevents()
1983 libinput_device_remove_event_listener(&kbd->listener); in tp_remove_sendevents()
1986 if (tp->lid_switch.lid_switch) in tp_remove_sendevents()
1988 &tp->lid_switch.listener); in tp_remove_sendevents()
1990 if (tp->tablet_mode_switch.tablet_mode_switch) in tp_remove_sendevents()
1992 &tp->tablet_mode_switch.listener); in tp_remove_sendevents()
2001 libinput_timer_cancel(&tp->arbitration.arbitration_timer); in tp_interface_remove()
2003 list_for_each_safe(kbd, &tp->dwt.paired_keyboard_list, link) { in tp_interface_remove()
2006 tp->dwt.keyboard_active = false; in tp_interface_remove()
2020 libinput_timer_destroy(&tp->arbitration.arbitration_timer); in tp_interface_destroy()
2021 libinput_timer_destroy(&tp->palm.trackpoint_timer); in tp_interface_destroy()
2022 libinput_timer_destroy(&tp->dwt.keyboard_timer); in tp_interface_destroy()
2023 libinput_timer_destroy(&tp->tap.timer); in tp_interface_destroy()
2024 libinput_timer_destroy(&tp->gesture.finger_count_switch_timer); in tp_interface_destroy()
2025 libinput_timer_destroy(&tp->gesture.hold_timer); in tp_interface_destroy()
2026 free(tp->touches); in tp_interface_destroy()
2033 tp->fake_touches = 0; in tp_release_fake_touches()
2044 * must come before the touch up. If it isn't, the order doesn't in tp_clear_state()
2073 if (tp->suspend_reason & trigger) in tp_suspend()
2076 if (tp->suspend_reason != 0) in tp_suspend()
2085 if (tp->buttons.has_topbuttons) { in tp_suspend()
2094 tp->suspend_reason |= trigger; in tp_suspend()
2112 struct libevdev *evdev = device->evdev; in tp_sync_touch()
2118 &t->point.x)) in tp_sync_touch()
2119 t->point.x = libevdev_get_event_value(evdev, EV_ABS, ABS_X); in tp_sync_touch()
2123 &t->point.y)) in tp_sync_touch()
2124 t->point.y = libevdev_get_event_value(evdev, EV_ABS, ABS_Y); in tp_sync_touch()
2129 &t->pressure)) in tp_sync_touch()
2130 t->pressure = libevdev_get_event_value(evdev, in tp_sync_touch()
2137 &t->major); in tp_sync_touch()
2141 &t->minor); in tp_sync_touch()
2147 tracking_id != -1) in tp_sync_touch()
2148 tp->nactive_slots++; in tp_sync_touch()
2155 /* Always sync the first touch so we get ABS_X/Y synced on in tp_sync_slots()
2156 * single-touch touchpads */ in tp_sync_slots()
2157 tp_sync_touch(tp, device, &tp->touches[0], 0); in tp_sync_slots()
2158 for (unsigned int i = 1; i < tp->num_slots; i++) in tp_sync_slots()
2159 tp_sync_touch(tp, device, &tp->touches[i], i); in tp_sync_slots()
2167 tp->suspend_reason &= ~trigger; in tp_resume()
2168 if (tp->suspend_reason != 0) in tp_resume()
2171 if (tp->buttons.has_topbuttons) { in tp_resume()
2172 /* tap state-machine is offline while suspended, reset state */ in tp_resume()
2189 if (tp->palm.trackpoint_active) { in tp_trackpoint_timeout()
2191 tp->palm.trackpoint_active = false; in tp_trackpoint_timeout()
2193 tp->palm.trackpoint_event_count = 0; in tp_trackpoint_timeout()
2201 if (!tp->palm.dwtp_enabled) in tp_trackpoint_event()
2206 if (event->type == LIBINPUT_EVENT_POINTER_BUTTON) in tp_trackpoint_event()
2209 tp->palm.trackpoint_last_event_time = time; in tp_trackpoint_event()
2210 tp->palm.trackpoint_event_count++; in tp_trackpoint_event()
2213 if (tp->palm.trackpoint_event_count < 3) { in tp_trackpoint_event()
2214 libinput_timer_set(&tp->palm.trackpoint_timer, in tp_trackpoint_event()
2219 if (!tp->palm.trackpoint_active) { in tp_trackpoint_event()
2221 tp->palm.trackpoint_active = true; in tp_trackpoint_event()
2224 libinput_timer_set(&tp->palm.trackpoint_timer, in tp_trackpoint_event()
2233 if (tp->dwt.dwt_enabled && in tp_keyboard_timeout()
2234 long_any_bit_set(tp->dwt.key_mask, in tp_keyboard_timeout()
2235 ARRAY_LENGTH(tp->dwt.key_mask))) { in tp_keyboard_timeout()
2236 libinput_timer_set(&tp->dwt.keyboard_timer, in tp_keyboard_timeout()
2238 tp->dwt.keyboard_last_press_time = now; in tp_keyboard_timeout()
2239 evdev_log_debug(tp->device, "palm: keyboard timeout refresh\n"); in tp_keyboard_timeout()
2245 tp->dwt.keyboard_active = false; in tp_keyboard_timeout()
2247 evdev_log_debug(tp->device, "palm: keyboard timeout\n"); in tp_keyboard_timeout()
2254 /* Ignore modifiers to be responsive to ctrl-click, alt-tab, etc. */ in tp_key_is_modifier()
2276 /* Ignore keys not part of the "typewriter set", i.e. F-keys, in tp_key_ignore_for_dwt()
2301 if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY) in tp_keyboard_event()
2310 long_clear_bit(tp->dwt.key_mask, key); in tp_keyboard_event()
2311 long_clear_bit(tp->dwt.mod_mask, key); in tp_keyboard_event()
2315 if (!tp->dwt.dwt_enabled) in tp_keyboard_event()
2321 /* modifier keys don't trigger disable-while-typing so things like in tp_keyboard_event()
2325 long_set_bit(tp->dwt.mod_mask, key); in tp_keyboard_event()
2329 if (!tp->dwt.keyboard_active) { in tp_keyboard_event()
2330 /* This is the first non-modifier key press. Check if the in tp_keyboard_event()
2335 if (long_any_bit_set(tp->dwt.mod_mask, in tp_keyboard_event()
2336 ARRAY_LENGTH(tp->dwt.mod_mask))) in tp_keyboard_event()
2340 tp->dwt.keyboard_active = true; in tp_keyboard_event()
2346 tp->dwt.keyboard_last_press_time = time; in tp_keyboard_event()
2347 long_set_bit(tp->dwt.key_mask, key); in tp_keyboard_event()
2348 libinput_timer_set(&tp->dwt.keyboard_timer, in tp_keyboard_event()
2363 if (touchpad->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD) in tp_want_dwt()
2366 if (keyboard->tags & EVDEV_TAG_INTERNAL_KEYBOARD) in tp_want_dwt()
2378 struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch; in tp_dwt_pair_keyboard()
2382 if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0) in tp_dwt_pair_keyboard()
2388 list_for_each(kbd, &tp->dwt.paired_keyboard_list, link) { in tp_dwt_pair_keyboard()
2398 kbd->device = keyboard; in tp_dwt_pair_keyboard()
2399 libinput_device_add_event_listener(&keyboard->base, in tp_dwt_pair_keyboard()
2400 &kbd->listener, in tp_dwt_pair_keyboard()
2402 list_insert(&tp->dwt.paired_keyboard_list, &kbd->link); in tp_dwt_pair_keyboard()
2404 "palm: dwt activated with %s<->%s\n", in tp_dwt_pair_keyboard()
2405 touchpad->devname, in tp_dwt_pair_keyboard()
2406 keyboard->devname); in tp_dwt_pair_keyboard()
2413 struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch; in tp_pair_trackpoint()
2414 unsigned int bus_trp = libevdev_get_id_bustype(trackpoint->evdev); in tp_pair_trackpoint()
2417 if ((trackpoint->tags & EVDEV_TAG_TRACKPOINT) == 0) in tp_pair_trackpoint()
2420 tp_is_internal = !!(touchpad->tags & EVDEV_TAG_INTERNAL_TOUCHPAD); in tp_pair_trackpoint()
2423 if (tp->buttons.trackpoint == NULL && in tp_pair_trackpoint()
2426 tp->buttons.active_is_topbutton = false; in tp_pair_trackpoint()
2427 tp->buttons.trackpoint = trackpoint; in tp_pair_trackpoint()
2428 if (tp->palm.monitor_trackpoint) in tp_pair_trackpoint()
2429 libinput_device_add_event_listener(&trackpoint->base, in tp_pair_trackpoint()
2430 &tp->palm.trackpoint_listener, in tp_pair_trackpoint()
2450 tp_resume(tp, tp->device, SUSPEND_LID); in tp_lid_switch_event()
2451 evdev_log_debug(tp->device, "lid: resume touchpad\n"); in tp_lid_switch_event()
2454 tp_suspend(tp, tp->device, SUSPEND_LID); in tp_lid_switch_event()
2455 evdev_log_debug(tp->device, "lid: suspending touchpad\n"); in tp_lid_switch_event()
2478 tp_resume(tp, tp->device, SUSPEND_TABLET_MODE); in tp_tablet_mode_switch_event()
2479 evdev_log_debug(tp->device, "tablet-mode: resume touchpad\n"); in tp_tablet_mode_switch_event()
2482 tp_suspend(tp, tp->device, SUSPEND_TABLET_MODE); in tp_tablet_mode_switch_event()
2483 evdev_log_debug(tp->device, "tablet-mode: suspending touchpad\n"); in tp_tablet_mode_switch_event()
2492 struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch; in tp_pair_lid_switch()
2494 if ((lid_switch->tags & EVDEV_TAG_LID_SWITCH) == 0) in tp_pair_lid_switch()
2497 if (touchpad->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD) in tp_pair_lid_switch()
2500 if (tp->lid_switch.lid_switch == NULL) { in tp_pair_lid_switch()
2502 "lid: activated for %s<->%s\n", in tp_pair_lid_switch()
2503 touchpad->devname, in tp_pair_lid_switch()
2504 lid_switch->devname); in tp_pair_lid_switch()
2506 libinput_device_add_event_listener(&lid_switch->base, in tp_pair_lid_switch()
2507 &tp->lid_switch.listener, in tp_pair_lid_switch()
2509 tp->lid_switch.lid_switch = lid_switch; in tp_pair_lid_switch()
2517 struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch; in tp_pair_tablet_mode_switch()
2519 if ((tablet_mode_switch->tags & EVDEV_TAG_TABLET_MODE_SWITCH) == 0) in tp_pair_tablet_mode_switch()
2522 if (tp->tablet_mode_switch.tablet_mode_switch) in tp_pair_tablet_mode_switch()
2525 if (touchpad->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD) in tp_pair_tablet_mode_switch()
2533 "tablet-mode: activated for %s<->%s\n", in tp_pair_tablet_mode_switch()
2534 touchpad->devname, in tp_pair_tablet_mode_switch()
2535 tablet_mode_switch->devname); in tp_pair_tablet_mode_switch()
2537 libinput_device_add_event_listener(&tablet_mode_switch->base, in tp_pair_tablet_mode_switch()
2538 &tp->tablet_mode_switch.listener, in tp_pair_tablet_mode_switch()
2540 tp->tablet_mode_switch.tablet_mode_switch = tablet_mode_switch; in tp_pair_tablet_mode_switch()
2552 struct tp_dispatch *tp = (struct tp_dispatch *)device->dispatch; in tp_change_rotation()
2553 struct evdev_device *tablet_device = tp->left_handed.tablet_device; in tp_change_rotation()
2556 if (!tp->left_handed.must_rotate) in tp_change_rotation()
2559 touchpad_is_left = device->left_handed.enabled; in tp_change_rotation()
2560 tablet_is_left = tp->left_handed.tablet_left_handed_state; in tp_change_rotation()
2562 tp->left_handed.want_rotate = touchpad_is_left || tablet_is_left; in tp_change_rotation()
2567 struct evdev_dispatch *dispatch = tablet_device->dispatch; in tp_change_rotation()
2569 if (dispatch->interface->left_handed_toggle) in tp_change_rotation()
2570 dispatch->interface->left_handed_toggle(dispatch, in tp_change_rotation()
2572 tp->left_handed.want_rotate); in tp_change_rotation()
2580 struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch; in tp_pair_tablet()
2582 if (!tp->left_handed.must_rotate) in tp_pair_tablet()
2585 if ((tablet->seat_caps & EVDEV_DEVICE_TABLET) == 0) in tp_pair_tablet()
2588 if (libinput_device_get_device_group(&touchpad->base) != in tp_pair_tablet()
2589 libinput_device_get_device_group(&tablet->base)) in tp_pair_tablet()
2592 tp->left_handed.tablet_device = tablet; in tp_pair_tablet()
2595 "touchpad-rotation: %s will rotate %s\n", in tp_pair_tablet()
2596 touchpad->devname, in tp_pair_tablet()
2597 tablet->devname); in tp_pair_tablet()
2599 if (libinput_device_config_left_handed_get(&tablet->base)) { in tp_pair_tablet()
2600 tp->left_handed.want_rotate = true; in tp_pair_tablet()
2601 tp->left_handed.tablet_left_handed_state = true; in tp_pair_tablet()
2610 struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch; in tp_interface_device_added()
2618 if (tp->sendevents.current_mode != in tp_interface_device_added()
2622 if (added_device->tags & EVDEV_TAG_EXTERNAL_MOUSE) in tp_interface_device_added()
2630 struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch; in tp_interface_device_removed()
2633 if (removed_device == tp->buttons.trackpoint) { in tp_interface_device_removed()
2635 if (tp->buttons.active && tp->buttons.active_is_topbutton) { in tp_interface_device_removed()
2636 tp->buttons.active = 0; in tp_interface_device_removed()
2637 tp->buttons.active_is_topbutton = false; in tp_interface_device_removed()
2639 if (tp->palm.monitor_trackpoint) in tp_interface_device_removed()
2641 &tp->palm.trackpoint_listener); in tp_interface_device_removed()
2642 tp->buttons.trackpoint = NULL; in tp_interface_device_removed()
2645 list_for_each_safe(kbd, &tp->dwt.paired_keyboard_list, link) { in tp_interface_device_removed()
2646 if (kbd->device == removed_device) { in tp_interface_device_removed()
2648 tp->dwt.keyboard_active = false; in tp_interface_device_removed()
2652 if (removed_device == tp->lid_switch.lid_switch) { in tp_interface_device_removed()
2654 &tp->lid_switch.listener); in tp_interface_device_removed()
2655 tp->lid_switch.lid_switch = NULL; in tp_interface_device_removed()
2659 if (removed_device == tp->tablet_mode_switch.tablet_mode_switch) { in tp_interface_device_removed()
2661 &tp->tablet_mode_switch.listener); in tp_interface_device_removed()
2662 tp->tablet_mode_switch.tablet_mode_switch = NULL; in tp_interface_device_removed()
2666 if (tp->sendevents.current_mode == in tp_interface_device_removed()
2671 list_for_each(dev, &device->base.seat->devices_list, link) { in tp_interface_device_removed()
2674 (d->tags & EVDEV_TAG_EXTERNAL_MOUSE)) { in tp_interface_device_removed()
2683 if (removed_device == tp->left_handed.tablet_device) { in tp_interface_device_removed()
2684 tp->left_handed.tablet_device = NULL; in tp_interface_device_removed()
2685 tp->left_handed.tablet_left_handed_state = false; in tp_interface_device_removed()
2689 * set to left-handed. Niche case, nothing to worry about in tp_interface_device_removed()
2698 device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD; in evdev_tag_touchpad_internal()
2699 device->tags &= ~EVDEV_TAG_EXTERNAL_TOUCHPAD; in evdev_tag_touchpad_internal()
2705 device->tags |= EVDEV_TAG_EXTERNAL_TOUCHPAD; in evdev_tag_touchpad_external()
2706 device->tags &= ~EVDEV_TAG_INTERNAL_TOUCHPAD; in evdev_tag_touchpad_external()
2742 bustype = libevdev_get_id_bustype(device->evdev); in evdev_tag_touchpad()
2743 vendor = libevdev_get_id_vendor(device->evdev); in evdev_tag_touchpad()
2762 if (device->model_flags & EVDEV_MODEL_WACOM_TOUCHPAD) in evdev_tag_touchpad()
2765 if ((device->tags & in evdev_tag_touchpad()
2778 if (tp->arbitration.state != ARBITRATION_NOT_ACTIVE) in tp_arbitration_timeout()
2779 tp->arbitration.state = ARBITRATION_NOT_ACTIVE; in tp_arbitration_timeout()
2791 if (which == tp->arbitration.state) in tp_interface_toggle_touch()
2797 libinput_timer_cancel(&tp->arbitration.arbitration_timer); in tp_interface_toggle_touch()
2799 tp->arbitration.state = which; in tp_interface_toggle_touch()
2802 /* if in-kernel arbitration is in use and there is a touch in tp_interface_toggle_touch()
2804 * causes a touch begin for the touch. On a hand-lift the in tp_interface_toggle_touch()
2805 * proximity out precedes the touch up by a few ms, so we in tp_interface_toggle_touch()
2807 * arbitration by just a little bit so that any touch in in tp_interface_toggle_touch()
2808 * event is caught as palm touch. */ in tp_interface_toggle_touch()
2809 libinput_timer_set(&tp->arbitration.arbitration_timer, in tp_interface_toggle_touch()
2815 /* Called when the tablet toggles to left-handed */
2823 if (!tp->left_handed.tablet_device) in touchpad_left_handed_toggled()
2827 "touchpad-rotation: tablet is %s\n", in touchpad_left_handed_toggled()
2828 left_handed_enabled ? "left-handed" : "right-handed"); in touchpad_left_handed_toggled()
2830 /* Our left-handed config is independent even though rotation is in touchpad_left_handed_toggled()
2831 * locked. So we rotate when either device is left-handed. But it in touchpad_left_handed_toggled()
2835 tp->left_handed.tablet_left_handed_state = left_handed_enabled; in touchpad_left_handed_toggled()
2860 t->tp = tp; in tp_init_touch()
2861 t->has_ended = true; in tp_init_touch()
2862 t->index = index; in tp_init_touch()
2868 struct libevdev *evdev = device->evdev; in tp_disable_abs_mt()
2891 absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT); in tp_init_slots()
2893 tp->num_slots = absinfo->maximum + 1; in tp_init_slots()
2894 tp->slot = absinfo->value; in tp_init_slots()
2895 tp->has_mt = true; in tp_init_slots()
2897 tp->num_slots = 1; in tp_init_slots()
2898 tp->slot = 0; in tp_init_slots()
2899 tp->has_mt = false; in tp_init_slots()
2902 tp->semi_mt = libevdev_has_property(device->evdev, INPUT_PROP_SEMI_MT); in tp_init_slots()
2904 /* Semi-mt devices are not reliable for true multitouch data, so we in tp_init_slots()
2905 * simply pretend they're single touch touchpads with BTN_TOOL bits. in tp_init_slots()
2908 * causing scroll jumps. The single-touch emulation ABS_X/Y is in tp_init_slots()
2912 * On three-finger taps/clicks, one slot doesn't get a coordinate in tp_init_slots()
2920 * for single-finger movement. See fdo bug 91135 in tp_init_slots()
2922 if (tp->semi_mt || in tp_init_slots()
2923 evdev_device_has_model_quirk(tp->device, in tp_init_slots()
2925 tp->num_slots = 1; in tp_init_slots()
2926 tp->slot = 0; in tp_init_slots()
2927 tp->has_mt = false; in tp_init_slots()
2930 if (!tp->has_mt) in tp_init_slots()
2934 if (libevdev_has_event_code(device->evdev, in tp_init_slots()
2936 m->code)) { in tp_init_slots()
2937 n_btn_tool_touches = m->ntouches; in tp_init_slots()
2942 tp->ntouches = max(tp->num_slots, n_btn_tool_touches); in tp_init_slots()
2943 tp->touches = zalloc(tp->ntouches * sizeof(struct tp_touch)); in tp_init_slots()
2945 for (i = 0; i < tp->ntouches; i++) in tp_init_slots()
2946 tp_init_touch(tp, &tp->touches[i], i); in tp_init_slots()
2950 /* Some touchpads don't reset BTN_TOOL_FINGER on touch up and only in tp_init_slots()
2952 * to ignore the first touches events until a two-finger gesture is in tp_init_slots()
2955 if (libevdev_get_event_value(device->evdev, EV_KEY, BTN_TOOL_FINGER)) in tp_init_slots()
2968 struct evdev_device *device = tp->device; in tp_init_accel()
2971 int dpi = device->dpi; in tp_init_accel()
2972 bool use_v_avg = device->use_velocity_averaging; in tp_init_accel()
2974 res_x = tp->device->abs.absinfo_x->resolution; in tp_init_accel()
2975 res_y = tp->device->abs.absinfo_y->resolution; in tp_init_accel()
2984 tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x; in tp_init_accel()
2985 tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y; in tp_init_accel()
2986 tp->accel.xy_scale_coeff = 1.0 * res_x/res_y; in tp_init_accel()
2993 tp->device->model_flags & EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81) { in tp_init_accel()
2999 if (libevdev_get_id_bustype(device->evdev) == BUS_BLUETOOTH) { in tp_init_accel()
3012 evdev_device_init_pointer_acceleration(tp->device, filter); in tp_init_accel()
3014 device->pointer.config.set_profile = tp_accel_config_set_profile; in tp_init_accel()
3024 if (!filter_set_speed(dev->pointer.filter, speed)) in tp_accel_config_set_speed()
3035 struct tp_dispatch *tp = tp_dispatch(device->dispatch); in tp_accel_config_set_profile()
3039 filter = device->pointer.filter; in tp_accel_config_set_profile()
3044 device->pointer.filter = NULL; in tp_accel_config_set_profile()
3050 device->pointer.filter = filter; in tp_accel_config_set_profile()
3065 if (evdev_device_has_model_quirk(tp->device, in tp_scroll_get_methods()
3069 if (tp->ntouches >= 2) in tp_scroll_get_methods()
3079 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_scroll_config_scroll_method_get_methods()
3089 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_scroll_config_scroll_method_set_method()
3092 if (method == tp->scroll.method) in tp_scroll_config_scroll_method_set_method()
3098 tp->scroll.method = method; in tp_scroll_config_scroll_method_set_method()
3107 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_scroll_config_scroll_method_get_method()
3109 return tp->scroll.method; in tp_scroll_config_scroll_method_get_method()
3126 evdev_log_bug_libinput(tp->device, in tp_scroll_get_default_method()
3136 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_scroll_config_scroll_method_get_default_method()
3157 device->scroll.config_natural.get_default_enabled = tp_scroll_config_natural_get_default; in tp_init_scroll()
3158 device->scroll.natural_scrolling_enabled = tp_scroll_config_natural_get_default(&device->base); in tp_init_scroll()
3160 tp->scroll.config_method.get_methods = tp_scroll_config_scroll_method_get_methods; in tp_init_scroll()
3161 tp->scroll.config_method.set_method = tp_scroll_config_scroll_method_set_method; in tp_init_scroll()
3162 tp->scroll.config_method.get_method = tp_scroll_config_scroll_method_get_method; in tp_init_scroll()
3163 tp->scroll.config_method.get_default_method = tp_scroll_config_scroll_method_get_default_method; in tp_init_scroll()
3164 tp->scroll.method = tp_scroll_get_default_method(tp); in tp_init_scroll()
3165 tp->device->base.config.scroll_method = &tp->scroll.config_method; in tp_init_scroll()
3168 tp->device->scroll.threshold = 0.0; in tp_init_scroll()
3169 tp->device->scroll.direction_lock_threshold = 5.0; in tp_init_scroll()
3183 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_dwt_config_set()
3193 tp->dwt.dwt_enabled = (enable == LIBINPUT_CONFIG_DWT_ENABLED); in tp_dwt_config_set()
3202 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_dwt_config_get()
3204 return tp->dwt.dwt_enabled ? in tp_dwt_config_get()
3219 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_dwt_config_get_default()
3237 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_dwtp_config_set()
3247 tp->palm.dwtp_enabled = (enable == LIBINPUT_CONFIG_DWTP_ENABLED); in tp_dwtp_config_set()
3256 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_dwtp_config_get()
3258 return tp->palm.dwtp_enabled ? in tp_dwtp_config_get()
3273 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_dwtp_config_get_default()
3289 quirks = evdev_libinput_context(device)->quirks; in tp_is_tpkb_combo_below()
3290 q = quirks_fetch_for_device(quirks, device->udev_device); in tp_is_tpkb_combo_below()
3307 return device->tags & EVDEV_TAG_TABLET_TOUCHPAD; in tp_is_tablet()
3314 if (device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD && in tp_init_dwt()
3318 tp->dwt.config.is_available = tp_dwt_config_is_available; in tp_init_dwt()
3319 tp->dwt.config.set_enabled = tp_dwt_config_set; in tp_init_dwt()
3320 tp->dwt.config.get_enabled = tp_dwt_config_get; in tp_init_dwt()
3321 tp->dwt.config.get_default_enabled = tp_dwt_config_get_default; in tp_init_dwt()
3322 tp->dwt.dwt_enabled = tp_dwt_default_enabled(tp); in tp_init_dwt()
3323 device->base.config.dwt = &tp->dwt.config; in tp_init_dwt()
3330 tp->palm.dwtp_enabled = tp_dwtp_default_enabled(tp); in tp_init_dwtp()
3332 if (device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD) in tp_init_dwtp()
3335 tp->palm.config.is_available = tp_dwtp_config_is_available; in tp_init_dwtp()
3336 tp->palm.config.set_enabled = tp_dwtp_config_set; in tp_init_dwtp()
3337 tp->palm.config.get_enabled = tp_dwtp_config_get; in tp_init_dwtp()
3338 tp->palm.config.get_default_enabled = tp_dwtp_config_get_default; in tp_init_dwtp()
3339 device->base.config.dwtp = &tp->palm.config; in tp_init_dwtp()
3350 if (device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD && in tp_init_palmdetect_edge()
3368 tp->palm.left_edge = edges.x; in tp_init_palmdetect_edge()
3370 mm.x = width - min(8, width * 0.08); in tp_init_palmdetect_edge()
3372 tp->palm.right_edge = edges.x; in tp_init_palmdetect_edge()
3374 if (!tp->buttons.has_topbuttons && height > 55) { in tp_init_palmdetect_edge()
3378 tp->palm.upper_edge = edges.y; in tp_init_palmdetect_edge()
3391 quirks = evdev_libinput_context(device)->quirks; in tp_read_palm_pressure_prop()
3392 q = quirks_fetch_for_device(quirks, device->udev_device); in tp_read_palm_pressure_prop()
3406 if (!libevdev_has_event_code(device->evdev, EV_ABS, ABS_MT_PRESSURE)) { in tp_init_palmdetect_pressure()
3407 tp->palm.use_pressure = false; in tp_init_palmdetect_pressure()
3411 tp->palm.pressure_threshold = tp_read_palm_pressure_prop(tp, device); in tp_init_palmdetect_pressure()
3412 if (tp->palm.pressure_threshold != 0) { in tp_init_palmdetect_pressure()
3413 tp->palm.use_pressure = true; in tp_init_palmdetect_pressure()
3417 tp->palm.pressure_threshold); in tp_init_palmdetect_pressure()
3429 quirks = evdev_libinput_context(device)->quirks; in tp_init_palmdetect_size()
3430 q = quirks_fetch_for_device(quirks, device->udev_device); in tp_init_palmdetect_size()
3436 tp->palm.use_size = true; in tp_init_palmdetect_size()
3437 tp->palm.size_threshold = threshold; in tp_init_palmdetect_size()
3453 libinput_timer_init(&tp->arbitration.arbitration_timer, in tp_init_palmdetect_arbitration()
3457 tp->arbitration.state = ARBITRATION_NOT_ACTIVE; in tp_init_palmdetect_arbitration()
3465 tp->palm.right_edge = INT_MAX; in tp_init_palmdetect()
3466 tp->palm.left_edge = INT_MIN; in tp_init_palmdetect()
3467 tp->palm.upper_edge = INT_MIN; in tp_init_palmdetect()
3471 if (device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD && in tp_init_palmdetect()
3477 tp->palm.monitor_trackpoint = true; in tp_init_palmdetect()
3479 if (libevdev_has_event_code(device->evdev, in tp_init_palmdetect()
3482 tp->palm.use_mt_tool = true; in tp_init_palmdetect()
3500 libinput_timer_init(&tp->palm.trackpoint_timer, in tp_init_sendevents()
3509 libinput_timer_init(&tp->dwt.keyboard_timer, in tp_init_sendevents()
3519 struct libevdev *evdev = device->evdev; in tp_pass_sanity_check()
3546 if (!device->abs.is_fake_resolution) in tp_init_default_resolution()
3550 * - the touchpad provides no resolution in tp_init_default_resolution()
3551 * - the udev hwdb didn't override the resolution in tp_init_default_resolution()
3552 * - no ATTR_SIZE_HINT is set in tp_init_default_resolution()
3563 xres = device->abs.dimensions.x/touchpad_width_mm; in tp_init_default_resolution()
3564 yres = device->abs.dimensions.y/touchpad_height_mm; in tp_init_default_resolution()
3565 libevdev_set_abs_resolution(device->evdev, ABS_X, xres); in tp_init_default_resolution()
3566 libevdev_set_abs_resolution(device->evdev, ABS_Y, yres); in tp_init_default_resolution()
3567 libevdev_set_abs_resolution(device->evdev, ABS_MT_POSITION_X, xres); in tp_init_default_resolution()
3568 libevdev_set_abs_resolution(device->evdev, ABS_MT_POSITION_Y, yres); in tp_init_default_resolution()
3569 device->abs.is_fake_resolution = false; in tp_init_default_resolution()
3576 const struct input_absinfo *ax = tp->device->abs.absinfo_x, in tp_init_hysteresis()
3577 *ay = tp->device->abs.absinfo_y; in tp_init_hysteresis()
3579 if (ax->fuzz) in tp_init_hysteresis()
3580 xmargin = ax->fuzz; in tp_init_hysteresis()
3582 xmargin = ax->resolution/4; in tp_init_hysteresis()
3584 if (ay->fuzz) in tp_init_hysteresis()
3585 ymargin = ay->fuzz; in tp_init_hysteresis()
3587 ymargin = ay->resolution/4; in tp_init_hysteresis()
3589 tp->hysteresis.margin.x = xmargin; in tp_init_hysteresis()
3590 tp->hysteresis.margin.y = ymargin; in tp_init_hysteresis()
3591 tp->hysteresis.enabled = (ax->fuzz || ay->fuzz); in tp_init_hysteresis()
3592 if (tp->hysteresis.enabled) in tp_init_hysteresis()
3593 evdev_log_debug(tp->device, in tp_init_hysteresis()
3595 "See %s/touchpad-jitter.html for details\n", in tp_init_hysteresis()
3610 code = tp->has_mt ? ABS_MT_PRESSURE : ABS_PRESSURE; in tp_init_pressure()
3611 if (!libevdev_has_event_code(device->evdev, EV_ABS, code)) { in tp_init_pressure()
3612 tp->pressure.use_pressure = false; in tp_init_pressure()
3616 abs = libevdev_get_abs_info(device->evdev, code); in tp_init_pressure()
3619 quirks = evdev_libinput_context(device)->quirks; in tp_init_pressure()
3620 q = quirks_fetch_for_device(quirks, device->udev_device); in tp_init_pressure()
3627 "pressure-based touch detection disabled\n"); in tp_init_pressure()
3634 hi = abs->minimum + 0.12 * range; in tp_init_pressure()
3635 lo = abs->minimum + 0.10 * range; in tp_init_pressure()
3638 if (hi > abs->maximum || hi < abs->minimum || in tp_init_pressure()
3639 lo > abs->maximum || lo < abs->minimum) { in tp_init_pressure()
3641 "discarding out-of-bounds pressure range %d:%d\n", in tp_init_pressure()
3646 tp->pressure.use_pressure = true; in tp_init_pressure()
3647 tp->pressure.high = hi; in tp_init_pressure()
3648 tp->pressure.low = lo; in tp_init_pressure()
3651 "using pressure-based touch detection (%d:%d)\n", in tp_init_pressure()
3668 if (!libevdev_has_event_code(device->evdev, in tp_init_touch_size()
3674 quirks = evdev_libinput_context(device)->quirks; in tp_init_touch_size()
3675 q = quirks_fetch_for_device(quirks, device->udev_device); in tp_init_touch_size()
3683 if (libevdev_get_num_slots(device->evdev) < 5) { in tp_init_touch_size()
3685 "Expected 5+ slots for touch size detection\n"); in tp_init_touch_size()
3691 "touch size based touch detection disabled\n"); in tp_init_touch_size()
3696 tp->touch_size.low = lo; in tp_init_touch_size()
3697 tp->touch_size.high = hi; in tp_init_touch_size()
3698 tp->touch_size.use_touch_size = true; in tp_init_touch_size()
3701 "using size-based touch detection (%d:%d)\n", in tp_init_touch_size()
3717 * with it anyway and using it for touch size messes things up. in tp_init_pressurepad()
3719 * The kernel/udev set the resolution to non-zero on those devices in tp_init_pressurepad()
3724 if (libevdev_get_abs_resolution(device->evdev, ABS_MT_PRESSURE) != 0 || in tp_init_pressurepad()
3726 libevdev_disable_event_code(device->evdev, EV_ABS, ABS_MT_PRESSURE); in tp_init_pressurepad()
3727 libevdev_disable_event_code(device->evdev, EV_ABS, ABS_PRESSURE); in tp_init_pressurepad()
3737 tp->base.dispatch_type = DISPATCH_TOUCHPAD; in tp_init()
3738 tp->base.interface = &tp_interface; in tp_init()
3739 tp->device = device; in tp_init()
3740 list_init(&tp->dwt.paired_keyboard_list); in tp_init()
3758 ratelimit_init(&tp->jump.warning, h2us(24), 5); in tp_init()
3762 device->dpi = device->abs.absinfo_x->resolution * 25.4; in tp_init()
3781 * https://gitlab.freedesktop.org/libinput/libinput/-/issues/506 in tp_init()
3785 tp->jump.detection_disabled = true; in tp_init()
3787 device->seat_caps |= EVDEV_DEVICE_POINTER; in tp_init()
3788 if (tp->gesture.enabled) in tp_init()
3789 device->seat_caps |= EVDEV_DEVICE_GESTURE; in tp_init()
3800 if (evdev->tags & EVDEV_TAG_INTERNAL_TOUCHPAD) in tp_sendevents_get_modes()
3812 list_for_each(dev, &device->base.seat->devices_list, link) { in tp_suspend_conditional()
3814 if (d->tags & EVDEV_TAG_EXTERNAL_MOUSE) { in tp_suspend_conditional()
3826 struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; in tp_sendevents_set_mode()
3833 if (mode == tp->sendevents.current_mode) in tp_sendevents_set_mode()
3853 tp->sendevents.current_mode = mode; in tp_sendevents_set_mode()
3862 struct tp_dispatch *dispatch = (struct tp_dispatch*)evdev->dispatch; in tp_sendevents_get_mode()
3864 return dispatch->sendevents.current_mode; in tp_sendevents_get_mode()
3876 struct tp_dispatch *tp = (struct tp_dispatch *)device->dispatch; in tp_change_to_left_handed()
3878 if (device->left_handed.want_enabled == device->left_handed.enabled) in tp_change_to_left_handed()
3881 if (tp->buttons.state & 0x3) /* BTN_LEFT|BTN_RIGHT */ in tp_change_to_left_handed()
3884 /* tapping and clickfinger aren't affected by left-handed config, in tp_change_to_left_handed()
3887 device->left_handed.enabled = device->left_handed.want_enabled; in tp_change_to_left_handed()
3896 struct libinput *li = tp_libinput_context(tp); in tp_requires_rotation()
3904 if ((device->tags & EVDEV_TAG_TABLET_TOUCHPAD) == 0) in tp_requires_rotation()
3956 tp->left_handed.must_rotate = tp_requires_rotation(tp, device); in tp_init_left_handed()
3958 if (device->model_flags & EVDEV_MODEL_APPLE_TOUCHPAD_ONEBUTTON) in tp_init_left_handed()
3970 evdev_tag_touchpad(device, device->udev_device); in evdev_mt_touchpad_create()
3975 tp_interface_destroy(&tp->base); in evdev_mt_touchpad_create()
3979 device->base.config.sendevents = &tp->sendevents.config; in evdev_mt_touchpad_create()
3981 tp->sendevents.current_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; in evdev_mt_touchpad_create()
3982 tp->sendevents.config.get_modes = tp_sendevents_get_modes; in evdev_mt_touchpad_create()
3983 tp->sendevents.config.set_mode = tp_sendevents_set_mode; in evdev_mt_touchpad_create()
3984 tp->sendevents.config.get_mode = tp_sendevents_get_mode; in evdev_mt_touchpad_create()
3985 tp->sendevents.config.get_default_mode = tp_sendevents_get_default_mode; in evdev_mt_touchpad_create()
3989 return &tp->base; in evdev_mt_touchpad_create()