[PATCH weston 4/5] Make use of new wl_cursors

Daniel Stone daniel at fooishbar.org
Mon Jul 23 11:55:00 PDT 2012


Port the existing manual (and somewhat fragile) cursor-handling code to
the new wl_cursor interface.

Signed-off-by: Daniel Stone <daniel at fooishbar.org>
---
 clients/window.c |    6 +-
 src/compositor.c |  378 ++++++++++++++++++++----------------------------------
 src/compositor.h |   16 ++-
 src/shell.c      |   34 ++++-
 4 files changed, 183 insertions(+), 251 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index 93299e1..2a7010a 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -2372,12 +2372,12 @@ input_set_pointer_image_index(struct input *input, int index)
 	if (!buffer)
 		return;
 
-	wl_pointer_set_cursor(input->pointer, input->display->serial,
-			      input->pointer_surface,
-			      image->hotspot_x, image->hotspot_y);
 	wl_surface_attach(input->pointer_surface, buffer, 0, 0);
 	wl_surface_damage(input->pointer_surface, 0, 0,
 			  image->width, image->height);
+	wl_pointer_set_cursor(input->pointer, input->display->serial,
+			      input->pointer_surface,
+			      image->hotspot_x, image->hotspot_y);
 }
 
 static const struct wl_callback_listener pointer_surface_listener;
diff --git a/src/compositor.c b/src/compositor.c
index 132f09f..92abab1 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1109,8 +1109,6 @@ weston_output_repaint(struct weston_output *output, int msecs)
 	pixman_region32_t opaque, new_damage, output_damage;
 	int32_t width, height;
 
-	weston_compositor_update_drag_surfaces(ec);
-
 	width = output->current->width +
 		output->border.left + output->border.right;
 	height = output->current->height +
@@ -1381,6 +1379,28 @@ weston_surface_assign_output(struct weston_surface *es)
 	weston_surface_update_output_mask(es, mask);
 }
 
+/**
+ * If the surface we just reconfigured is current for any cursor, update
+ * the cursor and signal.
+ */
+static void
+check_cursor_configure(struct weston_surface *es, int32_t dx, int32_t dy)
+{
+	struct weston_seat *seat;
+	struct weston_cursor *cursor;
+
+	wl_list_for_each(seat, &es->compositor->seat_list, link) {
+		wl_list_for_each(cursor, &seat->cursor_list, link) {
+			if (cursor->cursor->icon != &es->surface)
+				continue;
+			empty_region(&es->input);
+			cursor->cursor->hotspot_x -= dx;
+			cursor->cursor->hotspot_y -= dy;
+			wl_signal_emit(&cursor->cursor->update_signal, cursor->cursor);
+		}
+	}
+}
+
 static void
 surface_attach(struct wl_client *client,
 	       struct wl_resource *resource,
@@ -1394,8 +1414,13 @@ surface_attach(struct wl_client *client,
 
 	weston_surface_attach(&es->surface, buffer);
 
-	if (buffer && es->configure)
+	if (!buffer)
+		return;
+
+	if (es->configure)
 		es->configure(es, sx, sy);
+
+	check_cursor_configure(es, sx, sy);
 }
 
 static void
@@ -1432,7 +1457,7 @@ surface_frame(struct wl_client *client,
 		wl_resource_post_no_memory(resource);
 		return;
 	}
-		
+
 	cb->resource.object.interface = &wl_callback_interface;
 	cb->resource.object.id = callback;
 	cb->resource.destroy = destroy_frame_callback;
@@ -1656,9 +1681,6 @@ idle_handler(void *data)
 	return 1;
 }
 
