[RFC PATCH weston 2/2] clients: add fake kinetic-scrolling to eventdemo

Peter Hutterer peter.hutterer at who-t.net
Sun Mar 8 20:28:06 PDT 2015


Very much a proof-of-concept only.
---
 clients/eventdemo.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/clients/eventdemo.c b/clients/eventdemo.c
index 57aa716..e4e4283 100644
--- a/clients/eventdemo.c
+++ b/clients/eventdemo.c
@@ -34,6 +34,9 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/timerfd.h>
+#include <sys/epoll.h>
+#include <unistd.h>
 
 #include <cairo.h>
 
@@ -91,6 +94,14 @@ struct eventdemo {
 	struct display *display;
 
 	int x, y, w, h;
+
+	int scroll_timeout_fd;
+	struct task scroll_timeout_task;
+	int scroll_max_timeout;
+	int scroll_next_timeout;
+	uint32_t scroll_last_time;
+	double scroll_ms_value;
+	double scroll_speed;
 };
 
 /**
@@ -234,6 +245,18 @@ button_handler(struct widget *widget, struct input *input, uint32_t time,
 	       x, y);
 }
 
+static void
+scroll_timeout_reset(struct eventdemo *e)
+{
+	struct itimerspec its;
+
+	its.it_interval.tv_sec = 0;
+	its.it_interval.tv_nsec = 0;
+	its.it_value.tv_sec = e->scroll_next_timeout / 1000;
+	its.it_value.tv_nsec = (e->scroll_next_timeout % 1000) * 1000 * 1000;
+	timerfd_settime(e->scroll_timeout_fd, 0, &its, NULL);
+}
+
 /**
  * \brief CALLBACK function, Wayland informs about axis event
  * \param widget widget
@@ -252,6 +275,7 @@ axis_handler(struct widget *widget,
 	     enum wl_pointer_axis_source_flags flags,
 	     void *data)
 {
+	struct eventdemo *e = data;
 	const char *axis_source;
 	const char *stop_scroll;
 
@@ -285,6 +309,23 @@ axis_handler(struct widget *widget,
 	       axis_source,
 	       wl_fixed_to_double(value),
 	       stop_scroll);
+
+	if (flags & WL_POINTER_AXIS_SOURCE_FLAGS_STOP_SCROLL) {
+		if (time == e->scroll_last_time)
+			e->scroll_speed = e->scroll_ms_value/(time - e->scroll_last_time);
+		e->scroll_max_timeout = abs(e->scroll_speed * 1000);
+		e->scroll_next_timeout = 20;
+		scroll_timeout_reset(e);
+	} else if (source == WL_POINTER_AXIS_SOURCE_FINGER) {
+		uint32_t tdelta = time - e->scroll_last_time;
+		if (tdelta == 0) {
+			e->scroll_ms_value += wl_fixed_to_double(value);
+		} else {
+			e->scroll_speed = e->scroll_ms_value/(time - e->scroll_last_time);
+			e->scroll_ms_value = 0;
+			e->scroll_last_time = time;
+		}
+	}
 }
 
 /**
@@ -317,6 +358,26 @@ motion_handler(struct widget *widget, struct input *input, uint32_t time,
 	return CURSOR_LEFT_PTR;
 }
 
+static void
+scroll_timeout_func(struct task *task, uint32_t events)
+{
+	struct eventdemo *e =
+		container_of(task, struct eventdemo, scroll_timeout_task);
+	uint64_t exp;
+
+	if (read(e->scroll_timeout_fd, &exp, sizeof (uint64_t)) !=
+	    sizeof(uint64_t))
+		abort();
+
+	e->scroll_next_timeout *= 1.50;
+	if (e->scroll_next_timeout < e->scroll_max_timeout) {
+		scroll_timeout_reset(e);
+		printf("Wheee!\n");
+	} else {
+		printf("Doink!\n");
+	}
+}
+
 /**
  * \brief Create and initialise a new eventdemo window.
  * The returned eventdemo instance should be destroyed using \c eventdemo_destroy().
@@ -381,6 +442,12 @@ eventdemo_create(struct display *d)
 	/* Initial drawing of the window */
 	window_schedule_resize(e->window, width, height);
 
+	e->scroll_timeout_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+	e->scroll_timeout_task.run = scroll_timeout_func;
+	display_watch_fd(window_get_display(e->window),
+			 e->scroll_timeout_fd,
+			 EPOLLIN, &e->scroll_timeout_task);
+
 	return e;
 }
 /**
-- 
2.1.0



More information about the wayland-devel mailing list