src/: Add basic support for app switching
[src/agl-compositor.git] / src / layout.c
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;
+}