[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