[PATCH libinput 5/5] Change to micro seconds for measuring time internally

Jonas Ã…dahl jadahl at gmail.com
Mon Jul 27 21:47:06 PDT 2015


In order to provide higher precision event time stamps, change the
internal time measuring from milliseconds to microseconds.
Microseconds are chosen because it is the most fine grained time stamp
we can get from evdev.

The API is extended with high precision getters whenever the given
information is available.
---
 src/evdev-middle-button.c           |  2 +-
 src/evdev-mt-touchpad-buttons.c     |  8 ++---
 src/evdev-mt-touchpad-edge-scroll.c |  2 +-
 src/evdev-mt-touchpad-gestures.c    |  4 +--
 src/evdev-mt-touchpad-tap.c         |  4 +--
 src/evdev-mt-touchpad.c             |  8 ++---
 src/evdev.c                         |  8 ++---
 src/filter.c                        | 43 ++++++++++++-------------
 src/libinput-private.h              | 20 +++++++++++-
 src/libinput-util.c                 | 12 +++----
 src/libinput.c                      | 64 ++++++++++++++++++++++++++++++++++---
 src/libinput.h                      | 32 +++++++++++++++++++
 src/libinput.sym                    |  4 +++
 src/timer.c                         |  6 ++--
 src/timer.h                         |  4 +--
 test/gestures.c                     | 37 +++++++++++++++++++++
 test/keyboard.c                     | 27 ++++++++++++++++
 test/misc.c                         |  2 +-
 test/pointer.c                      | 28 ++++++++++++++++
 test/touch.c                        | 23 +++++++++++++
 test/touchpad.c                     | 36 +++++++++++++++++++++
 tools/ptraccel-debug.c              | 10 +++---
 22 files changed, 323 insertions(+), 61 deletions(-)

diff --git a/src/evdev-middle-button.c b/src/evdev-middle-button.c
index 48330d3..397b699 100644
--- a/src/evdev-middle-button.c
+++ b/src/evdev-middle-button.c
@@ -27,7 +27,7 @@
 
 #include "evdev.h"
 
-#define MIDDLEBUTTON_TIMEOUT 50
+#define MIDDLEBUTTON_TIMEOUT ms2us(50)
 
 /*****************************************
  * BEFORE YOU EDIT THIS FILE, look at the state diagram in
diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
index f16d1b8..3dfddea 100644
--- a/src/evdev-mt-touchpad-buttons.c
+++ b/src/evdev-mt-touchpad-buttons.c
@@ -32,8 +32,8 @@
 
 #include "evdev-mt-touchpad.h"
 
-#define DEFAULT_BUTTON_ENTER_TIMEOUT 100 /* ms */
-#define DEFAULT_BUTTON_LEAVE_TIMEOUT 300 /* ms */
+#define DEFAULT_BUTTON_ENTER_TIMEOUT ms2us(100)
+#define DEFAULT_BUTTON_LEAVE_TIMEOUT ms2us(300)
 
 /*****************************************
  * BEFORE YOU EDIT THIS FILE, look at the state diagram in
@@ -913,8 +913,8 @@ tp_notify_clickpadbutton(struct tp_dispatch *tp,
 		struct evdev_dispatch *dispatch = tp->buttons.trackpoint->dispatch;
 		struct input_event event;
 
-		event.time.tv_sec = time/1000;
-		event.time.tv_usec = (time % 1000) * 1000;
+		event.time.tv_sec = time / s2us(1);
+		event.time.tv_usec = time % s2us(1);
 		event.type = EV_KEY;
 		event.code = button;
 		event.value = (state == LIBINPUT_BUTTON_STATE_PRESSED) ? 1 : 0;
diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c
index 928f602..4902808 100644
--- a/src/evdev-mt-touchpad-edge-scroll.c
+++ b/src/evdev-mt-touchpad-edge-scroll.c
@@ -93,7 +93,7 @@ static inline void
 tp_edge_scroll_set_timer(struct tp_dispatch *tp,
 			 struct tp_touch *t)
 {
-	const int DEFAULT_SCROLL_LOCK_TIMEOUT = 300; /* ms */
+	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.
diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c
index 1acf111..c1605f3 100644
--- a/src/evdev-mt-touchpad-gestures.c
+++ b/src/evdev-mt-touchpad-gestures.c
@@ -29,8 +29,8 @@
 
 #include "evdev-mt-touchpad.h"
 
