src/: Add basic support for app switching 03/23303/6
authorScott Anderson <daniels@collabora.com>
Tue, 10 Dec 2019 11:48:04 +0000 (11:48 +0000)
committerMarius Vlad <marius.vlad@collabora.com>
Wed, 29 Jan 2020 23:02:12 +0000 (01:02 +0200)
- adds a new request for agl-shell, 'activate_app', which allows to
specify which application should switch to.  With it, client shell
commands which application to switch to.

- ties the layout (panel and background initizatlon) bits into its own
specific file

Bug-AGL: SPEC-3117

Change-Id: I1b3d89ff77c0e0e439666227ef3319b2107406c0
Signed-off-by: Daniel Stone <daniels@collabora.com>
meson.build
protocol/agl-shell.xml
src/desktop.c
src/ivi-compositor.h
src/layout.c [new file with mode: 0644]
src/main.c
src/shell.c

index a7e1bfc..08548f8 100644 (file)
@@ -92,6 +92,7 @@ deps_libweston = [
 srcs_agl_compositor = [
        'src/main.c',
        'src/desktop.c',
+       'src/layout.c',
        'src/shell.c',
        'shared/option-parser.c',
        'shared/os-compatibility.c',
index 59548e7..1096c64 100644 (file)
       <arg name="output" type="object" interface="wl_output"/>
       <arg name="edge" type="uint" enum="edge"/>
     </request>
+
+    <request name="activate_app">
+      <description summary="make client current window">
+        Ask the compositor to make a toplevel to become the current/focused
+        window for window management purposes.
+
+        See xdg_toplevel.set_app_id from the xdg-shell protocol for a
+        description of app_id.
+
+        If multiple toplevels have the same app_id, the result is unspecified.
+
+        XXX: Do we need feedback to say it didn't work? (e.g. client does
+        not exist)
+      </description>
+      <arg name="app_id" type="string"/>
+      <arg name="output" type="object" interface="wl_output"/>
+    </request>
   </interface>
 </protocol>
index fbeefec..ed6208f 100644 (file)
@@ -69,18 +69,21 @@ desktop_surface_added(struct weston_desktop_surface *dsurface, void *userdata)
                return;
        }
 
+       surface->view = weston_desktop_surface_create_view(dsurface);
+       if (!surface->view) {
+               free(surface);
+               wl_client_post_no_memory(client);
+               return;
+       }
+
        surface->ivi = ivi;
        surface->dsurface = dsurface;
        surface->role = IVI_SURFACE_ROLE_NONE;
