diff options
author | Marius Vlad <marius.vlad@collabora.com> | 2020-05-21 01:29:37 +0300 |
---|---|---|
committer | Marius Vlad <marius.vlad@collabora.com> | 2020-05-25 14:39:41 +0300 |
commit | 353064abff83403f8a6e46f0469c4dc07b648534 (patch) | |
tree | b57cac83479565ed3c032d4fb5fbaf94657c0d58 | |
parent | 056e977e85cc40774a82659819ccb455056fbb39 (diff) |
src/ Adding remote surface rolesandbox/mvlad/appids-per-output
This patch adds the 'remote' surface role, which clients can make use of
to hint the compositor that is should place the surface on other
output.
While both private extension protocols explicitly require to provide an
wl_output when activating or when setting surface roles, we still need
the inform the compositor that the surface should be placed on another
output. This is due to the activate_by_default functionality that
requires having an output being present, with the default regular XDG
desktop roles deriving its own output by using output of the backgound
surface role.
Just like pop-up dialog role and split surface role this patch adds
another temporary hold up place before the surface is actually created.
Once that is done the surface role will be re-assigned to the desktop
role (being no difference whatsoever between them).
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Change-Id: I8804cc3478974f0b0cb323db46cb0814405c34d1
-rw-r--r-- | protocol/agl-shell-desktop.xml | 1 | ||||
-rw-r--r-- | src/desktop.c | 1 | ||||
-rw-r--r-- | src/ivi-compositor.h | 13 | ||||
-rw-r--r-- | src/layout.c | 86 | ||||
-rw-r--r-- | src/main.c | 1 | ||||
-rw-r--r-- | src/shell.c | 69 |
6 files changed, 143 insertions, 28 deletions
diff --git a/protocol/agl-shell-desktop.xml b/protocol/agl-shell-desktop.xml index 9ef4cca..4f942f5 100644 --- a/protocol/agl-shell-desktop.xml +++ b/protocol/agl-shell-desktop.xml @@ -37,6 +37,7 @@ <entry name="fullscreen" value="1"/> <entry name="split_vertical" value="2"/> <entry name="split_horizontal" value="3"/> + <entry name="remote" value="4"/> </enum> <enum name="app_state"> diff --git a/src/desktop.c b/src/desktop.c index 211c7e2..cf97a52 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -168,6 +168,7 @@ desktop_committed(struct weston_desktop_surface *dsurface, switch (surface->role) { case IVI_SURFACE_ROLE_DESKTOP: + case IVI_SURFACE_ROLE_REMOTE: ivi_layout_desktop_committed(surface); break; case IVI_SURFACE_ROLE_PANEL: diff --git a/src/ivi-compositor.h b/src/ivi-compositor.h index f8f2780..e12b454 100644 --- a/src/ivi-compositor.h +++ b/src/ivi-compositor.h @@ -91,6 +91,7 @@ struct ivi_compositor { struct wl_list popup_pending_apps; struct wl_list fullscreen_pending_apps; struct wl_list split_pending_apps; + struct wl_list remote_pending_apps; struct weston_layer hidden; struct weston_layer background; @@ -149,6 +150,7 @@ enum ivi_surface_role { IVI_SURFACE_ROLE_FS, IVI_SURFACE_ROLE_SPLIT_V, IVI_SURFACE_ROLE_SPLIT_H, + IVI_SURFACE_ROLE_REMOTE, }; struct pending_popup { @@ -172,6 +174,12 @@ struct pending_split { struct wl_list link; /** ivi_compositor::split_pending_apps */ }; +struct pending_remote { + struct ivi_output *ioutput; + char *app_id; + struct wl_list link; /** ivi_compositor::remote_pending_apps */ +}; + struct ivi_desktop_surface { struct ivi_output *pending_output; struct ivi_output *last_output; @@ -191,6 +199,10 @@ struct ivi_fs_surface { struct ivi_output *output; }; +struct ivi_remote_surface { + struct ivi_output *output; +}; + struct ivi_split_surface { struct ivi_output *output; uint32_t orientation; @@ -229,6 +241,7 @@ struct ivi_surface { struct ivi_popup_surface popup; struct ivi_fs_surface fs; struct ivi_split_surface split; + struct ivi_remote_surface remote; }; }; diff --git a/src/layout.c b/src/layout.c index fd01c5b..872a548 100644 --- a/src/layout.c +++ b/src/layout.c @@ -216,6 +216,7 @@ ivi_layout_activate_complete(struct ivi_output *output, /* force repaint of the entire output */ weston_output_damage(output->output); + surf->desktop.last_output = surf->desktop.pending_output; surf->desktop.pending_output = NULL; } @@ -234,19 +235,48 @@ ivi_layout_find_bg_output(struct ivi_compositor *ivi) return NULL; } +static struct ivi_output * +ivi_layout_get_output_from_surface(struct ivi_surface *surf) +{ + struct ivi_output *ivi_output = NULL; + + switch (surf->role) { + case IVI_SURFACE_ROLE_DESKTOP: + if (surf->desktop.pending_output) + ivi_output = surf->desktop.pending_output; + else + ivi_output = surf->desktop.last_output; + break; + case IVI_SURFACE_ROLE_POPUP: + ivi_output = surf->popup.output; + break; + case IVI_SURFACE_ROLE_REMOTE: + ivi_output = surf->remote.output; + break; + default: + case IVI_SURFACE_ROLE_BACKGROUND: + case IVI_SURFACE_ROLE_PANEL: + case IVI_SURFACE_ROLE_NONE: + break; + } + + return ivi_output; +} + 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; + struct ivi_policy *policy = surf->ivi->policy; - assert(surf->role == IVI_SURFACE_ROLE_DESKTOP); + assert(surf->role == IVI_SURFACE_ROLE_DESKTOP || + surf->role == IVI_SURFACE_ROLE_REMOTE); - output = surf->desktop.pending_output; + output = ivi_layout_get_output_from_surface(surf); if (!output) { struct ivi_output *ivi_bg_output; - struct ivi_policy *policy = surf->ivi->policy; if (policy && policy->api.surface_activate_by_default) if (policy->api.surface_activate_by_default(surf, surf->ivi)) @@ -276,6 +306,30 @@ skip_config_check: return; } + if (surf->role == IVI_SURFACE_ROLE_REMOTE && output) { + const char *app_id; + + if (policy && policy->api.surface_activate_by_default && + !policy->api.surface_activate_by_default(surf, surf->ivi)) + return; + + app_id = weston_desktop_surface_get_app_id(dsurf); + if (app_id) { + ivi_layout_activate(output, app_id); + + /* we transition to the desktop role from remote one, + * as they're basically one and the same, but in order + * to keep the same functionality (that is to display + * it by default when starting), we need to know the + * output before hand, fact that that is not true for, + * regular desktop ones. + */ + surf->role = IVI_SURFACE_ROLE_DESKTOP; + surf->activated_by_default = true; + } + return; + } + if (!weston_desktop_surface_get_maximized(dsurf) || geom.width != output->area.width || geom.height != output->area.height) @@ -321,6 +375,7 @@ ivi_layout_fs_committed(struct ivi_surface *surface) surface->view->is_mapped = true; } + void ivi_layout_desktop_resize(struct ivi_surface *surface, struct weston_geometry area) @@ -636,31 +691,6 @@ ivi_layout_activate(struct ivi_output *output, const char *app_id) } } -static struct ivi_output * -ivi_layout_get_output_from_surface(struct ivi_surface *surf) -{ - struct ivi_output *ivi_output = NULL; - - switch (surf->role) { - case IVI_SURFACE_ROLE_DESKTOP: - if (surf->desktop.pending_output) - ivi_output = surf->desktop.pending_output; - else - ivi_output = surf->desktop.last_output; - break; - case IVI_SURFACE_ROLE_POPUP: - ivi_output = surf->popup.output; - break; - default: - case IVI_SURFACE_ROLE_BACKGROUND: - case IVI_SURFACE_ROLE_PANEL: - case IVI_SURFACE_ROLE_NONE: - break; - } - - return ivi_output; -} - void ivi_layout_deactivate(struct ivi_compositor *ivi, const char *app_id) { @@ -1175,6 +1175,7 @@ int main(int argc, char *argv[]) wl_list_init(&ivi.popup_pending_apps); wl_list_init(&ivi.fullscreen_pending_apps); wl_list_init(&ivi.split_pending_apps); + wl_list_init(&ivi.remote_pending_apps); wl_list_init(&ivi.desktop_clients); /* Prevent any clients we spawn getting our stdin */ diff --git a/src/shell.c b/src/shell.c index cb70691..3205804 100644 --- a/src/shell.c +++ b/src/shell.c @@ -87,6 +87,18 @@ ivi_set_desktop_surface_fs(struct ivi_surface *surface) } static void +ivi_set_desktop_surface_remote(struct ivi_surface *surface) +{ + struct ivi_compositor *ivi = surface->ivi; + assert(surface->role == IVI_SURFACE_ROLE_NONE); + + /* remote type are the same as desktop just that client can tell + * the compositor to start on another output */ + surface->role = IVI_SURFACE_ROLE_REMOTE; + wl_list_insert(&ivi->surfaces, &surface->link); +} + +static void ivi_set_desktop_surface_split(struct ivi_surface *surface) { struct ivi_compositor *ivi = surface->ivi; @@ -166,6 +178,23 @@ ivi_set_pending_desktop_surface_split(struct ivi_output *ioutput, } static void +ivi_set_pending_desktop_surface_remote(struct ivi_output *ioutput, + const char *app_id) +{ + struct ivi_compositor *ivi = ioutput->ivi; + size_t len_app_id = strlen(app_id); + + struct pending_remote *remote = zalloc(sizeof(*remote)); + + remote->app_id = zalloc(sizeof(char) * (len_app_id + 1)); + memcpy(remote->app_id, app_id, len_app_id); + + remote->ioutput = ioutput; + + wl_list_insert(&ivi->remote_pending_apps, &remote->link); +} + +static void ivi_remove_pending_desktop_surface_split(struct pending_split *split) { free(split->app_id); @@ -189,6 +218,14 @@ ivi_remove_pending_desktop_surface_popup(struct pending_popup *p_popup) free(p_popup); } +static void +ivi_remove_pending_desktop_surface_remote(struct pending_remote *remote) +{ + free(remote->app_id); + wl_list_remove(&remote->link); + free(remote); +} + static bool ivi_check_pending_desktop_surface_popup(struct ivi_surface *surface) { @@ -261,6 +298,29 @@ ivi_check_pending_desktop_surface_fs(struct ivi_surface *surface) return false; } +static bool +ivi_check_pending_desktop_surface_remote(struct ivi_surface *surface) +{ + struct pending_remote *remote_surf, *next_remote_surf; + struct ivi_compositor *ivi = surface->ivi; + const char *_app_id = + weston_desktop_surface_get_app_id(surface->dsurface); + + if (wl_list_empty(&ivi->remote_pending_apps)) + return false; + + wl_list_for_each_safe(remote_surf, next_remote_surf, + &ivi->remote_pending_apps, link) { + if (!strcmp(_app_id, remote_surf->app_id)) { + surface->remote.output = remote_surf->ioutput; + ivi_remove_pending_desktop_surface_remote(remote_surf); + return true; + } + } + + return false; +} + void ivi_check_pending_desktop_surface(struct ivi_surface *surface) { @@ -284,6 +344,12 @@ ivi_check_pending_desktop_surface(struct ivi_surface *surface) return; } + ret = ivi_check_pending_desktop_surface_remote(surface); + if (ret) { + ivi_set_desktop_surface_remote(surface); + return; + } + /* if we end up here means we have a regular desktop app and * try to activate it */ ivi_set_desktop_surface(surface); @@ -767,6 +833,9 @@ shell_desktop_set_app_property(struct wl_client *client, case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL: ivi_set_pending_desktop_surface_split(output, app_id, role); break; + case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE: + ivi_set_pending_desktop_surface_remote(output, app_id); + break; default: break; } |