[PATCH weston 5/6] desktop-shell: Port to libweston-desktop

Quentin Glidic sardemff7+wayland at sardemff7.net
Fri Aug 12 08:41:36 UTC 2016


From: Quentin Glidic <sardemff7+git at sardemff7.net>

All the shell protocol details, Xwayland glue and popups (and their
grab) are now handled in libweston-desktop.
Fullscreen methods (for wl_shell) are removed for now.

Signed-off-by: Quentin Glidic <sardemff7+git at sardemff7.net>
Reviewed-by: Jonas Ådahl <jadahl at gmail.com>
Acked-by: Giulio Camuffo <giulio.camuffo at kdab.com>

Differential Revision: https://phabricator.freedesktop.org/D1209
---
 Makefile.am            |    2 +-
 desktop-shell/shell.c  | 2988 +++++++++---------------------------------------
 desktop-shell/shell.h  |    4 +
 libweston/compositor.h |   29 -
 shared/helpers.h       |   11 +
 5 files changed, 571 insertions(+), 2463 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index e7a76c1..85fd718 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -896,7 +896,7 @@ desktop_shell_la_CPPFLAGS =			\
 	-DIN_WESTON
 
 desktop_shell_la_LDFLAGS = -module -avoid-version
-desktop_shell_la_LIBADD = libshared.la $(COMPOSITOR_LIBS)
+desktop_shell_la_LIBADD = libshared.la libweston-desktop- at LIBWESTON_MAJOR@.la $(COMPOSITOR_LIBS)
 desktop_shell_la_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS)
 desktop_shell_la_SOURCES =				\
 	desktop-shell/shell.h				\
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index b6ee729..786020b 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -41,7 +41,7 @@
 #include "weston-desktop-shell-server-protocol.h"
 #include "shared/config-parser.h"
 #include "shared/helpers.h"
-#include "xdg-shell-unstable-v5-server-protocol.h"
+#include "libweston-desktop/libweston-desktop.h"
 
 #define DEFAULT_NUM_WORKSPACES 1
 #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
@@ -59,15 +59,6 @@ struct focus_state {
 	struct wl_listener surface_destroy_listener;
 };
 
-enum shell_surface_type {
-	SHELL_SURFACE_NONE,
-	SHELL_SURFACE_TOPLEVEL,
-	SHELL_SURFACE_POPUP,
-	SHELL_SURFACE_XWAYLAND
-};
-
-struct shell_client;
-
 /*
  * Surface stacking and ordering.
  *
@@ -107,24 +98,14 @@ struct shell_client;
  */
 
 struct shell_surface {
-	struct wl_resource *resource;
 	struct wl_signal destroy_signal;
-	struct shell_client *owner;
-	struct wl_resource *owner_resource;
 
-	struct weston_surface *surface;
+	struct weston_desktop_surface *desktop_surface;
 	struct weston_view *view;
 	int32_t last_width, last_height;
-	struct wl_listener surface_destroy_listener;
-	struct wl_listener resource_destroy_listener;
 
-	struct weston_surface *parent;
-	struct wl_list children_list;  /* child surfaces of this one */
-	struct wl_list children_link;  /* sibling surfaces of this one */
 	struct desktop_shell *shell;
 
-	enum shell_surface_type type;
-	char *title, *class;
 	int32_t saved_x, saved_y;
 	bool saved_position_valid;
 	bool saved_rotation_valid;
@@ -137,21 +118,7 @@ struct shell_surface {
 	} rotation;
 
 	struct {
-		struct wl_list grab_link;
-		int32_t x, y;
-		struct shell_seat *shseat;
-		uint32_t serial;
-	} popup;
-
-	struct {
-		int32_t x, y;
-		uint32_t flags;
-	} transient;
-
-	struct {
-		enum wl_shell_surface_fullscreen_method type;
 		struct weston_transform transform; /* matrix from x, y */
-		uint32_t framerate;
 		struct weston_view *black_view;
 	} fullscreen;
 
@@ -159,23 +126,10 @@ struct shell_surface {
 
 	struct weston_output *fullscreen_output;
 	struct weston_output *output;
-	struct wl_list link;
-
-	const struct weston_shell_client *client;
 
 	struct surface_state {
-		bool maximized;
-		bool fullscreen;
-		bool relative;
 		bool lowered;
-	} state, next_state, requested_state; /* surface states */
-	bool state_changed;
-	bool state_requested;
-
-	struct {
-		int32_t x, y, width, height;
-	} geometry, next_geometry;
-	bool has_set_geometry, has_next_geometry;
+	} state;
 
 	int focus_count;
 
@@ -224,31 +178,15 @@ struct shell_seat {
 	struct wl_listener caps_changed_listener;
 	struct wl_listener pointer_focus_listener;
 	struct wl_listener keyboard_focus_listener;
-
-	struct {
-		struct weston_pointer_grab grab;
-		struct weston_touch_grab touch_grab;
-		struct wl_list surfaces_list;
-		struct wl_client *client;
-		int32_t initial_up;
-		enum { POINTER, TOUCH } type;
-	} popup_grab;
 };
 
-struct shell_client {
-	struct wl_resource *resource;
-	struct wl_client *client;
-	struct desktop_shell *shell;
-	struct wl_listener destroy_listener;
-	struct wl_event_source *ping_timer;
-	uint32_t ping_serial;
-	int unresponsive;
-	struct wl_list surface_list;
-};
 
 static struct desktop_shell *
 shell_surface_get_shell(struct shell_surface *shsurf);
 
+static void
+set_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer);
+
 static void
 surface_rotate(struct shell_surface *surface, struct weston_pointer *pointer);
 
@@ -266,73 +204,22 @@ get_output_panel_size(struct desktop_shell *shell,
 static void
 shell_surface_update_child_surface_layers(struct shell_surface *shsurf);
 
-static bool
-shell_surface_is_wl_shell_surface(struct shell_surface *shsurf);
-
-static bool
-shell_surface_is_xdg_surface(struct shell_surface *shsurf);
-
-static bool
-shell_surface_is_xdg_popup(struct shell_surface *shsurf);
-
-static void
-shell_surface_set_parent(struct shell_surface *shsurf,
-                         struct weston_surface *parent);
-
 static int
 shell_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
 {
-	struct shell_surface *shsurf;
-	const char *typestr[] = {
-		[SHELL_SURFACE_NONE] = "unidentified",
-		[SHELL_SURFACE_TOPLEVEL] = "top-level",
-		[SHELL_SURFACE_POPUP] = "popup",
-		[SHELL_SURFACE_XWAYLAND] = "Xwayland",
-	};
 	const char *t, *c;
+	struct weston_desktop_surface *desktop_surface =
+		weston_surface_get_desktop_surface(surface);
 
-	shsurf = get_shell_surface(surface);
-	if (!shsurf)
-		return snprintf(buf, len, "unidentified window");
-
-	t = shsurf->title;
-	c = shsurf->class;
+	t = weston_desktop_surface_get_title(desktop_surface);
+	c = weston_desktop_surface_get_app_id(desktop_surface);
 
 	return snprintf(buf, len, "%s window%s%s%s%s%s",
-		typestr[shsurf->type],
+		"top-level",
 		t ? " '" : "", t ?: "", t ? "'" : "",
 		c ? " of " : "", c ?: "");
 }
 
-static bool
-shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
-{
-	struct desktop_shell *shell;
-	struct weston_view *view;
-	struct shell_surface *top_fs_shsurf = NULL;
-
-	shell = shell_surface_get_shell(shsurf);
-
-	if (wl_list_empty(&shell->fullscreen_layer.view_list.link))
-		return false;
-
-	/* Find topmost shsurf on the same fullscreen output on which shsurf
-	 * is displaying. We don't care about other outputs.
-	 */
-	wl_list_for_each(view, &shell->fullscreen_layer.view_list.link,
-					 layer_link.link) {
-		struct shell_surface *cand_shsurf = get_shell_surface(view->surface);
-
-		if (cand_shsurf &&
-			(cand_shsurf->fullscreen_output == shsurf->fullscreen_output)) {
-			top_fs_shsurf = cand_shsurf;
-			break;
-		}
-	}
-
-	return (shsurf == top_fs_shsurf);
-}
-
 static void
 destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
 {
@@ -364,11 +251,6 @@ get_default_view(struct weston_surface *surface)
 	return container_of(surface->views.next, struct weston_view, surface_link);
 }
 
-static void
-popup_grab_end(struct weston_pointer *pointer);
-static void
-touch_popup_grab_end(struct weston_touch *touch);
-
 static void
 shell_grab_start(struct shell_grab *grab,
 		 const struct weston_pointer_grab_interface *interface,
@@ -377,11 +259,8 @@ shell_grab_start(struct shell_grab *grab,
 		 enum weston_desktop_shell_cursor cursor)
 {
 	struct desktop_shell *shell = shsurf->shell;
-	struct weston_touch *touch = weston_seat_get_touch(pointer->seat);
 
-	popup_grab_end(pointer);
-	if (touch)
-		touch_popup_grab_end(touch);
+	weston_seat_break_desktop_grabs(pointer->seat);
 
 	grab->grab.interface = interface;
 	grab->shsurf = shsurf;
@@ -481,65 +360,6 @@ get_output_work_area(void *data,
 	}
 }
 
-static struct shell_surface *
-find_toplevel_surface(struct shell_surface *in_surface)
-{
-	struct shell_surface *surface = in_surface;
-
-	while (surface) {
-		if (surface->type == SHELL_SURFACE_TOPLEVEL)
-			return surface;
-		surface = get_shell_surface(surface->parent);
-	}
-
-	/* If no top level surface was found, just use whatever surface was
-	   originally provided. */
-	return in_surface;
-}
-
-static void
-send_configure_for_surface(struct shell_surface *shsurf)
-{
-	int32_t width, height;
-	struct surface_state *state;
-
-	if (shsurf->state_requested)
-		state = &shsurf->requested_state;
-	else if (shsurf->state_changed)
-		state = &shsurf->next_state;
-	else
-		state = &shsurf->state;
-
-	if (state->fullscreen) {
-		width = shsurf->output->width;
-		height = shsurf->output->height;
-	} else if (state->maximized) {
-		struct desktop_shell *shell;
-		pixman_rectangle32_t area;
-
-		shell = shell_surface_get_shell(shsurf);
-		get_output_work_area(shell, shsurf->output, &area);
-
-		width = area.width;
-		height = area.height;
-	} else if (shsurf->resize_edges) {
-		width = shsurf->geometry.width;
-		height = shsurf->geometry.height;
-	} else {
-		width = 0;
-		height = 0;
-	}
-
-	shsurf->client->send_configure(shsurf->surface, width, height);
-}
-
-static void
-shell_surface_state_changed(struct shell_surface *shsurf)
-{
-	if (shell_surface_is_xdg_surface(shsurf))
-		send_configure_for_surface(shsurf);
-}
-
 static void
 shell_grab_end(struct shell_grab *grab)
 {
@@ -549,7 +369,6 @@ shell_grab_end(struct shell_grab *grab)
 
 		if (grab->shsurf->resize_edges) {
 			grab->shsurf->resize_edges = 0;
-			shell_surface_state_changed(grab->shsurf);
 		}
 	}
 
@@ -563,11 +382,8 @@ shell_touch_grab_start(struct shell_touch_grab *grab,
 		       struct weston_touch *touch)
 {
 	struct desktop_shell *shell = shsurf->shell;
-	struct weston_pointer *pointer = weston_seat_get_pointer(touch->seat);
 
-	touch_popup_grab_end(touch);
-	if (pointer)
-		popup_grab_end(pointer);
+	weston_seat_break_desktop_grabs(touch->seat);
 
 	grab->grab.interface = interface;
 	grab->shsurf = shsurf;
@@ -831,6 +647,8 @@ focus_state_surface_destroy(struct wl_listener *listener, void *data)
 			continue;
 		if (is_focus_view(view))
 			continue;
+		if (!get_shell_surface(view->surface))
+			continue;
 
 		next = view;
 		break;
@@ -1541,7 +1359,7 @@ touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
 	if (!shsurf || !move->active)
 		return;
 
-	es = shsurf->surface;
+	es = weston_desktop_surface_get_surface(shsurf->desktop_surface);
 
 	weston_view_set_position(shsurf->view, dx, dy);
 
@@ -1580,7 +1398,8 @@ surface_touch_move(struct shell_surface *shsurf, struct weston_touch *touch)
 	if (!shsurf)
 		return -1;
 
-	if (shsurf->state.fullscreen || shsurf->state.maximized)
+	if (weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) ||
+	    weston_desktop_surface_get_maximized(shsurf->desktop_surface))
 		return 0;
 
 	move = malloc(sizeof *move);
@@ -1589,9 +1408,9 @@ surface_touch_move(struct shell_surface *shsurf, struct weston_touch *touch)
 
 	move->active = 1;
 	move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
-			touch->grab_x;
+		   touch->grab_x;
 	move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
-			touch->grab_y;
+		   touch->grab_y;
 
 	shell_touch_grab_start(&move->base, &touch_move_grab_interface, shsurf,
 			       touch);
@@ -1625,29 +1444,31 @@ static void
 constrain_position(struct weston_move_grab *move, int *cx, int *cy)
 {
 	struct shell_surface *shsurf = move->base.shsurf;
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
 	struct weston_pointer *pointer = move->base.grab.pointer;
 	int x, y, bottom;
 	const int safety = 50;
 	pixman_rectangle32_t area;
+	struct weston_geometry geometry;
 
 	x = wl_fixed_to_int(pointer->x + move->dx);
 	y = wl_fixed_to_int(pointer->y + move->dy);
 
 	if (shsurf->shell->panel_position ==
 	    WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP) {
-		get_output_work_area(shsurf->shell,
-				     shsurf->surface->output,
-				     &area);
+		get_output_work_area(shsurf->shell, surface->output, &area);
+		geometry =
+			weston_desktop_surface_get_geometry(shsurf->desktop_surface);
 
-		bottom = y + shsurf->geometry.height + shsurf->geometry.y;
+		bottom = y + geometry.height + geometry.y;
 		if (bottom - safety < area.y)
-			y = area.y + safety - shsurf->geometry.height
-			  - shsurf->geometry.y;
+			y = area.y + safety - geometry.height
+			  - geometry.y;
 
 		if (move->client_initiated &&
-		    y + shsurf->geometry.y < area.y)
-			y = area.y - shsurf->geometry.y;
-
+		    y + geometry.y < area.y)
+			y = area.y - geometry.y;
 	}
 
 	*cx = x;
@@ -1661,17 +1482,20 @@ move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
 	struct weston_move_grab *move = (struct weston_move_grab *) grab;
 	struct weston_pointer *pointer = grab->pointer;
 	struct shell_surface *shsurf = move->base.shsurf;
+	struct weston_surface *surface;
 	int cx, cy;
 
 	weston_pointer_move(pointer, event);
 	if (!shsurf)
 		return;
 
+	surface = weston_desktop_surface_get_surface(shsurf->desktop_surface);
+
 	constrain_position(move, &cx, &cy);
 
 	weston_view_set_position(shsurf->view, cx, cy);
 
-	weston_compositor_schedule_repaint(shsurf->surface->compositor);
+	weston_compositor_schedule_repaint(surface->compositor);
 }
 
 static void
@@ -1719,10 +1543,9 @@ surface_move(struct shell_surface *shsurf, struct weston_pointer *pointer,
 	if (!shsurf)
 		return -1;
 
-	shsurf = find_toplevel_surface(shsurf);
-
 	if (shsurf->grabbed ||
-	    shsurf->state.fullscreen || shsurf->state.maximized)
+	    weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) ||
+	    weston_desktop_surface_get_maximized(shsurf->desktop_surface))
 		return 0;
 
 	move = malloc(sizeof *move);