-       surface->old_geom.width = -1;
-       surface->old_geom.height = -1;
 
        weston_desktop_surface_set_user_data(dsurface, surface);
 
        if (ivi->shell_client.ready) {
                ivi_set_desktop_surface(surface);
-
-               ivi_reflow_outputs(ivi);
        } else {
                /*
                 * We delay creating "normal" desktop surfaces until later, to
@@ -98,112 +101,17 @@ desktop_surface_removed(struct weston_desktop_surface *dsurface, void *userdata)
                weston_desktop_surface_get_user_data(dsurface);
        struct weston_surface *wsurface =
                weston_desktop_surface_get_surface(dsurface);
-       struct ivi_compositor *ivi = surface->ivi;
 
        /* TODO */
        if (surface->role != IVI_SURFACE_ROLE_DESKTOP)
                return;
 
        if (weston_surface_is_mapped(wsurface)) {
-               weston_desktop_surface_unlink_view(surface->desktop.view);
-               weston_view_destroy(surface->desktop.view);
+               weston_desktop_surface_unlink_view(surface->view);
+               weston_view_destroy(surface->view);
                wl_list_remove(&surface->link);
        }
        free(surface);
-
-       ivi_reflow_outputs(ivi);
-}
-
-static void
-surface_committed(struct ivi_surface *surface)
-{
-       struct ivi_compositor *ivi = surface->ivi;
-       struct weston_desktop_surface *dsurface = surface->dsurface;
-       struct weston_geometry geom, old_geom;
-
-       old_geom = surface->old_geom;
-       geom = weston_desktop_surface_get_geometry(dsurface);
-
-       surface->old_geom = geom;
-
-       if (geom.width != old_geom.width || geom.height != old_geom.height) {
-               ivi_reflow_outputs(ivi);
-       }
-
-       //wl_list_insert(&ivi->surfaces, &surface->link);
-}
-
-static void
-background_committed(struct ivi_surface *surface)
-{
-       struct ivi_compositor *ivi = surface->ivi;
-       struct ivi_output *output = surface->bg.output;
-       struct weston_output *woutput = output->output;
-       struct weston_desktop_surface *dsurface = surface->dsurface;
-       struct weston_surface *wsurface =
-               weston_desktop_surface_get_surface(dsurface);
-
-       if (wsurface->is_mapped)
-               return;
-
-       surface->bg.view = weston_desktop_surface_create_view(dsurface);
-
-       weston_view_set_output(surface->bg.view, woutput);
-       weston_view_set_position(surface->bg.view,
-                                woutput->x,
-                                woutput->y);
-       weston_layer_entry_insert(&ivi->background.view_list,
-                                 &surface->bg.view->layer_link);
-
-       weston_view_update_transform(surface->bg.view);
-       weston_view_schedule_repaint(surface->bg.view);
-
-       wsurface->is_mapped = true;
-}
-
-static void
-panel_committed(struct ivi_surface *surface)
-{
-       struct ivi_compositor *ivi = surface->ivi;
-       struct ivi_output *output = surface->bg.output;
-       struct weston_output *woutput = output->output;
-       struct weston_desktop_surface *dsurface = surface->dsurface;
-       struct weston_surface *wsurface =
-               weston_desktop_surface_get_surface(dsurface);
-       struct weston_geometry geom;
-       int32_t x = woutput->x;
-       int32_t y = woutput->y;
-
-       if (wsurface->is_mapped)
-               return;
-
-       surface->panel.view = weston_desktop_surface_create_view(dsurface);
-
-       geom = weston_desktop_surface_get_geometry(dsurface);
-       switch (surface->panel.edge) {
-       case AGL_SHELL_EDGE_TOP:
-               /* Do nothing */
-               break;
-       case AGL_SHELL_EDGE_BOTTOM:
-               y += woutput->height - geom.height;
-               break;
-       case AGL_SHELL_EDGE_LEFT:
-               /* Do nothing */
-               break;
-       case AGL_SHELL_EDGE_RIGHT:
-               x += woutput->width - geom.width;
-               break;
-       }
-
-       weston_view_set_output(surface->panel.view, woutput);
-       weston_view_set_position(surface->panel.view, x, y);
-       weston_layer_entry_insert(&ivi->normal.view_list,
-                                 &surface->panel.view->layer_link);
-
-       weston_view_update_transform(surface->panel.view);
-       weston_view_schedule_repaint(surface->panel.view);
-
-       wsurface->is_mapped = true;
 }
 
 static void
@@ -212,22 +120,8 @@ desktop_committed(struct weston_desktop_surface *dsurface,
 {
        struct ivi_surface *surface =
                weston_desktop_surface_get_user_data(dsurface);
-
-       weston_compositor_schedule_repaint(surface->ivi->compositor);
-
-       switch (surface->role) {
-       case IVI_SURFACE_ROLE_NONE:
-               break;
-       case IVI_SURFACE_ROLE_DESKTOP:
-               surface_committed(surface);
-               break;
-       case IVI_SURFACE_ROLE_BACKGROUND:
-               background_committed(surface);
-               break;
-       case IVI_SURFACE_ROLE_PANEL:
-               panel_committed(surface);
-               break;
-       }
+       if (surface->role == IVI_SURFACE_ROLE_DESKTOP)
+               ivi_layout_desktop_committed(surface);
 }
 
 static void
index 65e06ad..3765f65 100644 (file)
@@ -68,18 +68,17 @@ struct ivi_compositor {
        } shell_client;
 
        struct wl_list outputs; /* ivi_output.link */
-       struct wl_list surfaces; /* ivi_desktop_surface.link */
+       struct wl_list surfaces; /* ivi_surface.link */
 
        struct weston_desktop *desktop;
 
        struct wl_list pending_surfaces;
 
+       struct weston_layer hidden;
        struct weston_layer background;
        struct weston_layer normal;
        struct weston_layer panel;
        struct weston_layer fullscreen;
-
-       struct wl_list shell_clients; /* ivi_shell_client.link */
 };
 
 struct ivi_surface;
