Replace fprintf() by weston_log()
[profile/ivi/weston.git] / src / shell.c
index 765b0a4..73af751 100644 (file)
 #include <assert.h>
 #include <signal.h>
 #include <math.h>
+#include <sys/types.h>
 
 #include <wayland-server.h>
 #include "compositor.h"
 #include "desktop-shell-server-protocol.h"
 #include "../shared/config-parser.h"
+#include "log.h"
 
-struct shell_surface;
+enum animation_type {
+       ANIMATION_NONE,
 
-struct wl_shell {
+       ANIMATION_ZOOM,
+       ANIMATION_FADE
+};
+
+struct desktop_shell {
        struct weston_compositor *compositor;
-       struct weston_shell shell;
+
+       struct wl_listener lock_listener;
+       struct wl_listener unlock_listener;
+       struct wl_listener destroy_listener;
 
        struct weston_layer fullscreen_layer;
        struct weston_layer panel_layer;
@@ -48,6 +58,9 @@ struct wl_shell {
        struct weston_layer background_layer;
        struct weston_layer lock_layer;
 
+       struct wl_listener pointer_focus_listener;
+       struct weston_surface *busy_surface;
+
        struct {
                struct weston_process process;
                struct wl_client *client;
@@ -74,6 +87,8 @@ struct wl_shell {
                struct weston_process process;
        } screensaver;
 
+       uint32_t binding_modifier;
+       enum animation_type win_animation_type;
        struct weston_surface *debug_repaint_surface;
 };
 
@@ -92,16 +107,25 @@ enum shell_surface_type {
        SHELL_SURFACE_POPUP
 };
 
+struct ping_timer {
+       struct wl_event_source *source;
+       uint32_t serial;
+};
+
 struct shell_surface {
        struct wl_resource resource;
 
        struct weston_surface *surface;
        struct wl_listener surface_destroy_listener;
        struct shell_surface *parent;
+       struct desktop_shell *shell;
 
-       enum shell_surface_type type;
+       enum shell_surface_type type, next_type;
+       char *title, *class;
        int32_t saved_x, saved_y;
        bool saved_position_valid;
+       bool saved_rotation_valid;
+       int unresponsive;
 
        struct {
                struct weston_transform transform;
@@ -110,50 +134,155 @@ struct shell_surface {
 
        struct {
                struct wl_pointer_grab grab;
-               uint32_t time;
                int32_t x, y;
                struct weston_transform parent_transform;
                int32_t initial_up;
+               struct wl_seat *seat;
+               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_surface *black_surface;
        } fullscreen;
 
+       struct ping_timer *ping_timer;
+
        struct weston_output *fullscreen_output;
        struct weston_output *output;
        struct wl_list link;
+
+       const struct weston_shell_client *client;
 };
 
-struct weston_move_grab {
+struct shell_grab {
        struct wl_pointer_grab grab;
-       struct weston_surface *surface;
-       int32_t dx, dy;
+       struct shell_surface *shsurf;
+       struct wl_listener shsurf_destroy_listener;
+};
+
+struct weston_move_grab {
+       struct shell_grab base;
+       wl_fixed_t dx, dy;
 };
 
 struct rotate_grab {
-       struct wl_pointer_grab grab;
-       struct shell_surface *surface;
+       struct shell_grab base;
        struct weston_matrix rotation;
        struct {
-               int32_t x;
-               int32_t y;
+               GLfloat x;
+               GLfloat y;
        } center;
 };
 
+static struct shell_surface *
+get_shell_surface(struct weston_surface *surface);
+
+static struct desktop_shell *
+shell_surface_get_shell(struct shell_surface *shsurf);
+
+static bool
+shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
+{
+       struct desktop_shell *shell;
+       struct weston_surface *top_fs_es;
+
+       shell = shell_surface_get_shell(shsurf);
+       
+       if (wl_list_empty(&shell->fullscreen_layer.surface_list))
+               return false;
+
+       top_fs_es = container_of(shell->fullscreen_layer.surface_list.next,
+                                struct weston_surface, 
+                                layer_link);
+       return (shsurf == get_shell_surface(top_fs_es));
+}
+
+static void
+destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
+{
+       struct shell_grab *grab;
+
+       grab = container_of(listener, struct shell_grab,
+                           shsurf_destroy_listener);
+
+       grab->shsurf = NULL;
+}
+
+static void
+shell_grab_init(struct shell_grab *grab,
+               const struct wl_pointer_grab_interface *interface,
+               struct shell_surface *shsurf)
+{
+       grab->grab.interface = interface;
+       grab->shsurf = shsurf;
+       grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
+       wl_signal_add(&shsurf->resource.destroy_signal,
+                     &grab->shsurf_destroy_listener);
+
+}
+
+static void
+shell_grab_finish(struct shell_grab *grab)
+{
+       if (grab->shsurf)
+               wl_list_remove(&grab->shsurf_destroy_listener.link);
+}
+
 static void
 center_on_output(struct weston_surface *surface,
                 struct weston_output *output);
 
+static enum weston_keyboard_modifier
+get_modifier(char *modifier)
+{
+       if (!modifier)
+               return MODIFIER_SUPER;
+
+       if (!strcmp("ctrl", modifier))
+               return MODIFIER_CTRL;
+       else if (!strcmp("alt", modifier))
+               return MODIFIER_ALT;
+       else if (!strcmp("super", modifier))
+               return MODIFIER_SUPER;
+       else
+               return MODIFIER_SUPER;
+}
+
+static enum animation_type
+get_animation_type(char *animation)
+{
+       if (!animation)
+               return ANIMATION_NONE;
+
+       if (!strcmp("zoom", animation))
+               return ANIMATION_ZOOM;
+       else if (!strcmp("fade", animation))
+               return ANIMATION_FADE;
+       else
+               return ANIMATION_NONE;
+}
+
 static void
-shell_configuration(struct wl_shell *shell)
+shell_configuration(struct desktop_shell *shell)
 {
        char *config_file;
        char *path = NULL;
        int duration = 60;
+       char *modifier = NULL;
+       char *win_animation = NULL;
+
+       struct config_key shell_keys[] = {
+               { "binding-modifier",   CONFIG_KEY_STRING, &modifier },
+               { "animation",          CONFIG_KEY_STRING, &win_animation},
+       };
 
        struct config_key saver_keys[] = {
                { "path",       CONFIG_KEY_STRING,  &path },
@@ -161,46 +290,60 @@ shell_configuration(struct wl_shell *shell)
        };
 
        struct config_section cs[] = {
+               { "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL },
                { "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL },
        };
 
-       config_file = config_file_path("weston-desktop-shell.ini");
+       config_file = config_file_path("weston.ini");
        parse_config_file(config_file, cs, ARRAY_LENGTH(cs), shell);
        free(config_file);
 
        shell->screensaver.path = path;
        shell->screensaver.duration = duration;
+       shell->binding_modifier = get_modifier(modifier);
+       shell->win_animation_type = get_animation_type(win_animation);
 }
 
 static void
-noop_grab_focus(struct wl_pointer_grab *grab, uint32_t time,
-               struct wl_surface *surface, int32_t x, int32_t y)
+noop_grab_focus(struct wl_pointer_grab *grab,
+               struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
 {
        grab->focus = NULL;
 }
 
 static void
 move_grab_motion(struct wl_pointer_grab *grab,
-                uint32_t time, int32_t x, int32_t y)
+                uint32_t time, wl_fixed_t x, wl_fixed_t y)
 {
        struct weston_move_grab *move = (struct weston_move_grab *) grab;
-       struct wl_input_device *device = grab->input_device;
-       struct weston_surface *es = move->surface;
+       struct wl_pointer *pointer = grab->pointer;
+       struct shell_surface *shsurf = move->base.shsurf;
+       struct weston_surface *es;
+       int dx = wl_fixed_to_int(pointer->x + move->dx);
+       int dy = wl_fixed_to_int(pointer->y + move->dy);
 
-       weston_surface_configure(es,
-                                device->x + move->dx,
-                                device->y + move->dy,
+       if (!shsurf)
+               return;
+
+       es = shsurf->surface;
+
+       weston_surface_configure(es, dx, dy,
                                 es->geometry.width, es->geometry.height);
 }
 
 static void
 move_grab_button(struct wl_pointer_grab *grab,
-                uint32_t time, int32_t button, int32_t state)
+                uint32_t time, uint32_t button, uint32_t state_w)
 {
-       struct wl_input_device *device = grab->input_device;
+       struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
+                                                   grab);
+       struct wl_pointer *pointer = grab->pointer;
+       enum wl_pointer_button_state state = state_w;
 
-       if (device->button_count == 0 && state == 0) {
-               wl_input_device_end_pointer_grab(device, time);
+       if (pointer->button_count == 0 &&
+           state == WL_POINTER_BUTTON_STATE_RELEASED) {
+               shell_grab_finish(shell_grab);
+               wl_pointer_end_grab(pointer);
                free(grab);
        }
 }
@@ -211,95 +354,314 @@ static const struct wl_pointer_grab_interface move_grab_interface = {
        move_grab_button,
 };
 
+static void
+busy_cursor_grab_focus(struct wl_pointer_grab *base,
+                      struct wl_surface *surface, int32_t x, int32_t y)
+{
+       struct shell_grab *grab = (struct shell_grab *) base;
+       struct wl_pointer *pointer = base->pointer;
+
+       if (grab->grab.focus != surface) {
+               shell_grab_finish(grab);
+               wl_pointer_end_grab(pointer);
+               free(grab);
+       }
+}
+
+static void
+busy_cursor_grab_motion(struct wl_pointer_grab *grab,
+                       uint32_t time, int32_t x, int32_t y)
+{
+}
+
+static void
+busy_cursor_grab_button(struct wl_pointer_grab *grab,
+                       uint32_t time, uint32_t button, uint32_t state)
+{
+}
+
+static const struct wl_pointer_grab_interface busy_cursor_grab_interface = {
+       busy_cursor_grab_focus,
+       busy_cursor_grab_motion,
+       busy_cursor_grab_button,
+};
+
+static void
+set_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer)
+{
+       struct shell_grab *grab;
+       struct desktop_shell *shell = shsurf->shell;
+       struct weston_seat *seat = (struct weston_seat *) pointer->seat;
+       struct weston_surface *sprite;
+
+       grab = malloc(sizeof *grab);
+       if (!grab)
+               return;
+
+       shell_grab_init(grab, &busy_cursor_grab_interface, shsurf);
+       grab->grab.focus = &shsurf->surface->surface;
+       wl_pointer_start_grab(pointer, &grab->grab);
+       wl_pointer_set_focus(pointer, &shell->busy_surface->surface, 0, 0);
+
+       sprite = (struct weston_surface *) seat->sprite;
+       shell->busy_surface->output = sprite->output;
+}
+
+static void
+end_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer)
+{
+       struct shell_grab *grab = (struct shell_grab *) pointer->grab;
+
+       if (grab->grab.interface == &busy_cursor_grab_interface) {
+               shell_grab_finish(grab);
+               wl_pointer_end_grab(pointer);
+               free(grab);
+       }
+}
+
+static void
+ping_timer_destroy(struct shell_surface *shsurf)
+{
+       if (!shsurf || !shsurf->ping_timer)
+               return;
+
+       if (shsurf->ping_timer->source)
+               wl_event_source_remove(shsurf->ping_timer->source);
+
+       free(shsurf->ping_timer);
+       shsurf->ping_timer = NULL;
+}
+
 static int
-weston_surface_move(struct weston_surface *es,
-                   struct weston_input_device *wd, uint32_t time)
+ping_timeout_handler(void *data)
+{
+       struct shell_surface *shsurf = data;
+       struct weston_seat *seat;
+
+       /* Client is not responding */
+       shsurf->unresponsive = 1;
+
+       wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link)
+               if (seat->seat.pointer->focus == &shsurf->surface->surface)
+                       set_busy_cursor(shsurf, seat->seat.pointer);
+
+       return 1;
+}
+
+static void
+ping_handler(struct weston_surface *surface, uint32_t serial)
+{
+       struct shell_surface *shsurf = get_shell_surface(surface);
+       struct wl_event_loop *loop;
+       int ping_timeout = 200;
+
+       if (!shsurf)
+               return;
+       if (!shsurf->resource.client)
+               return;
+
+       if (!shsurf->ping_timer) {
+               shsurf->ping_timer = malloc(sizeof *shsurf->ping_timer);
+               if (!shsurf->ping_timer)
+                       return;
+
+               shsurf->ping_timer->serial = serial;
+               loop = wl_display_get_event_loop(surface->compositor->wl_display);
+               shsurf->ping_timer->source =
+                       wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf);
+               wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout);
+
+               wl_shell_surface_send_ping(&shsurf->resource, serial);
+       }
+}
+
+static void
+handle_pointer_focus(struct wl_listener *listener, void *data)
+{
+       struct wl_pointer *pointer = data;
+       struct weston_surface *surface =
+               (struct weston_surface *) pointer->focus;
+       struct weston_compositor *compositor;
+       struct shell_surface *shsurf;
+       uint32_t serial;
+
+       if (!surface)
+               return;
+
+       compositor = surface->compositor;
+       shsurf = get_shell_surface(surface);
+
+       if (shsurf && shsurf->unresponsive) {
+               set_busy_cursor(shsurf, pointer);
+       } else {
+               serial = wl_display_next_serial(compositor->wl_display);
+               ping_handler(surface, serial);
+       }
+}
+
+static void
+shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
+                                                       uint32_t serial)
+{
+       struct shell_surface *shsurf = resource->data;
+       struct desktop_shell *shell = shsurf->shell;
+       struct weston_seat *seat;
+       struct weston_compositor *ec = shsurf->surface->compositor;
+       struct wl_pointer *pointer;
+       int was_unresponsive;
+
+       if (shsurf->ping_timer->serial == serial) {
+               was_unresponsive = shsurf->unresponsive;
+               shsurf->unresponsive = 0;
+               if (was_unresponsive) {
+                       /* Received pong from previously unresponsive client */
+                       wl_list_for_each(seat, &ec->seat_list, link) {
+                               pointer = seat->seat.pointer;
+                               if (pointer->focus ==
+                                   &shell->busy_surface->surface &&
+                                   pointer->current ==
+                                   &shsurf->surface->surface)
+                                       end_busy_cursor(shsurf, pointer);
+                       }
+               }
+               ping_timer_destroy(shsurf);
+       }
+}
+
+static void
+shell_surface_set_title(struct wl_client *client,
+                       struct wl_resource *resource, const char *title)
+{
+       struct shell_surface *shsurf = resource->data;
+
+       free(shsurf->title);
+       shsurf->title = strdup(title);
+}
+
+static void
+shell_surface_set_class(struct wl_client *client,
+                       struct wl_resource *resource, const char *class)
+{
+       struct shell_surface *shsurf = resource->data;
+
+       free(shsurf->class);
+       shsurf->class = strdup(class);
+}
+
+static int
+surface_move(struct shell_surface *shsurf, struct weston_seat *ws)
 {
        struct weston_move_grab *move;
 
+       if (!shsurf)
+               return -1;
+
        move = malloc(sizeof *move);
        if (!move)
                return -1;
 
-       move->grab.interface = &move_grab_interface;
-       move->dx = es->geometry.x - wd->input_device.grab_x;
-       move->dy = es->geometry.y - wd->input_device.grab_y;
-       move->surface = es;
+       shell_grab_init(&move->base, &move_grab_interface, shsurf);
 
-       wl_input_device_start_pointer_grab(&wd->input_device, &move->grab, time);
+       move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) -
+                       ws->seat.pointer->grab_x;
+       move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) -
+                       ws->seat.pointer->grab_y;
 
-       wl_input_device_set_pointer_focus(&wd->input_device, NULL, time, 0, 0);
+       wl_pointer_start_grab(ws->seat.pointer, &move->base.grab);
+
+       wl_pointer_set_focus(ws->seat.pointer, NULL,
+                            wl_fixed_from_int(0),
+                            wl_fixed_from_int(0));
 
        return 0;
 }
 
 static void
 shell_surface_move(struct wl_client *client, struct wl_resource *resource,
-                  struct wl_resource *input_resource, uint32_t time)
+                  struct wl_resource *seat_resource, uint32_t serial)
 {
-       struct weston_input_device *wd = input_resource->data;
+       struct weston_seat *ws = seat_resource->data;
        struct shell_surface *shsurf = resource->data;
 
-       if (wd->input_device.button_count == 0 ||
-           wd->input_device.grab_time != time ||
-           wd->input_device.pointer_focus != &shsurf->surface->surface)
+       if (ws->seat.pointer->button_count == 0 ||
+           ws->seat.pointer->grab_serial != serial ||
+           ws->seat.pointer->focus != &shsurf->surface->surface)
                return;
 
-       if (weston_surface_move(shsurf->surface, wd, time) < 0)
+       if (surface_move(shsurf, ws) < 0)
                wl_resource_post_no_memory(resource);
 }
 
 struct weston_resize_grab {
-       struct wl_pointer_grab grab;
+       struct shell_grab base;
        uint32_t edges;
        int32_t width, height;
-       struct shell_surface *shsurf;
 };
 
 static void
 resize_grab_motion(struct wl_pointer_grab *grab,
-                  uint32_t time, int32_t x, int32_t y)
+                  uint32_t time, wl_fixed_t x, wl_fixed_t y)
 {
        struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
-       struct wl_input_device *device = grab->input_device;
+       struct wl_pointer *pointer = grab->pointer;
+       struct shell_surface *shsurf = resize->base.shsurf;
        int32_t width, height;
-       int32_t from_x, from_y;
-       int32_t to_x, to_y;
+       wl_fixed_t from_x, from_y;
+       wl_fixed_t to_x, to_y;
+
+       if (!shsurf)
+               return;
 
-       weston_surface_from_global(resize->shsurf->surface,
-                                  device->grab_x, device->grab_y,
-                                  &from_x, &from_y);
-       weston_surface_from_global(resize->shsurf->surface,
-                                  device->x, device->y, &to_x, &to_y);
+       weston_surface_from_global_fixed(shsurf->surface,
+                                        pointer->grab_x, pointer->grab_y,
+                                        &from_x, &from_y);
+       weston_surface_from_global_fixed(shsurf->surface,
+                                        pointer->x, pointer->y, &to_x, &to_y);
 
+       width = resize->width;
        if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
-               width = resize->width + from_x - to_x;
+               width += wl_fixed_to_int(from_x - to_x);
        } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
