diff options
author | 2019-12-10 11:48:04 +0000 | |
---|---|---|
committer | 2020-01-30 01:02:12 +0200 | |
commit | 2d7243208d3e455decd730e7e33ab2452b1a0508 (patch) | |
tree | 68fda63d82e57ad96c231b32592b0a62becaaa96 /src/layout.c | |
parent | aa4ba5d283d641da25722af7a966c31d61a9686b (diff) |
src/: Add basic support for app switching
- 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>
Diffstat (limited to 'src/layout.c')
-rw-r--r-- | src/layout.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/src/layout.c b/src/layout.c new file mode 100644 index 0000000..1088bd5 --- /dev/null +++ b/src/layout.c @@ -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; +} |