-#define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */
-#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT 1000 /* ms */
+#define DEFAULT_GESTURE_SWITCH_TIMEOUT ms2us(100)
+#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT s2us(1)
 
 static inline const char*
 gesture_state_to_str(enum tp_gesture_2fg_state state)
diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c
index b297754..de4945e 100644
--- a/src/evdev-mt-touchpad-tap.c
+++ b/src/evdev-mt-touchpad-tap.c
@@ -35,8 +35,8 @@
 
 #include "evdev-mt-touchpad.h"
 
-#define DEFAULT_TAP_TIMEOUT_PERIOD 180
-#define DEFAULT_DRAG_TIMEOUT_PERIOD 300
+#define DEFAULT_TAP_TIMEOUT_PERIOD ms2us(180)
+#define DEFAULT_DRAG_TIMEOUT_PERIOD ms2us(300)
 #define DEFAULT_TAP_MOVE_THRESHOLD TP_MM_TO_DPI_NORMALIZED(3)
 
 enum tap_event {
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 257af99..ebb8cee 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -30,9 +30,9 @@
 
 #include "evdev-mt-touchpad.h"
 
-#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 300 /* ms */
-#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 200 /* ms */
-#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 500 /* ms */
+#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT ms2us(300)
+#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 ms2us(200)
+#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 ms2us(500)
 #define FAKE_FINGER_OVERFLOW (1 << 7)
 
 static inline int
@@ -588,7 +588,7 @@ tp_palm_detect_trackpoint(struct tp_dispatch *tp,
 static void
 tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
 {
-	const int PALM_TIMEOUT = 200; /* ms */
+	const int PALM_TIMEOUT = ms2us(200);
 	const int DIRECTIONS = NE|E|SE|SW|W|NW;
 	struct device_float_coords delta;
 	int dirs;
diff --git a/src/evdev.c b/src/evdev.c
index 9af1841..ee904d3 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -44,7 +44,7 @@
 #include "libinput-private.h"
 
 #define DEFAULT_WHEEL_CLICK_ANGLE 15
-#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT 200
+#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT ms2us(200)
 
 enum evdev_key_type {
 	EVDEV_KEY_TYPE_NONE,
@@ -457,7 +457,7 @@ evdev_button_scroll_button(struct evdev_device *device,
 {
 	if (is_press) {
 		libinput_timer_set(&device->scroll.timer,
-				time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT);
+				   time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT);
 		device->scroll.button_down_time = time;
 	} else {
 		libinput_timer_cancel(&device->scroll.timer);
@@ -1270,7 +1270,7 @@ static inline void
 evdev_process_event(struct evdev_device *device, struct input_event *e)
 {
 	struct evdev_dispatch *dispatch = device->dispatch;
-	uint64_t time = e->time.tv_sec * 1000ULL + e->time.tv_usec / 1000;
+	uint64_t time = s2us(e->time.tv_sec) + e->time.tv_usec;
 
 #if 0
 	if (libevdev_event_is_code(e, EV_SYN, SYN_REPORT))
@@ -2153,7 +2153,7 @@ evdev_device_create(struct libinput_seat *seat,
 	device->dpi = DEFAULT_MOUSE_DPI;
 
 	/* at most 5 SYN_DROPPED log-messages per 30s */
-	ratelimit_init(&device->syn_drop_limit, 30ULL * 1000, 5);
+	ratelimit_init(&device->syn_drop_limit, s2us(30), 5);
 
 	matrix_init_identity(&device->abs.calibration);
 	matrix_init_identity(&device->abs.usermatrix);
diff --git a/src/filter.c b/src/filter.c
index 35449f5..0d8818f 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -77,7 +77,7 @@ filter_get_speed(struct motion_filter *filter)
  * Default parameters for pointer acceleration profiles.
  */
 
-#define DEFAULT_THRESHOLD 0.4			/* in units/ms */
+#define DEFAULT_THRESHOLD 0.0004		/* in units/us */
 #define DEFAULT_ACCELERATION 2.0		/* unitless factor */
 #define DEFAULT_INCLINE 1.1			/* unitless factor */
 
@@ -85,13 +85,13 @@ filter_get_speed(struct motion_filter *filter)
  * Pointer acceleration filter constants
  */
 
-#define MAX_VELOCITY_DIFF	1.0 /* units/ms */
-#define MOTION_TIMEOUT		1000 /* (ms) */
+#define MAX_VELOCITY_DIFF	0.001 /* units/us */
+#define MOTION_TIMEOUT		s2us(1)
 #define NUM_POINTER_TRACKERS	16
 
 struct pointer_tracker {
 	struct normalized_coords delta; /* delta to most recent event */
-	uint64_t time;  /* ms */
+	uint64_t time;  /* us */
 	int dir;
 };
 
@@ -101,14 +101,14 @@ struct pointer_accelerator {
 
 	accel_profile_func_t profile;
 
-	double velocity;	/* units/ms */
-	double last_velocity;	/* units/ms */
+	double velocity;	/* units/us */
+	double last_velocity;	/* units/us */
 	struct normalized_coords last;
 
 	struct pointer_tracker *trackers;
 	int cur_tracker;
 
-	double threshold;	/* units/ms */
+	double threshold;	/* units/us */
 	double accel;		/* unitless factor */
 	double incline;		/* incline of the function */
 
@@ -150,8 +150,7 @@ static double
 calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time)
 {
 	double tdelta = time - tracker->time + 1;
-
-	return normalized_length(tracker->delta) / tdelta; /* units/ms */
+	return normalized_length(tracker->delta) / tdelta; /* units/us */
 }
 
 static inline double
@@ -221,7 +220,7 @@ calculate_velocity(struct pointer_accelerator *accel, uint64_t time)
 		}
 	}
 
-	return result; /* units/ms */
+	return result; /* units/us */
 }
 
 static double
@@ -261,7 +260,7 @@ accelerator_filter(struct motion_filter *filter,
 {
 	struct pointer_accelerator *accel =
 		(struct pointer_accelerator *) filter;
-	double velocity; /* units/ms */
+	double velocity; /* units/us */
 	double accel_value; /* unitless factor */
 	struct normalized_coords accelerated;
 	struct normalized_coords unnormalized;
@@ -334,9 +333,9 @@ accelerator_set_speed(struct motion_filter *filter,
 	assert(speed >= -1.0 && speed <= 1.0);
 
 	/* delay when accel kicks in */
-	accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4.0;
-	if (accel_filter->threshold < 0.2)
-		accel_filter->threshold = 0.2;
+	accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4000.0;
+	if (accel_filter->threshold < 0.0002)
+		accel_filter->threshold = 0.0002;
 
 	/* adjust max accel factor */
 	accel_filter->accel = DEFAULT_ACCELERATION + speed * 1.5;
@@ -398,7 +397,7 @@ create_pointer_accelerator_filter(accel_profile_func_t profile,
 double
 pointer_accel_profile_linear_low_dpi(struct motion_filter *filter,
 				     void *data,
-				     double speed_in, /* in device units */
+				     double speed_in, /* in device units (units/us) */
 				     uint64_t time)
 {
 	struct pointer_accelerator *accel_filter =
@@ -406,15 +405,15 @@ pointer_accel_profile_linear_low_dpi(struct motion_filter *filter,
 
 	double s1, s2;
 	double max_accel = accel_filter->accel; /* unitless factor */
-	const double threshold = accel_filter->threshold; /* units/ms */
+	const double threshold = accel_filter->threshold; /* units/us */
 	const double incline = accel_filter->incline;
 	double factor;
 	double dpi_factor = accel_filter->dpi_factor;
 
 	max_accel /= dpi_factor;
 
-	s1 = min(1, 0.3 + speed_in * 10);
-	s2 = 1 + (speed_in - threshold * dpi_factor) * incline;
+	s1 = min(1, 0.3 + speed_in * 10000.0);
+	s2 = 1 + (speed_in * 1000.0 - threshold * dpi_factor * 1000.0) * incline;
 
 	factor = min(max_accel, s2 > 1 ? s2 : s1);
 
@@ -432,12 +431,12 @@ pointer_accel_profile_linear(struct motion_filter *filter,
 
 	double s1, s2;
 	const double max_accel = accel_filter->accel; /* unitless factor */
-	const double threshold = accel_filter->threshold; /* units/ms */
+	const double threshold = accel_filter->threshold; /* units/us */
 	const double incline = accel_filter->incline;
 	double factor;
 
-	s1 = min(1, 0.3 + speed_in * 10);
-	s2 = 1 + (speed_in - threshold) * incline;
+	s1 = min(1, 0.3 + speed_in * 10 * 1000.0);
+	s2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline;
 
 	factor =  min(max_accel, s2 > 1 ? s2 : s1);
 
@@ -489,7 +488,7 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
 	const double max_accel = accel_filter->accel *
 				  TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */
 	const double threshold = accel_filter->threshold /
-				  TP_MAGIC_LOW_RES_FACTOR; /* units/ms */
+				  TP_MAGIC_LOW_RES_FACTOR; /* units/us */
 	const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR;
 
 	speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 110955d..dc9cc66 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -413,6 +413,24 @@ touch_notify_frame(struct libinput_device *device,
 		   uint64_t time);
 
 static inline uint64_t
+us(uint64_t us)
+{
+	return us;
+}
+
+static inline uint64_t
+ms2us(uint64_t ms)
+{
+	return us(ms * 1000);
+}
+
+static inline uint64_t
+s2us(uint64_t s)
+{
+	return ms2us(s * 1000);
+}
+
+static inline uint64_t
 libinput_now(struct libinput *libinput)
 {
 	struct timespec ts = { 0, 0 };
@@ -422,7 +440,7 @@ libinput_now(struct libinput *libinput)
 		return 0;
 	}
 
-	return ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000;
+	return s2us(ts.tv_sec) + ts.tv_nsec / 1000;
 }
 
 static inline struct device_float_coords
diff --git a/src/libinput-util.c b/src/libinput-util.c
index a383fa1..62b5942 100644
--- a/src/libinput-util.c
+++ b/src/libinput-util.c
@@ -72,9 +72,9 @@ list_empty(const struct list *list)
 }
 
 void
-ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst)
+ratelimit_init(struct ratelimit *r, uint64_t ival_us, unsigned int burst)
 {
-	r->interval = ival_ms;
+	r->interval = ival_us;
 	r->begin = 0;
 	r->burst = burst;
 	r->num = 0;
@@ -97,17 +97,17 @@ enum ratelimit_state
 ratelimit_test(struct ratelimit *r)
 {
 	struct timespec ts;
-	uint64_t mtime;
+	uint64_t utime;
 
 	if (r->interval <= 0 || r->burst <= 0)
 		return RATELIMIT_PASS;
 
 	clock_gettime(CLOCK_MONOTONIC, &ts);
-	mtime = ts.tv_sec * 1000 + ts.tv_nsec / 1000 / 1000;
+	utime = s2us(ts.tv_sec) + ts.tv_nsec / 1000ULL;
 
-	if (r->begin <= 0 || r->begin + r->interval < mtime) {
+	if (r->begin <= 0 || r->begin + r->interval < utime) {
 		/* reset counter */
-		r->begin = mtime;
+		r->begin = utime;
 		r->num = 1;
 		return RATELIMIT_PASS;
 	} else if (r->num < r->burst) {
diff --git a/src/libinput.c b/src/libinput.c
index cab6224..fe4df46 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -86,7 +86,7 @@ struct libinput_event_device_notify {
 
 struct libinput_event_keyboard {
 	struct libinput_event base;
-	uint32_t time;
+	uint64_t time;
 	uint32_t key;
 	uint32_t seat_key_count;
 	enum libinput_key_state state;
@@ -94,7 +94,7 @@ struct libinput_event_keyboard {
 
 struct libinput_event_pointer {
 	struct libinput_event base;
-	uint32_t time;
+	uint64_t time;
 	struct normalized_coords delta;
 	struct device_float_coords delta_raw;
 	struct device_coords absolute;
@@ -108,7 +108,7 @@ struct libinput_event_pointer {
 
 struct libinput_event_touch {
 	struct libinput_event base;
-	uint32_t time;
+	uint64_t time;
 	int32_t slot;
 	int32_t seat_slot;
 	struct device_coords point;
@@ -116,7 +116,7 @@ struct libinput_event_touch {
 
 struct libinput_event_gesture {
 	struct libinput_event base;
-	uint32_t time;
+	uint64_t time;
 	int finger_count;
 	int cancelled;
 	struct normalized_coords delta;
@@ -284,6 +284,17 @@ libinput_event_keyboard_get_time(struct libinput_event_keyboard *event)
 			   0,
 			   LIBINPUT_EVENT_KEYBOARD_KEY);
 
+	return (uint32_t)(event->time / 1000);
+}
+
+LIBINPUT_EXPORT uint64_t
+libinput_event_keyboard_get_time_usec(struct libinput_event_keyboard *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0,
+			   LIBINPUT_EVENT_KEYBOARD_KEY);
+
 	return event->time;
 }
 
@@ -332,6 +343,20 @@ libinput_event_pointer_get_time(struct libinput_event_pointer *event)
 			   LIBINPUT_EVENT_POINTER_BUTTON,
 			   LIBINPUT_EVENT_POINTER_AXIS);
 
+	return (uint32_t)(event->time / 1000);
+}
+
+LIBINPUT_EXPORT uint64_t
+libinput_event_pointer_get_time_usec(struct libinput_event_pointer *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0,
+			   LIBINPUT_EVENT_POINTER_MOTION,
+			   LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE,
+			   LIBINPUT_EVENT_POINTER_BUTTON,
+			   LIBINPUT_EVENT_POINTER_AXIS);
+
 	return event->time;
 }
 
@@ -571,6 +596,21 @@ libinput_event_touch_get_time(struct libinput_event_touch *event)
 			   LIBINPUT_EVENT_TOUCH_CANCEL,
 			   LIBINPUT_EVENT_TOUCH_FRAME);
 
+	return (uint32_t)(event->time / 1000);
+}
+
+LIBINPUT_EXPORT uint64_t
+libinput_event_touch_get_time_usec(struct libinput_event_touch *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0,
+			   LIBINPUT_EVENT_TOUCH_DOWN,
+			   LIBINPUT_EVENT_TOUCH_UP,
+			   LIBINPUT_EVENT_TOUCH_MOTION,
+			   LIBINPUT_EVENT_TOUCH_CANCEL,
+			   LIBINPUT_EVENT_TOUCH_FRAME);
+
 	return event->time;
 }
 
@@ -677,6 +717,22 @@ libinput_event_gesture_get_time(struct libinput_event_gesture *event)
 			   LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
 			   LIBINPUT_EVENT_GESTURE_SWIPE_END);
 
+	return (uint32_t)(event->time / 1000);
+}
+
+LIBINPUT_EXPORT uint64_t
+libinput_event_gesture_get_time_usec(struct libinput_event_gesture *event)
+{
+	require_event_type(libinput_event_get_context(&event->base),
+			   event->base.type,
+			   0,
+			   LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
+			   LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
+			   LIBINPUT_EVENT_GESTURE_PINCH_END,
+			   LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
+			   LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
+			   LIBINPUT_EVENT_GESTURE_SWIPE_END);
+
 	return event->time;
 }
 
diff --git a/src/libinput.h b/src/libinput.h
index f9a7d68..c09b3f0 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -421,6 +421,14 @@ libinput_event_keyboard_get_time(struct libinput_event_keyboard *event);
 /**
  * @ingroup event_keyboard
  *
+ * @return The event time for this event in micro seconds
+ */
+uint64_t
+libinput_event_keyboard_get_time_usec(struct libinput_event_keyboard *event);
+
+/**
+ * @ingroup event_keyboard
+ *
  * @return The keycode that triggered this key event
  */
 uint32_t
@@ -476,6 +484,14 @@ libinput_event_pointer_get_time(struct libinput_event_pointer *event);
 /**
  * @ingroup event_pointer
  *
+ * @return The event time for this event in micro seconds
+ */
+uint64_t
+libinput_event_pointer_get_time_usec(struct libinput_event_pointer *event);
+
+/**
+ * @ingroup event_pointer
+ *
  * Return the delta between the last event and the current event. For pointer
  * events that are not of type @ref LIBINPUT_EVENT_POINTER_MOTION, this
  * function returns 0.
@@ -818,6 +834,14 @@ libinput_event_touch_get_time(struct libinput_event_touch *event);
 /**
  * @ingroup event_touch
  *
+ * @return The event time for this event in micro seconds
+ */
+uint64_t
+libinput_event_touch_get_time_usec(struct libinput_event_touch *event);
+
+/**
+ * @ingroup event_touch
+ *
  * Get the slot of this touch event. See the kernel's multitouch
  * protocol B documentation for more information.
  *
@@ -970,6 +994,14 @@ libinput_event_gesture_get_time(struct libinput_event_gesture *event);
 /**
  * @ingroup event_gesture
  *
+ * @return The event time for this event in micro seconds
+ */
+uint64_t
+libinput_event_gesture_get_time_usec(struct libinput_event_gesture *event);
+
+/**
+ * @ingroup event_gesture
+ *
  * @return The generic libinput_event of this event
  */
 struct libinput_event *
diff --git a/src/libinput.sym b/src/libinput.sym
index d7d12e4..7e0ef1c 100644
--- a/src/libinput.sym
+++ b/src/libinput.sym
@@ -167,4 +167,8 @@ LIBINPUT_0.21.0 {
 	libinput_device_config_dwt_set_enabled;
 	libinput_device_config_dwt_get_enabled;
 	libinput_device_config_dwt_get_default_enabled;
+	libinput_event_gesture_get_time_usec;
+	libinput_event_keyboard_get_time_usec;
+	libinput_event_pointer_get_time_usec;
+	libinput_event_touch_get_time_usec;
 } LIBINPUT_0.20.0;
diff --git a/src/timer.c b/src/timer.c
index a945f78..e8fb0b5 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -57,8 +57,8 @@ libinput_timer_arm_timer_fd(struct libinput *libinput)
 	}
 
 	if (earliest_expire != UINT64_MAX) {
-		its.it_value.tv_sec = earliest_expire / 1000;
-		its.it_value.tv_nsec = (earliest_expire % 1000) * 1000 * 1000;
+		its.it_value.tv_sec = earliest_expire / s2us(1);
+		its.it_value.tv_nsec = (earliest_expire % s2us(1)) * 1000;
 	}
 
 	r = timerfd_settime(libinput->timer.fd, TFD_TIMER_ABSTIME, &its, NULL);
@@ -74,7 +74,7 @@ libinput_timer_set(struct libinput_timer *timer, uint64_t expire)
 	if (expire < now)
 		log_bug_libinput(timer->libinput,
 				 "timer offset negative\n");
-	else if ((expire - now) > 5000ULL)
+	else if ((expire - now) > s2us(5))
 		log_bug_libinput(timer->libinput,
 				 "timer offset more than 5s, now %"
 				 PRIu64 " expire %" PRIu64 "\n",
diff --git a/src/timer.h b/src/timer.h
index b005fbb..f8315cf 100644
--- a/src/timer.h
+++ b/src/timer.h
@@ -33,7 +33,7 @@ struct libinput;
 struct libinput_timer {
 	struct libinput *libinput;
 	struct list link;
-	uint64_t expire; /* in absolute ms CLOCK_MONOTONIC */
+	uint64_t expire; /* in absolute us CLOCK_MONOTONIC */
 	void (*timer_func)(uint64_t now, void *timer_func_data);
 	void *timer_func_data;
 };
@@ -43,7 +43,7 @@ libinput_timer_init(struct libinput_timer *timer, struct libinput *libinput,
 		    void (*timer_func)(uint64_t now, void *timer_func_data),
 		    void *timer_func_data);
 
-/* Set timer expire time, in absolute ms CLOCK_MONOTONIC */
+/* Set timer expire time, in absolute us CLOCK_MONOTONIC */
 void
 libinput_timer_set(struct libinput_timer *timer, uint64_t expire);
 
diff --git a/test/gestures.c b/test/gestures.c
index b9d7325..3b7ba7b 100644
--- a/test/gestures.c
+++ b/test/gestures.c
@@ -349,6 +349,41 @@ START_TEST(gestures_spread)
 }
 END_TEST
 
+START_TEST(gestures_time_usec)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_gesture *gevent;
+
+	if (libevdev_get_num_slots(dev->evdev) < 3)
+		return;
+
+	litest_drain_events(li);
+
+	litest_touch_down(dev, 0, 40, 40);
+	litest_touch_down(dev, 1, 40, 50);
+	litest_touch_down(dev, 2, 40, 60);
+	libinput_dispatch(li);
+	litest_touch_move_three_touches(dev,
+					40, 40,
+					40, 50,
+					40, 60,
+					0, 30,
+					4, 2);
+
+	litest_wait_for_event(li);
+
+	event = libinput_get_event(li);
+	gevent = litest_is_gesture_event(event,
+					 LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
+					 3);
+	ck_assert_int_eq(libinput_event_gesture_get_time(gevent),
+			 libinput_event_gesture_get_time_usec(gevent) / 1000);
+	libinput_event_destroy(event);
+}
+END_TEST
+
 void
 litest_setup_tests(void)
 {
@@ -361,4 +396,6 @@ litest_setup_tests(void)
 	litest_add_ranged("gestures:swipe", gestures_swipe_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals);
 	litest_add_ranged("gestures:pinch", gestures_pinch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals);
 	litest_add_ranged("gestures:pinch", gestures_spread, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals);
+
+	litest_add("gesture:time", gestures_time_usec, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
 }
diff --git a/test/keyboard.c b/test/keyboard.c
index 204d57c..4eed814 100644
--- a/test/keyboard.c
+++ b/test/keyboard.c
@@ -311,6 +311,32 @@ START_TEST(keyboard_keys_bad_device)
 }
 END_TEST
 
+START_TEST(keyboard_time_usec)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event_keyboard *kev;
+	struct libinput_event *event;
+
+	litest_drain_events(dev->libinput);
+
+	litest_keyboard_key(dev, KEY_A, true);
+
+	litest_wait_for_event(li);
+
+	event = libinput_get_event(li);
+	kev = litest_is_keyboard_event(event,
+				       KEY_A,
+				       LIBINPUT_KEY_STATE_PRESSED);
+
+	ck_assert_int_eq(libinput_event_keyboard_get_time(kev),
+			 libinput_event_keyboard_get_time_usec(kev) / 1000);
+
+	libinput_event_destroy(event);
+	litest_drain_events(dev->libinput);
+}
+END_TEST
+
 void
 litest_setup_tests(void)
 {
@@ -319,4 +345,5 @@ litest_setup_tests(void)
 	litest_add_no_device("keyboard:key counting", keyboard_key_auto_release);
 	litest_add("keyboard:keys", keyboard_has_key, LITEST_KEYS, LITEST_ANY);
 	litest_add("keyboard:keys", keyboard_keys_bad_device, LITEST_ANY, LITEST_ANY);
+	litest_add("keyboard:time", keyboard_time_usec, LITEST_KEYS, LITEST_ANY);
 }
diff --git a/test/misc.c b/test/misc.c
index 6412b3b..99aa707 100644
--- a/test/misc.c
+++ b/test/misc.c
@@ -507,7 +507,7 @@ START_TEST(ratelimit_helpers)
 	unsigned int i, j;
 
 	/* 10 attempts every 100ms */
-	ratelimit_init(&rl, 100, 10);
+	ratelimit_init(&rl, 100000, 10);
 
 	for (j = 0; j < 3; ++j) {
 		/* a burst of 9 attempts must succeed */
diff --git a/test/pointer.c b/test/pointer.c
index 10b9fdc..f711d38 100644
--- a/test/pointer.c
+++ b/test/pointer.c
@@ -1419,6 +1419,32 @@ START_TEST(middlebutton_default_disabled)
 }
 END_TEST
 
+START_TEST(pointer_time_usec)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event_pointer *ptrev;
+	struct libinput_event *event;
+
+	litest_drain_events(dev->libinput);
+
+	litest_event(dev, EV_REL, REL_X, 1);
+	litest_event(dev, EV_REL, REL_Y, 1);
+	litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+	litest_wait_for_event(li);
+
+	event = libinput_get_event(li);
+	ptrev = litest_is_motion_event(event);
+
+	ck_assert_int_eq(libinput_event_pointer_get_time(ptrev),
+			 libinput_event_pointer_get_time_usec(ptrev) / 1000);
+
+	libinput_event_destroy(event);
+	litest_drain_events(dev->libinput);
+}
+END_TEST
+
 void
 litest_setup_tests(void)
 {
@@ -1466,4 +1492,6 @@ litest_setup_tests(void)
 	litest_add_for_device("pointer:middlebutton", middlebutton_default_alps, LITEST_ALPS_SEMI_MT);
 
 	litest_add_ranged("pointer:state", pointer_absolute_initial_state, LITEST_ABSOLUTE, LITEST_ANY, &axis_range);
+
+	litest_add("pointer:time", pointer_time_usec, LITEST_RELATIVE, LITEST_ANY);
 }
diff --git a/test/touch.c b/test/touch.c
index b519613..eae8007 100644
--- a/test/touch.c
+++ b/test/touch.c
@@ -652,6 +652,27 @@ START_TEST(touch_initial_state)
 }
 END_TEST
 
+START_TEST(touch_time_usec)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_touch *tev;
+
+	litest_drain_events(dev->libinput);
+
+	litest_touch_down(dev, 0, 10, 10);
+
+	litest_wait_for_event(li);
+
+	event = libinput_get_event(li);
+	tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN);
+	ck_assert_int_eq(libinput_event_touch_get_time(tev),
+			 libinput_event_touch_get_time_usec(tev) / 1000);
+	libinput_event_destroy(event);
+}
+END_TEST
+
 void
 litest_setup_tests(void)
 {
@@ -678,4 +699,6 @@ litest_setup_tests(void)
 	litest_add("touch:protocol a", touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY);
 
 	litest_add_ranged("touch:state", touch_initial_state, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes);
+
+	litest_add("touch:time", touch_time_usec, LITEST_TOUCH, LITEST_TOUCHPAD);
 }
diff --git a/test/touchpad.c b/test/touchpad.c
index 5db79f8..1935d19 100644
--- a/test/touchpad.c
+++ b/test/touchpad.c
@@ -3458,6 +3458,40 @@ START_TEST(touchpad_tool_tripletap_touch_count)
 }
 END_TEST
 
+START_TEST(touchpad_time_usec)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_pointer *ptrev;
+
+	litest_disable_tap(dev->libinput_device);
+
+	litest_drain_events(li);
+
+	litest_touch_down(dev, 0, 50, 50);
+	litest_touch_move_to(dev, 0, 50, 50, 80, 50, 5, 0);
+	litest_touch_up(dev, 0);
+
+	libinput_dispatch(li);
+
+	event = libinput_get_event(li);
+	ck_assert_notnull(event);
+
+	while (event) {
+		uint64_t utime;
+
+		ptrev = litest_is_motion_event(event);
+		utime = libinput_event_pointer_get_time_usec(ptrev);
+
+		ck_assert_int_eq(libinput_event_pointer_get_time(ptrev),
+				 utime / 1000);
+		libinput_event_destroy(event);
+		event = libinput_get_event(li);
+	}
+}
+END_TEST
+
 void
 litest_setup_tests(void)
 {
@@ -3562,4 +3596,6 @@ litest_setup_tests(void)
 	litest_add("touchpad:thumb", touchpad_thumb_tap_hold_2ndfg_tap, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH);
 
 	litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count, LITEST_SYNAPTICS_TOPBUTTONPAD);
+
+	litest_add("touchpad:time", touchpad_time_usec, LITEST_TOUCHPAD, LITEST_ANY);
 }
diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c
index b2dd1f9..6dad7f0 100644
--- a/tools/ptraccel-debug.c
+++ b/tools/ptraccel-debug.c
@@ -26,12 +26,14 @@
 #include <errno.h>
 #include <stdbool.h>
 #include <stdio.h>
-#include <filter.h>
 #include <getopt.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
+#include <filter.h>
+#include <libinput-private.h>
+
 static void
 print_ptraccel_deltas(struct motion_filter *filter, double step)
 {
@@ -50,7 +52,7 @@ print_ptraccel_deltas(struct motion_filter *filter, double step)
 	for (i = 0.0; i < 15.0; i += step) {
 		motion.x = i;
 		motion.y = 0;
-		time += 12; /* pretend 80Hz data */
+		time += us(12500); /* pretend 80Hz data */
 
 		motion = filter_dispatch(filter, &motion, NULL, time);
 
@@ -93,7 +95,7 @@ print_ptraccel_movement(struct motion_filter *filter,
 	for (i = 0; i < nevents; i++) {
 		motion.x = dx;
 		motion.y = 0;
-		time += 12; /* pretend 80Hz data */
+		time += us(12500); /* pretend 80Hz data */
 
 		motion = filter_dispatch(filter, &motion, NULL, time);
 
@@ -127,7 +129,7 @@ print_ptraccel_sequence(struct motion_filter *filter,
 	for (i = 0; i < nevents; i++, dx++) {
 		motion.x = *dx;
 		motion.y = 0;
-		time += 12; /* pretend 80Hz data */
+		time += us(12500); /* pretend 80Hz data */
 
 		motion = filter_dispatch(filter, &motion, NULL, time);
 
-- 
2.1.0



More information about the wayland-devel mailing list