@@ -1730,9 +1553,9 @@ surface_move(struct shell_surface *shsurf, struct weston_pointer *pointer,
 		return -1;
 
 	move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
-			pointer->grab_x;
+		   pointer->grab_x;
 	move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
-			pointer->grab_y;
+		   pointer->grab_y;
 	move->client_initiated = client_initiated;
 
 	shell_grab_start(&move->base, &move_grab_interface, shsurf,
@@ -1741,41 +1564,6 @@ surface_move(struct shell_surface *shsurf, struct weston_pointer *pointer,
 	return 0;
 }
 
-static void
-common_surface_move(struct wl_resource *resource,
-		    struct wl_resource *seat_resource, uint32_t serial)
-{
-	struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
-	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
-	struct weston_touch *touch = weston_seat_get_touch(seat);
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-	struct weston_surface *surface;
-
-	if (pointer &&
-	    pointer->focus &&
-	    pointer->button_count > 0 &&
-	    pointer->grab_serial == serial) {
-		surface = weston_surface_get_main_surface(pointer->focus->surface);
-		if ((surface == shsurf->surface) &&
-		    (surface_move(shsurf, pointer, true) < 0))
-			wl_resource_post_no_memory(resource);
-	} else if (touch &&
-		   touch->focus &&
-		   touch->grab_serial == serial) {
-		surface = weston_surface_get_main_surface(touch->focus->surface);
-		if ((surface == shsurf->surface) &&
-		    (surface_touch_move(shsurf, touch) < 0))
-			wl_resource_post_no_memory(resource);
-	}
-}
-
-static void
-shell_surface_move(struct wl_client *client, struct wl_resource *resource,
-		   struct wl_resource *seat_resource, uint32_t serial)
-{
-	common_surface_move(resource, seat_resource, serial);
-}
-
 struct weston_resize_grab {
 	struct shell_grab base;
 	uint32_t edges;
@@ -1790,6 +1578,7 @@ resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
 	struct weston_pointer *pointer = grab->pointer;
 	struct shell_surface *shsurf = resize->base.shsurf;
 	int32_t width, height;
+	struct weston_size min_size, max_size;
 	wl_fixed_t from_x, from_y;
 	wl_fixed_t to_x, to_y;
 
@@ -1818,31 +1607,23 @@ resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
 		height += wl_fixed_to_int(to_y - from_y);
 	}
 
-	if (width < 1)
-		width = 1;
-	if (height < 1)
-		height = 1;
-	shsurf->client->send_configure(shsurf->surface, width, height);
-}
-
-static void
-send_configure(struct weston_surface *surface, int32_t width, int32_t height)
-{
-	struct shell_surface *shsurf = get_shell_surface(surface);
+	max_size = weston_desktop_surface_get_max_size(shsurf->desktop_surface);
+	min_size = weston_desktop_surface_get_min_size(shsurf->desktop_surface);
 
-	assert(shsurf);
+	min_size.width = MAX(1, min_size.width);
+	min_size.height = MAX(1, min_size.height);
 
-	if (shsurf->resource)
-		wl_shell_surface_send_configure(shsurf->resource,
-						shsurf->resize_edges,
-						width, height);
+	if (width < min_size.width)
+		width = min_size.width;
+	else if (max_size.width > 0 && width > max_size.width)
+		width = max_size.width;
+	if (height < min_size.height)
+		height = min_size.height;
+	else if (max_size.width > 0 && width > max_size.width)
+		width = max_size.width;
+	weston_desktop_surface_set_size(shsurf->desktop_surface, width, height);
 }
 
-static const struct weston_shell_client shell_client = {
-	send_configure,
-	NULL
-};
-
 static void
 resize_grab_button(struct weston_pointer_grab *grab,
 		   uint32_t time, uint32_t button, uint32_t state_w)
@@ -1922,9 +1703,11 @@ surface_resize(struct shell_surface *shsurf,
 	const unsigned resize_leftright =
 		WL_SHELL_SURFACE_RESIZE_LEFT | WL_SHELL_SURFACE_RESIZE_RIGHT;
 	const unsigned resize_any = resize_topbottom | resize_leftright;
+	struct weston_geometry geometry;
 
 	if (shsurf->grabbed ||
-	    shsurf->state.fullscreen || shsurf->state.maximized)
+	    weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) ||
+	    weston_desktop_surface_get_maximized(shsurf->desktop_surface))
 		return 0;
 
 	/* Check for invalid edge combinations. */
@@ -1939,62 +1722,32 @@ surface_resize(struct shell_surface *shsurf,
 
 	resize->edges = edges;
 
-	resize->width = shsurf->geometry.width;
-	resize->height = shsurf->geometry.height;
+	geometry = weston_desktop_surface_get_geometry(shsurf->desktop_surface);
+	resize->width = geometry.width;
+	resize->height = geometry.height;
 
 	shsurf->resize_edges = edges;
-	shell_surface_state_changed(shsurf);
 	shell_grab_start(&resize->base, &resize_grab_interface, shsurf,
 			 pointer, edges);
 
 	return 0;
 }
 
-static void
-common_surface_resize(struct wl_resource *resource,
-		      struct wl_resource *seat_resource, uint32_t serial,
-		      uint32_t edges)
-{
-	struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
-	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-	struct weston_surface *surface;
-
-	if (!pointer ||
-	    pointer->button_count == 0 ||
-	    pointer->grab_serial != serial ||
-	    pointer->focus == NULL)
-		return;
-
-	surface = weston_surface_get_main_surface(pointer->focus->surface);
-	if (surface != shsurf->surface)
-		return;
-
-	if (surface_resize(shsurf, pointer, edges) < 0)
-		wl_resource_post_no_memory(resource);
-}
-
-static void
-shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
-		     struct wl_resource *seat_resource, uint32_t serial,
-		     uint32_t edges)
-{
-	common_surface_resize(resource, seat_resource, serial, edges);
-}
-
 static void
 busy_cursor_grab_focus(struct weston_pointer_grab *base)
 {
 	struct shell_grab *grab = (struct shell_grab *) base;
 	struct weston_pointer *pointer = base->pointer;
+	struct weston_desktop_surface *desktop_surface;
 	struct weston_view *view;
 	wl_fixed_t sx, sy;
 
 	view = weston_compositor_pick_view(pointer->seat->compositor,
 					   pointer->x, pointer->y,
 					   &sx, &sy);
+	desktop_surface = weston_surface_get_desktop_surface(view->surface);
 
-	if (!grab->shsurf || grab->shsurf->surface != view->surface) {
+	if (!grab->shsurf || grab->shsurf->desktop_surface != desktop_surface) {
 		shell_grab_end(grab);
 		free(grab);
 	}
@@ -2047,152 +1800,40 @@ static const struct weston_pointer_grab_interface busy_cursor_grab_interface = {
 };
 
 static void
-set_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
-{
-	struct shell_grab *grab;
-
-	if (pointer->grab->interface == &busy_cursor_grab_interface)
-		return;
-
-	grab = malloc(sizeof *grab);
-	if (!grab)
-		return;
-
-	shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer,
-			 WESTON_DESKTOP_SHELL_CURSOR_BUSY);
-	/* Mark the shsurf as ungrabbed so that button binding is able
-	 * to move it. */
-	shsurf->grabbed = 0;
-}
-
-static void
-end_busy_cursor(struct weston_compositor *compositor, struct wl_client *client)
-{
-	struct shell_grab *grab;
-	struct weston_seat *seat;
-
-	wl_list_for_each(seat, &compositor->seat_list, link) {
-		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
-
-		if (!pointer)
-			continue;
-
-		grab = (struct shell_grab *) pointer->grab;
-		if (grab->grab.interface == &busy_cursor_grab_interface &&
-		    grab->shsurf->resource &&
-		    wl_resource_get_client(grab->shsurf->resource) == client) {
-			shell_grab_end(grab);
-			free(grab);
-		}
-	}
-}
-
-static void
-handle_shell_client_destroy(struct wl_listener *listener, void *data);
-
-static int
-xdg_ping_timeout_handler(void *data)
+handle_pointer_focus(struct wl_listener *listener, void *data)
 {
-	struct shell_client *sc = data;
-	struct weston_seat *seat;
+	struct weston_pointer *pointer = data;
+	struct weston_view *view = pointer->focus;
 	struct shell_surface *shsurf;
+	struct weston_desktop_client *client;
 
-	/* Client is not responding */
-	sc->unresponsive = 1;
-	wl_list_for_each(seat, &sc->shell->compositor->seat_list, link) {
-		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
-
-		if (!pointer ||
-		    !pointer->focus ||
-		    !pointer->focus->surface->resource)
-			continue;
-
-		shsurf = get_shell_surface(pointer->focus->surface);
-		if (shsurf && shsurf->resource &&
-		    wl_resource_get_client(shsurf->resource) == sc->client)
-			set_busy_cursor(shsurf, pointer);
-	}
-
-	return 1;
-}
-
-static void
-handle_xdg_ping(struct shell_surface *shsurf, uint32_t serial)
-{
-	struct weston_compositor *compositor = shsurf->shell->compositor;
-	struct shell_client *sc = shsurf->owner;
-	struct wl_event_loop *loop;
-	static const int ping_timeout = 200;
-
-	if (sc->unresponsive) {
-		xdg_ping_timeout_handler(sc);
-		return;
-	}
-
-	sc->ping_serial = serial;
-	loop = wl_display_get_event_loop(compositor->wl_display);
-	if (sc->ping_timer == NULL)
-		sc->ping_timer =
-			wl_event_loop_add_timer(loop,
-						xdg_ping_timeout_handler, sc);
-	if (sc->ping_timer == NULL)
+	if (!view)
 		return;
 
-	wl_event_source_timer_update(sc->ping_timer, ping_timeout);
-
-	if (shell_surface_is_xdg_surface(shsurf) ||
-	    shell_surface_is_xdg_popup(shsurf))
-		xdg_shell_send_ping(sc->resource, serial);
-	else if (shell_surface_is_wl_shell_surface(shsurf)
-		 && shsurf->resource)
-		wl_shell_surface_send_ping(shsurf->resource, serial);
-}
-
-static void
-ping_handler(struct weston_surface *surface, uint32_t serial)
-{
-	struct shell_surface *shsurf = get_shell_surface(surface);
-
+	shsurf = get_shell_surface(view->surface);
 	if (!shsurf)
 		return;
-	if (!shsurf->resource)
-		return;
-	if (shsurf->surface == shsurf->shell->grab_surface)
-		return;
-	if (!shsurf->owner)
-		return;
-
-	handle_xdg_ping(shsurf, serial);
-}
-
-static void
-handle_pointer_focus(struct wl_listener *listener, void *data)
-{
-	struct weston_pointer *pointer = data;
-	struct weston_view *view = pointer->focus;
-	struct weston_compositor *compositor;
-	uint32_t serial;
 
-	if (!view)
-		return;
+	client = weston_desktop_surface_get_client(shsurf->desktop_surface);
 
-	compositor = view->surface->compositor;
-	serial = wl_display_next_serial(compositor->wl_display);
-	ping_handler(view->surface, serial);
+	if (shsurf->unresponsive)
+		set_busy_cursor(shsurf, pointer);
+	else
+		weston_desktop_client_ping(client);
 }
 
 static void
 shell_surface_lose_keyboard_focus(struct shell_surface *shsurf)
 {
 	if (--shsurf->focus_count == 0)
-		shell_surface_state_changed(shsurf);
+		weston_desktop_surface_set_activated(shsurf->desktop_surface, false);
 }
 
 static void
 shell_surface_gain_keyboard_focus(struct shell_surface *shsurf)
 {
 	if (shsurf->focus_count++ == 0)
-		shell_surface_state_changed(shsurf);
+		weston_desktop_surface_set_activated(shsurf->desktop_surface, true);
 }
 
 static void
@@ -2216,183 +1857,45 @@ handle_keyboard_focus(struct wl_listener *listener, void *data)
 	}
 }
 
-static void
-shell_client_pong(struct shell_client *sc, uint32_t serial)
+/* The surface will be inserted into the list immediately after the link
+ * returned by this function (i.e. will be stacked immediately above the
+ * returned link). */
+static struct weston_layer_entry *
+shell_surface_calculate_layer_link (struct shell_surface *shsurf)
 {
-	if (sc->ping_serial != serial)
-		return;
-
-	sc->unresponsive = 0;
-	end_busy_cursor(sc->shell->compositor, sc->client);
+	struct workspace *ws;
 
-	if (sc->ping_timer) {
-		wl_event_source_remove(sc->ping_timer);
-		sc->ping_timer = NULL;
+	if (weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) &&
+	    !shsurf->state.lowered) {
+		return &shsurf->shell->fullscreen_layer.view_list;
 	}
 
+	/* Move the surface to a normal workspace layer so that surfaces
+	 * which were previously fullscreen or transient are no longer
+	 * rendered on top. */
+	ws = get_current_workspace(shsurf->shell);
+	return &ws->layer.view_list;
 }
 
 static void
-shell_surface_pong(struct wl_client *client,
-		   struct wl_resource *resource, uint32_t serial)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-	struct shell_client *sc = shsurf->owner;
-
-	shell_client_pong(sc, serial);
-}
-
-static void
-set_title(struct shell_surface *shsurf, const char *title)
+shell_surface_update_child_surface_layers (struct shell_surface *shsurf)
 {
-	free(shsurf->title);
-	shsurf->title = strdup(title);
-	shsurf->surface->timeline.force_refresh = 1;
+	weston_desktop_surface_propagate_layer(shsurf->desktop_surface);
 }
 
+/* Update the surface’s layer. Mark both the old and new views as having dirty
+ * geometry to ensure the changes are redrawn.
+ *
+ * If any child surfaces exist and are mapped, ensure they’re in the same layer
+ * as this surface. */
 static void
-set_pid(struct shell_surface *shsurf, pid_t pid)
+shell_surface_update_layer(struct shell_surface *shsurf)
 {
-	/* We have no use for it */
-}
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
+	struct weston_layer_entry *new_layer_link;
 
-static void
-set_type(struct shell_surface *shsurf, enum shell_surface_type t)
-{
-	shsurf->type = t;
-	shsurf->surface->timeline.force_refresh = 1;
-}
-
-static void
-set_window_geometry(struct shell_surface *shsurf,
-		    int32_t x, int32_t y, int32_t width, int32_t height)
-{
-	shsurf->next_geometry.x = x;
-	shsurf->next_geometry.y = y;
-	shsurf->next_geometry.width = width;
-	shsurf->next_geometry.height = height;
-	shsurf->has_next_geometry = true;
-}
-
-static void
-shell_surface_set_title(struct wl_client *client,
-			struct wl_resource *resource, const char *title)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-
-	set_title(shsurf, title);
-}
-
-static void
-shell_surface_set_class(struct wl_client *client,
-			struct wl_resource *resource, const char *class)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-
-	free(shsurf->class);
-	shsurf->class = strdup(class);
-	shsurf->surface->timeline.force_refresh = 1;
-}
-
-static void
-restore_output_mode(struct weston_output *output)
-{
-	if (output && output->original_mode)
-		weston_output_mode_switch_to_native(output);
-}
-
-static void
-restore_all_output_modes(struct weston_compositor *compositor)
-{
-	struct weston_output *output;
-
-	wl_list_for_each(output, &compositor->output_list, link)
-		restore_output_mode(output);
-}
-
-/* The surface will be inserted into the list immediately after the link
- * returned by this function (i.e. will be stacked immediately above the
- * returned link). */
-static struct weston_layer_entry *
-shell_surface_calculate_layer_link (struct shell_surface *shsurf)
-{
-	struct workspace *ws;
-	struct weston_view *parent;
-
-	switch (shsurf->type) {
-	case SHELL_SURFACE_XWAYLAND:
-		return &shsurf->shell->fullscreen_layer.view_list;
-
-	case SHELL_SURFACE_NONE:
-		return NULL;
-
-	case SHELL_SURFACE_POPUP:
-	case SHELL_SURFACE_TOPLEVEL:
-		if (shsurf->state.fullscreen && !shsurf->state.lowered) {
-			return &shsurf->shell->fullscreen_layer.view_list;
-		} else if (shsurf->parent) {
-			/* Move the surface to its parent layer so
-			 * that surfaces which are transient for
-			 * fullscreen surfaces don't get hidden by the
-			 * fullscreen surfaces. */
-
-			/* TODO: Handle a parent with multiple views */
-			parent = get_default_view(shsurf->parent);
-			if (parent)
-				return container_of(parent->layer_link.link.prev,
-						    struct weston_layer_entry, link);
-		}
-
-		/* Move the surface to a normal workspace layer so that surfaces
-		 * which were previously fullscreen or transient are no longer
-		 * rendered on top. */
-		ws = get_current_workspace(shsurf->shell);
-		return &ws->layer.view_list;
-	}
-
-	assert(0 && "Unknown shell surface type");
-}
-
-static void
-shell_surface_update_child_surface_layers (struct shell_surface *shsurf)
-{
-	struct shell_surface *child;
-	struct weston_layer_entry *prev;
-
-	/* Move the child layers to the same workspace as shsurf. They will be
-	 * stacked above shsurf. */
-	wl_list_for_each_reverse(child, &shsurf->children_list, children_link) {
-		if (shsurf->view->layer_link.link.prev != &child->view->layer_link.link) {
-			weston_view_damage_below(child->view);
-			weston_view_geometry_dirty(child->view);
-			prev = container_of(shsurf->view->layer_link.link.prev,
-					    struct weston_layer_entry, link);
-			weston_layer_entry_remove(&child->view->layer_link);
-			weston_layer_entry_insert(prev,
-						  &child->view->layer_link);
-			weston_view_geometry_dirty(child->view);
-			weston_surface_damage(child->surface);
-
-			/* Recurse. We don’t expect this to recurse very far (if
-			 * at all) because that would imply we have transient
-			 * (or popup) children of transient surfaces, which
-			 * would be unusual. */
-			shell_surface_update_child_surface_layers(child);
-		}
-	}
-}
-
-/* Update the surface’s layer. Mark both the old and new views as having dirty
- * geometry to ensure the changes are redrawn.
- *
- * If any child surfaces exist and are mapped, ensure they’re in the same layer
- * as this surface. */
-static void
-shell_surface_update_layer(struct shell_surface *shsurf)
-{
-	struct weston_layer_entry *new_layer_link;
-
-	new_layer_link = shell_surface_calculate_layer_link(shsurf);
+	new_layer_link = shell_surface_calculate_layer_link(shsurf);
 
 	if (new_layer_link == NULL)
 		return;
@@ -2403,34 +1906,17 @@ shell_surface_update_layer(struct shell_surface *shsurf)
 	weston_layer_entry_remove(&shsurf->view->layer_link);
 	weston_layer_entry_insert(new_layer_link, &shsurf->view->layer_link);
 	weston_view_geometry_dirty(shsurf->view);
-	weston_surface_damage(shsurf->surface);
+	weston_surface_damage(surface);
 
 	shell_surface_update_child_surface_layers(shsurf);
 }
 
-static void
-shell_surface_set_parent(struct shell_surface *shsurf,
-                         struct weston_surface *parent)
-{
-	shsurf->parent = parent;
-
-	wl_list_remove(&shsurf->children_link);
-	wl_list_init(&shsurf->children_link);
-
-	/* Insert into the parent surface’s child list. */
-	if (parent != NULL) {
-		struct shell_surface *parent_shsurf = get_shell_surface(parent);
-		if (parent_shsurf != NULL)
-			wl_list_insert(&parent_shsurf->children_list,
-			               &shsurf->children_link);
-	}
-}
-
 static void
 shell_surface_set_output(struct shell_surface *shsurf,
                          struct weston_output *output)
 {
-	struct weston_surface *es = shsurf->surface;
+	struct weston_surface *es =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
 
 	/* get the default output, if the client set it as NULL
 	   check whether the ouput is available */
@@ -2442,88 +1928,6 @@ shell_surface_set_output(struct shell_surface *shsurf,
 		shsurf->output = get_default_output(es->compositor);
 }
 
-static void
-surface_clear_next_states(struct shell_surface *shsurf)
-{
-	shsurf->next_state.maximized = false;
-	shsurf->next_state.fullscreen = false;
-
-	if ((shsurf->next_state.maximized != shsurf->state.maximized) ||
-	    (shsurf->next_state.fullscreen != shsurf->state.fullscreen))
-		shsurf->state_changed = true;
-}
-
-static void
-set_toplevel(struct shell_surface *shsurf)
-{
-	shell_surface_set_parent(shsurf, NULL);
-	surface_clear_next_states(shsurf);
-	set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
-
-	/* The layer_link is updated in set_surface_type(),
-	 * called from configure. */
-}
-
-static void
-shell_surface_set_toplevel(struct wl_client *client,
-			   struct wl_resource *resource)
-{
-	struct shell_surface *surface = wl_resource_get_user_data(resource);
-
-	set_toplevel(surface);
-}
-
-static void
-set_transient(struct shell_surface *shsurf,
-	      struct weston_surface *parent, int x, int y, uint32_t flags)
-{
-	assert(parent != NULL);
-
-	shell_surface_set_parent(shsurf, parent);
-
-	surface_clear_next_states(shsurf);
-
-	shsurf->transient.x = x;
-	shsurf->transient.y = y;
-	shsurf->transient.flags = flags;
-
-	shsurf->next_state.relative = true;
-	shsurf->state_changed = true;
-	set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
-
-	/* The layer_link is updated in set_surface_type(),
-	 * called from configure. */
-}
-
-static void
-shell_surface_set_transient(struct wl_client *client,
-			    struct wl_resource *resource,
-			    struct wl_resource *parent_resource,
-			    int x, int y, uint32_t flags)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-	struct weston_surface *parent =
-		wl_resource_get_user_data(parent_resource);
-
-	set_transient(shsurf, parent, x, y, flags);
-}
-
-static void
-set_fullscreen(struct shell_surface *shsurf,
-	       uint32_t method,
-	       uint32_t framerate,
-	       struct weston_output *output)
-{
-	shell_surface_set_output(shsurf, output);
-	set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
-
-	shsurf->fullscreen_output = shsurf->output;
-	shsurf->fullscreen.type = method;
-	shsurf->fullscreen.framerate = framerate;
-
-	send_configure_for_surface(shsurf);
-}
-
 static void
 weston_view_set_initial_position(struct weston_view *view,
 				 struct desktop_shell *shell);
@@ -2532,14 +1936,6 @@ static void
 unset_fullscreen(struct shell_surface *shsurf)
 {
 	/* Unset the fullscreen output, driver configuration and transforms. */
-	if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
-	    shell_surface_is_top_fullscreen(shsurf)) {
-		restore_output_mode(shsurf->fullscreen_output);
-	}
-
-	shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
-	shsurf->fullscreen.framerate = 0;
-
 	wl_list_remove(&shsurf->fullscreen.transform.link);
 	wl_list_init(&shsurf->fullscreen.transform.link);
 
@@ -2562,80 +1958,14 @@ unset_fullscreen(struct shell_surface *shsurf)
 	/* Layer is updated in set_surface_type(). */
 }
 
-static void
-shell_surface_set_fullscreen(struct wl_client *client,
-			     struct wl_resource *resource,
-			     uint32_t method,
-			     uint32_t framerate,
-			     struct wl_resource *output_resource)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-	struct weston_output *output;
-
-	if (shsurf->fullscreen_output == shsurf->output &&
-	    shsurf->fullscreen.type == method &&
-	    shsurf->fullscreen.framerate == framerate) {
-		send_configure_for_surface(shsurf);
-		return;
-	}
-
-	if (output_resource)
-		output = wl_resource_get_user_data(output_resource);
-	else
-		output = NULL;
-
-	shell_surface_set_parent(shsurf, NULL);
-
-	surface_clear_next_states(shsurf);
-	shsurf->next_state.fullscreen = true;
-	shsurf->state_changed = true;
-	set_fullscreen(shsurf, method, framerate, output);
-}
-
-static void
-set_popup(struct shell_surface *shsurf,
-          struct weston_surface *parent,
-          struct weston_seat *seat,
-          uint32_t serial,
-          int32_t x,
-          int32_t y)
-{
-	assert(parent != NULL);
-
-	shsurf->popup.shseat = get_shell_seat(seat);
-	shsurf->popup.serial = serial;
-	shsurf->popup.x = x;
-	shsurf->popup.y = y;
-
-	set_type(shsurf, SHELL_SURFACE_POPUP);
-}
-
-static void
-shell_surface_set_popup(struct wl_client *client,
-			struct wl_resource *resource,
-			struct wl_resource *seat_resource,
-			uint32_t serial,
-			struct wl_resource *parent_resource,
-			int32_t x, int32_t y, uint32_t flags)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-	struct weston_surface *parent =
-		wl_resource_get_user_data(parent_resource);
-
-	shell_surface_set_parent(shsurf, parent);
-
-	surface_clear_next_states(shsurf);
-	set_popup(shsurf,
-	          parent,
-	          wl_resource_get_user_data(seat_resource),
-	          serial, x, y);
-}
-
 static void
 unset_maximized(struct shell_surface *shsurf)
 {
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
+
 	/* undo all maximized things here */
-	shsurf->output = get_default_output(shsurf->surface->compositor);
+	shsurf->output = get_default_output(surface->compositor);
 
 	if (shsurf->saved_position_valid)
 		weston_view_set_position(shsurf->view,
@@ -2678,95 +2008,6 @@ set_minimized(struct weston_surface *surface)
 	weston_view_damage_below(view);
 }
 
-static void
-shell_surface_set_maximized(struct wl_client *client,
-                            struct wl_resource *resource,
-                            struct wl_resource *output_resource)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-	struct weston_output *output;
-
-	surface_clear_next_states(shsurf);
-	shsurf->next_state.maximized = true;
-	shsurf->state_changed = true;
-
-	set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
-	shell_surface_set_parent(shsurf, NULL);
-
-	if (output_resource)
-		output = wl_resource_get_user_data(output_resource);
-	else
-		output = NULL;
-
-	shell_surface_set_output(shsurf, output);
-
-	send_configure_for_surface(shsurf);
-}
-
-/* This is only ever called from set_surface_type(), so there’s no need to
- * update layer_links here, since they’ll be updated when we return. */
-static int
-reset_surface_type(struct shell_surface *surface)
-{
-	if (surface->state.fullscreen)
-		unset_fullscreen(surface);
-	if (surface->state.maximized)
-		unset_maximized(surface);
-
-	return 0;
-}
-
-static void
-set_full_output(struct shell_surface *shsurf)
-{
-	shsurf->saved_x = shsurf->view->geometry.x;
-	shsurf->saved_y = shsurf->view->geometry.y;
-	shsurf->saved_position_valid = true;
-
-	if (!wl_list_empty(&shsurf->rotation.transform.link)) {
-		wl_list_remove(&shsurf->rotation.transform.link);
-		wl_list_init(&shsurf->rotation.transform.link);
-		weston_view_geometry_dirty(shsurf->view);
-		shsurf->saved_rotation_valid = true;
-	}
-}
-
-static void
-set_surface_type(struct shell_surface *shsurf)
-{
-	struct weston_surface *pes = shsurf->parent;
-	struct weston_view *pev = get_default_view(pes);
-
-	reset_surface_type(shsurf);
-
-	shsurf->state = shsurf->next_state;
-	shsurf->state_changed = false;
-
-	switch (shsurf->type) {
-	case SHELL_SURFACE_TOPLEVEL:
-		if (shsurf->state.maximized || shsurf->state.fullscreen) {
-			set_full_output(shsurf);
-		} else if (shsurf->state.relative && pev) {
-			weston_view_set_position(shsurf->view,
-						 pev->geometry.x + shsurf->transient.x,
-						 pev->geometry.y + shsurf->transient.y);
-		}
-		break;
-
-	case SHELL_SURFACE_XWAYLAND:
-		weston_view_set_position(shsurf->view, shsurf->transient.x,
-					 shsurf->transient.y);
-		break;
-
-	case SHELL_SURFACE_POPUP:
-	case SHELL_SURFACE_NONE:
-	default:
-		break;
-	}
-
-	/* Update the surface’s layer. */
-	shell_surface_update_layer(shsurf);
-}
 
 static struct desktop_shell *
 shell_surface_get_shell(struct shell_surface *shsurf)
