shell: Animate window closing

This provides an example of keeping a weston_surface alive after the client
destroys it.  We install a destroy listener for the resource, so that we'll
be notifified when the client destroys it.  Then we increase the weston_surface
refcount so that we keep the surface and initiate an animation.  When
the animation finishes we can finally destroy the surface.
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index fd9ead0..f9fedac 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -109,6 +109,8 @@
 	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 */
@@ -3001,7 +3003,7 @@
 {
 	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
 
-	destroy_shell_surface(shsurf);
+	shsurf->resource = NULL;
 }
 
 static void
@@ -3018,6 +3020,30 @@
 }
 
 static void
+fade_out_done(struct weston_view_animation *animation, void *data)
+{
+	struct shell_surface *shsurf = data;
+
+	weston_surface_destroy(shsurf->surface);
+}
+
+static void
+handle_resource_destroy(struct wl_listener *listener, void *data)
+{
+	struct shell_surface *shsurf =
+		container_of(listener, struct shell_surface,
+			     resource_destroy_listener);
+
+	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);
+	weston_fade_run(shsurf->view, 1.0, 0.0, 300.0, fade_out_done, shsurf);
+}
+
+static void
 shell_surface_configure(struct weston_surface *, int32_t, int32_t);
 
 struct shell_surface *
@@ -3056,6 +3082,10 @@
 	surface->configure = shell_surface_configure;
 	surface->configure_private = shsurf;
 
+	shsurf->resource_destroy_listener.notify = handle_resource_destroy;
+	wl_resource_add_destroy_listener(surface->resource,
+					 &shsurf->resource_destroy_listener);
+
 	shsurf->shell = (struct desktop_shell *) shell;
 	shsurf->unresponsive = 0;
 	shsurf->saved_position_valid = false;