[PATCH weston] input: Schedule pointer sprite repaint when cursor is set

Jonas Ådahl jadahl at gmail.com
Mon Sep 8 10:33:41 PDT 2014


If a cursor was set with wl_pointer.set_cursor but not in combination
with an action that has the side effect of damaging the region where the
cursor is positioned, it would not be drawn. This patch explicitly
schedules a repaint of the pointer sprite when it is set.

clickdot is updated to illustrate the bug; when moving the pointer over
clickdot, the pointer is hidden. When not having moved the pointer for
500 ms it is made visible using wl_pointer.set_pointer.

Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
---
 clients/clickdot.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/input.c        |  4 +++-
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/clients/clickdot.c b/clients/clickdot.c
index e09cb14..5137ba6 100644
--- a/clients/clickdot.c
+++ b/clients/clickdot.c
@@ -31,6 +31,9 @@
 #include <cairo.h>
 #include <math.h>
 #include <assert.h>
+#include <sys/timerfd.h>
+#include <sys/epoll.h>
+#include <unistd.h>
 
 #include <linux/input.h>
 #include <wayland-client.h>
@@ -54,6 +57,10 @@ struct clickdot {
 	} line;
 
 	int reset;
+
+	struct input *cursor_timeout_input;
+	int cursor_timeout_fd;
+	struct task cursor_timeout_task;
 };
 
 static void
@@ -211,6 +218,19 @@ button_handler(struct widget *widget,
 	widget_schedule_redraw(widget);
 }
 
+static void
+cursor_timeout_reset(struct clickdot *clickdot)
+{
+	const long cursor_timeout = 500;
+	struct itimerspec its;
+
+	its.it_interval.tv_sec = 0;
+	its.it_interval.tv_nsec = 0;
+	its.it_value.tv_sec = cursor_timeout / 1000;
+	its.it_value.tv_nsec = (cursor_timeout % 1000) * 1000 * 1000;
+	timerfd_settime(clickdot->cursor_timeout_fd, 0, &its, NULL);
+}
+
 static int
 motion_handler(struct widget *widget,
 	       struct input *input, uint32_t time,
@@ -222,7 +242,10 @@ motion_handler(struct widget *widget,
 
 	window_schedule_redraw(clickdot->window);
 
-	return CURSOR_LEFT_PTR;
+	cursor_timeout_reset(clickdot);
+	clickdot->cursor_timeout_input = input;
+
+	return CURSOR_BLANK;
 }
 
 static void
@@ -244,6 +267,21 @@ leave_handler(struct widget *widget,
 	clickdot->reset = 1;
 }
 
+static void
+cursor_timeout_func(struct task *task, uint32_t events)
+{
+	struct clickdot *clickdot =
+		container_of(task, struct clickdot, cursor_timeout_task);
+	uint64_t exp;
+
+	if (read(clickdot->cursor_timeout_fd, &exp, sizeof (uint64_t)) !=
+	    sizeof(uint64_t))
+		abort();
+
+	input_set_pointer_image(clickdot->cursor_timeout_input,
+				CURSOR_LEFT_PTR);
+}
+
 static struct clickdot *
 clickdot_create(struct display *display)
 {
@@ -276,12 +314,22 @@ clickdot_create(struct display *display)
 	clickdot->line.old_y = -1;
 	clickdot->reset = 0;
 
+	clickdot->cursor_timeout_fd =
+		timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+	clickdot->cursor_timeout_task.run = cursor_timeout_func;
+	display_watch_fd(window_get_display(clickdot->window),
+			 clickdot->cursor_timeout_fd,
+			 EPOLLIN, &clickdot->cursor_timeout_task);
+
 	return clickdot;
 }
 
 static void
 clickdot_destroy(struct clickdot *clickdot)
 {
+	display_unwatch_fd(window_get_display(clickdot->window),
+			   clickdot->cursor_timeout_fd);
+	close(clickdot->cursor_timeout_fd);
 	if (clickdot->buffer)
 		cairo_surface_destroy(clickdot->buffer);
 	widget_destroy(clickdot->widget);
diff --git a/src/input.c b/src/input.c
index 5e82f5d..530904d 100644
--- a/src/input.c
+++ b/src/input.c
@@ -1665,8 +1665,10 @@ pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
 	pointer->hotspot_x = x;
 	pointer->hotspot_y = y;
 
-	if (surface->buffer_ref.buffer)
+	if (surface->buffer_ref.buffer) {
 		pointer_cursor_surface_configure(surface, 0, 0);
+		weston_view_schedule_repaint(pointer->sprite);
+	}
 }
 
 static void
-- 
1.8.5.1



More information about the wayland-devel mailing list