-               width = resize->width + to_x - from_x;
-       } else {
-               width = resize->width;
+               width += wl_fixed_to_int(to_x - from_x);
        }
 
+       height = resize->height;
        if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
-               height = resize->height + from_y - to_y;
+               height += wl_fixed_to_int(from_y - to_y);
        } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
-               height = resize->height + to_y - from_y;
-       } else {
-               height = resize->height;
+               height += wl_fixed_to_int(to_y - from_y);
        }
 
-       wl_shell_surface_send_configure(&resize->shsurf->resource,
-                                       time, resize->edges, width, height);
+       shsurf->client->send_configure(shsurf->surface,
+                                      resize->edges, width, height);
 }
 
 static void
+send_configure(struct weston_surface *surface,
+              uint32_t edges, int32_t width, int32_t height)
+{
+       struct shell_surface *shsurf = get_shell_surface(surface);
+
+       wl_shell_surface_send_configure(&shsurf->resource,
+                                       edges, width, height);
+}
+
+static const struct weston_shell_client shell_client = {
+       send_configure
+};
+
+static void
 resize_grab_button(struct wl_pointer_grab *grab,
-                  uint32_t time, int32_t button, int32_t state)
+                  uint32_t time, uint32_t button, uint32_t state_w)
 {
-       struct wl_input_device *device = grab->input_device;
+       struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
+       struct wl_pointer *pointer = grab->pointer;
+       enum wl_pointer_button_state state = state_w;
 
-       if (device->button_count == 0 && state == 0) {
-               wl_input_device_end_pointer_grab(device, time);
+       if (pointer->button_count == 0 &&
+           state == WL_POINTER_BUTTON_STATE_RELEASED) {
+               shell_grab_finish(&resize->base);
+               wl_pointer_end_grab(pointer);
                free(grab);
        }
 }
@@ -311,9 +673,8 @@ static const struct wl_pointer_grab_interface resize_grab_interface = {
 };
 
 static int
-weston_surface_resize(struct shell_surface *shsurf,
-                   struct weston_input_device *wd,
-                   uint32_t time, uint32_t edges)
+surface_resize(struct shell_surface *shsurf,
+              struct weston_seat *ws, uint32_t edges)
 {
        struct weston_resize_grab *resize;
 
@@ -328,36 +689,38 @@ weston_surface_resize(struct shell_surface *shsurf,
        if (!resize)
                return -1;
 
-       resize->grab.interface = &resize_grab_interface;
+       shell_grab_init(&resize->base, &resize_grab_interface, shsurf);
+
        resize->edges = edges;
        resize->width = shsurf->surface->geometry.width;
        resize->height = shsurf->surface->geometry.height;
-       resize->shsurf = shsurf;
 
-       wl_input_device_start_pointer_grab(&wd->input_device, &resize->grab, time);
+       wl_pointer_start_grab(ws->seat.pointer, &resize->base.grab);
 
-       wl_input_device_set_pointer_focus(&wd->input_device, NULL, time, 0, 0);
+       wl_pointer_set_focus(ws->seat.pointer, NULL,
+                            wl_fixed_from_int(0),
+                            wl_fixed_from_int(0));
 
        return 0;
 }
 
 static void
 shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
-                    struct wl_resource *input_resource, uint32_t time,
+                    struct wl_resource *seat_resource, uint32_t serial,
                     uint32_t edges)
 {
-       struct weston_input_device *wd = input_resource->data;
+       struct weston_seat *ws = seat_resource->data;
        struct shell_surface *shsurf = resource->data;
 
        if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
                return;
 
-       if (wd->input_device.button_count == 0 ||
-           wd->input_device.grab_time != time ||
-           wd->input_device.pointer_focus != &shsurf->surface->surface)
+       if (ws->seat.pointer->button_count == 0 ||
+           ws->seat.pointer->grab_serial != serial ||
+           ws->seat.pointer->focus != &shsurf->surface->surface)
                return;
 
-       if (weston_surface_resize(shsurf, wd, time, edges) < 0)
+       if (surface_resize(shsurf, ws, edges) < 0)
                wl_resource_post_no_memory(resource);
 }
 
@@ -372,16 +735,26 @@ static void
 shell_unset_fullscreen(struct shell_surface *shsurf)
 {
        /* undo all fullscreen things here */
+       if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
+           shell_surface_is_top_fullscreen(shsurf)) {
+               weston_output_switch_mode(shsurf->fullscreen_output,
+                                         shsurf->fullscreen_output->origin);
+       }
        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);
-       weston_surface_destroy(shsurf->fullscreen.black_surface);
+       if (shsurf->fullscreen.black_surface)
+               weston_surface_destroy(shsurf->fullscreen.black_surface);
        shsurf->fullscreen.black_surface = NULL;
        shsurf->fullscreen_output = NULL;
-       shsurf->surface->force_configure = 1;
        weston_surface_set_position(shsurf->surface,
                                    shsurf->saved_x, shsurf->saved_y);