@@ -2843,13 +2084,15 @@ create_black_surface(struct weston_compositor *ec,
 static void
 shell_ensure_fullscreen_black_view(struct shell_surface *shsurf)
 {
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
 	struct weston_output *output = shsurf->fullscreen_output;
 
-	assert(shsurf->state.fullscreen);
+	assert(weston_desktop_surface_get_fullscreen(shsurf->desktop_surface));
 
 	if (!shsurf->fullscreen.black_view)
 		shsurf->fullscreen.black_view =
-			create_black_surface(shsurf->surface->compositor,
+			create_black_surface(surface->compositor,
 			                     shsurf->view,
 			                     output->x, output->y,
 			                     output->width,
@@ -2860,7 +2103,7 @@ shell_ensure_fullscreen_black_view(struct shell_surface *shsurf)
 	weston_layer_entry_insert(&shsurf->view->layer_link,
 				  &shsurf->fullscreen.black_view->layer_link);
 	weston_view_geometry_dirty(shsurf->fullscreen.black_view);
-	weston_surface_damage(shsurf->surface);
+	weston_surface_damage(surface);
 
 	shsurf->fullscreen.black_view->is_mapped = true;
 	shsurf->state.lowered = false;
@@ -2871,94 +2114,22 @@ shell_ensure_fullscreen_black_view(struct shell_surface *shsurf)
 static void
 shell_configure_fullscreen(struct shell_surface *shsurf)
 {
-	struct weston_output *output = shsurf->fullscreen_output;
-	struct weston_surface *surface = shsurf->surface;
-	struct weston_matrix *matrix;
-	float scale, output_aspect, surface_aspect, x, y;
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
 	int32_t surf_x, surf_y, surf_width, surf_height;
 
-	if (shsurf->fullscreen.type != WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER)
-		restore_output_mode(output);
-
 	/* Reverse the effect of lower_fullscreen_layer() */
 	weston_layer_entry_remove(&shsurf->view->layer_link);
-	weston_layer_entry_insert(&shsurf->shell->fullscreen_layer.view_list, &shsurf->view->layer_link);
+	weston_layer_entry_insert(&shsurf->shell->fullscreen_layer.view_list,
+				  &shsurf->view->layer_link);
 
 	shell_ensure_fullscreen_black_view(shsurf);
 
-	surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
+	surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y,
 	                                &surf_width, &surf_height);
 
-	switch (shsurf->fullscreen.type) {
-	case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
-		if (surface->buffer_ref.buffer)
-			center_on_output(shsurf->view, shsurf->fullscreen_output);
-		break;
-	case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
-		/* 1:1 mapping between surface and output dimensions */
-		if (output->width == surf_width &&
-			output->height == surf_height) {
-			weston_view_set_position(shsurf->view,
-						 output->x - surf_x,
-						 output->y - surf_y);
-			break;
-		}
-
-		matrix = &shsurf->fullscreen.transform.matrix;
-		weston_matrix_init(matrix);
-
-		output_aspect = (float) output->width /
-			(float) output->height;
-		/* XXX: Use surf_width and surf_height here? */
-		surface_aspect = (float) surface->width /
-			(float) surface->height;
-		if (output_aspect < surface_aspect)
-			scale = (float) output->width /
-				(float) surf_width;
-		else
-			scale = (float) output->height /
-				(float) surf_height;
-
-		weston_matrix_scale(matrix, scale, scale, 1);
-		wl_list_remove(&shsurf->fullscreen.transform.link);
-		wl_list_insert(&shsurf->view->geometry.transformation_list,
-			       &shsurf->fullscreen.transform.link);
-		x = output->x + (output->width - surf_width * scale) / 2 - surf_x;
-		y = output->y + (output->height - surf_height * scale) / 2 - surf_y;
-		weston_view_set_position(shsurf->view, x, y);
-
-		break;
-	case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
-		if (shell_surface_is_top_fullscreen(shsurf)) {
-			struct weston_mode mode = {0,
-				surf_width * surface->buffer_viewport.buffer.scale,
-				surf_height * surface->buffer_viewport.buffer.scale,
-				shsurf->fullscreen.framerate};
-
-			if (weston_output_mode_switch_to_temporary(output, &mode,
-					surface->buffer_viewport.buffer.scale) == 0) {
-				weston_view_set_position(shsurf->view,
-							 output->x - surf_x,
-							 output->y - surf_y);
-				shsurf->fullscreen.black_view->surface->width = output->width;
-				shsurf->fullscreen.black_view->surface->height = output->height;
-				weston_view_set_position(shsurf->fullscreen.black_view,
-							 output->x - surf_x,
-							 output->y - surf_y);
-				break;
-			} else {
-				weston_log("shell: Can't switch to temporary mode.\n");
-				restore_output_mode(output);
-				center_on_output(shsurf->view, output);
-			}
-		}
-		break;
-	case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
-		center_on_output(shsurf->view, output);
-		break;
-	default:
-		break;
-	}
+	if (surface->buffer_ref.buffer)
+		center_on_output(shsurf->view, shsurf->fullscreen_output);
 }
 
 static void
@@ -2967,34 +2138,6 @@ shell_map_fullscreen(struct shell_surface *shsurf)
 	shell_configure_fullscreen(shsurf);
 }
 
-static void
-set_xwayland(struct shell_surface *shsurf, int x, int y, uint32_t flags)
-{
-	/* XXX: using the same fields for transient type */
-	surface_clear_next_states(shsurf);
-	shsurf->transient.x = x;
-	shsurf->transient.y = y;
-	shsurf->transient.flags = flags;
-
-	shell_surface_set_parent(shsurf, NULL);
-
-	set_type(shsurf, SHELL_SURFACE_XWAYLAND);
-	shsurf->state_changed = true;
-}
-
-static void
-shell_interface_set_fullscreen(struct shell_surface *shsurf,
-			       uint32_t method,
-			       uint32_t framerate,
-			       struct weston_output *output)
-{
-	surface_clear_next_states(shsurf);
-	shsurf->next_state.fullscreen = true;
-	shsurf->state_changed = true;
-
-	set_fullscreen(shsurf, method, framerate, output);
-}
-
 static struct weston_output *
 get_focused_output(struct weston_compositor *compositor)
 {
@@ -3026,60 +2169,12 @@ get_focused_output(struct weston_compositor *compositor)
 	return output;
 }
 
-static void
-shell_interface_set_maximized(struct shell_surface *shsurf)
-{
-	struct weston_output *output;
-
-	surface_clear_next_states(shsurf);
-	shsurf->next_state.maximized = true;
-	shsurf->state_changed = true;
-	shsurf->type = SHELL_SURFACE_TOPLEVEL;
-
-	if (!weston_surface_is_mapped(shsurf->surface))
-		output = get_focused_output(shsurf->surface->compositor);
-	else
-		output = shsurf->surface->output;
-
-	shell_surface_set_output(shsurf, output);
-	send_configure_for_surface(shsurf);
-}
-
-static int
-shell_interface_move(struct shell_surface *shsurf, struct weston_pointer *pointer)
-{
-	return surface_move(shsurf, pointer, true);
-}
-
-static int
-shell_interface_resize(struct shell_surface *shsurf,
-		       struct weston_pointer *pointer,
-		       uint32_t edges)
-{
-	return surface_resize(shsurf, pointer, edges);
-}
-
-static const struct weston_pointer_grab_interface popup_grab_interface;
-
 static void
 destroy_shell_seat(struct wl_listener *listener, void *data)
 {
 	struct shell_seat *shseat =
 		container_of(listener,
 			     struct shell_seat, seat_destroy_listener);
-	struct shell_surface *shsurf, *next;
-
-	if (shseat->popup_grab.grab.interface == &popup_grab_interface) {
-		weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
-		shseat->popup_grab.client = NULL;
-
-		wl_list_for_each_safe(shsurf, next,
-				      &shseat->popup_grab.surfaces_list,
-				      popup.grab_link) {
-			shsurf->popup.shseat = NULL;
-			wl_list_init(&shsurf->popup.grab_link);
-		}
-	}
 
 	wl_list_remove(&shseat->seat_destroy_listener.link);
 	free(shseat);
@@ -3127,7 +2222,6 @@ create_shell_seat(struct weston_seat *seat)
 	}
 
 	shseat->seat = seat;
-	wl_list_init(&shseat->popup_grab.surfaces_list);
 
 	shseat->seat_destroy_listener.notify = destroy_shell_seat;
 	wl_signal_add(&seat->destroy_signal,
@@ -3160,586 +2254,83 @@ get_shell_seat(struct weston_seat *seat)
 }
 
 static void
-popup_grab_focus(struct weston_pointer_grab *grab)
+fade_out_done_idle_cb(void *data)
 {
-	struct weston_pointer *pointer = grab->pointer;
-	struct weston_view *view;
-	struct shell_seat *shseat =
-	    container_of(grab, struct shell_seat, popup_grab.grab);
-	struct wl_client *client = shseat->popup_grab.client;
-	wl_fixed_t sx, sy;
-
-	view = weston_compositor_pick_view(pointer->seat->compositor,
-					   pointer->x, pointer->y,
-					   &sx, &sy);
+	struct shell_surface *shsurf = data;
 
-	if (view && view->surface->resource &&
-	    wl_resource_get_client(view->surface->resource) == client) {
-		weston_pointer_set_focus(pointer, view, sx, sy);
-	} else {
-		weston_pointer_clear_focus(pointer);
-	}
+	weston_surface_destroy(shsurf->view->surface);
+	free(shsurf);
 }
 
 static void
-popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
-		  struct weston_pointer_motion_event *event)
+fade_out_done(struct weston_view_animation *animation, void *data)
 {
-	struct weston_pointer *pointer = grab->pointer;
-	struct wl_resource *resource;
-	struct wl_list *resource_list;
-	wl_fixed_t x, y;
-	wl_fixed_t sx, sy;
+	struct shell_surface *shsurf = data;
+	struct wl_event_loop *loop;
 
-	if (pointer->focus) {
-		weston_pointer_motion_to_abs(pointer, event, &x, &y);
-		weston_view_from_global_fixed(pointer->focus, x, y,
-					      &pointer->sx, &pointer->sy);
-	}
+	loop = wl_display_get_event_loop(shsurf->shell->compositor->wl_display);
 
-	weston_pointer_move(pointer, event);
+	if (weston_view_is_mapped(shsurf->view)) {
+		shsurf->view->is_mapped = false;
+		wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
+	}
+}
 
-	if (!pointer->focus_client)
-		return;
-
-	resource_list = &pointer->focus_client->pointer_resources;
-	wl_resource_for_each(resource, resource_list) {
-		weston_view_from_global_fixed(pointer->focus,
-					      pointer->x, pointer->y,
-					      &sx, &sy);
-		wl_pointer_send_motion(resource, time, sx, sy);
-	}
-}
-
-static void
-popup_grab_button(struct weston_pointer_grab *grab,
-		  uint32_t time, uint32_t button, uint32_t state_w)
-{
-	struct wl_resource *resource;
-	struct shell_seat *shseat =
-	    container_of(grab, struct shell_seat, popup_grab.grab);
-	struct wl_display *display = shseat->seat->compositor->wl_display;
-	enum wl_pointer_button_state state = state_w;
-	uint32_t serial;
-	struct wl_list *resource_list = NULL;
-
-	if (grab->pointer->focus_client)
-		resource_list = &grab->pointer->focus_client->pointer_resources;
-	if (resource_list && !wl_list_empty(resource_list)) {
-		serial = wl_display_get_serial(display);
-		wl_resource_for_each(resource, resource_list) {
-			wl_pointer_send_button(resource, serial,
-					       time, button, state);
-		}
-	} else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
-		   (shseat->popup_grab.initial_up ||
-		    time - grab->pointer->grab_time > 500)) {
-		popup_grab_end(grab->pointer);
-	}
-
-	if (state == WL_POINTER_BUTTON_STATE_RELEASED)
-		shseat->popup_grab.initial_up = 1;
-}
-
-static void
-popup_grab_axis(struct weston_pointer_grab *grab,
-		uint32_t time,
-		struct weston_pointer_axis_event *event)
-{
-	weston_pointer_send_axis(grab->pointer, time, event);
-}
-
-static void
-popup_grab_axis_source(struct weston_pointer_grab *grab, uint32_t source)
-{
-	weston_pointer_send_axis_source(grab->pointer, source);
-}
-
-static void
-popup_grab_frame(struct weston_pointer_grab *grab)
-{
-	weston_pointer_send_frame(grab->pointer);
-}
-
-static void
-popup_grab_cancel(struct weston_pointer_grab *grab)
-{
-	popup_grab_end(grab->pointer);
-}
-
-static const struct weston_pointer_grab_interface popup_grab_interface = {
-	popup_grab_focus,
-	popup_grab_motion,
-	popup_grab_button,
-	popup_grab_axis,
-	popup_grab_axis_source,
-	popup_grab_frame,
-	popup_grab_cancel,
-};
-
-static void
-touch_popup_grab_down(struct weston_touch_grab *grab, uint32_t time,
-		      int touch_id, wl_fixed_t x, wl_fixed_t y)
-{
-	struct wl_resource *resource;
-	struct shell_seat *shseat =
-	    container_of(grab, struct shell_seat, popup_grab.touch_grab);
-	struct wl_display *display = shseat->seat->compositor->wl_display;
-	uint32_t serial;
-	struct wl_list *resource_list;
-	wl_fixed_t sx, sy;
-
-	weston_view_from_global_fixed(grab->touch->focus, x, y, &sx, &sy);
-
-	resource_list = &grab->touch->focus_resource_list;
-	if (!wl_list_empty(resource_list)) {
-		serial = wl_display_get_serial(display);
-		wl_resource_for_each(resource, resource_list) {
-			wl_touch_send_down(resource, serial, time,
-				grab->touch->focus->surface->resource,
-				touch_id, sx, sy);
-		}
-	}
-}
-
-static void
-touch_popup_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
-{
-	struct wl_resource *resource;
-	struct shell_seat *shseat =
-	    container_of(grab, struct shell_seat, popup_grab.touch_grab);
-	struct wl_display *display = shseat->seat->compositor->wl_display;
-	uint32_t serial;
-	struct wl_list *resource_list;
-
-	resource_list = &grab->touch->focus_resource_list;
-	if (!wl_list_empty(resource_list)) {
-		serial = wl_display_get_serial(display);
-		wl_resource_for_each(resource, resource_list) {
-			wl_touch_send_up(resource, serial, time, touch_id);
-		}
-	}
-}
-
-static void
-touch_popup_grab_motion(struct weston_touch_grab *grab, uint32_t time,
-			int touch_id, wl_fixed_t x, wl_fixed_t y)
+struct shell_surface *
+get_shell_surface(struct weston_surface *surface)
 {
-	struct wl_resource *resource;
-	struct wl_list *resource_list;
-	wl_fixed_t sx, sy;
-
-	weston_view_from_global_fixed(grab->touch->focus, x, y, &sx, &sy);
-
-	resource_list = &grab->touch->focus_resource_list;
-	if (!wl_list_empty(resource_list)) {
-		wl_resource_for_each(resource, resource_list) {
-			wl_touch_send_motion(resource, time, touch_id, sx, sy);
-		}
+	if (weston_surface_is_desktop_surface(surface)) {
+		struct weston_desktop_surface *desktop_surface =
+			weston_surface_get_desktop_surface(surface);
+		return weston_desktop_surface_get_user_data(desktop_surface);
 	}
+	return NULL;
 }
 
-static void
-touch_popup_grab_frame(struct weston_touch_grab *grab)
-{
-}
-
-static void
-touch_popup_grab_cancel(struct weston_touch_grab *grab)
-{
-	touch_popup_grab_end(grab->touch);
-}
-
-static const struct weston_touch_grab_interface touch_popup_grab_interface = {
-	touch_popup_grab_down,
-	touch_popup_grab_up,
-	touch_popup_grab_motion,
-	touch_popup_grab_frame,
-	touch_popup_grab_cancel,
-};
-
-static void
-shell_surface_send_popup_done(struct shell_surface *shsurf)
-{
-	if (shsurf->resource == NULL)
-		return;
-	else if (shell_surface_is_wl_shell_surface(shsurf))
-		wl_shell_surface_send_popup_done(shsurf->resource);
-	else if (shell_surface_is_xdg_popup(shsurf))
-		xdg_popup_send_popup_done(shsurf->resource);
-}
-
-static void
-popup_grab_end(struct weston_pointer *pointer)
-{
-	struct weston_pointer_grab *grab = pointer->grab;
-	struct shell_seat *shseat =
-	    container_of(grab, struct shell_seat, popup_grab.grab);
-	struct shell_surface *shsurf;
-	struct shell_surface *next;
-
-	if (pointer->grab->interface == &popup_grab_interface) {
-		weston_pointer_end_grab(grab->pointer);
-		shseat->popup_grab.client = NULL;
-		shseat->popup_grab.grab.interface = NULL;
-		assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
-		/* Send the popup_done event to all the popups open */
-		wl_list_for_each_safe(shsurf, next,
-				      &shseat->popup_grab.surfaces_list,
-				      popup.grab_link) {
-			shell_surface_send_popup_done(shsurf);
-			shsurf->popup.shseat = NULL;
-			wl_list_init(&shsurf->popup.grab_link);
-		}
-		wl_list_init(&shseat->popup_grab.surfaces_list);
-	}
-}
+/*
+ * libweston-desktop
+ */
 
 static void
-touch_popup_grab_end(struct weston_touch *touch)
-{
-	struct weston_touch_grab *grab = touch->grab;
-	struct shell_seat *shseat =
-	    container_of(grab, struct shell_seat, popup_grab.touch_grab);
-	struct shell_surface *shsurf;
-	struct shell_surface *next;
-
-	if (touch->grab->interface == &touch_popup_grab_interface) {
-		weston_touch_end_grab(grab->touch);
-		shseat->popup_grab.client = NULL;
-		shseat->popup_grab.touch_grab.interface = NULL;
-		assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
-		/* Send the popup_done event to all the popups open */
-		wl_list_for_each_safe(shsurf, next,
-				      &shseat->popup_grab.surfaces_list,
-				      popup.grab_link) {
-			shell_surface_send_popup_done(shsurf);
-			shsurf->popup.shseat = NULL;
-			wl_list_init(&shsurf->popup.grab_link);
-		}
-		wl_list_init(&shseat->popup_grab.surfaces_list);
-	}
-}
-
-static struct shell_surface *
-get_top_popup(struct shell_seat *shseat)
+desktop_surface_added(struct weston_desktop_surface *desktop_surface,
+		      void *shell)
 {
+	struct weston_desktop_client *client =
+		weston_desktop_surface_get_client(desktop_surface);
+	struct wl_client *wl_client =
+		weston_desktop_client_get_client(client);
+	struct weston_view *view;
 	struct shell_surface *shsurf;
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(desktop_surface);
 
-	if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
-		return NULL;
-	} else {
-		shsurf = container_of(shseat->popup_grab.surfaces_list.next,
-				      struct shell_surface,
-				      popup.grab_link);
-		return shsurf;
-	}
-}
-
-static int
-add_popup_grab(struct shell_surface *shsurf,
-	       struct shell_seat *shseat,
-	       int32_t type)
-{
-	struct weston_seat *seat = shseat->seat;
-	struct shell_surface *parent, *top_surface;
-	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
-	struct weston_touch *touch = weston_seat_get_touch(seat);
-
-	parent = get_shell_surface(shsurf->parent);
-	top_surface = get_top_popup(shseat);
-	if (shell_surface_is_xdg_popup(shsurf) &&
-	    (!parent ||
-	     (top_surface == NULL && !shell_surface_is_xdg_surface(parent)) ||
-	     (top_surface != NULL && parent != top_surface))) {
-		wl_resource_post_error(shsurf->owner_resource,
-				       XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
-				       "xdg_popup was not created on the "
-				       "topmost popup");
-		return -1;
-	}
-
-	if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
-		shseat->popup_grab.type = type;
-		shseat->popup_grab.client =
-			wl_resource_get_client(shsurf->resource);
-
-		if (type == POINTER) {
-			shseat->popup_grab.grab.interface =
-				&popup_grab_interface;
-
-			/* We must make sure here that this popup was opened
-			 * after a mouse press, and not just by moving around
-			 * with other popups already open. */
-			if (pointer->button_count > 0)
-				shseat->popup_grab.initial_up = 0;
-		} else if (type == TOUCH) {
-			shseat->popup_grab.touch_grab.interface =
-				&touch_popup_grab_interface;
-		}
-
-		wl_list_insert(&shseat->popup_grab.surfaces_list,
-			       &shsurf->popup.grab_link);
-
-		if (type == POINTER) {
-			weston_pointer_start_grab(pointer,
-						  &shseat->popup_grab.grab);
-		} else if (type == TOUCH) {
-			weston_touch_start_grab(touch,
-						&shseat->popup_grab.touch_grab);
-		}
-	} else {
-		wl_list_insert(&shseat->popup_grab.surfaces_list,
-			       &shsurf->popup.grab_link);
-	}
-
-	return 0;
-}
-
-static void
-remove_popup_grab(struct shell_surface *shsurf)
-{
-	struct shell_seat *shseat = shsurf->popup.shseat;
-
-	if (shell_surface_is_xdg_popup(shsurf) &&
-	    get_top_popup(shseat) != shsurf) {
-		wl_resource_post_error(shsurf->owner_resource,
-				       XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
-				       "xdg_popup was destroyed while it was "
-				       "not the topmost popup.");
-		return;
-	}
-
-	wl_list_remove(&shsurf->popup.grab_link);
-	wl_list_init(&shsurf->popup.grab_link);
-	if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
-		if (shseat->popup_grab.type == POINTER) {
-			weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
-			shseat->popup_grab.grab.interface = NULL;
-		} else if (shseat->popup_grab.type == TOUCH) {
-			weston_touch_end_grab(shseat->popup_grab.touch_grab.touch);
-			shseat->popup_grab.touch_grab.interface = NULL;
-		}
-	}
-}
-
-static int
-shell_map_popup(struct shell_surface *shsurf)
-{
-	struct shell_seat *shseat = shsurf->popup.shseat;
-	struct weston_view *parent_view = get_default_view(shsurf->parent);
-	struct weston_pointer *pointer = weston_seat_get_pointer(shseat->seat);
-	struct weston_touch *touch = weston_seat_get_touch(shseat->seat);
-
-	shsurf->surface->output = parent_view->output;
-	shsurf->surface->is_mapped = true;
-	shsurf->view->output = parent_view->output;
-
-	weston_view_set_transform_parent(shsurf->view, parent_view);
-	weston_view_set_position(shsurf->view, shsurf->popup.x, shsurf->popup.y);
-	weston_view_update_transform(shsurf->view);
-	shsurf->view->is_mapped = true;
-
-	if (pointer &&
-	    pointer->grab_serial == shsurf->popup.serial) {
-		if (add_popup_grab(shsurf, shseat, POINTER) != 0)
-			return -1;
-	} else if (touch &&
-	           touch->grab_serial == shsurf->popup.serial) {
-		if (add_popup_grab(shsurf, shseat, TOUCH) != 0)
-			return -1;
-	} else {
-		shell_surface_send_popup_done(shsurf);
-		shseat->popup_grab.client = NULL;
-	}
-
-	return 0;
-}
-
-static const struct wl_shell_surface_interface shell_surface_implementation = {
-	shell_surface_pong,
-	shell_surface_move,
-	shell_surface_resize,
-	shell_surface_set_toplevel,
-	shell_surface_set_transient,
-	shell_surface_set_fullscreen,
-	shell_surface_set_popup,
-	shell_surface_set_maximized,
-	shell_surface_set_title,
-	shell_surface_set_class
-};
-
-static void
-destroy_shell_surface(struct shell_surface *shsurf)
-{
-	struct shell_surface *child, *next;
-
-	wl_signal_emit(&shsurf->destroy_signal, shsurf);
-
-	if (!wl_list_empty(&shsurf->popup.grab_link)) {
-		remove_popup_grab(shsurf);
-	}
-
-	if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
-	    shell_surface_is_top_fullscreen(shsurf))
-		restore_output_mode (shsurf->fullscreen_output);
-
-	if (shsurf->fullscreen.black_view)
-		weston_surface_destroy(shsurf->fullscreen.black_view->surface);
-
-	/* As destroy_resource() use wl_list_for_each_safe(),
-	 * we can always remove the listener.
-	 */
-	wl_list_remove(&shsurf->surface_destroy_listener.link);
-	shsurf->surface->committed = NULL;
-	weston_surface_set_label_func(shsurf->surface, NULL);
-	free(shsurf->title);
-
-	weston_view_destroy(shsurf->view);
-
-	wl_list_remove(&shsurf->children_link);
-	wl_list_for_each_safe(child, next, &shsurf->children_list, children_link)
-		shell_surface_set_parent(child, NULL);
-
-	wl_list_remove(&shsurf->link);
-	free(shsurf);
-}
-
-static void
-shell_destroy_shell_surface(struct wl_resource *resource)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-
-	if (!wl_list_empty(&shsurf->popup.grab_link))
-		remove_popup_grab(shsurf);
-	if (shsurf->resource)
-		wl_list_remove(wl_resource_get_link(shsurf->resource));
-	shsurf->resource = NULL;
-}
-
-static void
-shell_handle_surface_destroy(struct wl_listener *listener, void *data)
-{
-	struct shell_surface *shsurf = container_of(listener,
-						    struct shell_surface,
-						    surface_destroy_listener);
-
-	if (shsurf->resource)
-		wl_resource_destroy(shsurf->resource);
-
-	destroy_shell_surface(shsurf);
-}
-
-static void
-fade_out_done_idle_cb(void *data)
-{
-	struct shell_surface *shsurf = data;
-
-	weston_surface_destroy(shsurf->surface);
-}
-
-static void
-fade_out_done(struct weston_view_animation *animation, void *data)
-{
-	struct shell_surface *shsurf = data;
-	struct wl_event_loop *loop;
-
-	loop = wl_display_get_event_loop(
-				shsurf->surface->compositor->wl_display);
-
-	if (!shsurf->destroying) {
-		wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
-		shsurf->destroying = true;
-	}
-}
-
-static void
-handle_resource_destroy(struct wl_listener *listener, void *data)
-{
-	struct shell_surface *shsurf =
-		container_of(listener, struct shell_surface,
-			     resource_destroy_listener);
-
-	if (!weston_surface_is_mapped(shsurf->surface))
+	view = weston_desktop_surface_create_view(desktop_surface);
+	if (!view)
 		return;
 
-	shsurf->surface->ref_count++;
-
-	pixman_region32_fini(&shsurf->surface->pending.input);
-	pixman_region32_init(&shsurf->surface->pending.input);
-	pixman_region32_fini(&shsurf->surface->input);
-	pixman_region32_init(&shsurf->surface->input);
-	if (shsurf->shell->win_close_animation_type == ANIMATION_FADE) {
-		weston_fade_run(shsurf->view, 1.0, 0.0, 300.0,
-				fade_out_done, shsurf);
-	} else {
-		weston_surface_destroy(shsurf->surface);
-	}
-}
-
-static void
-shell_surface_committed(struct weston_surface *, int32_t, int32_t);
-
-struct shell_surface *
-get_shell_surface(struct weston_surface *surface)
-{
-	if (surface->committed == shell_surface_committed)
-		return surface->committed_private;
-	else
-		return NULL;
-}
-
-static struct shell_surface *
-create_common_surface(struct shell_client *owner, void *shell,
-		      struct weston_surface *surface,
-		      const struct weston_shell_client *client)
-{
-	struct shell_surface *shsurf;
-
-	assert(surface->committed == NULL);
-
 	shsurf = calloc(1, sizeof *shsurf);
 	if (!shsurf) {
-		weston_log("no memory to allocate shell surface\n");
-		return NULL;
-	}
-
-	shsurf->view = weston_view_create(surface);
-	if (!shsurf->view) {
-		weston_log("no memory to allocate shell surface\n");
-		free(shsurf);
-		return NULL;
+		if (wl_client)
+			wl_client_post_no_memory(wl_client);
+		else
+			weston_log("no memory to allocate shell surface\n");
+		return;
 	}
 
-	surface->committed = shell_surface_committed;
-	surface->committed_private = shsurf;
 	weston_surface_set_label_func(surface, shell_surface_get_label);
-
-	shsurf->resource_destroy_listener.notify = handle_resource_destroy;
-	wl_resource_add_destroy_listener(surface->resource,
-					 &shsurf->resource_destroy_listener);
-	shsurf->owner = owner;
 
 	shsurf->shell = (struct desktop_shell *) shell;
 	shsurf->unresponsive = 0;
 	shsurf->saved_position_valid = false;
 	shsurf->saved_rotation_valid = false;
-	shsurf->surface = surface;
-	shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
-	shsurf->fullscreen.framerate = 0;
+	shsurf->desktop_surface = desktop_surface;
+	shsurf->view = view;
 	shsurf->fullscreen.black_view = NULL;
 	wl_list_init(&shsurf->fullscreen.transform.link);
 
 	shsurf->output = get_default_output(shsurf->shell->compositor);
 
 	wl_signal_init(&shsurf->destroy_signal);
-	shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
-	wl_signal_add(&surface->destroy_signal,
-		      &shsurf->surface_destroy_listener);
-
-	/* init link so its safe to always remove it in destroy_shell_surface */
-	wl_list_init(&shsurf->link);
-	wl_list_init(&shsurf->popup.grab_link);
 
 	/* empty when not in use */
 	wl_list_init(&shsurf->rotation.transform.link);
@@ -3747,614 +2338,452 @@ create_common_surface(struct shell_client *owner, void *shell,
 
 	wl_list_init(&shsurf->workspace_transform.link);
 
-	wl_list_init(&shsurf->children_link);
-	wl_list_init(&shsurf->children_list);
-	shsurf->parent = NULL;
-
-	set_type(shsurf, SHELL_SURFACE_NONE);
-
-	shsurf->client = client;
-
-	return shsurf;
-}
-
-static struct shell_surface *
-create_shell_surface(void *shell, struct weston_surface *surface,
-		     const struct weston_shell_client *client)
-{
-	return create_common_surface(NULL, shell, surface, client);
+	weston_desktop_surface_set_user_data(desktop_surface, shsurf);
+	weston_desktop_surface_set_activated(desktop_surface,
+					     shsurf->focus_count > 0);
 }
 
 static void
-shell_get_shell_surface(struct wl_client *client,
-			struct wl_resource *resource,
-			uint32_t id,
-			struct wl_resource *surface_resource)
+desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
+			void *shell)
 {
+	struct shell_surface *shsurf =
+		weston_desktop_surface_get_user_data(desktop_surface);
 	struct weston_surface *surface =
-		wl_resource_get_user_data(surface_resource);
-	struct shell_client *sc = wl_resource_get_user_data(resource);
-	struct desktop_shell *shell = sc->shell;
-	struct shell_surface *shsurf;
+		weston_desktop_surface_get_surface(desktop_surface);
 
-	if (weston_surface_set_role(surface, "wl_shell_surface",
-				    resource, WL_SHELL_ERROR_ROLE) < 0)
+	if (!shsurf)
 		return;
 
-	shsurf = create_common_surface(sc, shell, surface, &shell_client);
-	if (!shsurf) {
-		wl_resource_post_no_memory(surface_resource);
-		return;
-	}
+	wl_signal_emit(&shsurf->destroy_signal, shsurf);
 
-	shsurf->resource =
-		wl_resource_create(client,
-				   &wl_shell_surface_interface, 1, id);
-	if (!shsurf->resource) {
-		wl_resource_post_no_memory(surface_resource);
-	        return;
-	}
-	wl_resource_set_implementation(shsurf->resource,
-				       &shell_surface_implementation,
-				       shsurf, shell_destroy_shell_surface);
-	wl_list_insert(&sc->surface_list,
-		       wl_resource_get_link(shsurf->resource));
-}
+	if (shsurf->fullscreen.black_view)
+		weston_surface_destroy(shsurf->fullscreen.black_view->surface);
 