@@ -107,8 +106,7 @@ struct ivi_output {
         */
        struct weston_geometry area;
 
-       //int32_t width;
-       //int32_t height;
+       struct ivi_surface *active;
 
        /* Temporary: only used during configuration */
        size_t add_len;
@@ -123,18 +121,16 @@ enum ivi_surface_role {
 };
 
 struct ivi_desktop_surface {
-       struct weston_view *view;
+       struct ivi_output *pending_output;
 };
 
 struct ivi_background_surface {
        struct ivi_output *output;
-       struct weston_view *view;
 };
 
 struct ivi_panel_surface {
        struct ivi_output *output;
        enum agl_shell_edge edge;
-       struct weston_view *view;
 };
 
 enum ivi_surface_flags {
@@ -146,6 +142,7 @@ enum ivi_surface_flags {
 struct ivi_surface {
        struct ivi_compositor *ivi;
        struct weston_desktop_surface *dsurface;
+       struct weston_view *view;
 
        struct wl_list link;
 
@@ -155,8 +152,6 @@ struct ivi_surface {
                int32_t width, height;
        } pending;
 
-       struct weston_geometry old_geom;
-
        enum ivi_surface_role role;
        union {
                struct ivi_desktop_surface desktop;
@@ -217,4 +212,13 @@ ivi_layout_set_position(struct ivi_surface *surface,
 void
 ivi_layout_commit(struct ivi_compositor *ivi);
 
+void
+ivi_layout_init(struct ivi_compositor *ivi, struct ivi_output *output);
+
+void
+ivi_layout_activate(struct ivi_output *output, const char *app_id);
+
+void
+ivi_layout_desktop_committed(struct ivi_surface *surf);
+
 #endif
diff --git a/src/layout.c b/src/layout.c
new file mode 100644 (file)
index 0000000..1088bd5
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Copyright © 2019 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ivi-compositor.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include <libweston-6/compositor.h>
+#include <libweston-6/libweston-desktop.h>
+
+static void
+ivi_background_init(struct ivi_compositor *ivi, struct ivi_output *output)
+{
+       struct weston_output *woutput = output->output;
+       struct ivi_surface *bg = output->background;
+       struct weston_view *view;
+
+       if (!bg) {
+               weston_log("WARNING: Output does not have a background\n");
+               return;
+       }
+
+       assert(bg->role == IVI_SURFACE_ROLE_BACKGROUND);
+
+       view = bg->view;
+
+       weston_view_set_output(view, woutput);
+       weston_view_set_position(view, woutput->x, woutput->y);
+
+       view->is_mapped = true;
+       view->surface->is_mapped = true;
+
+       weston_layer_entry_insert(&ivi->background.view_list, &view->layer_link);
+}
+
+static void
+ivi_panel_init(struct ivi_compositor *ivi, struct ivi_output *output,
+              struct ivi_surface *panel)
+{
+       struct weston_output *woutput = output->output;
+       struct weston_desktop_surface *dsurface;
+       struct weston_view *view;
+       struct weston_geometry geom;
+       int x = woutput->x;
+       int y = woutput->y;
+
+       if (!panel)
+               return;
+
+       assert(panel->role == IVI_SURFACE_ROLE_PANEL);
+       dsurface = panel->dsurface;
+       view = panel->view;
+       geom = weston_desktop_surface_get_geometry(dsurface);
+
+       switch (panel->panel.edge) {
+       case AGL_SHELL_EDGE_TOP:
+               output->area.y += geom.height;
+               output->area.height -= geom.height;
+               break;
+       case AGL_SHELL_EDGE_BOTTOM:
+               y += woutput->height - geom.height;
+               output->area.height -= geom.height;
+               break;
+       case AGL_SHELL_EDGE_LEFT:
+               output->area.x += geom.width;
+               output->area.width -= geom.width;
+               break;
+       case AGL_SHELL_EDGE_RIGHT:
+               x += woutput->width - geom.width;
+               output->area.width -= geom.width;
+               break;
+       }
+
+       x -= geom.x;
+       y -= geom.y;
+
+       weston_view_set_output(view, woutput);
+       weston_view_set_position(view, x, y);
+
+       view->is_mapped = true;
+       view->surface->is_mapped = true;
+
+       weston_layer_entry_insert(&ivi->panel.view_list, &view->layer_link);
+}
+
+/*
+ * Initializes all static parts of the layout, i.e. the background and panels.
+ */
+void
+ivi_layout_init(struct ivi_compositor *ivi, struct ivi_output *output)
+{
+       ivi_background_init(ivi, output);
+
+       output->area.x = 0;
+       output->area.y = 0;
+       output->area.width = output->output->width;
+       output->area.height = output->output->height;
+
+       ivi_panel_init(ivi, output, output->top);
+       ivi_panel_init(ivi, output, output->bottom);
+       ivi_panel_init(ivi, output, output->left);
+       ivi_panel_init(ivi, output, output->right);
+
+       weston_compositor_schedule_repaint(ivi->compositor);
+
+       weston_log("Usable area: %dx%d+%d,%d\n",
+                  output->area.width, output->area.height,
+                  output->area.x, output->area.y);
+}
+
+static struct ivi_surface *
+ivi_find_app(struct ivi_compositor *ivi, const char *app_id)
+{
+       struct ivi_surface *surf;
+       const char *id;
+
+       wl_list_for_each(surf, &ivi->surfaces, link) {
+               id = weston_desktop_surface_get_app_id(surf->dsurface);
+               if (id && strcmp(app_id, id) == 0)
+                       return surf;
+       }
+
+       return NULL;
+}
+
+static void
+ivi_layout_activate_complete(struct ivi_output *output,
+                            struct ivi_surface *surf)
+{
+       struct ivi_compositor *ivi = output->ivi;
+       struct weston_output *woutput = output->output;
+       struct weston_view *view = surf->view;
+
+       if (weston_view_is_mapped(view)) {
+               weston_layer_entry_remove(&view->layer_link);
+       }
+
+       weston_view_set_output(view, woutput);
+       weston_view_set_position(view,
+                                woutput->x + output->area.x,
+                                woutput->y + output->area.y);
+
+       view->is_mapped = true;
+       view->surface->is_mapped = true;
+
+       if (output->active) {
+               output->active->view->is_mapped = false;
+               output->active->view->surface->is_mapped = false;
+
+               weston_layer_entry_remove(&output->active->view->layer_link);
+       }
+       output->active = surf;
+
+       weston_layer_entry_insert(&ivi->normal.view_list, &view->layer_link);
+       weston_view_update_transform(view);
+
+       weston_view_schedule_repaint(view);
+       surf->desktop.pending_output = NULL;
+}
+
+void
+ivi_layout_desktop_committed(struct ivi_surface *surf)
+{
+       struct weston_desktop_surface *dsurf = surf->dsurface;
+       struct weston_geometry geom = weston_desktop_surface_get_geometry(dsurf);
+       struct ivi_output *output;
+
+       assert(surf->role == IVI_SURFACE_ROLE_DESKTOP);
+
+       output = surf->desktop.pending_output;
+       if (!output)
+               return;
+
+       if (!weston_desktop_surface_get_maximized(dsurf) ||
+           geom.width != output->area.width ||
+           geom.height != output->area.height)
+               return;
+
+       ivi_layout_activate_complete(output, surf);
+}
+
+void
+ivi_layout_activate(struct ivi_output *output, const char *app_id)
+{
+       struct ivi_compositor *ivi = output->ivi;
+       struct ivi_surface *surf;
+       struct weston_desktop_surface *dsurf;
+       struct weston_view *view;
+       struct weston_geometry geom;
+
+       surf = ivi_find_app(ivi, app_id);
+       if (!surf)
+               return;
+
+       weston_log("Found app_id %s\n", app_id);
+
+       if (surf == output->active)
+               return;
+
+       dsurf = surf->dsurface;
+       view = surf->view;
+       geom = weston_desktop_surface_get_geometry(dsurf);
+
+       if (weston_desktop_surface_get_maximized(dsurf) &&
+           geom.width == output->area.width &&
+           geom.height == output->area.height) {
+               ivi_layout_activate_complete(output, surf);
+               return;
+       }
+
+       weston_desktop_surface_set_maximized(dsurf, true);
+       weston_desktop_surface_set_size(dsurf,
+                                       output->area.width,
+                                       output->area.height);
+
+       /*
+        * If the view isn't mapped, we put it onto the hidden layer so it will
+        * start receiving frame events, and will be able to act on our
+        * configure event.
+        */
+       if (!weston_view_is_mapped(view)) {
+               view->is_mapped = true;
+               view->surface->is_mapped = true;
+
+               weston_view_set_output(view, output->output);
+               weston_layer_entry_insert(&ivi->hidden.view_list, &view->layer_link);
+               weston_view_schedule_repaint(view);
+       }
+
+       surf->desktop.pending_output = output;
+}
index 71a99ea..fd0006f 100644 (file)
@@ -114,15 +114,6 @@ ivi_ensure_output(struct ivi_compositor *ivi, char *name,
        return output;
 }
 
-static void
-ivi_output_destroy(struct ivi_output *output)
-{
-       weston_output_destroy(output->output);
-       free(output->name);
-       wl_list_remove(&output->link);
-       free(output);
-}
-
 static int
 count_heads(struct weston_output *output)
 {
@@ -421,7 +412,6 @@ head_disable(struct ivi_compositor *ivi, struct weston_head *head)
 
        weston_head_detach(head);
        if (count_heads(ivi_output->output) == 0) {
-               ivi_output_destroy(ivi_output);
                weston_output_disable(ivi_output->output);
        }
 }
@@ -865,7 +855,7 @@ activate_binding(struct weston_seat *seat,
        struct ivi_surface *surface;
 
        surface = to_ivi_surface(main_surface);
-       if (!surface || surface->role != IVI_SURFACE_ROLE_DESKTOP)
+       if (!surface)
                return;
 
        weston_seat_set_keyboard_focus(seat, focus);
@@ -938,14 +928,6 @@ static bool
 global_filter(const struct wl_client *client, const struct wl_global *global,
              void *data)
 {
-#if 0
-       struct ivi_compositor *ivi = data;
-       const struct wl_interface *iface = wl_global_get_interface(global);
-
-       if (iface == &agl_shell_interface)
-               return client == ivi->shell_client.client;
-#endif
-
        return true;
 }
 
@@ -1136,7 +1118,6 @@ int main(int argc, char *argv[])
 
        wl_list_init(&ivi.outputs);
        wl_list_init(&ivi.surfaces);
-       wl_list_init(&ivi.shell_clients);
        wl_list_init(&ivi.pending_surfaces);
 
        /* Prevent any clients we spawn getting our stdin */
@@ -1184,25 +1165,12 @@ int main(int argc, char *argv[])
                if (!signals[i])
                        goto error_signals;
 
-#if 0
-       log_ctx = weston_log_ctx_compositor_create();
-       if (!log_ctx) {
-               weston_log("Failed to initialize weston debug framework.\n");
-               goto error_signals;
-       }
-#endif
-
        ivi.compositor = weston_compositor_create(display, &ivi);
        if (!ivi.compositor) {
                weston_log("fatal: failed to create compositor.\n");
                goto error_signals;
        }
 
-#if 0
-       if (debug_protocol)
-               weston_compositor_enable_debug_protocol(ivi.compositor);
-#endif
-
        if (compositor_init_config(ivi.compositor, ivi.config) < 0)
                goto error_compositor;
 
index cac8fa2..67f6d88 100644 (file)
@@ -49,133 +49,17 @@ ivi_set_desktop_surface(struct ivi_surface *surface)
        wl_list_insert(&surface->ivi->surfaces, &surface->link);
 }
 
-/* TODO: Replace this with some callback or similar, to have
- * adjustable window management policy.
- */
-void
-ivi_reflow_outputs(struct ivi_compositor *ivi)
-{
-       struct ivi_surface *surface;
-       struct ivi_output *output;
-       int i = 0;
-
-       if (wl_list_empty(&ivi->outputs))
-               return;
-
-       output = wl_container_of(ivi->outputs.next, output, link);
-
-       wl_list_for_each(surface, &ivi->surfaces, link) {
-               struct weston_desktop_surface *dsurface = surface->dsurface;
-
-               int32_t w = output->area.width / 4;
-               int32_t h = output->area.height / 2;
-               int32_t x = output->output->x + output->area.x + w * (i % 4);
-               int32_t y = output->output->y + output->area.y + h * (i / 4);
-
-               if (surface->old_geom.width == -1) {
-                       weston_desktop_surface_set_size(dsurface, w, h);
-                       continue;
-               } else {
-                       ivi_layout_set_mapped(surface);
-                       ivi_layout_set_position(surface, x, y, w, h);
-               }
-
-               if (++i == 8) {
-                       if (output->link.next == &ivi->outputs)
-                               break;
-
-                       output = wl_container_of(output->link.next,
-                                                output, link);
-                       i = 0;
-               }
-       }
-
-       ivi_layout_commit(ivi);
-}
-
-void
-ivi_layout_set_mapped(struct ivi_surface *surface)
-{
-       surface->pending.flags |= IVI_SURFACE_PROP_MAP;
-}
-
-void
-ivi_layout_set_position(struct ivi_surface *surface,
-                       int32_t x, int32_t y,
-                       int32_t width, int32_t height)
-{
-       surface->pending.flags |= IVI_SURFACE_PROP_POSITION;
-       surface->pending.x = x;
-       surface->pending.y = y;
-       surface->pending.width = width;
-       surface->pending.height = height;
-}
-
-void
-ivi_layout_commit(struct ivi_compositor *ivi)
-{
-       struct ivi_surface *surface;
-
-       wl_list_for_each(surface, &ivi->surfaces, link) {
-               struct weston_desktop_surface *dsurface = surface->dsurface;
-               struct weston_surface *wsurface =
-                       weston_desktop_surface_get_surface(dsurface);
-               struct weston_geometry geom;
-               struct weston_view *view;
-
-               /*
-                * TODO: Hoist view into ivi_struct. It doesn't need ot be part
-                * of the tagged union.
-                */
-               switch (surface->role) {
-               case IVI_SURFACE_ROLE_DESKTOP:
-                       view = surface->desktop.view;
-                       break;
-               case IVI_SURFACE_ROLE_BACKGROUND:
-                       view = surface->bg.view;
-                       break;
-               case IVI_SURFACE_ROLE_PANEL:
-                       view = surface->panel.view;
-                       break;
-               default:
-                       continue;
-               }
-
-               if (surface->pending.flags & IVI_SURFACE_PROP_MAP) {
-                       view = weston_desktop_surface_create_view(dsurface);
-                       wsurface->is_mapped = true;
-
-                       surface->desktop.view = view;
-                       weston_layer_entry_insert(&ivi->normal.view_list,
-                                                 &view->layer_link);
-                       weston_view_update_transform(view);
-                       weston_view_set_mask_infinite(view);
-                       weston_view_schedule_repaint(view);
-               }
-
-               geom = weston_desktop_surface_get_geometry(dsurface);
-
-               if (surface->pending.flags & IVI_SURFACE_PROP_POSITION) {
-                       weston_desktop_surface_set_size(dsurface,
-                                                       surface->pending.width,
-                                                       surface->pending.height);
-                       weston_view_set_position(view,
-                                                surface->pending.x - geom.x,
-                                                surface->pending.y - geom.y);
-               }
-
-               surface->pending.flags = 0;
-       }
-}
-
 int
 ivi_shell_init(struct ivi_compositor *ivi)
 {
+       weston_layer_init(&ivi->hidden, ivi->compositor);
        weston_layer_init(&ivi->background, ivi->compositor);
        weston_layer_init(&ivi->normal, ivi->compositor);
        weston_layer_init(&ivi->panel, ivi->compositor);
        weston_layer_init(&ivi->fullscreen, ivi->compositor);
 
+       weston_layer_set_position(&ivi->hidden,
+                                 WESTON_LAYER_POSITION_HIDDEN);
        weston_layer_set_position(&ivi->background,
                                  WESTON_LAYER_POSITION_BACKGROUND);
        weston_layer_set_position(&ivi->normal,
@@ -298,44 +182,7 @@ shell_ready(struct wl_client *client, struct wl_resource *shell_res)
        /* TODO: Create a black screen and remove it here */
 
        wl_list_for_each(output, &ivi->outputs, link) {
-               struct weston_desktop_surface *dsurf;
-               struct weston_geometry geom;
-
-               output->area.x = 0;
-               output->area.y = 0;
-               output->area.width = output->output->width;
-               output->area.height = output->output->height;
-
-               if (output->top) {
-                       dsurf = output->top->dsurface;
-                       geom = weston_desktop_surface_get_geometry(dsurf);
-
-                       output->area.y += geom.height;
-                       output->area.height -= geom.height;
-               }
-               if (output->bottom) {
-                       dsurf = output->bottom->dsurface;
-                       geom = weston_desktop_surface_get_geometry(dsurf);
-
-                       output->area.height -= geom.height;
-               }
-               if (output->left) {
-                       dsurf = output->left->dsurface;
-                       geom = weston_desktop_surface_get_geometry(dsurf);
-
-                       output->area.x += geom.width;
-                       output->area.width -= geom.width;
-               }
-               if (output->right) {
-                       dsurf = output->right->dsurface;
-                       geom = weston_desktop_surface_get_geometry(dsurf);
-
-                       output->area.width -= geom.width;
-               }
-
-               weston_log("Usable area: %dx%d+%d,%d\n",
-                          output->area.width, output->area.height,
-                          output->area.x, output->area.y);
+               ivi_layout_init(ivi, output);
        }
 
        wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
@@ -474,10 +321,24 @@ shell_set_panel(struct wl_client *client,
        weston_desktop_surface_set_size(dsurface, width, height);
 }
 
+static void
+shell_activate_app(struct wl_client *client,
+                  struct wl_resource *shell_res,
+                  const char *app_id,
+                  struct wl_resource *output_res)
+{
+       struct weston_head *head = weston_head_from_resource(output_res);
+       struct weston_output *woutput = weston_head_get_output(head);
+       struct ivi_output *output = to_ivi_output(woutput);
+
+       ivi_layout_activate(output, app_id);
+}
+
 static const struct agl_shell_interface agl_shell_implementation = {
        .ready = shell_ready,
        .set_background = shell_set_background,
        .set_panel = shell_set_panel,
+       .activate_app = shell_activate_app,
 };
 
 static void