+       if (shsurf->saved_rotation_valid) {
+               wl_list_insert(&shsurf->surface->geometry.transformation_list,
+                              &shsurf->rotation.transform.link);
+               shsurf->saved_rotation_valid = false;
+       }
 }
 
 static int
@@ -420,16 +793,110 @@ reset_shell_surface_type(struct shell_surface *surface)
 }
 
 static void
+set_surface_type(struct shell_surface *shsurf)
+{
+       struct weston_surface *surface = shsurf->surface;
+       struct shell_surface *pshsurf = shsurf->parent;
+       struct weston_surface *pes;
+       struct shell_surface *priv;
+       struct desktop_shell *shell = shsurf->shell;
+
+       reset_shell_surface_type(shsurf);
+
+       shsurf->type = shsurf->next_type;
+       shsurf->next_type = SHELL_SURFACE_NONE;
+
+       switch (shsurf->type) {
+       case SHELL_SURFACE_TOPLEVEL:
+               break;
+       case SHELL_SURFACE_TRANSIENT:
+               pes = pshsurf->surface;
+               weston_surface_set_position(surface,
+                               pes->geometry.x + shsurf->transient.x,
+                               pes->geometry.y + shsurf->transient.y);
+               break;
+
+       case SHELL_SURFACE_MAXIMIZED:
+               shsurf->saved_x = surface->geometry.x;
+               shsurf->saved_y = surface->geometry.y;
+               shsurf->saved_position_valid = true;
+               break;
+
+       case SHELL_SURFACE_FULLSCREEN:
+               shsurf->saved_x = surface->geometry.x;
+               shsurf->saved_y = surface->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);
+                       shsurf->surface->geometry.dirty = 1;
+                       shsurf->saved_rotation_valid = true;
+               }
+               break;
+
+       case SHELL_SURFACE_BACKGROUND:
+               wl_list_for_each(priv, &shell->backgrounds, link) {
+                       if (priv->output == shsurf->output) {
+                               priv->surface->output = NULL;
+                               wl_list_remove(&priv->surface->layer_link);
+                               wl_list_remove(&priv->link);
+                               break;
+                       }
+               }
+
+               wl_list_insert(&shell->backgrounds, &shsurf->link);
+
+               weston_surface_set_position(surface, shsurf->output->x,
+                                           shsurf->output->y);
+               break;
+
+       case SHELL_SURFACE_PANEL:
+               wl_list_for_each(priv, &shell->panels, link) {
+                       if (priv->output == shsurf->output) {
+                               priv->surface->output = NULL;
+                               wl_list_remove(&priv->surface->layer_link);
+                               wl_list_remove(&priv->link);
+                               break;
+                       }
+               }
+
+               wl_list_insert(&shell->panels, &shsurf->link);
+
+               weston_surface_set_position(surface, shsurf->output->x,
+                                           shsurf->output->y);
+               break;
+
+       default:
+               break;
+       }
+}
+
+static void
+set_toplevel(struct shell_surface *shsurf)
+{
+       shsurf->next_type = SHELL_SURFACE_TOPLEVEL;
+}
+
+static void
 shell_surface_set_toplevel(struct wl_client *client,
                           struct wl_resource *resource)
-
 {
        struct shell_surface *surface = resource->data;
 
-       if (reset_shell_surface_type(surface))
-               return;
+       set_toplevel(surface);
+}
 
-       surface->type = SHELL_SURFACE_TOPLEVEL;
+static void
+set_transient(struct shell_surface *shsurf,
+             struct shell_surface *pshsurf, int x, int y, uint32_t flags)
+{
+       /* assign to parents output */
+       shsurf->parent = pshsurf;
+       shsurf->transient.x = x;
+       shsurf->transient.y = y;
+       shsurf->transient.flags = flags;
+       shsurf->next_type = SHELL_SURFACE_TRANSIENT;
 }
 
 static void
@@ -439,32 +906,20 @@ shell_surface_set_transient(struct wl_client *client,
                            int x, int y, uint32_t flags)
 {
        struct shell_surface *shsurf = resource->data;
-       struct weston_surface *es = shsurf->surface;
        struct shell_surface *pshsurf = parent_resource->data;
-       struct weston_surface *pes = pshsurf->surface;
-
-       if (reset_shell_surface_type(shsurf))
-               return;
-
-       /* assign to parents output */
-       shsurf->output = pes->output;
-       weston_surface_set_position(es, pes->geometry.x + x,
-                                       pes->geometry.y + y);
 
-       shsurf->type = SHELL_SURFACE_TRANSIENT;
+       set_transient(shsurf, pshsurf, x, y, flags);
 }
 
-static struct wl_shell *
+static struct desktop_shell *
 shell_surface_get_shell(struct shell_surface *shsurf)
 {
-       struct weston_surface *es = shsurf->surface;
-       struct weston_shell *shell = es->compositor->shell;
-
-       return (struct wl_shell *)container_of(shell, struct wl_shell, shell);
+       return shsurf->shell;
 }
 
 static int
-get_output_panel_height(struct wl_shell *wlshell,struct weston_output *output)
+get_output_panel_height(struct desktop_shell *shell,
+                       struct weston_output *output)
 {
        struct shell_surface *priv;
        int panel_height = 0;
@@ -472,7 +927,7 @@ get_output_panel_height(struct wl_shell *wlshell,struct weston_output *output)
        if (!output)
                return 0;
 
-       wl_list_for_each(priv, &wlshell->panels, link) {
+       wl_list_for_each(priv, &shell->panels, link) {
                if (priv->output == output) {
                        panel_height = priv->surface->geometry.height;
                        break;
@@ -488,7 +943,7 @@ shell_surface_set_maximized(struct wl_client *client,
 {
        struct shell_surface *shsurf = resource->data;
        struct weston_surface *es = shsurf->surface;
-       struct wl_shell *wlshell = NULL;
+       struct desktop_shell *shell = NULL;
        uint32_t edges = 0, panel_height = 0;
 
        /* get the default output, if the client set it as NULL
@@ -498,37 +953,35 @@ shell_surface_set_maximized(struct wl_client *client,
        else
                shsurf->output = get_default_output(es->compositor);
 
-       if (reset_shell_surface_type(shsurf))
-               return;
-
-       shsurf->saved_x = es->geometry.x;
-       shsurf->saved_y = es->geometry.y;
-       shsurf->saved_position_valid = true;
-
-       wlshell = shell_surface_get_shell(shsurf);
-       panel_height = get_output_panel_height(wlshell, es->output);
+       shell = shell_surface_get_shell(shsurf);
+       panel_height = get_output_panel_height(shell, es->output);
        edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
 
-       wl_shell_surface_send_configure(&shsurf->resource,
-                                       weston_compositor_get_time(), edges,
-                                       es->output->current->width,
-                                       es->output->current->height - panel_height);
+       shsurf->client->send_configure(shsurf->surface, edges,
+                                      es->output->current->width,
+                                      es->output->current->height - panel_height);
 
-       shsurf->type = SHELL_SURFACE_MAXIMIZED;
+       shsurf->next_type = SHELL_SURFACE_MAXIMIZED;
 }
 
+static void
+black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy);
+
 static struct weston_surface *
 create_black_surface(struct weston_compositor *ec,
+                    struct weston_surface *fs_surface,
                     GLfloat x, GLfloat y, int w, int h)
 {
        struct weston_surface *surface = NULL;
 
        surface = weston_surface_create(ec);
        if (surface == NULL) {
-               fprintf(stderr, "no memory\n");
+               weston_log("no memory\n");
                return NULL;
        }
 
+       surface->configure = black_surface_configure;
+       surface->private = fs_surface;
        weston_surface_configure(surface, x, y, w, h);
        weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
        return surface;
@@ -549,6 +1002,7 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
        if (!shsurf->fullscreen.black_surface)
                shsurf->fullscreen.black_surface =
                        create_black_surface(surface->compositor,
+                                            surface,
                                             output->x, output->y,
                                             output->current->width,
                                             output->current->height);
@@ -572,6 +1026,21 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
                weston_surface_set_position(surface, output->x, output->y);
                break;
        case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
+               if (shell_surface_is_top_fullscreen(shsurf)) {
+                       struct weston_mode mode = {0, 
+                               surface->geometry.width,
+                               surface->geometry.height,
+                               shsurf->fullscreen.framerate};
+
+                       if (weston_output_switch_mode(output, &mode) == 0) {
+                               weston_surface_configure(shsurf->fullscreen.black_surface, 
+                                                        output->x, output->y,
+                                                        output->current->width,
+                                                        output->current->height);
+                               weston_surface_set_position(surface, output->x, output->y);
+                               break;
+                       }
+               }
                break;
        case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
                break;
@@ -584,26 +1053,34 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
 static void
 shell_stack_fullscreen(struct shell_surface *shsurf)
 {
+       struct weston_output *output = shsurf->fullscreen_output;
        struct weston_surface *surface = shsurf->surface;
-       struct wl_shell *shell = shell_surface_get_shell(shsurf);
+       struct desktop_shell *shell = shell_surface_get_shell(shsurf);
 
        wl_list_remove(&surface->layer_link);
-       wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
-
        wl_list_insert(&shell->fullscreen_layer.surface_list,
                       &surface->layer_link);
+       weston_surface_damage(surface);
+
+       if (!shsurf->fullscreen.black_surface)
+               shsurf->fullscreen.black_surface =
+                       create_black_surface(surface->compositor,
+                                            surface,
+                                            output->x, output->y,
+                                            output->current->width,
+                                            output->current->height);
+
+       wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
        wl_list_insert(&surface->layer_link,
                       &shsurf->fullscreen.black_surface->layer_link);
-
-       weston_surface_damage(surface);
        weston_surface_damage(shsurf->fullscreen.black_surface);
 }
 
 static void
 shell_map_fullscreen(struct shell_surface *shsurf)
 {
-       shell_configure_fullscreen(shsurf);
        shell_stack_fullscreen(shsurf);
+       shell_configure_fullscreen(shsurf);
 }
 
 static void
@@ -621,76 +1098,74 @@ shell_surface_set_fullscreen(struct wl_client *client,
        else
                shsurf->output = get_default_output(es->compositor);
 
-       if (reset_shell_surface_type(shsurf))
-               return;
-
        shsurf->fullscreen_output = shsurf->output;
        shsurf->fullscreen.type = method;
        shsurf->fullscreen.framerate = framerate;
-       shsurf->type = SHELL_SURFACE_FULLSCREEN;
-
-       shsurf->saved_x = es->geometry.x;
-       shsurf->saved_y = es->geometry.y;
-       shsurf->saved_position_valid = true;
+       shsurf->next_type = SHELL_SURFACE_FULLSCREEN;
 
-       if (es->output)
-               shsurf->surface->force_configure = 1;
-
-       wl_shell_surface_send_configure(&shsurf->resource,
-                                       weston_compositor_get_time(), 0,
-                                       shsurf->output->current->width,
-                                       shsurf->output->current->height);
+       shsurf->client->send_configure(shsurf->surface, 0,
+                                      shsurf->output->current->width,
+                                      shsurf->output->current->height);
 }
 
 static void
-popup_grab_focus(struct wl_pointer_grab *grab, uint32_t time,
-                struct wl_surface *surface, int32_t x, int32_t y)
+popup_grab_focus(struct wl_pointer_grab *grab,
+                struct wl_surface *surface,
+                wl_fixed_t x,
+                wl_fixed_t y)
 {
-       struct wl_input_device *device = grab->input_device;
+       struct wl_pointer *pointer = grab->pointer;
        struct shell_surface *priv =
                container_of(grab, struct shell_surface, popup.grab);
        struct wl_client *client = priv->surface->surface.resource.client;
 
        if (surface && surface->resource.client == client) {
-               wl_input_device_set_pointer_focus(device, surface, time, x, y);
+               wl_pointer_set_focus(pointer, surface, x, y);
                grab->focus = surface;
        } else {
-               wl_input_device_set_pointer_focus(device, NULL, time, 0, 0);
+               wl_pointer_set_focus(pointer, NULL,
+                                    wl_fixed_from_int(0),
+                                    wl_fixed_from_int(0));
                grab->focus = NULL;
        }
 }
 
 static void
 popup_grab_motion(struct wl_pointer_grab *grab,
-                 uint32_t time, int32_t sx, int32_t sy)
+                 uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
 {
        struct wl_resource *resource;
 
-       resource = grab->input_device->pointer_focus_resource;
+       resource = grab->pointer->focus_resource;
        if (resource)
-               wl_input_device_send_motion(resource, time, sx, sy);
+               wl_pointer_send_motion(resource, time, sx, sy);
 }
 
 static void
 popup_grab_button(struct wl_pointer_grab *grab,
-                 uint32_t time, int32_t button, int32_t state)
+                 uint32_t time, uint32_t button, uint32_t state_w)
 {
        struct wl_resource *resource;
        struct shell_surface *shsurf =
                container_of(grab, struct shell_surface, popup.grab);
+       struct wl_display *display;
+       enum wl_pointer_button_state state = state_w;
+       uint32_t serial;
 
-       resource = grab->input_device->pointer_focus_resource;
+       resource = grab->pointer->focus_resource;
        if (resource) {
-               wl_input_device_send_button(resource, time, button, state);
-       } else if (state == 0 &&
+               display = wl_client_get_display(resource->client);
+               serial = wl_display_get_serial(display);
+               wl_pointer_send_button(resource, serial, time, button, state);
+       } else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
                   (shsurf->popup.initial_up ||
-                   time - shsurf->popup.time > 500)) {
+                   time - shsurf->popup.seat->pointer->grab_time > 500)) {
                wl_shell_surface_send_popup_done(&shsurf->resource);
-               wl_input_device_end_pointer_grab(grab->input_device, time);
-               shsurf->popup.grab.input_device = NULL;
+               wl_pointer_end_grab(grab->pointer);
+               shsurf->popup.grab.pointer = NULL;
        }
 
-       if (state == 0)
+       if (state == WL_POINTER_BUTTON_STATE_RELEASED)
                shsurf->popup.initial_up = 1;
 }
 
@@ -701,16 +1176,14 @@ static const struct wl_pointer_grab_interface popup_grab_interface = {
 };
 
 static void
-shell_map_popup(struct shell_surface *shsurf, uint32_t time)
+shell_map_popup(struct shell_surface *shsurf)
 {
-       struct wl_input_device *device;
+       struct wl_seat *seat = shsurf->popup.seat;
        struct weston_surface *es = shsurf->surface;
        struct weston_surface *parent = shsurf->parent->surface;
 
        es->output = parent->output;
-
        shsurf->popup.grab.interface = &popup_grab_interface;
-       device = es->compositor->input_device;
 
        weston_surface_update_transform(parent);
        if (parent->transform.enabled) {
@@ -728,19 +1201,22 @@ shell_map_popup(struct shell_surface *shsurf, uint32_t time)
                       &shsurf->popup.parent_transform.link);
        weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
 
-       shsurf->popup.grab.input_device = device;
-       shsurf->popup.time = device->grab_time;
        shsurf->popup.initial_up = 0;
 
-       wl_input_device_start_pointer_grab(shsurf->popup.grab.input_device,
-                                  &shsurf->popup.grab, shsurf->popup.time);
+       /* We don't require the grab to still be active, but if another
+        * grab has started in the meantime, we end the popup now. */
+       if (seat->pointer->grab_serial == shsurf->popup.serial) {
+               wl_pointer_start_grab(seat->pointer, &shsurf->popup.grab);
+       } else {
+               wl_shell_surface_send_popup_done(&shsurf->resource);
+       }
 }
 
 static void
 shell_surface_set_popup(struct wl_client *client,
                        struct wl_resource *resource,
-                       struct wl_resource *input_device_resource,
-                       uint32_t time,
+                       struct wl_resource *seat_resource,
+                       uint32_t serial,
                        struct wl_resource *parent_resource,
                        int32_t x, int32_t y, uint32_t flags)
 {
@@ -748,107 +1224,127 @@ shell_surface_set_popup(struct wl_client *client,
 
        shsurf->type = SHELL_SURFACE_POPUP;
        shsurf->parent = parent_resource->data;
+       shsurf->popup.seat = seat_resource->data;
+       shsurf->popup.serial = serial;
        shsurf->popup.x = x;
        shsurf->popup.y = y;
 }
 
 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_maximized,
+       shell_surface_set_title,
+       shell_surface_set_class
 };
 
 static void
-destroy_shell_surface(struct wl_resource *resource)
+destroy_shell_surface(struct shell_surface *shsurf)
 {
-       struct shell_surface *shsurf = resource->data;
-
-       if (shsurf->popup.grab.input_device)
-               wl_input_device_end_pointer_grab(shsurf->popup.grab.input_device, 0);
+       if (shsurf->popup.grab.pointer)
+               wl_pointer_end_grab(shsurf->popup.grab.pointer);
 
-       /* in case cleaning up a dead client destroys shell_surface first */
-       if (shsurf->surface)
-               wl_list_remove(&shsurf->surface_destroy_listener.link);
+       if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
+           shell_surface_is_top_fullscreen(shsurf)) {
+               weston_output_switch_mode(shsurf->fullscreen_output,
+                                         shsurf->fullscreen_output->origin);
+       }
 
        if (shsurf->fullscreen.black_surface)
                weston_surface_destroy(shsurf->fullscreen.black_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->configure = NULL;
+       ping_timer_destroy(shsurf);
+
        wl_list_remove(&shsurf->link);
        free(shsurf);
 }
 
 static void
-shell_handle_surface_destroy(struct wl_listener *listener,
-                            struct wl_resource *resource, uint32_t time)
+shell_destroy_shell_surface(struct wl_resource *resource)
+{
+       struct shell_surface *shsurf = resource->data;
+
+       destroy_shell_surface(shsurf);
+}
+
+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);
 
-       shsurf->surface = NULL;
-       wl_resource_destroy(&shsurf->resource, time);
+       if (shsurf->resource.client) {
+               wl_resource_destroy(&shsurf->resource);
+       } else {
+               wl_signal_emit(&shsurf->resource.destroy_signal,
+                              &shsurf->resource);
+               destroy_shell_surface(shsurf);
+       }
 }
 
 static struct shell_surface *
 get_shell_surface(struct weston_surface *surface)
 {
-       struct wl_list *lst = &surface->surface.resource.destroy_listener_list;
        struct wl_listener *listener;
 
-       /* search the destroy listener list for our callback */
-       wl_list_for_each(listener, lst, link) {
-               if (listener->func == shell_handle_surface_destroy) {
-                       return container_of(listener, struct shell_surface,
-                                           surface_destroy_listener);
-               }
-       }
+       listener = wl_signal_get(&surface->surface.resource.destroy_signal,
+                                shell_handle_surface_destroy);
+       if (listener)
+               return container_of(listener, struct shell_surface,
+                                   surface_destroy_listener);
 
        return NULL;
 }
 
 static void
-shell_get_shell_surface(struct wl_client *client,
-                       struct wl_resource *resource,
-                       uint32_t id,
-                       struct wl_resource *surface_resource)
+shell_surface_configure(struct weston_surface *, int32_t, int32_t);
+
+static         struct shell_surface *
+create_shell_surface(void *shell, struct weston_surface *surface,
+                    const struct weston_shell_client *client)
 {
-       struct weston_surface *surface = surface_resource->data;
        struct shell_surface *shsurf;
 
-       if (get_shell_surface(surface)) {
-               wl_resource_post_error(surface_resource,
-                       WL_DISPLAY_ERROR_INVALID_OBJECT,
-                       "wl_shell::get_shell_surface already requested");
-               return;
+       if (surface->configure) {
+               weston_log("surface->configure already set\n");
+               return NULL;
        }
 
        shsurf = calloc(1, sizeof *shsurf);
        if (!shsurf) {
-               wl_resource_post_no_memory(resource);
-               return;
+               weston_log("no memory to allocate shell surface\n");
+               return NULL;
        }
 
-       shsurf->resource.destroy = destroy_shell_surface;
-       shsurf->resource.object.id = id;
-       shsurf->resource.object.interface = &wl_shell_surface_interface;
-       shsurf->resource.object.implementation =
-               (void (**)(void)) &shell_surface_implementation;
-       shsurf->resource.data = shsurf;
+       surface->configure = shell_surface_configure;
+       surface->compositor->shell_interface.shell = shell;
 
+       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->fullscreen.black_surface = NULL;
+       shsurf->ping_timer = NULL;
        wl_list_init(&shsurf->fullscreen.transform.link);
 
-       shsurf->surface_destroy_listener.func = shell_handle_surface_destroy;
-       wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
-                      &shsurf->surface_destroy_listener.link);
+       wl_signal_init(&shsurf->resource.destroy_signal);
+       shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
+       wl_signal_add(&surface->surface.resource.destroy_signal,
+                     &shsurf->surface_destroy_listener);
 
        /* init link so its safe to always remove it in destroy_shell_surface */
        wl_list_init(&shsurf->link);
@@ -858,6 +1354,44 @@ shell_get_shell_surface(struct wl_client *client,
        weston_matrix_init(&shsurf->rotation.rotation);
 
        shsurf->type = SHELL_SURFACE_NONE;
+       shsurf->next_type = SHELL_SURFACE_NONE;
+
+       shsurf->client = client;
+
+       return shsurf;
+}
+
+static void
+shell_get_shell_surface(struct wl_client *client,
+                       struct wl_resource *resource,
+                       uint32_t id,
+                       struct wl_resource *surface_resource)
+{
+       struct weston_surface *surface = surface_resource->data;
+       struct desktop_shell *shell = resource->data;
+       struct shell_surface *shsurf;
+
+       if (get_shell_surface(surface)) {
+               wl_resource_post_error(surface_resource,
+                                      WL_DISPLAY_ERROR_INVALID_OBJECT,
+                                      "desktop_shell::get_shell_surface already requested");
+               return;
+       }
+
+       shsurf = create_shell_surface(shell, surface, &shell_client);
+       if (!shsurf) {
+               wl_resource_post_error(surface_resource,
+                                      WL_DISPLAY_ERROR_INVALID_OBJECT,
+                                      "surface->configure already set");
+               return;
+       }
+
+       shsurf->resource.destroy = shell_destroy_shell_surface;
+       shsurf->resource.object.id = id;
+       shsurf->resource.object.interface = &wl_shell_surface_interface;
+       shsurf->resource.object.implementation =
+               (void (**)(void)) &shell_surface_implementation;
+       shsurf->resource.data = shsurf;
 
        wl_client_add_resource(client, &shsurf->resource);
 }
@@ -873,7 +1407,7 @@ handle_screensaver_sigchld(struct weston_process *proc, int status)
 }
 
 static void
-launch_screensaver(struct wl_shell *shell)
+launch_screensaver(struct desktop_shell *shell)
 {
        if (shell->screensaver.binding)
                return;
@@ -882,7 +1416,7 @@ launch_screensaver(struct wl_shell *shell)
                return;
 
        if (shell->screensaver.process.pid != 0) {
-               fprintf(stderr, "old screensaver still running\n");
+               weston_log("old screensaver still running\n");
                return;
        }
 
@@ -893,7 +1427,7 @@ launch_screensaver(struct wl_shell *shell)
 }
 
 static void
-terminate_screensaver(struct wl_shell *shell)
+terminate_screensaver(struct desktop_shell *shell)
 {
        if (shell->screensaver.process.pid == 0)
                return;
@@ -902,7 +1436,7 @@ terminate_screensaver(struct wl_shell *shell)
 }
 
 static void
-show_screensaver(struct wl_shell *shell, struct shell_surface *surface)
+show_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
 {
        struct wl_list *list;
 
@@ -918,7 +1452,7 @@ show_screensaver(struct wl_shell *shell, struct shell_surface *surface)
 }
 
 static void
-hide_screensaver(struct wl_shell *shell, struct shell_surface *surface)
+hide_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
 {
        wl_list_remove(&surface->surface->layer_link);
        wl_list_init(&surface->surface->layer_link);
@@ -931,33 +1465,12 @@ desktop_shell_set_background(struct wl_client *client,
                             struct wl_resource *output_resource,
                             struct wl_resource *surface_resource)
 {
-       struct wl_shell *shell = resource->data;
        struct shell_surface *shsurf = surface_resource->data;
-       struct weston_surface *surface = shsurf->surface;
-       struct shell_surface *priv;
 
-       if (reset_shell_surface_type(shsurf))
-               return;
-
-       wl_list_for_each(priv, &shell->backgrounds, link) {
-               if (priv->output == output_resource->data) {
-                       priv->surface->output = NULL;
-                       wl_list_remove(&priv->surface->layer_link);
-                       wl_list_remove(&priv->link);
-                       break;
-               }
-       }
-
-       shsurf->type = SHELL_SURFACE_BACKGROUND;
+       shsurf->next_type = SHELL_SURFACE_BACKGROUND;
        shsurf->output = output_resource->data;
 
-       wl_list_insert(&shell->backgrounds, &shsurf->link);
-
-       weston_surface_set_position(surface, shsurf->output->x,
-                                   shsurf->output->y);
-
-       desktop_shell_send_configure(resource,
-                                    weston_compositor_get_time(), 0,
+       desktop_shell_send_configure(resource, 0,
                                     surface_resource,
                                     shsurf->output->current->width,
                                     shsurf->output->current->height);
@@ -969,46 +1482,24 @@ desktop_shell_set_panel(struct wl_client *client,
                        struct wl_resource *output_resource,
                        struct wl_resource *surface_resource)
 {
-       struct wl_shell *shell = resource->data;
        struct shell_surface *shsurf = surface_resource->data;
-       struct weston_surface *surface = shsurf->surface;
-       struct shell_surface *priv;
-
-       if (reset_shell_surface_type(shsurf))
-               return;
 
-       wl_list_for_each(priv, &shell->panels, link) {
-               if (priv->output == output_resource->data) {
-                       priv->surface->output = NULL;
-                       wl_list_remove(&priv->surface->layer_link);
-                       wl_list_remove(&priv->link);
-                       break;
-               }
-       }
-
-       shsurf->type = SHELL_SURFACE_PANEL;
+       shsurf->next_type = SHELL_SURFACE_PANEL;
        shsurf->output = output_resource->data;
 
-       wl_list_insert(&shell->panels, &shsurf->link);
-
-       weston_surface_set_position(surface, shsurf->output->x,
-                                   shsurf->output->y);
-
-       desktop_shell_send_configure(resource,
-                                    weston_compositor_get_time(), 0,
+       desktop_shell_send_configure(resource, 0,
                                     surface_resource,
                                     shsurf->output->current->width,
                                     shsurf->output->current->height);
 }
 
 static void
-handle_lock_surface_destroy(struct wl_listener *listener,
-                           struct wl_resource *resource, uint32_t time)
+handle_lock_surface_destroy(struct wl_listener *listener, void *data)
 {
-       struct wl_shell *shell =
-               container_of(listener, struct wl_shell, lock_surface_listener);
+       struct desktop_shell *shell =
+           container_of(listener, struct desktop_shell, lock_surface_listener);
 
-       fprintf(stderr, "lock surface gone\n");
+       weston_log("lock surface gone\n");
        shell->lock_surface = NULL;
 }
 
@@ -1017,12 +1508,9 @@ desktop_shell_set_lock_surface(struct wl_client *client,
                               struct wl_resource *resource,
                               struct wl_resource *surface_resource)
 {
-       struct wl_shell *shell = resource->data;
+       struct desktop_shell *shell = resource->data;
        struct shell_surface *surface = surface_resource->data;
 
-       if (reset_shell_surface_type(surface))
-               return;
-
        shell->prepare_event_sent = false;
 
        if (!shell->locked)
@@ -1030,15 +1518,15 @@ desktop_shell_set_lock_surface(struct wl_client *client,
 
        shell->lock_surface = surface;
 
-       shell->lock_surface_listener.func = handle_lock_surface_destroy;
-       wl_list_insert(&surface_resource->destroy_listener_list,
-                      &shell->lock_surface_listener.link);
+       shell->lock_surface_listener.notify = handle_lock_surface_destroy;
+       wl_signal_add(&surface_resource->destroy_signal,
+                     &shell->lock_surface_listener);
 
-       shell->lock_surface->type = SHELL_SURFACE_LOCK;
+       shell->lock_surface->next_type = SHELL_SURFACE_LOCK;
 }
 
 static void
-resume_desktop(struct wl_shell *shell)
+resume_desktop(struct desktop_shell *shell)
 {
        struct shell_surface *tmp;
 
@@ -1064,7 +1552,7 @@ static void
 desktop_shell_unlock(struct wl_client *client,
                     struct wl_resource *resource)
 {
-       struct wl_shell *shell = resource->data;
+       struct desktop_shell *shell = resource->data;
 
        shell->prepare_event_sent = false;
 
@@ -1072,11 +1560,22 @@ desktop_shell_unlock(struct wl_client *client,
                resume_desktop(shell);
 }
 
+static void
+desktop_shell_set_busy_surface(struct wl_client *client,
+                              struct wl_resource *resource,
+                              struct wl_resource *surface_resource)
+{
+       struct desktop_shell *shell = resource->data;
+
+       shell->busy_surface = surface_resource->data;
+}
+
 static const struct desktop_shell_interface desktop_shell_implementation = {
        desktop_shell_set_background,
        desktop_shell_set_panel,
        desktop_shell_set_lock_surface,
-       desktop_shell_unlock
+       desktop_shell_unlock,
+       desktop_shell_set_busy_surface
 };
 
 static enum shell_surface_type
@@ -1091,16 +1590,20 @@ get_shell_surface_type(struct weston_surface *surface)
 }
 
 static void
-move_binding(struct wl_input_device *device, uint32_t time,
-            uint32_t key, uint32_t button, uint32_t state, void *data)
+move_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
 {
        struct weston_surface *surface =
-               (struct weston_surface *) device->pointer_focus;
+               (struct weston_surface *) seat->pointer->focus;
+       struct shell_surface *shsurf;
 
        if (surface == NULL)
                return;
 
-       switch (get_shell_surface_type(surface)) {
+       shsurf = get_shell_surface(surface);
+       if (shsurf == NULL)
+               return;
+
+       switch (shsurf->type) {
                case SHELL_SURFACE_PANEL:
                case SHELL_SURFACE_BACKGROUND:
                case SHELL_SURFACE_FULLSCREEN:
@@ -1110,15 +1613,14 @@ move_binding(struct wl_input_device *device, uint32_t time,
                        break;
        }
 
-       weston_surface_move(surface, (struct weston_input_device *) device, time);
+       surface_move(shsurf, (struct weston_seat *) seat);
 }
 
 static void
-resize_binding(struct wl_input_device *device, uint32_t time,
-              uint32_t key, uint32_t button, uint32_t state, void *data)
+resize_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
 {
        struct weston_surface *surface =
-               (struct weston_surface *) device->pointer_focus;
+               (struct weston_surface *) seat->pointer->focus;
        uint32_t edges = 0;
        int32_t x, y;
        struct shell_surface *shsurf;
@@ -1141,7 +1643,9 @@ resize_binding(struct wl_input_device *device, uint32_t time,
        }
 
        weston_surface_from_global(surface,
-                                  device->grab_x, device->grab_y, &x, &y);
+                                  wl_fixed_to_int(seat->pointer->grab_x),
+                                  wl_fixed_to_int(seat->pointer->grab_y),
+                                  &x, &y);
 
        if (x < surface->geometry.width / 3)
                edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
@@ -1157,74 +1661,141 @@ resize_binding(struct wl_input_device *device, uint32_t time,
        else
                edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
 
-       weston_surface_resize(shsurf, (struct weston_input_device *) device,
-                           time, edges);
+       surface_resize(shsurf, (struct weston_seat *) seat, edges);
+}
+
+static void
+surface_opacity_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
+                       wl_fixed_t value, void *data)
+{
+       float step = 0.05;
+       struct shell_surface *shsurf;
+       struct weston_surface *surface =
+               (struct weston_surface *) seat->pointer->focus;
+
+       if (surface == NULL)
+               return;
+
+       shsurf = get_shell_surface(surface);
+       if (!shsurf)
+               return;
+
+       switch (shsurf->type) {
+               case SHELL_SURFACE_BACKGROUND:
+               case SHELL_SURFACE_SCREENSAVER:
+                       return;
+               default:
+                       break;
+       }
+
+       surface->alpha += wl_fixed_to_double(value) * step;
+
+       if (surface->alpha > 1.0)
+               surface->alpha = 1.0;
+       if (surface->alpha < step)
+               surface->alpha = step;
+
+       surface->geometry.dirty = 1;
+       weston_surface_damage(surface);
 }
 
 static void
-zoom_binding(struct wl_input_device *device, uint32_t time,
-              uint32_t key, uint32_t button, uint32_t state, void *data)
+do_zoom(struct wl_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
+       wl_fixed_t value)
 {
-       struct weston_input_device *wd = (struct weston_input_device *) device;
-       struct weston_compositor *compositor = wd->compositor;
+       struct weston_seat *ws = (struct weston_seat *) seat;
+       struct weston_compositor *compositor = ws->compositor;
        struct weston_output *output;
+       float maximum_level, increment;
 
        wl_list_for_each(output, &compositor->output_list, link) {
                if (pixman_region32_contains_point(&output->region,
-                                               device->x, device->y, NULL)) {
-                       if (state && key == KEY_UP) {
-                               output->zoom.active = 1;
-                               output->zoom.level -= output->zoom.increment;
-                       }
-                       if (state && key == KEY_DOWN)
-                               output->zoom.level += output->zoom.increment;
-
-                       if (output->zoom.level >= 1.0) {
+                                                  wl_fixed_to_double(seat->pointer->x),
+                                                  wl_fixed_to_double(seat->pointer->y),
+                                                  NULL)) {
+                       if (key == KEY_PAGEUP)
+                               increment = output->zoom.increment;
+                       else if (key == KEY_PAGEDOWN)
+                               increment = -output->zoom.increment;
+                       else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
+                               increment = output->zoom.increment *
+                                           wl_fixed_to_double(value);
+                       else
+                               increment = 0;
+
+                       output->zoom.active = 1;
+                       output->zoom.level += increment;
+
+                       if (output->zoom.level <= 0.0) {
                                output->zoom.active = 0;
-                               output->zoom.level = 1.0;
+                               output->zoom.level = 0.0;
                        }
 
-                       if (output->zoom.level < output->zoom.increment)
-                               output->zoom.level = output->zoom.increment;
+                       maximum_level = 1 - output->zoom.increment;
+
+                       if (output->zoom.level > maximum_level)
+                               output->zoom.level = maximum_level;
 
-                       weston_output_update_zoom(output, device->x, device->y);
+                       weston_output_update_zoom(output,
+                                                 seat->pointer->x,
+                                                 seat->pointer->y,
+                                                 ZOOM_POINTER);
                }
        }
 }
 
 static void
-terminate_binding(struct wl_input_device *device, uint32_t time,
-                 uint32_t key, uint32_t button, uint32_t state, void *data)
+zoom_axis_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
+                 wl_fixed_t value, void *data)
+{
+       do_zoom(seat, time, 0, axis, value);
+}
+
+static void
+zoom_key_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+                void *data)
+{
+       do_zoom(seat, time, key, 0, 0);
+}
+
+static void
+terminate_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+                 void *data)
 {
        struct weston_compositor *compositor = data;
 
-       if (state)
-               wl_display_terminate(compositor->wl_display);
+       wl_display_terminate(compositor->wl_display);
 }
 
 static void
 rotate_grab_motion(struct wl_pointer_grab *grab,
-                uint32_t time, int32_t x, int32_t y)
+                  uint32_t time, wl_fixed_t x, wl_fixed_t y)
 {
        struct rotate_grab *rotate =
-               container_of(grab, struct rotate_grab, grab);
-       struct wl_input_device *device = grab->input_device;
-       struct shell_surface *surface = rotate->surface;
-       GLfloat cx = 0.5f * surface->surface->geometry.width;
-       GLfloat cy = 0.5f * surface->surface->geometry.height;
-       GLfloat dx, dy;
-       GLfloat r;
+               container_of(grab, struct rotate_grab, base.grab);
+       struct wl_pointer *pointer = grab->pointer;
+       struct shell_surface *shsurf = rotate->base.shsurf;
+       struct weston_surface *surface;
+       GLfloat cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
+
+       if (!shsurf)
+               return;
+
+       surface = shsurf->surface;
 
-       dx = device->x - rotate->center.x;
-       dy = device->y - rotate->center.y;
+       cx = 0.5f * surface->geometry.width;
+       cy = 0.5f * surface->geometry.height;
+
+       dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
+       dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
        r = sqrtf(dx * dx + dy * dy);
 
-       wl_list_remove(&surface->rotation.transform.link);
-       surface->surface->geometry.dirty = 1;
+       wl_list_remove(&shsurf->rotation.transform.link);
+       shsurf->surface->geometry.dirty = 1;
 
        if (r > 20.0f) {
                struct weston_matrix *matrix =
-                       &surface->rotation.transform.matrix;
+                       &shsurf->rotation.transform.matrix;
 
                weston_matrix_init(&rotate->rotation);
                rotate->rotation.d[0] = dx / r;
@@ -1234,38 +1805,54 @@ rotate_grab_motion(struct wl_pointer_grab *grab,
 
                weston_matrix_init(matrix);
                weston_matrix_translate(matrix, -cx, -cy, 0.0f);
-               weston_matrix_multiply(matrix, &surface->rotation.rotation);
+               weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
                weston_matrix_multiply(matrix, &rotate->rotation);
                weston_matrix_translate(matrix, cx, cy, 0.0f);
 
                wl_list_insert(
-                       &surface->surface->geometry.transformation_list,
-                       &surface->rotation.transform.link);
+                       &shsurf->surface->geometry.transformation_list,
+                       &shsurf->rotation.transform.link);
        } else {
-               wl_list_init(&surface->rotation.transform.link);
-               weston_matrix_init(&surface->rotation.rotation);
+               wl_list_init(&shsurf->rotation.transform.link);
+               weston_matrix_init(&shsurf->rotation.rotation);
                weston_matrix_init(&rotate->rotation);
        }
 
+       /* We need to adjust the position of the surface
+        * in case it was resized in a rotated state before */
+       cposx = surface->geometry.x + cx;
+       cposy = surface->geometry.y + cy;
+       dposx = rotate->center.x - cposx;
+       dposy = rotate->center.y - cposy;
+       if (dposx != 0.0f || dposy != 0.0f) {
+               weston_surface_set_position(surface,
+                                           surface->geometry.x + dposx,
+                                           surface->geometry.y + dposy);
+       }
+
        /* Repaint implies weston_surface_update_transform(), which
         * lazily applies the damage due to rotation update.
         */
-       weston_compositor_schedule_repaint(surface->surface->compositor);
+       weston_compositor_schedule_repaint(shsurf->surface->compositor);
 }
 
 static void
 rotate_grab_button(struct wl_pointer_grab *grab,
-                uint32_t time, int32_t button, int32_t state)
+                uint32_t time, uint32_t button, uint32_t state_w)
 {
        struct rotate_grab *rotate =
-               container_of(grab, struct rotate_grab, grab);
-       struct wl_input_device *device = grab->input_device;
-       struct shell_surface *surface = rotate->surface;
-
-       if (device->button_count == 0 && state == 0) {
-               weston_matrix_multiply(&surface->rotation.rotation,
-                                      &rotate->rotation);
-               wl_input_device_end_pointer_grab(device, time);
+               container_of(grab, struct rotate_grab, base.grab);
+       struct wl_pointer *pointer = grab->pointer;
+       struct shell_surface *shsurf = rotate->base.shsurf;
+       enum wl_pointer_button_state state = state_w;
+
+       if (pointer->button_count == 0 &&
+           state == WL_POINTER_BUTTON_STATE_RELEASED) {
+               if (shsurf)
+                       weston_matrix_multiply(&shsurf->rotation.rotation,
+                                              &rotate->rotation);
+               shell_grab_finish(&rotate->base);
+               wl_pointer_end_grab(pointer);
                free(rotate);
        }
 }
@@ -1277,11 +1864,11 @@ static const struct wl_pointer_grab_interface rotate_grab_interface = {
 };
 
 static void
-rotate_binding(struct wl_input_device *device, uint32_t time,
-              uint32_t key, uint32_t button, uint32_t state, void *data)
+rotate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
+              void *data)
 {
        struct weston_surface *base_surface =
-               (struct weston_surface *) device->pointer_focus;
+               (struct weston_surface *) seat->pointer->focus;
        struct shell_surface *surface;
        struct rotate_grab *rotate;
        GLfloat dx, dy;
@@ -1308,18 +1895,17 @@ rotate_binding(struct wl_input_device *device, uint32_t time,
        if (!rotate)
                return;
 
-       rotate->grab.interface = &rotate_grab_interface;
-       rotate->surface = surface;
+       shell_grab_init(&rotate->base, &rotate_grab_interface, surface);
 
-       weston_surface_to_global(surface->surface,
-                                surface->surface->geometry.width / 2,
-                                surface->surface->geometry.height / 2,
-                                &rotate->center.x, &rotate->center.y);
+       weston_surface_to_global_float(surface->surface,
+                                      surface->surface->geometry.width / 2,
+                                      surface->surface->geometry.height / 2,
+                                      &rotate->center.x, &rotate->center.y);
 
-       wl_input_device_start_pointer_grab(device, &rotate->grab, time);
+       wl_pointer_start_grab(seat->pointer, &rotate->base.grab);
 
-       dx = device->x - rotate->center.x;
-       dy = device->y - rotate->center.y;
+       dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
+       dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
        r = sqrtf(dx * dx + dy * dy);
        if (r > 20.0f) {
                struct weston_matrix inverse;
@@ -1330,25 +1916,29 @@ rotate_binding(struct wl_input_device *device, uint32_t time,
                inverse.d[1] = -inverse.d[4];
                inverse.d[5] = inverse.d[0];
                weston_matrix_multiply(&surface->rotation.rotation, &inverse);
+
+               weston_matrix_init(&rotate->rotation);
+               rotate->rotation.d[0] = dx / r;
+               rotate->rotation.d[4] = -dy / r;
+               rotate->rotation.d[1] = -rotate->rotation.d[4];
+               rotate->rotation.d[5] = rotate->rotation.d[0];
        } else {
                weston_matrix_init(&surface->rotation.rotation);
                weston_matrix_init(&rotate->rotation);
        }
 
-       wl_input_device_set_pointer_focus(device, NULL, time, 0, 0);
+       wl_pointer_set_focus(seat->pointer, NULL,
+                            wl_fixed_from_int(0),
+                            wl_fixed_from_int(0));
 }
 
 static void
-activate(struct weston_shell *base, struct weston_surface *es,
-        struct weston_input_device *device, uint32_t time)
+activate(struct desktop_shell *shell, struct weston_surface *es,
+        struct weston_seat *seat)
 {
-       struct wl_shell *shell = container_of(base, struct wl_shell, shell);
-       struct weston_compositor *compositor = shell->compositor;
+       struct weston_surface *surf, *prev;
 
-       weston_surface_activate(es, device, time);
-
-       if (compositor->wxs)
-               weston_xserver_surface_activate(es);
+       weston_surface_activate(es, seat);
 
        switch (get_shell_surface_type(es)) {
        case SHELL_SURFACE_BACKGROUND:
@@ -1364,48 +1954,71 @@ activate(struct weston_shell *base, struct weston_surface *es,
                break;
        case SHELL_SURFACE_FULLSCREEN:
                /* should on top of panels */
+               shell_stack_fullscreen(get_shell_surface(es));
+               shell_configure_fullscreen(get_shell_surface(es));
                break;
        default:
+               /* move the fullscreen surfaces down into the toplevel layer */
+               if (!wl_list_empty(&shell->fullscreen_layer.surface_list)) {
+                       wl_list_for_each_reverse_safe(surf,
+                                                     prev, 
+                                                     &shell->fullscreen_layer.surface_list, 
+                                                     layer_link)
+                               weston_surface_restack(surf,
+                                                      &shell->toplevel_layer.surface_list); 
+               }
+
                weston_surface_restack(es,
                                       &shell->toplevel_layer.surface_list);
                break;
        }
 }
 
+/* no-op func for checking black surface */
 static void
-click_to_activate_binding(struct wl_input_device *device,
-                         uint32_t time, uint32_t key,
-                         uint32_t button, uint32_t state, void *data)
+black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
 {
-       struct weston_input_device *wd = (struct weston_input_device *) device;
-       struct weston_compositor *compositor = data;
+}
+
+static bool 
+is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
+{
+       if (es->configure == black_surface_configure) {
+               if (fs_surface)
+                       *fs_surface = (struct weston_surface *)es->private;
+               return true;
+       }
+       return false;
+}
+
+static void
+click_to_activate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
+                         void *data)
+{
+       struct weston_seat *ws = (struct weston_seat *) seat;
+       struct desktop_shell *shell = data;
        struct weston_surface *focus;
        struct weston_surface *upper;
 
-       focus = (struct weston_surface *) device->pointer_focus;
+       focus = (struct weston_surface *) seat->pointer->focus;
        if (!focus)
                return;
 
-       upper = container_of(focus->link.prev, struct weston_surface, link);
-       if (focus->link.prev != &compositor->surface_list &&
-           get_shell_surface_type(upper) == SHELL_SURFACE_FULLSCREEN) {
-               printf("%s: focus is black surface, raise its fullscreen surface\n", __func__);
-               shell_stack_fullscreen(get_shell_surface(upper));
+       if (is_black_surface(focus, &upper))
                focus = upper;
-       }
 
-       if (state && device->pointer_grab == &device->default_pointer_grab)
-               activate(compositor->shell, focus, wd, time);
+       if (seat->pointer->grab == &seat->pointer->default_grab)
+               activate(shell, focus, ws);
 }
 
 static void
-lock(struct weston_shell *base)
+lock(struct wl_listener *listener, void *data)
 {
-       struct wl_shell *shell = container_of(base, struct wl_shell, shell);
-       struct weston_input_device *device;
+       struct desktop_shell *shell =
+               container_of(listener, struct desktop_shell, lock_listener);
+       struct weston_seat *seat;
        struct shell_surface *shsurf;
        struct weston_output *output;
-       uint32_t time;
 
        if (shell->locked) {
                wl_list_for_each(output, &shell->compositor->output_list, link)
@@ -1442,10 +2055,8 @@ lock(struct weston_shell *base)
        weston_compositor_schedule_repaint(shell->compositor);
 
        /* reset keyboard foci */
-       time = weston_compositor_get_time();
-       wl_list_for_each(device, &shell->compositor->input_device_list, link) {
-               wl_input_device_set_keyboard_focus(&device->input_device,
-                                                  NULL, time);
+       wl_list_for_each(seat, &shell->compositor->seat_list, link) {
+               wl_keyboard_set_focus(seat->seat.keyboard, NULL);
        }
 
        /* TODO: disable bindings that should not work while locked. */
@@ -1454,9 +2065,10 @@ lock(struct weston_shell *base)
 }
 
 static void
-unlock(struct weston_shell *base)
+unlock(struct wl_listener *listener, void *data)
 {
-       struct wl_shell *shell = container_of(base, struct wl_shell, shell);
+       struct desktop_shell *shell =
+               container_of(listener, struct desktop_shell, unlock_listener);
 
        if (!shell->locked || shell->lock_surface) {
                weston_compositor_wake(shell->compositor);
@@ -1487,14 +2099,14 @@ center_on_output(struct weston_surface *surface, struct weston_output *output)
 }
 
 static void
-map(struct weston_shell *base, struct weston_surface *surface,
+map(struct desktop_shell *shell, struct weston_surface *surface,
     int32_t width, int32_t height, int32_t sx, int32_t sy)
 {
-       struct wl_shell *shell = container_of(base, struct wl_shell, shell);
        struct weston_compositor *compositor = shell->compositor;
        struct shell_surface *shsurf;
        enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
        struct weston_surface *parent;
+       struct weston_seat *seat;
        int panel_height = 0;
 
        shsurf = get_shell_surface(surface);
@@ -1505,8 +2117,6 @@ map(struct weston_shell *base, struct weston_surface *surface,
        surface->geometry.height = height;
        surface->geometry.dirty = 1;
 
-       weston_compositor_update_drag_surfaces(compositor);
-
        /* initial positioning, see also configure() */
        switch (surface_type) {
        case SHELL_SURFACE_TOPLEVEL:
@@ -1529,7 +2139,7 @@ map(struct weston_shell *base, struct weston_surface *surface,
                center_on_output(surface, get_default_output(compositor));
                break;
        case SHELL_SURFACE_POPUP:
-               shell_map_popup(shsurf, shsurf->popup.time);
+               shell_map_popup(shsurf);
        case SHELL_SURFACE_NONE:
                weston_surface_set_position(surface,
                                            surface->geometry.x + sx,
@@ -1588,31 +2198,42 @@ map(struct weston_shell *base, struct weston_surface *surface,
        }
 
        switch (surface_type) {
-       case SHELL_SURFACE_TOPLEVEL:
        case SHELL_SURFACE_TRANSIENT:
+               if (shsurf->transient.flags ==
+                               WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
+                       break;
+       case SHELL_SURFACE_TOPLEVEL:
        case SHELL_SURFACE_FULLSCREEN:
        case SHELL_SURFACE_MAXIMIZED:
-               if (!shell->locked)
-                       activate(base, surface,
-                                (struct weston_input_device *)
-                                compositor->input_device,
-                                weston_compositor_get_time());
+               if (!shell->locked) {
+                       wl_list_for_each(seat, &compositor->seat_list, link)
+                               activate(shell, surface, seat);
+               }
                break;
        default:
                break;
        }
 
        if (surface_type == SHELL_SURFACE_TOPLEVEL)
-               weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
+       {
+               switch (shell->win_animation_type) {
+               case ANIMATION_FADE:
+                       weston_fade_run(surface, NULL, NULL);
+                       break;
+               case ANIMATION_ZOOM:
+                       weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
+                       break;
+               default:
+                       break;
+               }
+       }
 }
 
 static void
-configure(struct weston_shell *base, struct weston_surface *surface,
+configure(struct desktop_shell *shell, struct weston_surface *surface,
          GLfloat x, GLfloat y, int32_t width, int32_t height)
 {
-       struct wl_shell *shell = container_of(base, struct wl_shell, shell);
        enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
-       enum shell_surface_type prev_surface_type = SHELL_SURFACE_NONE;
        struct shell_surface *shsurf;
 
        shsurf = get_shell_surface(surface);
@@ -1630,9 +2251,8 @@ configure(struct weston_shell *base, struct weston_surface *surface,
                center_on_output(surface, shsurf->fullscreen_output);
                break;
        case SHELL_SURFACE_FULLSCREEN:
+               shell_stack_fullscreen(shsurf);
                shell_configure_fullscreen(shsurf);
-               if (prev_surface_type != SHELL_SURFACE_FULLSCREEN)
-                       shell_stack_fullscreen(shsurf);
                break;
        case SHELL_SURFACE_MAXIMIZED:
                /* setting x, y and using configure to change that geometry */
@@ -1657,14 +2277,44 @@ configure(struct weston_shell *base, struct weston_surface *surface,
        }
 }
 
-static int launch_desktop_shell_process(struct wl_shell *shell);
+static void
+shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
+{
+       struct shell_surface *shsurf = get_shell_surface(es);
+       struct desktop_shell *shell = shsurf->shell;
+       int type_changed = 0;
+
+       if (shsurf->next_type != SHELL_SURFACE_NONE &&
+           shsurf->type != shsurf->next_type) {
+               set_surface_type(shsurf);
+               type_changed = 1;
+       }
+
+       if (!weston_surface_is_mapped(es)) {
+               map(shell, es, es->buffer->width, es->buffer->height, sx, sy);
+       } else if (type_changed || sx != 0 || sy != 0 ||
+                  es->geometry.width != es->buffer->width ||
+                  es->geometry.height != es->buffer->height) {
+               GLfloat from_x, from_y;
+               GLfloat to_x, to_y;
+
+               weston_surface_to_global_float(es, 0, 0, &from_x, &from_y);
+               weston_surface_to_global_float(es, sx, sy, &to_x, &to_y);
+               configure(shell, es,
+                         es->geometry.x + to_x - from_x,
+                         es->geometry.y + to_y - from_y,
+                         es->buffer->width, es->buffer->height);
+       }
+}
+
+static int launch_desktop_shell_process(struct desktop_shell *shell);
 
 static void
 desktop_shell_sigchld(struct weston_process *process, int status)
 {
        uint32_t time;
-       struct wl_shell *shell =
-               container_of(process, struct wl_shell, child.process);
+       struct desktop_shell *shell =
+               container_of(process, struct desktop_shell, child.process);
 
        shell->child.process.pid = 0;
        shell->child.client = NULL; /* already destroyed by wayland */
@@ -1678,16 +2328,16 @@ desktop_shell_sigchld(struct weston_process *process, int status)
 
        shell->child.deathcount++;
        if (shell->child.deathcount > 5) {
-               fprintf(stderr, "weston-desktop-shell died, giving up.\n");
+               weston_log("weston-desktop-shell died, giving up.\n");
                return;
        }
 
-       fprintf(stderr, "weston-desktop-shell died, respawning...\n");
+       weston_log("weston-desktop-shell died, respawning...\n");
        launch_desktop_shell_process(shell);
 }
 
 static int
-launch_desktop_shell_process(struct wl_shell *shell)
+launch_desktop_shell_process(struct desktop_shell *shell)
 {
        const char *shell_exe = LIBEXECDIR "/weston-desktop-shell";
 
@@ -1704,7 +2354,7 @@ launch_desktop_shell_process(struct wl_shell *shell)
 static void
 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 {
-       struct wl_shell *shell = data;
+       struct desktop_shell *shell = data;
 
        wl_client_add_object(client, &wl_shell_interface,
                             &shell_implementation, id, shell);
@@ -1713,7 +2363,7 @@ bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 static void
 unbind_desktop_shell(struct wl_resource *resource)
 {
-       struct wl_shell *shell = resource->data;
+       struct desktop_shell *shell = resource->data;
 
        if (shell->locked)
                resume_desktop(shell);
@@ -1727,7 +2377,7 @@ static void
 bind_desktop_shell(struct wl_client *client,
                   void *data, uint32_t version, uint32_t id)
 {
-       struct wl_shell *shell = data;
+       struct desktop_shell *shell = data;
        struct wl_resource *resource;
 
        resource = wl_client_add_object(client, &desktop_shell_interface,
@@ -1742,7 +2392,7 @@ bind_desktop_shell(struct wl_client *client,
 
        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
                               "permission to bind desktop_shell denied");
-       wl_resource_destroy(resource, 0);
+       wl_resource_destroy(resource);
 }
 
 static void
@@ -1751,14 +2401,11 @@ screensaver_set_surface(struct wl_client *client,
                        struct wl_resource *shell_surface_resource,
                        struct wl_resource *output_resource)
 {
-       struct wl_shell *shell = resource->data;
+       struct desktop_shell *shell = resource->data;
        struct shell_surface *surface = shell_surface_resource->data;
        struct weston_output *output = output_resource->data;
 
-       if (reset_shell_surface_type(surface))
-               return;
-
-       surface->type = SHELL_SURFACE_SCREENSAVER;
+       surface->next_type = SHELL_SURFACE_SCREENSAVER;
 
        surface->fullscreen_output = output;
        surface->output = output;
@@ -1772,7 +2419,7 @@ static const struct screensaver_interface screensaver_implementation = {
 static void
 unbind_screensaver(struct wl_resource *resource)
 {
-       struct wl_shell *shell = resource->data;
+       struct desktop_shell *shell = resource->data;
 
        shell->screensaver.binding = NULL;
        free(resource);
@@ -1782,7 +2429,7 @@ static void
 bind_screensaver(struct wl_client *client,
                 void *data, uint32_t version, uint32_t id)
 {
-       struct wl_shell *shell = data;
+       struct desktop_shell *shell = data;
        struct wl_resource *resource;
 
        resource = wl_client_add_object(client, &screensaver_interface,
@@ -1797,11 +2444,11 @@ bind_screensaver(struct wl_client *client,
 
        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
                               "interface object already bound");
-       wl_resource_destroy(resource, 0);
+       wl_resource_destroy(resource);
 }
 
 struct switcher {
-       struct weston_compositor *compositor;
+       struct desktop_shell *shell;
        struct weston_surface *current;
        struct wl_listener listener;
        struct wl_keyboard_grab grab;
@@ -1810,15 +2457,12 @@ struct switcher {
 static void
 switcher_next(struct switcher *switcher)
 {
-       struct weston_compositor *compositor = switcher->compositor;
+       struct weston_compositor *compositor = switcher->shell->compositor;
        struct weston_surface *surface;
        struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
+       struct shell_surface *shsurf;
 
        wl_list_for_each(surface, &compositor->surface_list, link) {
-               /* Workaround for cursor surfaces. */
-               if (surface->surface.resource.destroy_listener_list.next == NULL)
-                       continue;
-
                switch (get_shell_surface_type(surface)) {
                case SHELL_SURFACE_TOPLEVEL:
                case SHELL_SURFACE_FULLSCREEN:
@@ -1828,29 +2472,41 @@ switcher_next(struct switcher *switcher)
                        if (prev == switcher->current)
                                next = surface;
                        prev = surface;
-                       surface->alpha = 64;
+                       surface->alpha = 0.25;
                        surface->geometry.dirty = 1;
                        weston_surface_damage(surface);
                        break;
                default:
                        break;
                }
+
+               if (is_black_surface(surface, NULL)) {
+                       surface->alpha = 0.25;
+                       surface->geometry.dirty = 1;
+                       weston_surface_damage(surface);
+               }
        }
 
        if (next == NULL)
                next = first;
 
+       if (next == NULL)
+               return;
+
        wl_list_remove(&switcher->listener.link);
-       wl_list_insert(next->surface.resource.destroy_listener_list.prev,
-                      &switcher->listener.link);
+       wl_signal_add(&next->surface.resource.destroy_signal,
+                     &switcher->listener);
 
        switcher->current = next;
-       next->alpha = 255;
+       next->alpha = 1.0;
+
+       shsurf = get_shell_surface(switcher->current);
+       if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
+               shsurf->fullscreen.black_surface->alpha = 1.0;
 }
 
 static void
-switcher_handle_surface_destroy(struct wl_listener *listener,
-                               struct wl_resource *resource, uint32_t time)
+switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
 {
        struct switcher *switcher =
                container_of(listener, struct switcher, listener);
@@ -1859,70 +2515,79 @@ switcher_handle_surface_destroy(struct wl_listener *listener,
 }
 
 static void
-switcher_destroy(struct switcher *switcher, uint32_t time)
+switcher_destroy(struct switcher *switcher)
 {
-       struct weston_compositor *compositor = switcher->compositor;
+       struct weston_compositor *compositor = switcher->shell->compositor;
        struct weston_surface *surface;
-       struct weston_input_device *device =
-               (struct weston_input_device *) switcher->grab.input_device;
+       struct wl_keyboard *keyboard = switcher->grab.keyboard;
 
        wl_list_for_each(surface, &compositor->surface_list, link) {
-               surface->alpha = 255;
+               surface->alpha = 1.0;
                weston_surface_damage(surface);
        }
 
-       activate(compositor->shell, switcher->current, device, time);
+       if (switcher->current)
+               activate(switcher->shell, switcher->current,
+                        (struct weston_seat *) keyboard->seat);
        wl_list_remove(&switcher->listener.link);
-       wl_input_device_end_keyboard_grab(&device->input_device, time);
+       wl_keyboard_end_grab(keyboard);
        free(switcher);
 }
 
 static void
 switcher_key(struct wl_keyboard_grab *grab,
-            uint32_t time, uint32_t key, int32_t state)
+            uint32_t time, uint32_t key, uint32_t state_w)
 {
        struct switcher *switcher = container_of(grab, struct switcher, grab);
-       struct weston_input_device *device =
-               (struct weston_input_device *) grab->input_device;
+       enum wl_keyboard_key_state state = state_w;
 
-       if ((device->modifier_state & MODIFIER_SUPER) == 0) {
-               switcher_destroy(switcher, time);
-       } else if (key == KEY_TAB && state) {
+       if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
                switcher_next(switcher);
-       }
-};
+}
+
+static void
+switcher_modifier(struct wl_keyboard_grab *grab, uint32_t serial,
+                 uint32_t mods_depressed, uint32_t mods_latched,
+                 uint32_t mods_locked, uint32_t group)
+{
+       struct switcher *switcher = container_of(grab, struct switcher, grab);
+       struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat;
+
+       if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
+               switcher_destroy(switcher);
+}
 
 static const struct wl_keyboard_grab_interface switcher_grab = {
-       switcher_key
+       switcher_key,
+       switcher_modifier,
 };
 
 static void
-switcher_binding(struct wl_input_device *device, uint32_t time,
-                uint32_t key, uint32_t button,
-                uint32_t state, void *data)
+switcher_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+                void *data)
 {
-       struct weston_compositor *compositor = data;
+       struct desktop_shell *shell = data;
        struct switcher *switcher;
 
        switcher = malloc(sizeof *switcher);
-       switcher->compositor = compositor;
+       switcher->shell = shell;
        switcher->current = NULL;
-       switcher->listener.func = switcher_handle_surface_destroy;
+       switcher->listener.notify = switcher_handle_surface_destroy;
        wl_list_init(&switcher->listener.link);
 
        switcher->grab.interface = &switcher_grab;
-       wl_input_device_start_keyboard_grab(device, &switcher->grab, time);
-       wl_input_device_set_keyboard_focus(device, NULL,
-                                          weston_compositor_get_time());
+       wl_keyboard_start_grab(seat->keyboard, &switcher->grab);
+       wl_keyboard_set_focus(seat->keyboard, NULL);
        switcher_next(switcher);
 }
 
 static void
-backlight_binding(struct wl_input_device *device, uint32_t time,
-                 uint32_t key, uint32_t button, uint32_t state, void *data)
+backlight_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+                 void *data)
 {
        struct weston_compositor *compositor = data;
        struct weston_output *output;
+       long backlight_new = 0;
 
        /* TODO: we're limiting to simple use cases, where we assume just
         * control on the primary display. We'd have to extend later if we
@@ -1935,23 +2600,26 @@ backlight_binding(struct wl_input_device *device, uint32_t time,
        if (!output->set_backlight)
                return;
 
-       if ((key == KEY_F9 || key == KEY_BRIGHTNESSDOWN) &&
-           output->backlight_current > 1)
-               output->backlight_current--;
-       else if ((key == KEY_F10 || key == KEY_BRIGHTNESSUP) &&
-           output->backlight_current < 10)
-               output->backlight_current++;
+       if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
+               backlight_new = output->backlight_current - 25;
+       else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
+               backlight_new = output->backlight_current + 25;
 
+       if (backlight_new < 5)
+               backlight_new = 5;
+       if (backlight_new > 255)
+               backlight_new = 255;
+
+       output->backlight_current = backlight_new;
        output->set_backlight(output, output->backlight_current);
 }
 
 static void
-debug_repaint_binding(struct wl_input_device *device, uint32_t time,
-                     uint32_t key, uint32_t button, uint32_t state, void *data)
+debug_repaint_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+                     void *data)
 {
-       struct weston_compositor *compositor = data;
-       struct wl_shell *shell =
-               container_of(compositor->shell, struct wl_shell, shell);
+       struct desktop_shell *shell = data;
+       struct weston_compositor *compositor = shell->compositor;
        struct weston_surface *surface;
 
        if (shell->debug_repaint_surface) {
@@ -1981,24 +2649,90 @@ debug_repaint_binding(struct wl_input_device *device, uint32_t time,
 }
 
 static void
-shell_destroy(struct weston_shell *base)
+force_kill_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
+                  void *data)
 {
-       struct wl_shell *shell = container_of(base, struct wl_shell, shell);
+       struct wl_client *client;
+       pid_t pid;
+       uid_t uid;
+       gid_t gid;
+
+       client = seat->keyboard->focus->resource.client;
+       wl_client_get_credentials(client, &pid, &uid, &gid);
+
+       kill(pid, SIGKILL);
+}
+
+static void
+shell_destroy(struct wl_listener *listener, void *data)
+{
+       struct desktop_shell *shell =
+               container_of(listener, struct desktop_shell, destroy_listener);
 
        if (shell->child.client)
                wl_client_destroy(shell->child.client);
 
+       wl_list_remove(&shell->lock_listener.link);
+       wl_list_remove(&shell->unlock_listener.link);
+
        free(shell->screensaver.path);
        free(shell);
 }
 
+static void
+shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
+{
+       uint32_t mod;
+
+       /* fixed bindings */
+       weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
+                                         MODIFIER_CTRL | MODIFIER_ALT,
+                                         terminate_binding, ec);
+       weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
+                                            click_to_activate_binding,
+                                            shell);
+       weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
+                                          MODIFIER_SUPER | MODIFIER_ALT,
+                                          surface_opacity_binding, NULL);
+       weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
+                                          MODIFIER_SUPER, zoom_axis_binding,
+                                          NULL);
+
+       /* configurable bindings */
+       mod = shell->binding_modifier;
+       weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
+                                         zoom_key_binding, NULL);
+       weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
+                                         zoom_key_binding, NULL);
+       weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
+                                            shell);
+       weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
+                                            resize_binding, shell);
+       weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
+                                            rotate_binding, NULL);
+       weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
+                                         shell);
+       weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
+                                         ec);
+       weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
+                                         backlight_binding, ec);
+       weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
+                                         ec);
+       weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
+                                         backlight_binding, ec);
+       weston_compositor_add_key_binding(ec, KEY_SPACE, mod,
+                                         debug_repaint_binding, shell);
+       weston_compositor_add_key_binding(ec, KEY_K, mod,
+                                         force_kill_binding, shell);
+}
+
 int
 shell_init(struct weston_compositor *ec);
 
 WL_EXPORT int
 shell_init(struct weston_compositor *ec)
 {
-       struct wl_shell *shell;
+       struct desktop_shell *shell;
 
        shell = malloc(sizeof *shell);
        if (shell == NULL)
@@ -2006,11 +2740,19 @@ shell_init(struct weston_compositor *ec)
 
        memset(shell, 0, sizeof *shell);
        shell->compositor = ec;
-       shell->shell.lock = lock;
-       shell->shell.unlock = unlock;
-       shell->shell.map = map;
-       shell->shell.configure = configure;
-       shell->shell.destroy = shell_destroy;
+
+       shell->destroy_listener.notify = shell_destroy;
+       wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
+       shell->lock_listener.notify = lock;
+       wl_signal_add(&ec->lock_signal, &shell->lock_listener);
+       shell->unlock_listener.notify = unlock;
+       wl_signal_add(&ec->unlock_signal, &shell->unlock_listener);
+       ec->ping_handler = ping_handler;
+       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.move = surface_move;
+       ec->shell_interface.resize = surface_resize;
 
        wl_list_init(&shell->backgrounds);
        wl_list_init(&shell->panels);
@@ -2042,39 +2784,12 @@ shell_init(struct weston_compositor *ec)
        if (launch_desktop_shell_process(shell) != 0)
                return -1;
 
-       weston_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
-                                   move_binding, shell);
-       weston_compositor_add_binding(ec, 0, BTN_MIDDLE, MODIFIER_SUPER,
-                                   resize_binding, shell);
-       weston_compositor_add_binding(ec, KEY_BACKSPACE, 0,
-                                   MODIFIER_CTRL | MODIFIER_ALT,
-                                   terminate_binding, ec);
-       weston_compositor_add_binding(ec, 0, BTN_LEFT, 0,
-                                   click_to_activate_binding, ec);
-       weston_compositor_add_binding(ec, KEY_UP, 0, MODIFIER_SUPER,
-                                   zoom_binding, shell);
-       weston_compositor_add_binding(ec, KEY_DOWN, 0, MODIFIER_SUPER,
-                                   zoom_binding, shell);
-       weston_compositor_add_binding(ec, 0, BTN_LEFT,
-                                     MODIFIER_SUPER | MODIFIER_ALT,
-                                     rotate_binding, NULL);
-       weston_compositor_add_binding(ec, KEY_TAB, 0, MODIFIER_SUPER,
-                                     switcher_binding, ec);
-
-       /* brightness */
-       weston_compositor_add_binding(ec, KEY_F9, 0, MODIFIER_CTRL,
-                                     backlight_binding, ec);
-       weston_compositor_add_binding(ec, KEY_BRIGHTNESSDOWN, 0, 0,
-                                     backlight_binding, ec);
-       weston_compositor_add_binding(ec, KEY_F10, 0, MODIFIER_CTRL,
-                                     backlight_binding, ec);
-       weston_compositor_add_binding(ec, KEY_BRIGHTNESSUP, 0, 0,
-                                     backlight_binding, ec);
-
-       weston_compositor_add_binding(ec, KEY_SPACE, 0, MODIFIER_SUPER,
-                                   debug_repaint_binding, ec);
-
-       ec->shell = &shell->shell;
+       shell->pointer_focus_listener.notify = handle_pointer_focus;
+       if (ec->seat->seat.pointer)
+               wl_signal_add(&ec->seat->seat.pointer->focus_signal,
+                             &shell->pointer_focus_listener);
+
+       shell_add_bindings(ec, shell);
 
        return 0;
 }