Commit efb75f68 authored by Stefan Agner's avatar Stefan Agner

desktop-shell: make sure child window stays active

If a xdg_toplevel surface has a child (or multiple), the desktop shell
still allows to activate the parent. This can be problematic with
modal dialogs such as message boxes which then are hidden behind the
main window, which might be non-responsive to inputs at this this
point.

The protocol specifies set_parent as follows: "Set the 'parent' of
this surface. This surface should be stacked above the parent surface
and all other ancestor surfaces."

Track parent/child relationship in desktop-shell. Follow the protocol
recommendation and make sure the child stays stacked above the parent.

Fixes: #231
Signed-off-by: Stefan Agner's avatarStefan Agner <stefan@agner.ch>
parent 5d7877ad
Pipeline #45526 passed with stages
in 1 minute and 52 seconds
......@@ -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;
......@@ -2415,6 +2418,8 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
weston_matrix_init(&shsurf->rotation.rotation);
wl_list_init(&shsurf->workspace_transform.link);
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,
......@@ -2427,12 +2432,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)
......@@ -2747,6 +2759,20 @@ desktop_surface_resize(struct weston_desktop_surface *desktop_surface,
wl_resource_post_no_memory(resource);
}
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,
......@@ -2929,6 +2955,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,
......@@ -3786,12 +3813,20 @@ 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);
if (!wl_list_empty(&shsurf->children_list)) {
/* Activate last xdg child instead of parent. */
wl_list_for_each_reverse(shsurf_child, &shsurf->children_list, children_link) {
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)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment