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);
	}
}
Exemple #2
0
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;
}
Exemple #3
0
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);
}