-static bool
-shell_surface_is_wl_shell_surface(struct shell_surface *shsurf)
-{
-	/* A shell surface without a resource is created from xwayland
-	 * and is considered a wl_shell surface for now. */
+	weston_surface_set_label_func(surface, NULL);
+	weston_desktop_surface_set_user_data(shsurf->desktop_surface, NULL);
+	shsurf->desktop_surface = NULL;
 
-	return shsurf->resource == NULL ||
-		wl_resource_instance_of(shsurf->resource,
-					&wl_shell_surface_interface,
-					&shell_surface_implementation);
+	if (weston_surface_is_mapped(surface) &&
+	    shsurf->shell->win_close_animation_type == ANIMATION_FADE) {
+		pixman_region32_fini(&surface->pending.input);
+		pixman_region32_init(&surface->pending.input);
+		pixman_region32_fini(&surface->input);
+		pixman_region32_init(&surface->input);
+		weston_fade_run(shsurf->view, 1.0, 0.0, 300.0,
+				fade_out_done, shsurf);
+	} else {
+		weston_desktop_surface_destroy_view(shsurf->view);
+		weston_view_destroy(shsurf->view);
+		free(shsurf);
+	}
 }
-
-static const struct wl_shell_interface shell_implementation = {
-	shell_get_shell_surface
-};
-
-/****************************
- * xdg-shell implementation */
 
 static void
-xdg_surface_destroy(struct wl_client *client,
-		    struct wl_resource *resource)
+set_maximized_position(struct desktop_shell *shell,
+		       struct shell_surface *shsurf)
 {
-	wl_resource_destroy(resource);
-}
+	pixman_rectangle32_t area;
+	struct weston_geometry geometry;
 
-static void
-xdg_surface_set_parent(struct wl_client *client,
-		       struct wl_resource *resource,
-		       struct wl_resource *parent_resource)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-	struct shell_surface *parent;
+	get_output_work_area(shell, shsurf->output, &area);
+	geometry = weston_desktop_surface_get_geometry(shsurf->desktop_surface);
 
-	if (parent_resource) {
-		parent = wl_resource_get_user_data(parent_resource);
-		shell_surface_set_parent(shsurf, parent->surface);
-	} else {
-		shell_surface_set_parent(shsurf, NULL);
-	}
+	weston_view_set_position(shsurf->view,
+				 area.x - geometry.x,
+				 area.y - geometry.y);
 }
 
 static void
-xdg_surface_set_app_id(struct wl_client *client,
-		       struct wl_resource *resource,
-		       const char *app_id)
+map(struct desktop_shell *shell, struct shell_surface *shsurf,
+    int32_t sx, int32_t sy)
 {
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
+	struct weston_compositor *compositor = shell->compositor;
+	struct weston_seat *seat;
 
-	free(shsurf->class);
-	shsurf->class = strdup(app_id);
-	shsurf->surface->timeline.force_refresh = 1;
-}
+	/* initial positioning, see also configure() */
+	if (weston_desktop_surface_get_fullscreen(shsurf->desktop_surface)) {
+		center_on_output(shsurf->view, shsurf->fullscreen_output);
+		shell_map_fullscreen(shsurf);
+	} else if (weston_desktop_surface_get_maximized(shsurf->desktop_surface)) {
+		set_maximized_position(shell, shsurf);
+	} else {
+		weston_view_set_initial_position(shsurf->view, shell);
+	}
 
-static void
-xdg_surface_show_window_menu(struct wl_client *client,
-			     struct wl_resource *surface_resource,
-			     struct wl_resource *seat_resource,
-			     uint32_t serial,
-			     int32_t x,
-			     int32_t y)
-{
-	/* TODO */
-}
+	/* Surface stacking order, see also activate(). */
+	shell_surface_update_layer(shsurf);
 
-static void
-xdg_surface_set_title(struct wl_client *client,
-			struct wl_resource *resource, const char *title)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
+	weston_view_update_transform(shsurf->view);
+	shsurf->view->is_mapped = true;
+	if (weston_desktop_surface_get_maximized(shsurf->desktop_surface)) {
+		surface->output = shsurf->output;
+		shsurf->view->output = shsurf->output;
+	}
 
-	set_title(shsurf, title);
-}
+	if (!shell->locked) {
+		wl_list_for_each(seat, &compositor->seat_list, link)
+			activate(shell, shsurf->view, seat,
+				 WESTON_ACTIVATE_FLAG_CONFIGURE);
+	}
 
-static void
-xdg_surface_move(struct wl_client *client, struct wl_resource *resource,
-		 struct wl_resource *seat_resource, uint32_t serial)
-{
-	common_surface_move(resource, seat_resource, serial);
+	if (!weston_desktop_surface_get_maximized(shsurf->desktop_surface) &&
+	    !weston_desktop_surface_get_fullscreen(shsurf->desktop_surface)) {
+		switch (shell->win_animation_type) {
+		case ANIMATION_FADE:
+			weston_fade_run(shsurf->view, 0.0, 1.0, 300.0, NULL, NULL);
+			break;
+		case ANIMATION_ZOOM:
+			weston_zoom_run(shsurf->view, 0.5, 1.0, NULL, NULL);
+			break;
+		case ANIMATION_NONE:
+		default:
+			break;
+		}
+	}
 }
 
 static void
-xdg_surface_resize(struct wl_client *client, struct wl_resource *resource,
-		   struct wl_resource *seat_resource, uint32_t serial,
-		   uint32_t edges)
+desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
+			  int32_t sx, int32_t sy, void *data)
 {
-	common_surface_resize(resource, seat_resource, serial, edges);
-}
+	struct shell_surface *shsurf =
+		weston_desktop_surface_get_user_data(desktop_surface);
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(desktop_surface);
+	struct weston_view *view = shsurf->view;
+	struct desktop_shell *shell = data;
 
-static void
-xdg_surface_ack_configure(struct wl_client *client,
-			  struct wl_resource *resource,
-			  uint32_t serial)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
+	if (surface->width == 0)
+		return;
 
-	if (shsurf->state_requested) {
-		shsurf->next_state = shsurf->requested_state;
-		shsurf->state_changed = true;
-		shsurf->state_requested = false;
+	if (!weston_surface_is_mapped(surface)) {
+		map(shell, shsurf, sx, sy);
+		surface->is_mapped = true;
+		if (shsurf->shell->win_close_animation_type == ANIMATION_FADE)
+			++surface->ref_count;
+		return;
 	}
-}
 
-static void
-xdg_surface_set_window_geometry(struct wl_client *client,
-				struct wl_resource *resource,
-				int32_t x,
-				int32_t y,
-				int32_t width,
-				int32_t height)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
+	if (sx == 0 && sy == 0 &&
+	    shsurf->last_width == surface->width &&
+	    shsurf->last_height == surface->height)
+	    return;
 
-	set_window_geometry(shsurf, x, y, width, height);
-}
+	if (weston_desktop_surface_get_fullscreen(desktop_surface))
+		shell_configure_fullscreen(shsurf);
+	else if (weston_desktop_surface_get_maximized(desktop_surface)) {
+		set_maximized_position(shell, shsurf);
+		surface->output = shsurf->output;
+	} else {
+		float from_x, from_y;
+		float to_x, to_y;
+		float x, y;
 
-static void
-xdg_surface_set_maximized(struct wl_client *client,
-			  struct wl_resource *resource)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-	struct weston_output *output;
+		if (shsurf->resize_edges) {
+			sx = 0;
+			sy = 0;
+		}
 
-	shsurf->state_requested = true;
-	shsurf->requested_state.maximized = true;
+		if (shsurf->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT)
+			sx = shsurf->last_width - surface->width;
+		if (shsurf->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP)
+			sy = shsurf->last_height - surface->height;
 
-	if (!weston_surface_is_mapped(shsurf->surface))
-		output = get_focused_output(shsurf->surface->compositor);
-	else
-		output = shsurf->surface->output;
+		shsurf->last_width = surface->width;
+		shsurf->last_height = surface->height;
 
-	shell_surface_set_output(shsurf, output);
- 	send_configure_for_surface(shsurf);
-}
+		weston_view_to_global_float(shsurf->view, 0, 0, &from_x, &from_y);
+		weston_view_to_global_float(shsurf->view, sx, sy, &to_x, &to_y);
+		x = shsurf->view->geometry.x + to_x - from_x;
+		y = shsurf->view->geometry.y + to_y - from_y;
 
