void
tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time)
{
	unsigned int active_touches = 0;
	struct tp_touch *t;

	tp_for_each_touch(tp, t)
		if (tp_touch_active(tp, t))
			active_touches++;

	if (active_touches != tp->gesture.finger_count) {
		/* If all fingers are lifted immediately end the gesture */
		if (active_touches == 0) {
			tp_gesture_stop(tp, time);
			tp->gesture.finger_count = 0;
			tp->gesture.finger_count_pending = 0;
		/* Immediately switch to new mode to avoid initial latency */
		} else if (!tp->gesture.started) {
			tp->gesture.finger_count = active_touches;
			tp->gesture.finger_count_pending = 0;
		/* Else debounce finger changes */
		} else if (active_touches != tp->gesture.finger_count_pending) {
			tp->gesture.finger_count_pending = active_touches;
			libinput_timer_set(&tp->gesture.finger_count_switch_timer,
				time + DEFAULT_GESTURE_SWITCH_TIMEOUT);
		}
	} else {
		 tp->gesture.finger_count_pending = 0;
	}
}
static inline void
tp_edge_scroll_set_timer(struct tp_dispatch *tp,
			 struct tp_touch *t)
{
	const int DEFAULT_SCROLL_LOCK_TIMEOUT = ms2us(300);
	/* if we use software buttons, we disable timeout-based
	 * edge scrolling. A finger resting on the button areas is
	 * likely there to trigger a button event.
	 */
	if (tp->buttons.click_method ==
	    LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS)
		return;

	libinput_timer_set(&t->scroll.timer,
			   t->millis + DEFAULT_SCROLL_LOCK_TIMEOUT);
}
static void
middlebutton_timer_set(struct evdev_device *device, uint64_t now)
{
	libinput_timer_set(&device->middlebutton.timer,
			   now + MIDDLEBUTTON_TIMEOUT);
}
static void
tp_button_set_leave_timer(struct tp_dispatch *tp, struct tp_touch *t)
{
	libinput_timer_set(&t->button.timer,
			   t->millis + DEFAULT_BUTTON_LEAVE_TIMEOUT);
}
static void
tp_tap_set_drag_timer(struct tp_dispatch *tp, uint64_t time)
{
	libinput_timer_set(&tp->tap.timer, time + DEFAULT_DRAG_TIMEOUT_PERIOD);
}