[PATCH|demos] Support new mechanic for shell move and resize (cast to shell-surface)

Casey Dahlin cdahlin at redhat.com
Thu Jun 9 18:52:50 PDT 2011


---
 clients/window.c                |   26 +++---
 compositor/compositor-wayland.c |   18 -----
 compositor/compositor.h         |    1 +
 compositor/shell.c              |  156 ++++++++++++++++++++++++++++-----------
 4 files changed, 127 insertions(+), 74 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index 758a536..f3c3da8 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -90,6 +90,7 @@ struct window {
 	struct display *display;
 	struct window *parent;
 	struct wl_surface *surface;
+	struct wl_shell_surface *shell_surface;
 	char *title;
 	struct rectangle allocation, saved_allocation, server_allocation;
 	int x, y;
@@ -1078,8 +1079,8 @@ window_handle_button(void *data,
 	if (button == BTN_LEFT && state == 1) {
 		switch (location) {
 		case WINDOW_TITLEBAR:
-			wl_shell_move(window->display->shell,
-				      window->surface, input_device, time);
+			wl_shell_surface_move(window->shell_surface,
+					      input_device, time);
 			break;
 		case WINDOW_RESIZING_TOP:
 		case WINDOW_RESIZING_BOTTOM:
@@ -1089,9 +1090,8 @@ window_handle_button(void *data,
 		case WINDOW_RESIZING_TOP_RIGHT:
 		case WINDOW_RESIZING_BOTTOM_LEFT:
 		case WINDOW_RESIZING_BOTTOM_RIGHT:
-			wl_shell_resize(window->display->shell,
-					window->surface, input_device, time,
-					location);
+			wl_shell_surface_resize(window->shell_surface,
+						input_device, time, location);
 			break;
 		case WINDOW_CLIENT_AREA:
 			if (window->button_handler)
@@ -1251,8 +1251,8 @@ window_create_drag(struct window *window)
 void
 window_move(struct window *window, struct input *input, uint32_t time)
 {
-	wl_shell_move(window->display->shell,
-		      window->surface, input->input_device, time);
+	wl_shell_surface_move(window->shell_surface, input->input_device,
+			      time);
 }
 
 void
@@ -1263,11 +1263,10 @@ window_activate_drag(struct wl_drag *drag, struct window *window,
 }
 
 static void
-handle_configure(void *data, struct wl_shell *shell,
-		 uint32_t time, uint32_t edges,
-		 struct wl_surface *surface, int32_t width, int32_t height)
+handle_configure(void *data, struct wl_shell_surface *shell_surface,
+		 uint32_t time, uint32_t edges, int32_t width, int32_t height)
 {
-	struct window *window = wl_surface_get_user_data(surface);
+	struct window *window = wl_shell_surface_get_user_data(shell_surface);
 	int32_t child_width, child_height;
 
 	/* FIXME: this is probably the wrong place to check for width
@@ -1294,7 +1293,7 @@ handle_configure(void *data, struct wl_shell *shell,
 	}
 }
 
-static const struct wl_shell_listener shell_listener = {
+static const struct wl_shell_surface_listener shell_surface_listener = {
 	handle_configure,
 };
 
@@ -1490,6 +1489,8 @@ window_create_internal(struct display *display, struct window *parent,
 	window->display = display;
 	window->parent = parent;
 	window->surface = wl_compositor_create_surface(display->compositor);
+	window->shell_surface =
+		wl_shell_create_shell_surface(display->shell, window->surface);
 	window->allocation.x = 0;
 	window->allocation.y = 0;
 	window->allocation.width = width;
@@ -1732,7 +1733,6 @@ display_handle_global(struct wl_display *display, uint32_t id,
 		display_add_input(d, id);
 	} else if (strcmp(interface, "wl_shell") == 0) {
 		d->shell = wl_shell_create(display, id, 1);
-		wl_shell_add_listener(d->shell, &shell_listener, d);
 	} else if (strcmp(interface, "wl_shm") == 0) {
 		d->shm = wl_shm_create(display, id, 1);
 	} else if (strcmp(interface, "wl_selection_offer") == 0) {
diff --git a/compositor/compositor-wayland.c b/compositor/compositor-wayland.c
index 6cd02ed..648f452 100644
--- a/compositor/compositor-wayland.c
+++ b/compositor/compositor-wayland.c
@@ -299,23 +299,6 @@ static const struct wl_output_listener output_listener = {
 	display_handle_geometry,
 };
 
-/* parent shell interface */
-static void
-handle_configure(void *data, struct wl_shell *shell,
-		 uint32_t time, uint32_t edges,
-		 struct wl_surface *surface, int32_t width, int32_t height)
-{
-#if 0
-	struct output *output = wl_surface_get_user_data(surface);
-
-	/* FIXME: add resize? */
-#endif
-}
-
-static const struct wl_shell_listener shell_listener = {
-	handle_configure,
-};
-
 /* parent input interface */
 static void
 input_handle_motion(void *data, struct wl_input_device *input_device,
@@ -431,7 +414,6 @@ display_handle_global(struct wl_display *display, uint32_t id,
 		display_add_input(c, id);
 	} else if (strcmp(interface, "wl_shell") == 0) {
 		c->parent.shell = wl_shell_create(display, id, 1);
-		wl_shell_add_listener(c->parent.shell, &shell_listener, c);
 	}
 }
 
diff --git a/compositor/compositor.h b/compositor/compositor.h
index 2546d58..c2fa3bc 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -222,6 +222,7 @@ enum wlsc_surface_map_type {
 struct wlsc_surface {
 	struct wl_surface surface;
 	struct wlsc_compositor *compositor;
+	void *shell_data;
 	GLuint texture, saved_texture;
 	int32_t x, y, width, height;
 	int32_t pitch;
diff --git a/compositor/shell.c b/compositor/shell.c
index ddf4d5f..beaa6fe 100644
--- a/compositor/shell.c
+++ b/compositor/shell.c
@@ -33,6 +33,13 @@ struct wl_shell {
 	struct wlsc_shell shell;
 };
 
+struct wl_shell_surface {
+	struct wl_resource resource;
+	struct wlsc_surface *surface;
+	struct wl_listener destroy_listener;
+	struct wl_client *client;
+};
+
 struct wlsc_move_grab {
 	struct wl_grab grab;
 	struct wlsc_surface *surface;
@@ -80,19 +87,18 @@ static const struct wl_grab_interface move_grab_interface = {
 };
 
 static void
-shell_move(struct wl_client *client, struct wl_shell *shell,
-	   struct wl_surface *surface,
-	   struct wl_input_device *device, uint32_t time)
+do_move(struct wl_client *client, struct wlsc_surface *es,
+	struct wl_input_device *device, uint32_t time)
 {
 	struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
-	struct wlsc_surface *es = (struct wlsc_surface *) surface;
 	struct wlsc_move_grab *move;
 
 	/* FIXME: Reject if fullscreen */
 
 	move = malloc(sizeof *move);
 	if (!move) {
-		wl_client_post_no_memory(client);
+		if (client)
+			wl_client_post_no_memory(client);
 		return;
 	}
 
@@ -101,20 +107,28 @@ shell_move(struct wl_client *client, struct wl_shell *shell,
 	move->dy = es->y - wd->input_device.grab_y;
 	move->surface = es;
 
-	if (wl_input_device_update_grab(&wd->input_device,
-					&move->grab, surface, time) < 0)
+	if (wl_input_device_update_grab(&wd->input_device, &move->grab,
+					&es->surface, time) < 0)
 		return;
 
 	wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING);
 	wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
 }
 
+static void
+shell_surface_move(struct wl_client *client,
+		   struct wl_shell_surface *shell_surface,
+		   struct wl_input_device *device, uint32_t time)
+{
+	do_move(client, shell_surface->surface, device, time);
+}
+
 struct wlsc_resize_grab {
 	struct wl_grab grab;
 	uint32_t edges;
 	int32_t dx, dy, width, height;
 	struct wlsc_surface *surface;
-	struct wl_shell *shell;
+	struct wl_shell_surface *shell_surface;
 };
 
 static void
@@ -126,24 +140,24 @@ resize_grab_motion(struct wl_grab *grab,
 	struct wl_surface *surface = &resize->surface->surface;
 	int32_t width, height;
 
-	if (resize->edges & WL_SHELL_RESIZE_LEFT) {
+	if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
 		width = device->grab_x - x + resize->width;
-	} else if (resize->edges & WL_SHELL_RESIZE_RIGHT) {
+	} else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
 		width = x - device->grab_x + resize->width;
 	} else {
 		width = resize->width;
 	}
 
-	if (resize->edges & WL_SHELL_RESIZE_TOP) {
+	if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
 		height = device->grab_y - y + resize->height;
-	} else if (resize->edges & WL_SHELL_RESIZE_BOTTOM) {
+	} else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
 		height = y - device->grab_y + resize->height;
 	} else {
 		height = resize->height;
 	}
 
-	wl_client_post_event(surface->client, &resize->shell->object,
-			     WL_SHELL_CONFIGURE, time, resize->edges,
+	wl_client_post_event(surface->client, &resize->shell_surface->resource.object,
+			     WL_SHELL_SURFACE_CONFIGURE, time, resize->edges,
 			     surface, width, height);
 }
 
@@ -174,14 +188,16 @@ static const struct wl_grab_interface resize_grab_interface = {
 };
 
 static void
-shell_resize(struct wl_client *client, struct wl_shell *shell,
-	     struct wl_surface *surface,
-	     struct wl_input_device *device, uint32_t time, uint32_t edges)
+shell_surface_resize(struct wl_client *client,
+		     struct wl_shell_surface *shell_surface,
+		     struct wl_input_device *device, uint32_t time,
+		     uint32_t edges)
 {
 	struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
 	struct wlsc_resize_grab *resize;
 	enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR;
-	struct wlsc_surface *es = (struct wlsc_surface *) surface;
+	struct wlsc_surface *es =
+		(struct wlsc_surface *) shell_surface->surface;
 
 	/* FIXME: Reject if fullscreen */
 
@@ -198,41 +214,41 @@ shell_resize(struct wl_client *client, struct wl_shell *shell,
 	resize->width = es->width;
 	resize->height = es->height;
 	resize->surface = es;
-	resize->shell = shell;
+	resize->shell_surface = shell_surface;
 
 	if (edges == 0 || edges > 15 ||
 	    (edges & 3) == 3 || (edges & 12) == 12)
 		return;
 
 	switch (edges) {
-	case WL_SHELL_RESIZE_TOP:
+	case WL_SHELL_SURFACE_RESIZE_TOP:
 		pointer = WLSC_POINTER_TOP;
 		break;
-	case WL_SHELL_RESIZE_BOTTOM:
+	case WL_SHELL_SURFACE_RESIZE_BOTTOM:
 		pointer = WLSC_POINTER_BOTTOM;
 		break;
-	case WL_SHELL_RESIZE_LEFT:
+	case WL_SHELL_SURFACE_RESIZE_LEFT:
 		pointer = WLSC_POINTER_LEFT;
 		break;
-	case WL_SHELL_RESIZE_TOP_LEFT:
+	case WL_SHELL_SURFACE_RESIZE_TOP_LEFT:
 		pointer = WLSC_POINTER_TOP_LEFT;
 		break;
-	case WL_SHELL_RESIZE_BOTTOM_LEFT:
+	case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT:
 		pointer = WLSC_POINTER_BOTTOM_LEFT;
 		break;
-	case WL_SHELL_RESIZE_RIGHT:
+	case WL_SHELL_SURFACE_RESIZE_RIGHT:
 		pointer = WLSC_POINTER_RIGHT;
 		break;
-	case WL_SHELL_RESIZE_TOP_RIGHT:
+	case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT:
 		pointer = WLSC_POINTER_TOP_RIGHT;
 		break;
-	case WL_SHELL_RESIZE_BOTTOM_RIGHT:
+	case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT:
 		pointer = WLSC_POINTER_BOTTOM_RIGHT;
 		break;
 	}
 
-	if (wl_input_device_update_grab(&wd->input_device,
-					&resize->grab, surface, time) < 0)
+	if (wl_input_device_update_grab(&wd->input_device, &resize->grab,
+					&es->surface, time) < 0)
 		return;
 
 	wlsc_input_device_set_pointer_image(wd, pointer);
@@ -672,32 +688,85 @@ shell_create_selection(struct wl_client *client,
 	wl_client_add_resource(client, &selection->resource);
 }
 
+const static struct wl_shell_surface_interface shell_surface_implementation = {
+	shell_surface_move,
+	shell_surface_resize
+};
+
+static void
+destroy_shell_surface(struct wl_resource *resource, struct wl_client *client)
+{
+	struct wl_shell_surface *shell_surface =
+		container_of(resource, struct wl_shell_surface, resource);
+
+	wl_list_remove(&shell_surface->destroy_listener.link);
+	free(shell_surface);
+}
+
+static void
+shell_surface_cleanup(struct wl_listener *ss_listener,
+		      struct wl_resource *surf_resource, uint32_t time)
+{
+	struct wl_shell_surface *shell_surface =
+		container_of(ss_listener, struct wl_shell_surface,
+			     destroy_listener);
+
+	wl_resource_destroy(&shell_surface->resource,
+			    shell_surface->client, time);
+}
+
+static void
+shell_create_shell_surface(struct wl_client *client, struct wl_shell *wl_shell,
+			   uint32_t id, struct wl_surface *surface)
+{
+	struct wl_shell_surface *shell_surface;
+
+	shell_surface = malloc(sizeof *shell_surface);
+	if (shell_surface == NULL) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	memset(shell_surface, 0, sizeof *shell_surface);
+	shell_surface->resource.object.id = id;
+	shell_surface->resource.object.interface = &wl_shell_surface_interface;
+	shell_surface->resource.object.implementation =
+		(void (**)(void)) &shell_surface_implementation;
+
+	shell_surface->client = client;
+	shell_surface->surface = (struct wlsc_surface *)surface;
+	shell_surface->surface->shell_data = shell_surface;
+	shell_surface->resource.destroy = destroy_shell_surface;
+	shell_surface->destroy_listener.func = shell_surface_cleanup;
+	wl_list_insert(surface->resource.destroy_listener_list.prev,
+		       &shell_surface->destroy_listener.link);
+
+	wl_client_add_resource(client, &shell_surface->resource);
+}
+
 const static struct wl_shell_interface shell_interface = {
-	shell_move,
-	shell_resize,
 	shell_create_drag,
-	shell_create_selection
+	shell_create_selection,
+	shell_create_shell_surface
 };
 
 static void
 move_binding(struct wl_input_device *device, uint32_t time,
 	     uint32_t key, uint32_t button, uint32_t state, void *data)
 {
-	struct wl_shell *shell = data;
 	struct wlsc_surface *surface =
 		(struct wlsc_surface *) device->pointer_focus;
 
 	if (surface == NULL)
 		return;
 
-	shell_move(NULL, shell, &surface->surface, device, time);
+	do_move(NULL, surface, device, time);
 }
 
 static void
 resize_binding(struct wl_input_device *device, uint32_t time,
 	       uint32_t key, uint32_t button, uint32_t state, void *data)
 {
-	struct wl_shell *shell = data;
 	struct wlsc_surface *surface =
 		(struct wlsc_surface *) device->pointer_focus;
 	uint32_t edges = 0;
@@ -706,24 +775,28 @@ resize_binding(struct wl_input_device *device, uint32_t time,
 	if (surface == NULL)
 		return;
 
+	if (! surface->shell_data)
+		return;
+
 	x = device->grab_x - surface->x;
 	y = device->grab_y - surface->y;
 
 	if (x < surface->width / 3)
-		edges |= WL_SHELL_RESIZE_LEFT;
+		edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
 	else if (x < 2 * surface->width / 3)
 		edges |= 0;
 	else
-		edges |= WL_SHELL_RESIZE_RIGHT;
+		edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
 
 	if (y < surface->height / 3)
-		edges |= WL_SHELL_RESIZE_TOP;
+		edges |= WL_SHELL_SURFACE_RESIZE_TOP;
 	else if (y < 2 * surface->height / 3)
 		edges |= 0;
 	else
-		edges |= WL_SHELL_RESIZE_BOTTOM;
+		edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
 
-	shell_resize(NULL, shell, &surface->surface, device, time, edges);
+	shell_surface_resize(NULL, surface->shell_data,
+			     device, time, edges);
 }
 
 static void
@@ -736,9 +809,6 @@ attach(struct wlsc_shell *shell, struct wlsc_surface *surface)
 {
 }
 
-int
-shell_init(struct wlsc_compositor *ec);
-
 WL_EXPORT int
 shell_init(struct wlsc_compositor *ec)
 {
-- 
1.7.5.2



More information about the wayland-devel mailing list