static void tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) { struct normalized_coords delta, unaccel; /* When a clickpad is clicked, combine motion of all active touches */ if (tp->buttons.is_clickpad && tp->buttons.state) unaccel = tp_get_combined_touches_delta(tp); else unaccel = tp_get_average_touches_delta(tp); delta = tp_filter_motion(tp, &unaccel, time); if (!normalized_is_zero(delta) || !normalized_is_zero(unaccel)) { pointer_notify_motion(&tp->device->base, time, &delta, &unaccel); } }
static void evdev_flush_pending_event(struct evdev_device *device, uint32_t time) { int32_t cx, cy; int slot; struct libinput_device *base = &device->base; slot = device->mt.slot; switch (device->pending_event) { case EVDEV_NONE: return; case EVDEV_RELATIVE_MOTION: pointer_notify_motion(base, time, device->rel.dx, device->rel.dy); device->rel.dx = 0; device->rel.dy = 0; goto handled; case EVDEV_ABSOLUTE_MT_DOWN: touch_notify_touch(base, time, slot, li_fixed_from_int(device->mt.slots[slot].x), li_fixed_from_int(device->mt.slots[slot].y), LIBINPUT_TOUCH_TYPE_DOWN); goto handled; case EVDEV_ABSOLUTE_MT_MOTION: touch_notify_touch(base, time, slot, li_fixed_from_int(device->mt.slots[slot].x), li_fixed_from_int(device->mt.slots[slot].y), LIBINPUT_TOUCH_TYPE_MOTION); goto handled; case EVDEV_ABSOLUTE_MT_UP: touch_notify_touch(base, time, slot, 0, 0, LIBINPUT_TOUCH_TYPE_UP); goto handled; case EVDEV_ABSOLUTE_TOUCH_DOWN: transform_absolute(device, &cx, &cy); touch_notify_touch(base, time, slot, li_fixed_from_int(cx), li_fixed_from_int(cy), LIBINPUT_TOUCH_TYPE_DOWN); goto handled; case EVDEV_ABSOLUTE_MOTION: transform_absolute(device, &cx, &cy); if (device->caps & EVDEV_TOUCH) { touch_notify_touch(base, time, slot, li_fixed_from_int(cx), li_fixed_from_int(cy), LIBINPUT_TOUCH_TYPE_DOWN); } else { pointer_notify_motion_absolute(base, time, li_fixed_from_int(cx), li_fixed_from_int(cy)); } goto handled; case EVDEV_ABSOLUTE_TOUCH_UP: touch_notify_touch(base, time, 0, 0, 0, LIBINPUT_TOUCH_TYPE_UP); goto handled; } assert(0 && "Unknown pending event type"); handled: device->pending_event = EVDEV_NONE; }
static void touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) { int motion_index; int center_x, center_y; double dx = 0.0, dy = 0.0; struct libinput_device *base = &touchpad->device->base; if (touchpad->reset || touchpad->last_finger_state != touchpad->finger_state) { touchpad->reset = 0; touchpad->motion_count = 0; touchpad->event_mask = TOUCHPAD_EVENT_NONE; touchpad->event_mask_filter = TOUCHPAD_EVENT_ABSOLUTE_X | TOUCHPAD_EVENT_ABSOLUTE_Y; touchpad->last_finger_state = touchpad->finger_state; process_fsm_events(touchpad, time); return; } touchpad->last_finger_state = touchpad->finger_state; if (!(touchpad->event_mask & TOUCHPAD_EVENT_REPORT)) return; else touchpad->event_mask &= ~TOUCHPAD_EVENT_REPORT; if ((touchpad->event_mask & touchpad->event_mask_filter) != touchpad->event_mask_filter) return; touchpad->event_mask_filter = TOUCHPAD_EVENT_ABSOLUTE_ANY; touchpad->event_mask = 0; /* Avoid noise by moving center only when delta reaches a threshold * distance from the old center. */ if (touchpad->motion_count > 0) { center_x = hysteresis(touchpad->hw_abs.x, touchpad->hysteresis.center_x, touchpad->hysteresis.margin_x); center_y = hysteresis(touchpad->hw_abs.y, touchpad->hysteresis.center_y, touchpad->hysteresis.margin_y); } else { center_x = touchpad->hw_abs.x; center_y = touchpad->hw_abs.y; } touchpad->hysteresis.center_x = center_x; touchpad->hysteresis.center_y = center_y; touchpad->hw_abs.x = center_x; touchpad->hw_abs.y = center_y; /* Update motion history tracker */ motion_index = (touchpad->motion_index + 1) % TOUCHPAD_HISTORY_LENGTH; touchpad->motion_index = motion_index; touchpad->motion_history[motion_index].x = touchpad->hw_abs.x; touchpad->motion_history[motion_index].y = touchpad->hw_abs.y; if (touchpad->motion_count < 4) touchpad->motion_count++; if (touchpad->motion_count >= 4) { touchpad_get_delta(touchpad, &dx, &dy); filter_motion(touchpad, &dx, &dy, time); if (touchpad->finger_state == TOUCHPAD_FINGERS_ONE) { pointer_notify_motion( base, time, li_fixed_from_double(dx), li_fixed_from_double(dy)); } else if (touchpad->finger_state == TOUCHPAD_FINGERS_TWO) { if (dx != 0.0) pointer_notify_axis( base, time, LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL, li_fixed_from_double(dx)); if (dy != 0.0) pointer_notify_axis( base, time, LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL, li_fixed_from_double(dy)); } } if (!(touchpad->state & TOUCHPAD_STATE_MOVE) && ((int)dx || (int)dy)) { touchpad->state |= TOUCHPAD_STATE_MOVE; push_fsm_event(touchpad, FSM_EVENT_MOTION); } process_fsm_events(touchpad, time); }