-static void
-xdg_surface_unset_maximized(struct wl_client *client,
-			    struct wl_resource *resource)
-{
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
+		weston_view_set_position(shsurf->view, x, y);
+	}
 
-	shsurf->state_requested = true;
-	shsurf->requested_state.maximized = false;
-	send_configure_for_surface(shsurf);
+	/* XXX: would a fullscreen surface need the same handling? */
+	if (surface->output) {
+		wl_list_for_each(view, &surface->views, surface_link)
+			weston_view_update_transform(view);
+	}
 }
 
 static void
-xdg_surface_set_fullscreen(struct wl_client *client,
-			   struct wl_resource *resource,
-			   struct wl_resource *output_resource)
+set_fullscreen(struct shell_surface *shsurf, bool fullscreen,
+	       struct weston_output *output)
 {
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
-	struct weston_output *output;
-
-	shsurf->state_requested = true;
-	shsurf->requested_state.fullscreen = true;
+	struct weston_desktop_surface *desktop_surface = shsurf->desktop_surface;
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
+	int32_t width = 0, height = 0;
+
+	if (fullscreen) {
+		/* handle clients launching in fullscreen */
+		if (output == NULL && !weston_surface_is_mapped(surface)) {
+			/* Set the output to the one that has focus currently. */
+			output = get_focused_output(surface->compositor);
+		}
 
-	if (output_resource)
-		output = wl_resource_get_user_data(output_resource);
-	else
-		output = NULL;
+		shell_surface_set_output(shsurf, output);
+		shsurf->fullscreen_output = shsurf->output;
 
-	/* handle clients launching in fullscreen */
-	if (output == NULL && !weston_surface_is_mapped(shsurf->surface)) {
-		/* Set the output to the one that has focus currently. */
-		assert(shsurf->surface);
-		output = get_focused_output(shsurf->surface->compositor);
+		width = shsurf->output->width;
+		height = shsurf->output->height;
+	} else {
+		unset_fullscreen(shsurf);
 	}
-
-	shell_surface_set_output(shsurf, output);
-	shsurf->fullscreen_output = shsurf->output;
-
-	send_configure_for_surface(shsurf);
+	weston_desktop_surface_set_fullscreen(desktop_surface, fullscreen);
+	weston_desktop_surface_set_size(desktop_surface, width, height);
 }
 
 static void
-xdg_surface_unset_fullscreen(struct wl_client *client,
-			     struct wl_resource *resource)
+desktop_surface_move(struct weston_desktop_surface *desktop_surface,
+		     struct weston_seat *seat, uint32_t serial, void *shell)
 {
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
+	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+	struct weston_touch *touch = weston_seat_get_touch(seat);
+	struct shell_surface *shsurf =
+		weston_desktop_surface_get_user_data(desktop_surface);
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
+	struct wl_resource *resource = surface->resource;
+	struct weston_surface *focus;
 
-	shsurf->state_requested = true;
-	shsurf->requested_state.fullscreen = false;
-	send_configure_for_surface(shsurf);
+	if (pointer &&
+	    pointer->focus &&
+	    pointer->button_count > 0 &&
+	    pointer->grab_serial == serial) {
+		focus = weston_surface_get_main_surface(pointer->focus->surface);
+		if ((focus == surface) &&
+		    (surface_move(shsurf, pointer, true) < 0))
+			wl_resource_post_no_memory(resource);
+	} else if (touch &&
+		   touch->focus &&
+		   touch->grab_serial == serial) {
+		focus = weston_surface_get_main_surface(touch->focus->surface);
+		if ((focus == surface) &&
+		    (surface_touch_move(shsurf, touch) < 0))
+			wl_resource_post_no_memory(resource);
+	}
 }
 
 static void
-xdg_surface_set_minimized(struct wl_client *client,
-			    struct wl_resource *resource)
+desktop_surface_resize(struct weston_desktop_surface *desktop_surface,
+		       struct weston_seat *seat, uint32_t serial,
+		       enum weston_desktop_surface_edge edges, void *shell)
 {
-	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
+	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+	struct shell_surface *shsurf =
+		weston_desktop_surface_get_user_data(desktop_surface);
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
+	struct wl_resource *resource = surface->resource;
+	struct weston_surface *focus;
 
-	if (shsurf->type != SHELL_SURFACE_TOPLEVEL)
+	if (!pointer ||
+	    pointer->button_count == 0 ||
+	    pointer->grab_serial != serial ||
+	    pointer->focus == NULL)
 		return;
 
-	 /* apply compositor's own minimization logic (hide) */
-	set_minimized(shsurf->surface);
-}
-
-static const struct xdg_surface_interface xdg_surface_implementation = {
-	xdg_surface_destroy,
-	xdg_surface_set_parent,
-	xdg_surface_set_title,
-	xdg_surface_set_app_id,
-	xdg_surface_show_window_menu,
-	xdg_surface_move,
-	xdg_surface_resize,
-	xdg_surface_ack_configure,
-	xdg_surface_set_window_geometry,
-	xdg_surface_set_maximized,
-	xdg_surface_unset_maximized,
-	xdg_surface_set_fullscreen,
-	xdg_surface_unset_fullscreen,
-	xdg_surface_set_minimized,
-};
-
-static void
-xdg_send_configure(struct weston_surface *surface,
-		   int32_t width, int32_t height)
-{
-	struct shell_surface *shsurf = get_shell_surface(surface);
-	uint32_t *s;
-	struct wl_array states;
-	uint32_t serial;
-
-	assert(shsurf);
-
-	if (!shsurf->resource)
+	focus = weston_surface_get_main_surface(pointer->focus->surface);
+	if (focus != surface)
 		return;
 
-	wl_array_init(&states);
-	if (shsurf->requested_state.fullscreen) {
-		s = wl_array_add(&states, sizeof *s);
-		*s = XDG_SURFACE_STATE_FULLSCREEN;
-	} else if (shsurf->requested_state.maximized) {
-		s = wl_array_add(&states, sizeof *s);
-		*s = XDG_SURFACE_STATE_MAXIMIZED;
-	}
-	if (shsurf->resize_edges != 0) {
-		s = wl_array_add(&states, sizeof *s);
-		*s = XDG_SURFACE_STATE_RESIZING;
-	}
-	if (shsurf->focus_count > 0) {
-		s = wl_array_add(&states, sizeof *s);
-		*s = XDG_SURFACE_STATE_ACTIVATED;
-	}
-
-	serial = wl_display_next_serial(shsurf->surface->compositor->wl_display);
-	xdg_surface_send_configure(shsurf->resource, width, height, &states, serial);
-
-	wl_array_release(&states);
-}
-
-static const struct weston_shell_client xdg_client = {
-	xdg_send_configure,
-	NULL
-};
-
-static void
-xdg_shell_destroy(struct wl_client *client,
-		  struct wl_resource *resource)
-{
-	struct shell_client *sc = wl_resource_get_user_data(resource);
-	struct wl_resource *shsurf_resource;
-	struct shell_surface *shsurf;
-
-	wl_resource_for_each(shsurf_resource, &sc->surface_list) {
-		shsurf = wl_resource_get_user_data(shsurf_resource);
-		if (shsurf->owner_resource == resource) {
-			wl_resource_post_error(
-				resource,
-				XDG_SHELL_ERROR_DEFUNCT_SURFACES,
-				"not all child surface objects destroyed");
-			return;
-		}
-	}
-
-	wl_resource_destroy(resource);
+	if (surface_resize(shsurf, pointer, edges) < 0)
+		wl_resource_post_no_memory(resource);
 }
 
 static void
-xdg_use_unstable_version(struct wl_client *client,
-			 struct wl_resource *resource,
-			 int32_t version)
+desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surface,
+				     bool fullscreen,
+				     struct weston_output *output, void *shell)
 {
-	if (version > 1) {
-		wl_resource_post_error(resource,
-				       1,
-				       "xdg-shell:: version not implemented yet.");
-		return;
-	}
-}
-
-static struct shell_surface *
-create_xdg_surface(struct shell_client *owner, void *shell,
-		   struct weston_surface *surface,
-		   const struct weston_shell_client *client)
-{
-	struct shell_surface *shsurf;
-
-	shsurf = create_common_surface(owner, shell, surface, client);
-	if (!shsurf)
-		return NULL;
-
-	set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
+	struct shell_surface *shsurf =
+		weston_desktop_surface_get_user_data(desktop_surface);
 
-	return shsurf;
+	set_fullscreen(shsurf, fullscreen, output);
 }
 
 static void
-xdg_get_xdg_surface(struct wl_client *client,
-		    struct wl_resource *resource,
-		    uint32_t id,
-		    struct wl_resource *surface_resource)
+set_maximized(struct shell_surface *shsurf, bool maximized)
 {
+	struct weston_desktop_surface *desktop_surface = shsurf->desktop_surface;
 	struct weston_surface *surface =
-		wl_resource_get_user_data(surface_resource);
-	struct shell_client *sc = wl_resource_get_user_data(resource);
-	struct desktop_shell *shell = sc->shell;
-	struct shell_surface *shsurf;
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
+	int32_t width = 0, height = 0;
 
-	shsurf = get_shell_surface(surface);
-	if (shsurf && shell_surface_is_xdg_surface(shsurf)) {
-		wl_resource_post_error(resource, XDG_SHELL_ERROR_ROLE,
-				       "This wl_surface is already an "
-				       "xdg_surface");
-		return;
-	}
+	if (maximized) {
+		struct weston_output *output;
+		struct desktop_shell *shell;
+		pixman_rectangle32_t area;
 
-	if (weston_surface_set_role(surface, "xdg_surface",
-				    resource, XDG_SHELL_ERROR_ROLE) < 0)
-		return;
+		if (!weston_surface_is_mapped(surface))
+			output = get_focused_output(surface->compositor);
+		else
+			output = surface->output;
 
-	shsurf = create_xdg_surface(sc, shell, surface, &xdg_client);
-	if (!shsurf) {
-		wl_resource_post_no_memory(surface_resource);
-		return;
-	}
+		shell_surface_set_output(shsurf, output);
 
-	shsurf->resource =
-		wl_resource_create(client,
-				   &xdg_surface_interface, 1, id);
-	if (!shsurf->resource) {
-		wl_resource_post_no_memory(surface_resource);
-		return;
-	}
-	wl_resource_set_implementation(shsurf->resource,
-				       &xdg_surface_implementation,
-				       shsurf, shell_destroy_shell_surface);
-	shsurf->owner_resource = resource;
-	wl_list_insert(&sc->surface_list,
-		       wl_resource_get_link(shsurf->resource));
-}
+		shell = shell_surface_get_shell(shsurf);
+		get_output_work_area(shell, shsurf->output, &area);
 
-static bool
-shell_surface_is_xdg_surface(struct shell_surface *shsurf)
-{
-	return shsurf->resource &&
-		wl_resource_instance_of(shsurf->resource,
-					&xdg_surface_interface,
-					&xdg_surface_implementation);
+		width = area.width;
+		height = area.height;
+	} else {
+		unset_maximized(shsurf);
+	}
+	weston_desktop_surface_set_maximized(desktop_surface, maximized);
+	weston_desktop_surface_set_size(desktop_surface, width, height);
 }
 
-/* xdg-popup implementation */
-
 static void
-xdg_popup_destroy(struct wl_client *client,
-		  struct wl_resource *resource)
+desktop_surface_maximized_requested(struct weston_desktop_surface *desktop_surface,
+				    bool maximized, void *shell)
 {
-	wl_resource_destroy(resource);
-}
-
-static const struct xdg_popup_interface xdg_popup_implementation = {
-	xdg_popup_destroy,
-};
+	struct shell_surface *shsurf =
+		weston_desktop_surface_get_user_data(desktop_surface);
 
-static void
-xdg_popup_send_configure(struct weston_surface *surface,
-			 int32_t width, int32_t height)
-{
+	set_maximized(shsurf, maximized);
 }
 
-static const struct weston_shell_client xdg_popup_client = {
-	xdg_popup_send_configure,
-	NULL
-};
-
-static struct shell_surface *
-create_xdg_popup(struct shell_client *owner, void *shell,
-		 struct weston_surface *surface,
-		 const struct weston_shell_client *client,
-		 struct weston_surface *parent,
-		 struct shell_seat *seat,
-		 uint32_t serial,
-		 int32_t x, int32_t y)
+static void
+desktop_surface_minimized_requested(struct weston_desktop_surface *desktop_surface,
+				    void *shell)
 {
-	struct shell_surface *shsurf;
-
-	shsurf = create_common_surface(owner, shell, surface, client);
-	if (!shsurf)
-		return NULL;
-
-	set_type(shsurf, SHELL_SURFACE_POPUP);
-	shsurf->popup.shseat = seat;
-	shsurf->popup.serial = serial;
-	shsurf->popup.x = x;
-	shsurf->popup.y = y;
-	shell_surface_set_parent(shsurf, parent);
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(desktop_surface);
 
-	return shsurf;
+	 /* apply compositor's own minimization logic (hide) */
+	set_minimized(surface);
 }
 
 static void
-xdg_get_xdg_popup(struct wl_client *client,
-		  struct wl_resource *resource,
-		  uint32_t id,
-		  struct wl_resource *surface_resource,
-		  struct wl_resource *parent_resource,
-		  struct wl_resource *seat_resource,
-		  uint32_t serial,
-		  int32_t x, int32_t y)
+set_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
 {
-	struct weston_surface *surface =
-		wl_resource_get_user_data(surface_resource);
-	struct shell_client *sc = wl_resource_get_user_data(resource);
-	struct desktop_shell *shell = sc->shell;
-	struct shell_surface *shsurf;
-	struct shell_surface *parent_shsurf;
-	struct weston_surface *parent;
-	struct shell_seat *seat;
+	struct shell_grab *grab;
 
-	shsurf = get_shell_surface(surface);
-	if (shsurf && shell_surface_is_xdg_popup(shsurf)) {
-		wl_resource_post_error(resource, XDG_SHELL_ERROR_ROLE,
-				       "This wl_surface is already an "
-				       "xdg_popup");
+	if (pointer->grab->interface == &busy_cursor_grab_interface)
 		return;
-	}
 
-	if (weston_surface_set_role(surface, "xdg_popup",
-				    resource, XDG_SHELL_ERROR_ROLE) < 0)
+	grab = malloc(sizeof *grab);
+	if (!grab)
 		return;
 
-	if (!parent_resource) {
-		wl_resource_post_error(surface_resource,
-				       WL_DISPLAY_ERROR_INVALID_OBJECT,
-				       "xdg_shell::get_xdg_popup requires a parent shell surface");
-		return;
-	}
+	shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer,
+			 WESTON_DESKTOP_SHELL_CURSOR_BUSY);
+	/* Mark the shsurf as ungrabbed so that button binding is able
+	 * to move it. */
+	shsurf->grabbed = 0;
+}
 