-static  void
-weston_seat_update_drag_surface(struct wl_seat *seat, int dx, int dy);
-
 static void
 clip_pointer_motion(struct weston_seat *seat, wl_fixed_t *fx, wl_fixed_t *fy)
 {
@@ -1707,10 +1729,6 @@ notify_motion(struct wl_seat *seat, uint32_t time, wl_fixed_t x, wl_fixed_t y)
 
 	clip_pointer_motion(ws, &x, &y);
 
-	weston_seat_update_drag_surface(seat,
-					x - seat->pointer->x,
-					y - seat->pointer->y);
-
 	seat->pointer->x = x;
 	seat->pointer->y = y;
 
@@ -1727,13 +1745,103 @@ notify_motion(struct wl_seat *seat, uint32_t time, wl_fixed_t x, wl_fixed_t y)
 	interface = seat->pointer->grab->interface;
 	interface->motion(seat->pointer->grab, time,
 			  seat->pointer->grab->x, seat->pointer->grab->y);
+}
+
+static void
+cursor_unmap(struct weston_cursor *cursor)
+{
+	if (!cursor->sprite)
+		return;
+
+	if (weston_surface_is_mapped(cursor->sprite))
+		weston_surface_unmap(cursor->sprite);
+	cursor->sprite = NULL;
+	wl_list_remove(&cursor->sprite_destroy_listener.link);
+}
+
+static void
+cursor_destroy(struct wl_listener *listener, void *data)
+{
+	struct weston_cursor *cursor =
+		container_of(listener, struct weston_cursor,
+			     cursor_destroy_listener);
+
+	cursor_unmap(cursor);
+	wl_list_remove(&cursor->link);
+	free(cursor);
+}
+
+static void
+cursor_sprite_destroy(struct wl_listener *listener, void *data)
+{
+	struct weston_cursor *cursor =
+		container_of(listener, struct weston_cursor,
+			     sprite_destroy_listener);
+
+	cursor->cursor->icon = NULL;
+	cursor->sprite = NULL;
+}
+
+static void
+cursor_update(struct wl_listener *listener, void *data)
+{
+	struct wl_cursor *wl_cursor = data;
+	struct weston_surface *icon = (struct weston_surface *) wl_cursor->icon;
+	struct weston_cursor *cursor =
+		container_of(listener, struct weston_cursor, update_listener);
+	int32_t ix, iy;
+	unsigned int has_changed = (icon != cursor->sprite);
 
-	if (ws->sprite) {
-		weston_surface_set_position(ws->sprite,
-					    ix - ws->hotspot_x,
-					    iy - ws->hotspot_y);
-		weston_compositor_schedule_repaint(ec);
+	ix = wl_fixed_to_int(wl_cursor->x) - wl_cursor->hotspot_x;
+	iy = wl_fixed_to_int(wl_cursor->y) - wl_cursor->hotspot_y;
+
+	if (has_changed && cursor->sprite) {
+		if (weston_surface_is_mapped(cursor->sprite))
+			weston_surface_unmap(cursor->sprite);
+		wl_list_remove(&cursor->sprite_destroy_listener.link);
+	}
+
+	cursor->sprite = icon;
+
+	if (!cursor->sprite)
+		return;
+
+	weston_surface_set_position(icon, ix, iy);
+	if (has_changed) {
+		wl_signal_add(&icon->surface.resource.destroy_signal,
+			      &cursor->sprite_destroy_listener);
+		wl_list_insert(&icon->compositor->cursor_layer.surface_list,
+			       &icon->layer_link);
+	}
+	if (!weston_surface_is_mapped(icon) && icon->buffer) {
+		weston_surface_configure(icon, ix, iy, icon->buffer->width,
+					 icon->buffer->height);
+		weston_surface_assign_output(icon);
 	}
+	weston_compositor_schedule_repaint(cursor->seat->compositor);
+}
+
+static void
+cursor_new(struct wl_listener *listener, void *data)
+{
+	struct weston_cursor *cursor;
+	struct weston_seat *seat =
+		container_of(listener, struct weston_seat, cursor_listener);
+
+	cursor = malloc(sizeof *cursor);
+	if (!cursor)
+		return;
+
+	cursor->seat = seat;
+	cursor->cursor = data;
+	cursor->sprite = NULL;
+	cursor->update_listener.notify = cursor_update;
+	wl_signal_add(&cursor->cursor->update_signal, &cursor->update_listener);
+	cursor->sprite_destroy_listener.notify = cursor_sprite_destroy;
+	cursor->cursor_destroy_listener.notify = cursor_destroy;
+	wl_signal_add(&cursor->cursor->destroy_signal,
+		      &cursor->cursor_destroy_listener);
+	wl_list_insert(&seat->cursor_list, &cursor->link);
 }
 
 WL_EXPORT void
@@ -1963,10 +2071,6 @@ notify_pointer_focus(struct wl_seat *seat, struct weston_output *output,
 	struct weston_compositor *compositor = ws->compositor;
 
 	if (output) {
-		weston_seat_update_drag_surface(seat,
-						x - seat->pointer->x,
-						y - seat->pointer->y);
-
 		seat->pointer->x = x;
 		seat->pointer->y = y;
 		compositor->focus = 1;
@@ -2177,103 +2281,32 @@ notify_touch(struct wl_seat *seat, uint32_t time, int touch_id,
 }
 
 static void
-pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
-{
-	struct weston_seat *seat = container_of(listener, struct weston_seat,
-						sprite_destroy_listener);
-
-	seat->sprite = NULL;
-}
-
-static void
-pointer_cursor_surface_configure(struct weston_surface *es,
-				 int32_t dx, int32_t dy)
-{
-	struct weston_seat *seat = es->private;
-	int x, y;
-
-	assert(es == seat->sprite);
-
-	seat->hotspot_x -= dx;
-	seat->hotspot_y -= dy;
-
-	x = wl_fixed_to_int(seat->seat.pointer->x) - seat->hotspot_x;
-	y = wl_fixed_to_int(seat->seat.pointer->y) - seat->hotspot_y;
-
-	weston_surface_configure(seat->sprite, x, y,
-				 es->buffer->width, es->buffer->height);
-
-	empty_region(&es->input);
-
-	if (!weston_surface_is_mapped(es)) {
-		wl_list_insert(&es->compositor->cursor_layer.surface_list,
-			       &es->layer_link);
-		weston_surface_assign_output(es);
-	}
-}
-
-static void
-pointer_unmap_sprite(struct weston_seat *seat)
-{
-	if (weston_surface_is_mapped(seat->sprite))
-		weston_surface_unmap(seat->sprite);
-
-	wl_list_remove(&seat->sprite_destroy_listener.link);
-	seat->sprite->configure = NULL;
-	seat->sprite->private = NULL;
-	seat->sprite = NULL;
-}
-
-static void
 pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
 		   uint32_t serial, struct wl_resource *surface_resource,
 		   int32_t x, int32_t y)
 {
 	struct weston_seat *seat = resource->data;
-	struct weston_surface *surface = NULL;
-
-	if (surface_resource)
-		surface = container_of(surface_resource->data,
-				       struct weston_surface, surface);
+	struct weston_surface *surface;
 
-	if (serial < seat->seat.pointer->focus_serial)
+	if (!surface_resource) {
+		wl_pointer_set_cursor_icon(&seat->pointer, NULL, 0, 0);
 		return;
-
-	if (surface && surface != seat->sprite) {
-		if (seat->seat.pointer->focus == NULL)
-			return;
-		if (seat->seat.pointer->focus->resource.client != client)
-			return;
-
-		if (surface->configure) {
-			wl_resource_post_error(&surface->surface.resource,
-					       WL_DISPLAY_ERROR_INVALID_OBJECT,
-					       "surface->configure already "
-					       "set");
-			return;
-		}
 	}
 
-	if (seat->sprite)
-		pointer_unmap_sprite(seat);
+	surface = container_of(surface_resource->data,
+			       struct weston_surface, surface);
 
-	if (!surface)
+	if (serial < seat->seat.pointer->focus_serial)
 		return;
 
-	wl_signal_add(&surface->surface.resource.destroy_signal,
-		      &seat->sprite_destroy_listener);
+	if (seat->seat.pointer->focus == NULL ||
+	    seat->seat.pointer->focus->resource.client != client)
+		return;
 
-	surface->configure = pointer_cursor_surface_configure;
-	surface->private = seat;
 	empty_region(&surface->input);
 
-	seat->sprite = surface;
-	seat->hotspot_x = x;
-	seat->hotspot_y = y;
-
-	weston_surface_set_position(surface,
-				    wl_fixed_to_int(seat->seat.pointer->x) - x,
-				    wl_fixed_to_int(seat->seat.pointer->y) - y);
+	wl_pointer_set_cursor_icon(&seat->pointer, &surface->surface,
+				   x, y);
 }
 
 static const struct wl_pointer_interface pointer_interface = {
@@ -2399,17 +2432,6 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 	wl_seat_send_capabilities(resource, caps);
 }
 
-static void
-device_handle_new_drag_icon(struct wl_listener *listener, void *data)
-{
-	struct weston_seat *seat;
-
-	seat = container_of(listener, struct weston_seat,
-			    new_drag_icon_listener);
-
-	weston_seat_update_drag_surface(&seat->seat, 0, 0);
-}
-
 static void weston_compositor_xkb_init(struct weston_compositor *ec,
 				       struct xkb_rule_names *names)
 {
@@ -2602,8 +2624,9 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec)
 	wl_display_add_global(ec->wl_display, &wl_seat_interface, seat,
 			      bind_seat);
 
-	seat->sprite = NULL;
-	seat->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
+	wl_list_init(&seat->cursor_list);
+	seat->cursor_listener.notify = cursor_new;
+	wl_signal_add(&seat->seat.cursor_signal, &seat->cursor_listener);
 
 	seat->compositor = ec;
 	seat->hotspot_x = 16;
@@ -2616,10 +2639,6 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec)
 
 	wl_list_insert(ec->seat_list.prev, &seat->link);
 
-	seat->new_drag_icon_listener.notify = device_handle_new_drag_icon;
-	wl_signal_add(&seat->seat.drag_icon_signal,
-		      &seat->new_drag_icon_listener);
-
 	clipboard_create(seat);
 }
 
@@ -2629,9 +2648,6 @@ weston_seat_release(struct weston_seat *seat)
 	wl_list_remove(&seat->link);
 	/* The global object is destroyed at wl_display_destroy() time. */
 
-	if (seat->sprite)
-		pointer_unmap_sprite(seat);
-
 	if (seat->xkb_state.state != NULL)
 		xkb_state_unref(seat->xkb_state.state);
 	xkb_info_destroy(&seat->xkb_info);
@@ -2640,124 +2656,6 @@ weston_seat_release(struct weston_seat *seat)
 }
 
 static void
-drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
-{
-	weston_surface_configure(es,
-				 es->geometry.x + sx, es->geometry.y + sy,
-				 es->buffer->width, es->buffer->height);
-}
-
-static int
-device_setup_new_drag_surface(struct weston_seat *ws,
-			      struct weston_surface *surface)
-{
-	struct wl_seat *seat = &ws->seat;
-
-	if (surface->configure) {
-		wl_resource_post_error(&surface->surface.resource,
-				       WL_DISPLAY_ERROR_INVALID_OBJECT,
-				       "surface->configure already set");
-		return 0;
-	}
-
-	ws->drag_surface = surface;
-
-	weston_surface_set_position(ws->drag_surface,
-				    wl_fixed_to_double(seat->pointer->x),
-				    wl_fixed_to_double(seat->pointer->y));
-
-	surface->configure = drag_surface_configure;
-
-	wl_signal_add(&surface->surface.resource.destroy_signal,
-		       &ws->drag_surface_destroy_listener);
-
-	return 1;
-}
-
-static void
-device_release_drag_surface(struct weston_seat *seat)
-{
-	seat->drag_surface->configure = NULL;
-	undef_region(&seat->drag_surface->input);
-	wl_list_remove(&seat->drag_surface_destroy_listener.link);
-	seat->drag_surface = NULL;
-}
-
-static void
-device_map_drag_surface(struct weston_seat *seat)
-{
-	struct wl_list *list;
-
-	if (weston_surface_is_mapped(seat->drag_surface) ||
-	    !seat->drag_surface->buffer)
-		return;
-
-	if (seat->sprite && weston_surface_is_mapped(seat->sprite))
-		list = &seat->sprite->layer_link;
-	else
-		list = &seat->compositor->cursor_layer.surface_list;
-
-	wl_list_insert(list, &seat->drag_surface->layer_link);
-	weston_surface_assign_output(seat->drag_surface);
-	empty_region(&seat->drag_surface->input);
-}
-
-static  void
-weston_seat_update_drag_surface(struct wl_seat *seat,
-				int dx, int dy)
-{
-	int surface_changed = 0;
-	struct weston_seat *ws = (struct weston_seat *) seat;
-
-	if (!ws->drag_surface && !seat->drag_surface)
-		return;
-
-	if (ws->drag_surface && seat->drag_surface &&
-	    (&ws->drag_surface->surface.resource !=
-	     &seat->drag_surface->resource))
-		/* between calls to this funcion we got a new drag_surface */
-		surface_changed = 1;
-
-	if (!seat->drag_surface || surface_changed) {
-		device_release_drag_surface(ws);
-		if (!surface_changed)
-			return;
-	}
-
-	if (!ws->drag_surface || surface_changed) {
-		struct weston_surface *surface = (struct weston_surface *)
-			seat->drag_surface;
-		if (!device_setup_new_drag_surface(ws, surface))
-			return;
-	}
-
-	/* the client may not have attached a buffer to the drag surface
-	 * when we setup it up, so check if map is needed on every update */
-	device_map_drag_surface(ws);
-
-	/* the client may have attached a buffer with a different size to
-	 * the drag surface, causing the input region to be reset */
-	if (region_is_undefined(&ws->drag_surface->input))
-		empty_region(&ws->drag_surface->input);
-
-	if (!dx && !dy)
-		return;
-
-	weston_surface_set_position(ws->drag_surface,
-				    ws->drag_surface->geometry.x + wl_fixed_to_double(dx),
-				    ws->drag_surface->geometry.y + wl_fixed_to_double(dy));
-}
-
-WL_EXPORT void
-weston_compositor_update_drag_surfaces(struct weston_compositor *compositor)
-{
-	struct weston_seat *seat;
-
-	wl_list_for_each(seat, &compositor->seat_list, link)
-		weston_seat_update_drag_surface(&seat->seat, 0, 0);
-}
-
-static void
 bind_output(struct wl_client *client,
 	    void *data, uint32_t version, uint32_t id)
 {
diff --git a/src/compositor.h b/src/compositor.h
index 22c0174..41623e5 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -203,6 +203,16 @@ struct weston_xkb_info {
 	xkb_led_index_t scroll_led;
 };
 
+struct weston_cursor {
+	struct wl_cursor *cursor;
+	struct weston_seat *seat;
+	struct weston_surface *sprite;
+	struct wl_listener sprite_destroy_listener;
+	struct wl_listener cursor_destroy_listener;
+	struct wl_listener update_listener;
+	struct wl_list link;
+};
+
 struct weston_seat {
 	struct wl_seat seat;
 	struct wl_pointer pointer;
@@ -212,9 +222,9 @@ struct weston_seat {
 	struct wl_touch touch;
 	int has_touch;
 
+	struct wl_list cursor_list;
 	struct weston_compositor *compositor;
-	struct weston_surface *sprite;
-	struct wl_listener sprite_destroy_listener;
+	struct wl_listener cursor_listener;
 	struct weston_surface *drag_surface;
 	struct wl_listener drag_surface_destroy_listener;
 	int32_t hotspot_x, hotspot_y;
@@ -556,8 +566,6 @@ void
 weston_compositor_wake(struct weston_compositor *compositor);
 void
 weston_compositor_activity(struct weston_compositor *compositor);
-void
-weston_compositor_update_drag_surfaces(struct weston_compositor *compositor);
 
 
 struct weston_binding;
diff --git a/src/shell.c b/src/shell.c
index 344c690..264c9de 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -774,6 +774,11 @@ noop_grab_focus(struct wl_pointer_grab *grab,
 		struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
 {
 	grab->focus = NULL;
+
+	grab->pointer->cursor.x = grab->pointer->x;
+	grab->pointer->cursor.y = grab->pointer->y;
+	wl_signal_emit(&grab->pointer->cursor.update_signal,
+		       &grab->pointer->cursor);
 }
 
 static void
@@ -795,7 +800,9 @@ move_grab_motion(struct wl_pointer_grab *grab,
 	weston_surface_configure(es, dx, dy,
 				 es->geometry.width, es->geometry.height);
 
-	weston_compositor_schedule_repaint(es->compositor);
+	pointer->cursor.x = pointer->x;
+	pointer->cursor.y = pointer->y;
+	wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
 }
 
 static void
@@ -810,7 +817,6 @@ move_grab_button(struct wl_pointer_grab *grab,
 	if (pointer->button_count == 0 &&
 	    state == WL_POINTER_BUTTON_STATE_RELEASED) {
 		shell_grab_end(shell_grab);
-		wl_pointer_end_grab(pointer);
 		free(grab);
 	}
 }
@@ -826,11 +832,9 @@ busy_cursor_grab_focus(struct wl_pointer_grab *base,
 		       struct wl_surface *surface, int32_t x, int32_t y)
 {
 	struct shell_grab *grab = (struct shell_grab *) base;
-	struct wl_pointer *pointer = base->pointer;
 
 	if (grab->grab.focus != surface) {
 		shell_grab_end(grab);
-		wl_pointer_end_grab(pointer);
 		free(grab);
 	}
 }
@@ -839,6 +843,11 @@ static void
 busy_cursor_grab_motion(struct wl_pointer_grab *grab,
 			uint32_t time, int32_t x, int32_t y)
 {
+	struct wl_pointer *pointer = grab->pointer;
+
+	pointer->cursor.x = pointer->x;
+	pointer->cursor.y = pointer->y;
+	wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
 }
 
 static void
@@ -1093,6 +1102,10 @@ resize_grab_motion(struct wl_pointer_grab *grab,
 
 	shsurf->client->send_configure(shsurf->surface,
 				       resize->edges, width, height);
+
+	pointer->cursor.x = pointer->x;
+	pointer->cursor.y = pointer->y;
+	wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
 }
 
 static void
@@ -1552,17 +1565,26 @@ popup_grab_focus(struct wl_pointer_grab *grab,
 				     wl_fixed_from_int(0));
 		grab->focus = NULL;
 	}
+
+	pointer->cursor.x = pointer->x;
+	pointer->cursor.y = pointer->y;
+	wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
 }
 
 static void
 popup_grab_motion(struct wl_pointer_grab *grab,
 		  uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
 {
+	struct wl_pointer *pointer = grab->pointer;
 	struct wl_resource *resource;
 
 	resource = grab->pointer->focus_resource;
 	if (resource)
 		wl_pointer_send_motion(resource, time, sx, sy);
+
+	pointer->cursor.x = pointer->x;
+	pointer->cursor.y = pointer->y;
+	wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
 }
 
 static void
@@ -2266,6 +2288,10 @@ rotate_grab_motion(struct wl_pointer_grab *grab,
 					    surface->geometry.y + dposy);
 	}
 
+	pointer->cursor.x = pointer->x;
+	pointer->cursor.y = pointer->y;
+	wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
+
 	/* Repaint implies weston_surface_update_transform(), which
 	 * lazily applies the damage due to rotation update.
 	 */
-- 
1.7.10.4



More information about the wayland-devel mailing list