[PATCH wayland 06/10] Add cursor object representing the visible pointer

Daniel Stone daniel at fooishbar.org
Mon Jul 23 11:54:43 PDT 2012


The wl_cursor object represents a visible on-screen cursor, with
co-ordinates and a surface image.  Add hooks for compositors to be able
to discover new cursors and be informed when they change, and have the
core implementation track the location.

Signed-off-by: Daniel Stone <daniel at fooishbar.org>
---
 src/data-device.c    |   30 +++++++++++++++++-----
 src/wayland-server.c |   69 +++++++++++++++++++++++++++++++++++++++++++++++---
 src/wayland-server.h |   27 ++++++++++++++++++--
 3 files changed, 115 insertions(+), 11 deletions(-)

diff --git a/src/data-device.c b/src/data-device.c
index 82020af..c19e14f 100644
--- a/src/data-device.c
+++ b/src/data-device.c
@@ -212,6 +212,12 @@ drag_grab_focus(struct wl_pointer_grab *grab,
 		      &seat->drag_focus_listener);
 	seat->drag_focus_resource = resource;
 	grab->focus = surface;
+
+	seat->pointer->cursor.icon = seat->drag_cursor.icon;
+	seat->pointer->cursor.x = seat->pointer->x;
+	seat->pointer->cursor.y = seat->pointer->y;
+	wl_signal_emit(&seat->pointer->cursor.update_signal,
+		       &seat->pointer->cursor);
 }
 
 static void
@@ -223,6 +229,11 @@ drag_grab_motion(struct wl_pointer_grab *grab,
 	if (seat->drag_focus_resource)
 		wl_data_device_send_motion(seat->drag_focus_resource,
 					   time, x, y);
+
+	seat->pointer->cursor.x = seat->pointer->x;
+	seat->pointer->cursor.y = seat->pointer->y;
+	wl_signal_emit(&seat->pointer->cursor.update_signal,
+		       &seat->pointer->cursor);
 }
 
 static void
@@ -231,14 +242,15 @@ data_device_end_drag_grab(struct wl_seat *seat)
 	struct wl_resource *surface_resource;
 	struct wl_surface_interface *implementation;
 
-	if (seat->drag_surface) {
-		surface_resource = &seat->drag_surface->resource;
+	if (seat->drag_cursor.icon) {
+		surface_resource = &seat->drag_cursor.icon->resource;
 		implementation = (struct wl_surface_interface *)
 			surface_resource->object.implementation;
 
 		implementation->attach(surface_resource->client,
 				       surface_resource, NULL, 0, 0);
 		wl_list_remove(&seat->drag_icon_listener.link);
+		seat->drag_cursor.icon = NULL;
 	}
 
 	drag_grab_focus(&seat->drag_grab, NULL,
@@ -247,7 +259,7 @@ data_device_end_drag_grab(struct wl_seat *seat)
 	wl_pointer_end_grab(seat->pointer);
 
 	seat->drag_data_source = NULL;
-	seat->drag_surface = NULL;
+	seat->drag_cursor.icon = NULL;
 	seat->drag_client = NULL;
 }
 
@@ -292,7 +304,12 @@ destroy_data_device_icon(struct wl_listener *listener, void *data)
 	struct wl_seat *seat = container_of(listener, struct wl_seat,
 					    drag_icon_listener);
 
-	seat->drag_surface = NULL;
+	if (seat->pointer->cursor.icon == seat->drag_cursor.icon) {
+		seat->pointer->cursor.icon = NULL;
+		wl_signal_emit(&seat->pointer->cursor.update_signal,
+			       &seat->pointer->cursor);
+	}
+	seat->drag_cursor.icon = NULL;
 }
 
 static void
@@ -322,11 +339,12 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
 	}
 
 	if (icon_resource) {
-		seat->drag_surface = icon_resource->data;
+		seat->drag_cursor.icon = icon_resource->data;
+		seat->drag_cursor.hotspot_x = 0;
+		seat->drag_cursor.hotspot_y = 0;
 		seat->drag_icon_listener.notify = destroy_data_device_icon;
 		wl_signal_add(&icon_resource->destroy_signal,
 			      &seat->drag_icon_listener);
-		wl_signal_emit(&seat->drag_icon_signal, icon_resource);
 	}
 
 	wl_pointer_set_focus(seat->pointer, NULL,
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 88e8433..f9d2522 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -519,6 +519,13 @@ default_grab_focus(struct wl_pointer_grab *grab,
 		return;
 
 	wl_pointer_set_focus(pointer, surface, x, y);
+
+	pointer->cursor.icon = pointer->saved_cursor.icon;
+	pointer->cursor.hotspot_x = pointer->saved_cursor.hotspot_x;
+	pointer->cursor.hotspot_y = pointer->saved_cursor.hotspot_y;
+	pointer->cursor.x = pointer->x;
+	pointer->cursor.y = pointer->y;
+	wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
 }
 
 static void
@@ -526,10 +533,15 @@ default_grab_motion(struct wl_pointer_grab *grab,
 		    uint32_t time, wl_fixed_t x, wl_fixed_t y)
 {
 	struct wl_resource *resource;
+	struct wl_pointer *pointer = grab->pointer;
 
-	resource = grab->pointer->focus_resource;
+	resource = pointer->focus_resource;
 	if (resource)
 		wl_pointer_send_motion(resource, time, x, y);
+
+	pointer->cursor.x = pointer->x;
+	pointer->cursor.y = pointer->y;
+	wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
 }
 
 static void
@@ -627,6 +639,47 @@ static const struct wl_keyboard_grab_interface
 	default_grab_modifiers,
 };
 
+static void
+saved_cursor_destroy_listener(struct wl_listener *listener, void *data)
+{
+	struct wl_pointer *pointer =
+		container_of(listener, struct wl_pointer, icon_listener);
+
+	if (pointer->cursor.icon == pointer->saved_cursor.icon) {
+		pointer->cursor.icon = NULL;
+		wl_signal_emit(&pointer->cursor.update_signal,
+			       &pointer->cursor);
+	}
+
+	pointer->saved_cursor.icon = NULL;
+}
+
+WL_EXPORT void
+wl_pointer_set_cursor_icon(struct wl_pointer *pointer,
+			   struct wl_surface *cursor,
+			   int32_t hotspot_x,
+			   int32_t hotspot_y)
+{
+	if (pointer->saved_cursor.icon)
+		wl_list_remove(&pointer->icon_listener.link);
+
+	pointer->saved_cursor.icon = cursor;
+	if (cursor)
+		wl_signal_add(&cursor->resource.destroy_signal,
+			      &pointer->icon_listener);
+	pointer->saved_cursor.hotspot_x = hotspot_x;
+	pointer->saved_cursor.hotspot_y = hotspot_y;
+
+	/* Grabs will set their own cursor. */
+	if (pointer->grab != &pointer->default_grab)
+		return;
+
+	pointer->cursor.icon = pointer->saved_cursor.icon;
+	pointer->cursor.hotspot_x = pointer->saved_cursor.hotspot_x;
+	pointer->cursor.hotspot_y = pointer->saved_cursor.hotspot_y;
+	wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
+}
+
 WL_EXPORT void
 wl_pointer_init(struct wl_pointer *pointer)
 {
@@ -638,6 +691,10 @@ wl_pointer_init(struct wl_pointer *pointer)
 	pointer->grab = &pointer->default_grab;
 	wl_signal_init(&pointer->focus_signal);
 
+	pointer->icon_listener.notify = saved_cursor_destroy_listener;
+	wl_signal_init(&pointer->cursor.update_signal);
+	wl_signal_init(&pointer->cursor.destroy_signal);
+
 	/* FIXME: Pick better co-ords. */
 	pointer->x = wl_fixed_from_int(100);
 	pointer->y = wl_fixed_from_int(100);
@@ -649,6 +706,10 @@ wl_pointer_release(struct wl_pointer *pointer)
 	/* XXX: What about pointer->resource_list? */
 	if (pointer->focus_resource)
 		wl_list_remove(&pointer->focus_listener.link);
+	if (pointer->saved_cursor.icon)
+		wl_list_remove(&pointer->icon_listener.link);
+	wl_signal_emit(&pointer->cursor.destroy_signal,
+		       &pointer->cursor);
 }
 
 WL_EXPORT void
@@ -700,7 +761,7 @@ wl_seat_init(struct wl_seat *seat)
 	wl_list_init(&seat->base_resource_list);
 	wl_signal_init(&seat->selection_signal);
 	wl_list_init(&seat->drag_resource_list);
-	wl_signal_init(&seat->drag_icon_signal);
+	wl_signal_init(&seat->cursor_signal);
 }
 
 WL_EXPORT void
@@ -742,8 +803,10 @@ wl_seat_set_pointer(struct wl_seat *seat, struct wl_pointer *pointer)
 		return;
 
 	seat->pointer = pointer;
-	if (pointer)
+	if (pointer) {
 		pointer->seat = seat;
+		wl_signal_emit(&seat->cursor_signal, &pointer->cursor);
+	}
 
 	seat_send_updated_caps(seat);
 }
diff --git a/src/wayland-server.h b/src/wayland-server.h
index f092145..f7a0957 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -239,6 +239,19 @@ struct wl_data_source {
 	void (*cancel)(struct wl_data_source *source);
 };
 
+struct wl_cursor {
+	struct wl_signal update_signal;
+	struct wl_signal destroy_signal;
+
+	struct wl_surface *icon;
+
+	wl_fixed_t x;
+	wl_fixed_t y;
+
+	int32_t hotspot_x;
+	int32_t hotspot_y;
+};
+
 struct wl_pointer {
 	struct wl_seat *seat;
 
@@ -260,6 +273,10 @@ struct wl_pointer {
 	struct wl_surface *current;
 	wl_fixed_t current_x, current_y;
 
+	struct wl_cursor cursor;
+	struct wl_cursor saved_cursor;
+	struct wl_listener icon_listener;
+
 	uint32_t button_count;
 };
 
@@ -307,6 +324,8 @@ struct wl_seat {
 	struct wl_keyboard *keyboard;
 	struct wl_touch *touch;
 
+	struct wl_signal cursor_signal;
+
 	uint32_t selection_serial;
 	struct wl_data_source *selection_data_source;
 	struct wl_listener selection_data_source_listener;
@@ -320,9 +339,8 @@ struct wl_seat {
 	struct wl_resource *drag_focus_resource;
 	struct wl_listener drag_focus_listener;
 	struct wl_pointer_grab drag_grab;
-	struct wl_surface *drag_surface;
+	struct wl_cursor drag_cursor;
 	struct wl_listener drag_icon_listener;
-	struct wl_signal drag_icon_signal;
 };
 
 /*
@@ -389,6 +407,11 @@ wl_pointer_start_grab(struct wl_pointer *pointer,
 		      struct wl_pointer_grab *grab);
 void
 wl_pointer_end_grab(struct wl_pointer *pointer);
+void
+wl_pointer_set_cursor_icon(struct wl_pointer *pointer,
+			   struct wl_surface *cursor,
+			   wl_fixed_t hotspot_x,
+			   wl_fixed_t hotspot_y);
 
 void
 wl_keyboard_init(struct wl_keyboard *keyboard);
-- 
1.7.10.4



More information about the wayland-devel mailing list