summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop-shell/shell.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index a05a5fe0..7d9d703c 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -104,6 +104,9 @@ struct shell_surface {
struct desktop_shell *shell;
+ struct wl_list children_list;
+ struct wl_list children_link;
+
int32_t saved_x, saved_y;
bool saved_position_valid;
bool saved_rotation_valid;
@@ -2416,6 +2419,13 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
wl_list_init(&shsurf->workspace_transform.link);
+ /*
+ * initialize list as well as link. The latter allows to use
+ * wl_list_remove() even when this surface is not in another list.
+ */
+ wl_list_init(&shsurf->children_list);
+ wl_list_init(&shsurf->children_link);
+
weston_desktop_surface_set_user_data(desktop_surface, shsurf);
weston_desktop_surface_set_activated(desktop_surface,
shsurf->focus_count > 0);
@@ -2427,12 +2437,19 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
{
struct shell_surface *shsurf =
weston_desktop_surface_get_user_data(desktop_surface);
+ struct shell_surface *shsurf_child, *tmp;
struct weston_surface *surface =
weston_desktop_surface_get_surface(desktop_surface);
if (!shsurf)
return;
+ wl_list_for_each_safe(shsurf_child, tmp, &shsurf->children_list, children_link) {
+ wl_list_remove(&shsurf_child->children_link);
+ wl_list_init(&shsurf_child->children_link);
+ }
+ wl_list_remove(&shsurf->children_link);
+
wl_signal_emit(&shsurf->destroy_signal, shsurf);
if (shsurf->fullscreen.black_view)
@@ -2748,6 +2765,20 @@ desktop_surface_resize(struct weston_desktop_surface *desktop_surface,
}
static void
+desktop_surface_set_parent(struct weston_desktop_surface *desktop_surface,
+ struct weston_desktop_surface *parent,
+ void *shell)
+{
+ struct shell_surface *shsurf =
+ weston_desktop_surface_get_user_data(desktop_surface);
+ struct shell_surface *shsurf_parent =
+ weston_desktop_surface_get_user_data(parent);
+
+ wl_list_insert(shsurf_parent->children_list.prev,
+ &shsurf->children_link);
+}
+
+static void
desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surface,
bool fullscreen,
struct weston_output *output, void *shell)
@@ -2929,6 +2960,7 @@ static const struct weston_desktop_api shell_desktop_api = {
.committed = desktop_surface_committed,
.move = desktop_surface_move,
.resize = desktop_surface_resize,
+ .set_parent = desktop_surface_set_parent,
.fullscreen_requested = desktop_surface_fullscreen_requested,
.maximized_requested = desktop_surface_maximized_requested,
.minimized_requested = desktop_surface_minimized_requested,
@@ -3777,6 +3809,18 @@ lower_fullscreen_layer(struct desktop_shell *shell,
}
}
+static struct shell_surface *get_last_child(struct shell_surface *shsurf)
+{
+ struct shell_surface *shsurf_child;
+
+ wl_list_for_each_reverse(shsurf_child, &shsurf->children_list, children_link) {
+ if (weston_view_is_mapped(shsurf_child->view))
+ return shsurf_child;
+ }
+
+ return NULL;
+}
+
void
activate(struct desktop_shell *shell, struct weston_view *view,
struct weston_seat *seat, uint32_t flags)
@@ -3786,12 +3830,19 @@ activate(struct desktop_shell *shell, struct weston_view *view,
struct focus_state *state;
struct workspace *ws;
struct weston_surface *old_es;
- struct shell_surface *shsurf;
+ struct shell_surface *shsurf, *shsurf_child;
main_surface = weston_surface_get_main_surface(es);
shsurf = get_shell_surface(main_surface);
assert(shsurf);
+ shsurf_child = get_last_child(shsurf);
+ if (shsurf_child) {
+ /* Activate last xdg child instead of parent. */
+ activate(shell, shsurf_child->view, seat, flags);
+ return;
+ }
+
/* Only demote fullscreen surfaces on the output of activated shsurf.
* Leave fullscreen surfaces on unrelated outputs alone. */
if (shsurf->output)