-	parent = wl_resource_get_user_data(parent_resource);
-	seat = get_shell_seat(wl_resource_get_user_data(seat_resource));
+static void
+end_busy_cursor(struct weston_compositor *compositor,
+		struct weston_desktop_client *desktop_client)
+{
+	struct shell_surface *shsurf;
+	struct shell_grab *grab;
+	struct weston_seat *seat;
 
-	/* Verify that we are creating the top most popup when mapping,
-	 * as it's not until then we know whether it was mapped as most
-	 * top level or not. */
+	wl_list_for_each(seat, &compositor->seat_list, link) {
+		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+		struct weston_desktop_client *grab_client;
 
-	parent_shsurf = get_shell_surface(parent);
-	if (!parent_shsurf ||
-	    (!shell_surface_is_xdg_popup(parent_shsurf) &&
-	     !shell_surface_is_xdg_surface(parent_shsurf))) {
-		wl_resource_post_error(resource,
-				       XDG_SHELL_ERROR_INVALID_POPUP_PARENT,
-				       "xdg_popup parent was invalid");
-		return;
-	}
+		if (!pointer)
+			continue;
 
-	shsurf = create_xdg_popup(sc, shell, surface, &xdg_popup_client,
-				  parent, seat, serial, x, y);
-	if (!shsurf) {
-		wl_resource_post_no_memory(surface_resource);
-		return;
-	}
+		if (pointer->grab->interface != &busy_cursor_grab_interface)
+			continue;
 
-	shsurf->resource =
-		wl_resource_create(client,
-				   &xdg_popup_interface, 1, id);
-	if (!shsurf->resource) {
-		wl_resource_post_no_memory(surface_resource);
-		return;
+		grab = (struct shell_grab *) pointer->grab;
+		shsurf = grab->shsurf;
+		if (!shsurf)
+			continue;
+
+		grab_client =
+			weston_desktop_surface_get_client(shsurf->desktop_surface);
+		if (grab_client  == desktop_client) {
+			shell_grab_end(grab);
+			free(grab);
+		}
 	}
-	wl_resource_set_implementation(shsurf->resource,
-				       &xdg_popup_implementation,
-				       shsurf, shell_destroy_shell_surface);
-	shsurf->owner_resource = resource;
-	wl_list_insert(&sc->surface_list,
-		       wl_resource_get_link(shsurf->resource));
 }
 
 static void
-xdg_pong(struct wl_client *client,
-	 struct wl_resource *resource, uint32_t serial)
+desktop_surface_set_unresponsive(struct weston_desktop_surface *desktop_surface,
+				 void *user_data)
 {
-	struct shell_client *sc = wl_resource_get_user_data(resource);
+	struct shell_surface *shsurf =
+		weston_desktop_surface_get_user_data(desktop_surface);
+	bool *unresponsive = user_data;
 
-	shell_client_pong(sc, serial);
+	shsurf->unresponsive = *unresponsive;
 }
 
-static bool
-shell_surface_is_xdg_popup(struct shell_surface *shsurf)
+static void
+desktop_surface_ping_timeout(struct weston_desktop_client *desktop_client,
+			     void *shell_)
 {
-	return (shsurf->resource &&
-		wl_resource_instance_of(shsurf->resource,
-					&xdg_popup_interface,
-					&xdg_popup_implementation));
-}
+	struct desktop_shell *shell = shell_;
+	struct shell_surface *shsurf;
+	struct weston_seat *seat;
+	bool unresponsive = true;
 
-static const struct xdg_shell_interface xdg_implementation = {
-	xdg_shell_destroy,
-	xdg_use_unstable_version,
-	xdg_get_xdg_surface,
-	xdg_get_xdg_popup,
-	xdg_pong
-};
+	weston_desktop_client_for_each_surface(desktop_client,
+					       desktop_surface_set_unresponsive,
+					       &unresponsive);
 
-static int
-xdg_shell_unversioned_dispatch(const void *implementation,
-			       void *_target, uint32_t opcode,
-			       const struct wl_message *message,
-			       union wl_argument *args)
-{
-	struct wl_resource *resource = _target;
-	struct shell_client *sc = wl_resource_get_user_data(resource);
 
-	if (opcode != 1 /* XDG_SHELL_USE_UNSTABLE_VERSION */) {
-		wl_resource_post_error(resource,
-				       WL_DISPLAY_ERROR_INVALID_OBJECT,
-				       "must call use_unstable_version first");
-		return 0;
-	}
+	wl_list_for_each(seat, &shell->compositor->seat_list, link) {
+		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+		struct weston_desktop_client *grab_client;
 
-#define XDG_SERVER_VERSION 5
+		if (!pointer || !pointer->focus)
+			continue;
 
-	static_assert(XDG_SERVER_VERSION == XDG_SHELL_VERSION_CURRENT,
-		      "shell implementation doesn't match protocol version");
+		shsurf = get_shell_surface(pointer->focus->surface);
+		if (!shsurf)
+			continue;
 
-	if (args[0].i != XDG_SERVER_VERSION) {
-		wl_resource_post_error(resource,
-				       WL_DISPLAY_ERROR_INVALID_OBJECT,
-				       "incompatible version, server is %d "
-				       "client wants %d",
-				       XDG_SERVER_VERSION, args[0].i);
-		return 0;
+		grab_client =
+			weston_desktop_surface_get_client(shsurf->desktop_surface);
+		if (grab_client == desktop_client)
+			set_busy_cursor(shsurf, pointer);
 	}
+}
 
-	wl_resource_set_implementation(resource, &xdg_implementation,
-				       sc, NULL);
+static void
+desktop_surface_pong(struct weston_desktop_client *desktop_client,
+		     void *shell_)
+{
+	struct desktop_shell *shell = shell_;
+	bool unresponsive = false;
 
-	return 1;
+	weston_desktop_client_for_each_surface(desktop_client,
+					       desktop_surface_set_unresponsive,
+					       &unresponsive);
+	end_busy_cursor(shell->compositor, desktop_client);
 }
 
-/* end of xdg-shell implementation */
-/***********************************/
+static const struct weston_desktop_api shell_desktop_api = {
+	.struct_size = sizeof(struct weston_desktop_api),
+	.surface_added = desktop_surface_added,
+	.surface_removed = desktop_surface_removed,
+	.committed = desktop_surface_committed,
+	.move = desktop_surface_move,
+	.resize = desktop_surface_resize,
+	.fullscreen_requested = desktop_surface_fullscreen_requested,
+	.maximized_requested = desktop_surface_maximized_requested,
+	.minimized_requested = desktop_surface_minimized_requested,
+	.ping_timeout = desktop_surface_ping_timeout,
+	.pong = desktop_surface_pong,
+};
 
+/* ************************ *
+ * end of libweston-desktop *
+ * ************************ */
 static void
 shell_fade(struct desktop_shell *shell, enum fade_type type);
 
@@ -4383,7 +2812,8 @@ configure_static_view(struct weston_view *ev, struct weston_layer *layer)
 
 
 static struct shell_output *
-find_shell_output_from_weston_output(struct desktop_shell *shell, struct weston_output *output)
+find_shell_output_from_weston_output(struct desktop_shell *shell,
+				     struct weston_output *output)
 {
 	struct shell_output *shell_output;
 
@@ -4686,17 +3116,6 @@ static const struct weston_desktop_shell_interface desktop_shell_implementation
 	desktop_shell_set_panel_position
 };
 
-static enum shell_surface_type
-get_shell_surface_type(struct weston_surface *surface)
-{
-	struct shell_surface *shsurf;
-
-	shsurf = get_shell_surface(surface);
-	if (!shsurf)
-		return SHELL_SURFACE_NONE;
-	return shsurf->type;
-}
-
 static void
 move_binding(struct weston_pointer *pointer, uint32_t time,
 	     uint32_t button, void *data)
@@ -4715,8 +3134,9 @@ move_binding(struct weston_pointer *pointer, uint32_t time,
 		return;
 
 	shsurf = get_shell_surface(surface);
-	if (shsurf == NULL || shsurf->state.fullscreen ||
-	    shsurf->state.maximized)
+	if (shsurf == NULL ||
+	    weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) ||
+	    weston_desktop_surface_get_maximized(shsurf->desktop_surface))
 		return;
 
 	surface_move(shsurf, pointer, false);
@@ -4738,12 +3158,7 @@ maximize_binding(struct weston_keyboard *keyboard, uint32_t time,
 	if (shsurf == NULL)
 		return;
 
-	if (!shell_surface_is_xdg_surface(shsurf))
-		return;
-
-	shsurf->state_requested = true;
-	shsurf->requested_state.maximized = !shsurf->state.maximized;
-	send_configure_for_surface(shsurf);
+	set_maximized(shsurf, !weston_desktop_surface_get_maximized(shsurf->desktop_surface));
 }
 
 static void
@@ -4753,6 +3168,7 @@ fullscreen_binding(struct weston_keyboard *keyboard, uint32_t time,
 	struct weston_surface *focus = keyboard->focus;
 	struct weston_surface *surface;
 	struct shell_surface *shsurf;
+	bool fullscreen;
 
 	surface = weston_surface_get_main_surface(focus);
 	if (surface == NULL)
@@ -4762,13 +3178,10 @@ fullscreen_binding(struct weston_keyboard *keyboard, uint32_t time,
 	if (shsurf == NULL)
 		return;
 
-	if (!shell_surface_is_xdg_surface(shsurf))
-		return;
+	fullscreen =
+		weston_desktop_surface_get_fullscreen(shsurf->desktop_surface);
 
-	shsurf->state_requested = true;
-	shsurf->requested_state.fullscreen = !shsurf->state.fullscreen;
-	shsurf->fullscreen_output = shsurf->output;
-	send_configure_for_surface(shsurf);
+	set_fullscreen(shsurf, !fullscreen, NULL);
 }
 
 static void
@@ -4787,8 +3200,9 @@ touch_move_binding(struct weston_touch *touch, uint32_t time, void *data)
 		return;
 
 	shsurf = get_shell_surface(surface);
-	if (shsurf == NULL || shsurf->state.fullscreen ||
-	    shsurf->state.maximized)
+	if (shsurf == NULL ||
+	    weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) ||
+	    weston_desktop_surface_get_maximized(shsurf->desktop_surface))
 		return;
 
 	surface_touch_move(shsurf, touch);
@@ -4814,8 +3228,9 @@ resize_binding(struct weston_pointer *pointer, uint32_t time,
 		return;
 
 	shsurf = get_shell_surface(surface);
-	if (shsurf == NULL || shsurf->state.fullscreen ||
-	    shsurf->state.maximized)
+	if (shsurf == NULL ||
+	    weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) ||
+	    weston_desktop_surface_get_maximized(shsurf->desktop_surface))
 		return;
 
 	weston_view_from_global(shsurf->view,
@@ -4823,16 +3238,16 @@ resize_binding(struct weston_pointer *pointer, uint32_t time,
 				wl_fixed_to_int(pointer->grab_y),
 				&x, &y);
 
-	if (x < shsurf->surface->width / 3)
+	if (x < surface->width / 3)
 		edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
-	else if (x < 2 * shsurf->surface->width / 3)
+	else if (x < 2 * surface->width / 3)
 		edges |= 0;
 	else
 		edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
 
-	if (y < shsurf->surface->height / 3)
+	if (y < surface->height / 3)
 		edges |= WL_SHELL_SURFACE_RESIZE_TOP;
-	else if (y < 2 * shsurf->surface->height / 3)
+	else if (y < 2 * surface->height / 3)
 		edges |= 0;
 	else
 		edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
@@ -4952,6 +3367,8 @@ rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
 		container_of(grab, struct rotate_grab, base.grab);
 	struct weston_pointer *pointer = grab->pointer;
 	struct shell_surface *shsurf = rotate->base.shsurf;
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
 	float cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
 
 	weston_pointer_move(pointer, event);
@@ -4959,8 +3376,8 @@ rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
 	if (!shsurf)
 		return;
 
-	cx = 0.5f * shsurf->surface->width;
-	cy = 0.5f * shsurf->surface->height;
+	cx = 0.5f * surface->width;
+	cy = 0.5f * surface->height;
 
 	dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
 	dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
@@ -5006,7 +3423,7 @@ rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
 	/* Repaint implies weston_view_update_transform(), which
 	 * lazily applies the damage due to rotation update.
 	 */
-	weston_compositor_schedule_repaint(shsurf->surface->compositor);
+	weston_compositor_schedule_repaint(surface->compositor);
 }
 
 static void
@@ -5050,21 +3467,21 @@ static const struct weston_pointer_grab_interface rotate_grab_interface = {
 };
 
 static void
-surface_rotate(struct shell_surface *surface, struct weston_pointer *pointer)
+surface_rotate(struct shell_surface *shsurf, struct weston_pointer *pointer)
 {
+	struct weston_surface *surface =
+		weston_desktop_surface_get_surface(shsurf->desktop_surface);
 	struct rotate_grab *rotate;
 	float dx, dy;
 	float r;
-
-	surface = find_toplevel_surface(surface);
 
 	rotate = malloc(sizeof *rotate);
 	if (!rotate)
 		return;
 
-	weston_view_to_global_float(surface->view,
-				    surface->surface->width * 0.5f,
-				    surface->surface->height * 0.5f,
+	weston_view_to_global_float(shsurf->view,
+				    surface->width * 0.5f,
+				    surface->height * 0.5f,
 				    &rotate->center.x, &rotate->center.y);
 
 	dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
@@ -5075,16 +3492,16 @@ surface_rotate(struct shell_surface *surface, struct weston_pointer *pointer)
 
 		weston_matrix_init(&inverse);
 		weston_matrix_rotate_xy(&inverse, dx / r, -dy / r);
-		weston_matrix_multiply(&surface->rotation.rotation, &inverse);
+		weston_matrix_multiply(&shsurf->rotation.rotation, &inverse);
 
 		weston_matrix_init(&rotate->rotation);
 		weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
 	} else {
-		weston_matrix_init(&surface->rotation.rotation);
+		weston_matrix_init(&shsurf->rotation.rotation);
 		weston_matrix_init(&rotate->rotation);
 	}
 
-	shell_grab_start(&rotate->base, &rotate_grab_interface, surface,
+	shell_grab_start(&rotate->base, &rotate_grab_interface, shsurf,
 			 pointer, WESTON_DESKTOP_SHELL_CURSOR_ARROW);
 }
 
@@ -5106,8 +3523,9 @@ rotate_binding(struct weston_pointer *pointer, uint32_t time, uint32_t button,
 		return;
 
 	surface = get_shell_surface(base_surface);
-	if (surface == NULL || surface->state.fullscreen ||
-	    surface->state.maximized)
+	if (surface == NULL ||
+	    weston_desktop_surface_get_fullscreen(surface->desktop_surface) ||
+	    weston_desktop_surface_get_maximized(surface->desktop_surface))
 		return;
 
 	surface_rotate(surface, pointer);
@@ -5125,7 +3543,7 @@ rotate_binding(struct weston_pointer *pointer, uint32_t time, uint32_t button,
  * the alt-tab switcher, which need to de-promote fullscreen layers. */
 void
 lower_fullscreen_layer(struct desktop_shell *shell,
-					   struct weston_output *lowering_output)
+		       struct weston_output *lowering_output)
 {
 	struct workspace *ws;
 	struct weston_view *view, *prev;
@@ -5147,7 +3565,7 @@ lower_fullscreen_layer(struct desktop_shell *shell,
 
 		/* We can have a non-fullscreen popup for a fullscreen surface
 		 * in the fullscreen layer. */
-		if (shsurf->state.fullscreen) {
+		if (weston_desktop_surface_get_fullscreen(shsurf->desktop_surface)) {
 			/* Hide the black view */
 			weston_layer_entry_remove(&shsurf->fullscreen.black_view->layer_link);
 			wl_list_init(&shsurf->fullscreen.black_view->layer_link.link);
@@ -5193,10 +3611,9 @@ activate(struct desktop_shell *shell, struct weston_view *view,
 	old_es = state->keyboard_focus;
 	focus_state_set_focus(state, es);
 
-	if (shsurf->state.fullscreen && flags & WESTON_ACTIVATE_FLAG_CONFIGURE)
+	if (weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) &&
+	    flags & WESTON_ACTIVATE_FLAG_CONFIGURE)
 		shell_configure_fullscreen(shsurf);
-	else
-		restore_output_mode(shsurf->output);
 
 	/* Update the surface’s layer. This brings it to the top of the stacking
 	 * order as appropriate. */
@@ -5243,7 +3660,7 @@ activate_binding(struct weston_seat *seat,
 		focus_view = main_view;
 
 	main_surface = weston_surface_get_main_surface(focus_view->surface);
-	if (get_shell_surface_type(main_surface) == SHELL_SURFACE_NONE)
+	if (!get_shell_surface(main_surface))
 		return;
 
 	activate(shell, focus_view, seat, flags);
@@ -5524,17 +3941,11 @@ idle_handler(struct wl_listener *listener, void *data)
 {
 	struct desktop_shell *shell =
 		container_of(listener, struct desktop_shell, idle_listener);
-	struct weston_seat *seat;
 
-	wl_list_for_each(seat, &shell->compositor->seat_list, link) {
-		struct weston_touch *touch = weston_seat_get_touch(seat);
-		struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+	struct weston_seat *seat;
 
-		if (pointer)
-			popup_grab_end(pointer);
-		if (touch)
-			touch_popup_grab_end(touch);
-	}
+	wl_list_for_each(seat, &shell->compositor->seat_list, link)
+		weston_seat_break_desktop_grabs(seat);
 
 	shell_fade(shell, FADE_OUT);
 	/* lock() is called from shell_fade_done() */
@@ -5554,20 +3965,28 @@ transform_handler(struct wl_listener *listener, void *data)
 {
 	struct weston_surface *surface = data;
 	struct shell_surface *shsurf = get_shell_surface(surface);
-	struct weston_view *view;;
+	const struct weston_xwayland_surface_api *api;
 	int x, y;
 
-	if (!shsurf || !shsurf->client->send_position)
+	if (!shsurf)
+		return;
+
+	api = shsurf->shell->xwayland_surface_api;
+	if (!api) {
+		api = weston_xwayland_surface_get_api(shsurf->shell->compositor);
+		shsurf->shell->xwayland_surface_api = api;
+	}
+
+	if (!api || !api->is_xwayland_surface(surface))
 		return;
 
-	view = shsurf->view;
-	if (!view || !weston_view_is_mapped(view))
+	if (!weston_view_is_mapped(shsurf->view))
 		return;
 
-	x = view->geometry.x;
-	y = view->geometry.y;
+	x = shsurf->view->geometry.x;
+	y = shsurf->view->geometry.y;
 
-	shsurf->client->send_position(surface, x, y);
+	api->send_position(surface, x, y);
 }
 
 static void
@@ -5644,206 +4063,6 @@ weston_view_set_initial_position(struct weston_view *view,
 	weston_view_set_position(view, x, y);
 }
 
-static void
-set_maximized_position(struct desktop_shell *shell,
-		       struct shell_surface *shsurf)
-{
-	int32_t surf_x, surf_y;
-	pixman_rectangle32_t area;
-
-	get_output_work_area(shell, shsurf->output, &area);
-	if (shsurf->has_set_geometry) {
-		surf_x = shsurf->geometry.x;
-		surf_y = shsurf->geometry.y;
-	} else {
-		surface_subsurfaces_boundingbox(shsurf->surface,
-						&surf_x, &surf_y, NULL, NULL);
-	}
-
-	weston_view_set_position(shsurf->view,
-				 area.x - surf_x,
-				 area.y - surf_y);
-}
-
-static void
-map(struct desktop_shell *shell, struct shell_surface *shsurf,
-    int32_t sx, int32_t sy)
-{
-	struct weston_compositor *compositor = shell->compositor;
-	struct weston_seat *seat;
-
-	/* initial positioning, see also configure() */
-	switch (shsurf->type) {
-	case SHELL_SURFACE_TOPLEVEL:
-		if (shsurf->state.fullscreen) {
-			center_on_output(shsurf->view, shsurf->fullscreen_output);
-			shell_map_fullscreen(shsurf);
-		} else if (shsurf->state.maximized) {
-			set_maximized_position(shell, shsurf);
-		} else if (!shsurf->state.relative) {
-			weston_view_set_initial_position(shsurf->view, shell);
-		}
-		break;
-	case SHELL_SURFACE_POPUP:
-		if (shell_map_popup(shsurf) != 0)
-			return;
-		break;
-	case SHELL_SURFACE_NONE:
-		weston_view_set_position(shsurf->view,
-					 shsurf->view->geometry.x + sx,
-					 shsurf->view->geometry.y + sy);
-		break;
-	case SHELL_SURFACE_XWAYLAND:
-	default:
-		;
-	}
-
-	/* Surface stacking order, see also activate(). */
-	shell_surface_update_layer(shsurf);
-
-	if (shsurf->type != SHELL_SURFACE_NONE) {
-		weston_view_update_transform(shsurf->view);
-		shsurf->view->is_mapped = true;
-		if (shsurf->state.maximized) {
-			shsurf->surface->output = shsurf->output;
-			shsurf->view->output = shsurf->output;
-		}
-	}
-
-	switch (shsurf->type) {
-	/* XXX: xwayland's using the same fields for transient type */
-	case SHELL_SURFACE_XWAYLAND:
-		if (shsurf->transient.flags ==
-				WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
-			break;
-	case SHELL_SURFACE_TOPLEVEL:
-		if (shsurf->state.relative &&
-		    shsurf->transient.flags == WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
-			break;
-		if (shell->locked)
-			break;
-		wl_list_for_each(seat, &compositor->seat_list, link)
-			activate(shell, shsurf->view, seat,
-				 WESTON_ACTIVATE_FLAG_CONFIGURE);
-		break;
-	case SHELL_SURFACE_POPUP:
-	case SHELL_SURFACE_NONE:
-	default:
-		break;
-	}
-
-	if (shsurf->type == SHELL_SURFACE_TOPLEVEL &&
-	    !shsurf->state.maximized && !shsurf->state.fullscreen)
-	{
-		switch (shell->win_animation_type) {
-		case ANIMATION_FADE:
-			weston_fade_run(shsurf->view, 0.0, 1.0, 300.0, NULL, NULL);
-			break;
-		case ANIMATION_ZOOM:
-			weston_zoom_run(shsurf->view, 0.5, 1.0, NULL, NULL);
-			break;
-		case ANIMATION_NONE:
-		default:
-			break;
-		}
-	}
-}
-
-static void
-configure(struct desktop_shell *shell, struct weston_surface *surface,
-	  float x, float y)
-{
-	struct shell_surface *shsurf;
-	struct weston_view *view;
-
-	shsurf = get_shell_surface(surface);
-
-	assert(shsurf);
-
-	if (shsurf->state.fullscreen)
-		shell_configure_fullscreen(shsurf);
-	else if (shsurf->state.maximized) {
-		set_maximized_position(shell, shsurf);
-	} else {
-		weston_view_set_position(shsurf->view, x, y);
-	}
-
-	/* XXX: would a fullscreen surface need the same handling? */
-	if (surface->output) {
-		wl_list_for_each(view, &surface->views, surface_link)
-			weston_view_update_transform(view);
-
-		if (shsurf->state.maximized)
-			surface->output = shsurf->output;
-	}
-}
-
-static void
-shell_surface_committed(struct weston_surface *es, int32_t sx, int32_t sy)
-{
-	struct shell_surface *shsurf = get_shell_surface(es);
-	struct desktop_shell *shell;
-	int type_changed = 0;
-
-	assert(shsurf);
-
-	shell = shsurf->shell;
-
-	if (!weston_surface_is_mapped(es) &&
-	    !wl_list_empty(&shsurf->popup.grab_link)) {
-		remove_popup_grab(shsurf);
-	}
-
-	if (es->width == 0)
-		return;
-
-	if (shsurf->has_next_geometry) {
-		shsurf->geometry = shsurf->next_geometry;
-		shsurf->has_next_geometry = false;
-		shsurf->has_set_geometry = true;
-	} else if (!shsurf->has_set_geometry) {
-		surface_subsurfaces_boundingbox(shsurf->surface,
-						&shsurf->geometry.x,
-						&shsurf->geometry.y,
-						&shsurf->geometry.width,
-						&shsurf->geometry.height);
-	}
-
-	if (shsurf->state_changed) {
-		set_surface_type(shsurf);
-		type_changed = 1;
-	}
-
-	if (!weston_surface_is_mapped(es)) {
-		map(shell, shsurf, sx, sy);
-		es->is_mapped = true;
-	} else if (type_changed || sx != 0 || sy != 0 ||
-		   shsurf->last_width != es->width ||
-		   shsurf->last_height != es->height) {
-		float from_x, from_y;
-		float to_x, to_y;
-
-		if (shsurf->resize_edges) {
-			sx = 0;
-			sy = 0;
-		}
-
-		if (shsurf->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT)
-			sx = shsurf->last_width - es->width;
-		if (shsurf->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP)
-			sy = shsurf->last_height - es->height;
-
-		shsurf->last_width = es->width;
-		shsurf->last_height = es->height;
-
-		weston_view_to_global_float(shsurf->view, 0, 0, &from_x, &from_y);
-		weston_view_to_global_float(shsurf->view, sx, sy, &to_x, &to_y);
-		configure(shell, es,
-			  shsurf->view->geometry.x + to_x - from_x,
-			  shsurf->view->geometry.y + to_y - from_y);
-	}
-}
-
 static bool
 check_desktop_shell_crash_too_early(struct desktop_shell *shell)
 {
@@ -5937,84 +4156,6 @@ launch_desktop_shell_process(void *data)
 				       &shell->child.client_destroy_listener);
 }
 
-static void
-handle_shell_client_destroy(struct wl_listener *listener, void *data)
-{
-	struct shell_client *sc =
-		container_of(listener, struct shell_client, destroy_listener);
-	struct wl_resource *shsurf_resource;
-	struct shell_surface *shsurf;
-
-	if (sc->ping_timer)
-		wl_event_source_remove(sc->ping_timer);
-
-	/* Since we're about to free shell_client, we remove it from the
-	 * head of the surface list so we don't use that freed list node
-	 * during surface clean up later on.
-	 */
-	wl_resource_for_each(shsurf_resource, &sc->surface_list) {
-		shsurf = wl_resource_get_user_data(shsurf_resource);
-		shsurf->owner = NULL;
-	}
-	wl_list_remove(&sc->surface_list);
-
-	free(sc);
-}
-
-static struct shell_client *
-shell_client_create(struct wl_client *client, struct desktop_shell *shell,
-		    const struct wl_interface *interface, uint32_t id)
-{
-	struct shell_client *sc;
-
-	sc = zalloc(sizeof *sc);
-	if (sc == NULL) {
-		wl_client_post_no_memory(client);
-		return NULL;
-	}
-
-	sc->resource = wl_resource_create(client, interface, 1, id);
-	if (sc->resource == NULL) {
-		free(sc);
-		wl_client_post_no_memory(client);
-		return NULL;
-	}
-
-	sc->client = client;
-	sc->shell = shell;
-	sc->destroy_listener.notify = handle_shell_client_destroy;
-	wl_client_add_destroy_listener(client, &sc->destroy_listener);
-	wl_list_init(&sc->surface_list);
-
-	return sc;
-}
-
-static void
-bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
-{
-	struct desktop_shell *shell = data;
-	struct shell_client *sc;
-
-	sc = shell_client_create(client, shell, &wl_shell_interface, id);
-	if (sc)
-		wl_resource_set_implementation(sc->resource,
-					       &shell_implementation,
-					       sc, NULL);
-}
-
-static void
-bind_xdg_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
-{
-	struct desktop_shell *shell = data;
-	struct shell_client *sc;
-
-	sc = shell_client_create(client, shell, &xdg_shell_interface, id);
-	if (sc)
-		wl_resource_set_dispatcher(sc->resource,
-					   xdg_shell_unversioned_dispatch,
-					   NULL, sc, NULL);
-}
-
 static void
 unbind_desktop_shell(struct wl_resource *resource)
 {
@@ -6077,9 +4218,7 @@ switcher_next(struct switcher *switcher)
 
 	wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
 		shsurf = get_shell_surface(view->surface);
-		if (shsurf &&
-		    shsurf->type == SHELL_SURFACE_TOPLEVEL &&
-		    shsurf->parent == NULL) {
+		if (shsurf) {
 			if (first == NULL)
 				first = view;
 			if (prev == switcher->current)
@@ -6111,7 +4250,7 @@ switcher_next(struct switcher *switcher)
 		view->alpha = 1.0;
 
 	shsurf = get_shell_surface(switcher->current->surface);
-	if (shsurf && shsurf->state.fullscreen)
+	if (shsurf && weston_desktop_surface_get_fullscreen(shsurf->desktop_surface))
 		shsurf->fullscreen.black_view->alpha = 1.0;
 }
 
@@ -6216,7 +4355,6 @@ switcher_binding(struct weston_keyboard *keyboard, uint32_t time,
 	wl_list_init(&switcher->listener.link);
 	wl_array_init(&switcher->minimized_array);
 
-	restore_all_output_modes(shell->compositor);
 	lower_fullscreen_layer(switcher->shell, NULL);
 	switcher->grab.interface = &switcher_grab;
 	weston_keyboard_start_grab(keyboard, &switcher->grab);
@@ -6400,13 +4538,12 @@ shell_reposition_view_on_output_destroy(struct weston_view *view)
 
 
 	shsurf = get_shell_surface(view->surface);
+	if (!shsurf)
+		return;
 
-	if (shsurf) {
-		shsurf->saved_position_valid = false;
-		shsurf->next_state.maximized = false;
-		shsurf->next_state.fullscreen = false;
-		shsurf->state_changed = true;
-	}
+	shsurf->saved_position_valid = false;
+	set_maximized(shsurf, false);
+	set_fullscreen(shsurf, false, NULL);
 }
 
 void
@@ -6729,17 +4866,6 @@ module_init(struct weston_compositor *ec,
 	wl_signal_add(&ec->transform_signal, &shell->transform_listener);
 
 	ec->shell_interface.shell = shell;
-	ec->shell_interface.create_shell_surface = create_shell_surface;
-	ec->shell_interface.set_toplevel = set_toplevel;
-	ec->shell_interface.set_transient = set_transient;
-	ec->shell_interface.set_fullscreen = shell_interface_set_fullscreen;
-	ec->shell_interface.set_xwayland = set_xwayland;
-	ec->shell_interface.move = shell_interface_move;
-	ec->shell_interface.resize = shell_interface_resize;
-	ec->shell_interface.set_title = set_title;
-	ec->shell_interface.set_window_geometry = set_window_geometry;
-	ec->shell_interface.set_maximized = shell_interface_set_maximized;
-	ec->shell_interface.set_pid = set_pid;
 	ec->shell_interface.get_output_work_area = get_output_work_area;
 
 	weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
@@ -6780,12 +4906,8 @@ module_init(struct weston_compositor *ec,
 	wl_list_init(&shell->workspaces.animation.link);
 	shell->workspaces.animation.frame = animate_workspace_change_frame;
 
-	if (wl_global_create(ec->wl_display, &wl_shell_interface, 1,
-				  shell, bind_shell) == NULL)
-		return -1;
-
-	if (wl_global_create(ec->wl_display, &xdg_shell_interface, 1,
-				  shell, bind_xdg_shell) == NULL)
+	shell->desktop = weston_desktop_create(ec, &shell_desktop_api, shell);
+	if (!shell->desktop)
 		return -1;
 
 	if (wl_global_create(ec->wl_display,
diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
index f73cae5..a1cea75 100644
--- a/desktop-shell/shell.h
+++ b/desktop-shell/shell.h
@@ -28,6 +28,7 @@
 #include <time.h>
 
 #include "compositor.h"
+#include "xwayland/xwayland-api.h"
 
 #include "weston-desktop-shell-server-protocol.h"
 
@@ -123,8 +124,11 @@ struct shell_output {
 	struct wl_listener background_surface_listener;
 };
 
+struct weston_desktop;
 struct desktop_shell {
 	struct weston_compositor *compositor;
+	struct weston_desktop *desktop;
+	const struct weston_xwayland_surface_api *xwayland_surface_api;
 
 	struct wl_listener idle_listener;
 	struct wl_listener wake_listener;
diff --git a/libweston/compositor.h b/libweston/compositor.h
index beda341..26667ca 100644
--- a/libweston/compositor.h
+++ b/libweston/compositor.h
@@ -100,38 +100,9 @@ struct weston_mode {
 	struct wl_list link;
 };
 
-struct weston_shell_client {
-	void (*send_configure)(struct weston_surface *surface, int32_t width, int32_t height);
-	void (*send_position)(struct weston_surface *surface, int32_t x, int32_t y);
-};
-
 struct weston_shell_interface {
 	void *shell;			/* either desktop or tablet */
 
-	struct shell_surface *(*create_shell_surface)(void *shell,
-						      struct weston_surface *surface,
-						      const struct weston_shell_client *client);
-	void (*set_toplevel)(struct shell_surface *shsurf);
-
-	void (*set_transient)(struct shell_surface *shsurf,
-			      struct weston_surface *parent,
-			      int x, int y, uint32_t flags);
-	void (*set_fullscreen)(struct shell_surface *shsurf,
-			       uint32_t method,
-			       uint32_t framerate,
-			       struct weston_output *output);
-	void (*set_xwayland)(struct shell_surface *shsurf,
-			       int x, int y, uint32_t flags);
-	int (*move)(struct shell_surface *shsurf, struct weston_pointer *pointer);
-	int (*resize)(struct shell_surface *shsurf,
-		      struct weston_pointer *pointer, uint32_t edges);
-	void (*set_title)(struct shell_surface *shsurf,
-	                  const char *title);
-	void (*set_window_geometry)(struct shell_surface *shsurf,
-				    int32_t x, int32_t y,
-				    int32_t width, int32_t height);
-	void (*set_maximized)(struct shell_surface *shsurf);
-	void (*set_pid)(struct shell_surface *shsurf, pid_t pid);
 	void (*get_output_work_area)(void *shell, struct weston_output *output, pixman_rectangle32_t *area);
 };
 
diff --git a/shared/helpers.h b/shared/helpers.h
index 1d1e458..ac9ea8b 100644
--- a/shared/helpers.h
+++ b/shared/helpers.h
@@ -52,6 +52,17 @@ extern "C" {
 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
 #endif
 
+/**
+ * Returns the bigger of two values.
+ *
+ * @param x the first item to compare.
+ * @param y the second item to compare.
+ * @return the value that evaluates to more than the other.
+ */
+#ifndef MAX
+#define MAX(x,y) (((x) > (y)) ? (x) : (y))
+#endif
+
 /**
  * Returns a pointer the the containing struct of a given member item.
  *
-- 
2.9.2



More information about the wayland-devel mailing list