From 9e7c7598aa44a9caaa5ebd525426623e8e86880e Mon Sep 17 00:00:00 2001 From: Emilio Pozuelo Monfort Date: Thu, 30 Jan 2014 14:01:10 +0100 Subject: [PATCH] desktop-shell: Properly handle lowered fullscreen surfaces lower_fullscreen_surface() was removing fullscreen surfaces from the fullscreen layer and inserting them in the normal workspace layer. However, those fullscreen surfaces were never put back in the fullscreen layer, causing bugs such as unrelated surfaces being drawn between a fullscreen surface and its black view. Change the lower_fullscreen_surface() logic so that it lowers fullscreen surfaces to the workspace layer *and* hides the black views. Make this reversible by re-configuring the lowered fullscreen surface: when it is re-configured, the black view will be shown again and the surface will be restacked in the fullscreen layer. https://bugs.freedesktop.org/show_bug.cgi?id=73575 https://bugs.freedesktop.org/show_bug.cgi?id=74221 https://bugs.freedesktop.org/show_bug.cgi?id=74222 --- desktop-shell/exposay.c | 8 +++--- desktop-shell/shell.c | 58 +++++++++++++++++++++++++++-------------- desktop-shell/shell.h | 5 +--- 3 files changed, 43 insertions(+), 28 deletions(-) diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c index 9c649e77..1d8b40e1 100644 --- a/desktop-shell/exposay.c +++ b/desktop-shell/exposay.c @@ -160,7 +160,7 @@ exposay_highlight_surface(struct desktop_shell *shell, shell->exposay.column_current = esurface->column; shell->exposay.cur_output = esurface->eoutput; - activate(shell, view->surface, shell->exposay.seat); + activate(shell, view->surface, shell->exposay.seat, false); shell->exposay.focus_current = view; } @@ -318,8 +318,6 @@ exposay_layout(struct desktop_shell *shell, struct shell_output *shell_output) if (shell->exposay.focus_current == esurface->view) highlight = esurface; - set_alpha_if_fullscreen(get_shell_surface(view->surface)); - exposay_animate_in(esurface); i++; @@ -538,10 +536,10 @@ exposay_transition_inactive(struct desktop_shell *shell, int switch_focus) * to the new. */ if (switch_focus && shell->exposay.focus_current) activate(shell, shell->exposay.focus_current->surface, - shell->exposay.seat); + shell->exposay.seat, true); else if (shell->exposay.focus_prev) activate(shell, shell->exposay.focus_prev->surface, - shell->exposay.seat); + shell->exposay.seat, true); wl_list_for_each(esurface, &shell->exposay.surface_list, link) exposay_animate_out(esurface); diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index 43b93f69..9eda814c 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -166,6 +166,7 @@ struct shell_surface { bool maximized; bool fullscreen; bool relative; + bool lowered; } state, next_state, requested_state; /* surface states */ bool state_changed; bool state_requested; @@ -234,13 +235,6 @@ struct shell_client { int unresponsive; }; -void -set_alpha_if_fullscreen(struct shell_surface *shsurf) -{ - if (shsurf && shsurf->state.fullscreen) - shsurf->fullscreen.black_view->alpha = 0.25; -} - static struct desktop_shell * shell_surface_get_shell(struct shell_surface *shsurf); @@ -630,7 +624,7 @@ focus_state_surface_destroy(struct wl_listener *listener, void *data) shell = state->seat->compositor->shell_interface.shell; if (next) { state->keyboard_focus = NULL; - activate(shell, next, state->seat); + activate(shell, next, state->seat, true); } else { if (shell->focus_animation_type == ANIMATION_DIM_LAYER) { if (state->ws->focus_animation) @@ -1839,10 +1833,10 @@ busy_cursor_grab_button(struct weston_pointer_grab *base, struct weston_seat *seat = grab->grab.pointer->seat; if (shsurf && button == BTN_LEFT && state) { - activate(shsurf->shell, shsurf->surface, seat); + activate(shsurf->shell, shsurf->surface, seat, true); surface_move(shsurf, seat, 0); } else if (shsurf && button == BTN_RIGHT && state) { - activate(shsurf->shell, shsurf->surface, seat); + activate(shsurf->shell, shsurf->surface, seat, true); surface_rotate(shsurf, seat); } } @@ -2157,7 +2151,7 @@ shell_surface_calculate_layer_link (struct shell_surface *shsurf) switch (shsurf->type) { case SHELL_SURFACE_POPUP: case SHELL_SURFACE_TOPLEVEL: - if (shsurf->state.fullscreen) { + if (shsurf->state.fullscreen && !shsurf->state.lowered) { return &shsurf->shell->fullscreen_layer.view_list; } else if (shsurf->parent) { /* Move the surface to its parent layer so @@ -2540,7 +2534,7 @@ set_minimized(struct weston_surface *surface, uint32_t is_true) wl_list_for_each(seat, &shsurf->shell->compositor->seat_list, link) { if (!seat->keyboard) continue; - activate(shsurf->shell, view->surface, seat); + activate(shsurf->shell, view->surface, seat, true); } } @@ -2703,6 +2697,8 @@ shell_ensure_fullscreen_black_view(struct shell_surface *shsurf) &shsurf->fullscreen.black_view->layer_link); weston_view_geometry_dirty(shsurf->fullscreen.black_view); weston_surface_damage(shsurf->surface); + + shsurf->state.lowered = false; } /* Create black surface and append it to the associated fullscreen surface. @@ -2719,6 +2715,10 @@ shell_configure_fullscreen(struct shell_surface *shsurf) if (shsurf->fullscreen.type != WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER) restore_output_mode(output); + /* Reverse the effect of lower_fullscreen_layer() */ + wl_list_remove(&shsurf->view->layer_link); + wl_list_insert(&shsurf->shell->fullscreen_layer.view_list, &shsurf->view->layer_link); + shell_ensure_fullscreen_black_view(shsurf); surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y, @@ -4436,8 +4436,12 @@ rotate_binding(struct weston_seat *seat, uint32_t time, uint32_t button, surface_rotate(surface, seat); } -/* Move all fullscreen layers down to the current workspace in a non-reversible - * manner. This should be used when implementing shell-wide overlays, such as +/* Move all fullscreen layers down to the current workspace and hide their + * black views. The surfaces' state is set to both fullscreen and lowered, + * and this is reversed when such a surface is re-configured, see + * shell_configure_fullscreen() and shell_ensure_fullscreen_black_view(). + * + * This should be used when implementing shell-wide overlays, such as * the alt-tab switcher, which need to de-promote fullscreen layers. */ void lower_fullscreen_layer(struct desktop_shell *shell) @@ -4449,16 +4453,32 @@ lower_fullscreen_layer(struct desktop_shell *shell) wl_list_for_each_reverse_safe(view, prev, &shell->fullscreen_layer.view_list, layer_link) { + struct shell_surface *shsurf = get_shell_surface(view->surface); + + if (!shsurf) + continue; + + /* We can have a non-fullscreen popup for a fullscreen surface + * in the fullscreen layer. */ + if (shsurf->state.fullscreen) { + /* Hide the black view */ + wl_list_remove(&shsurf->fullscreen.black_view->layer_link); + wl_list_init(&shsurf->fullscreen.black_view->layer_link); + } + + /* Lower the view to the workspace layer */ wl_list_remove(&view->layer_link); wl_list_insert(&ws->layer.view_list, &view->layer_link); weston_view_damage_below(view); weston_surface_damage(view->surface); + + shsurf->state.lowered = true; } } void activate(struct desktop_shell *shell, struct weston_surface *es, - struct weston_seat *seat) + struct weston_seat *seat, bool configure) { struct weston_surface *main_surface; struct focus_state *state; @@ -4482,7 +4502,7 @@ activate(struct desktop_shell *shell, struct weston_surface *es, shsurf = get_shell_surface(main_surface); assert(shsurf); - if (shsurf->state.fullscreen) + if (shsurf->state.fullscreen && configure) shell_configure_fullscreen(shsurf); else restore_all_output_modes(shell->compositor); @@ -4531,7 +4551,7 @@ activate_binding(struct weston_seat *seat, if (get_shell_surface_type(main_surface) == SHELL_SURFACE_NONE) return; - activate(shell, focus, seat); + activate(shell, focus, seat, true); } static void @@ -4951,7 +4971,7 @@ map(struct desktop_shell *shell, struct shell_surface *shsurf, if (shell->locked) break; wl_list_for_each(seat, &compositor->seat_list, link) - activate(shell, shsurf->surface, seat); + activate(shell, shsurf->surface, seat, true); break; case SHELL_SURFACE_POPUP: case SHELL_SURFACE_NONE: @@ -5402,7 +5422,7 @@ switcher_destroy(struct switcher *switcher) if (switcher->current) activate(switcher->shell, switcher->current, - (struct weston_seat *) keyboard->seat); + (struct weston_seat *) keyboard->seat, true); wl_list_remove(&switcher->listener.link); weston_keyboard_end_grab(keyboard); if (keyboard->input_method_resource) diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h index 4ed11d54..09f8b79f 100644 --- a/desktop-shell/shell.h +++ b/desktop-shell/shell.h @@ -206,9 +206,6 @@ struct desktop_shell { char *client; }; -void -set_alpha_if_fullscreen(struct shell_surface *shsurf); - struct weston_output * get_default_output(struct weston_compositor *compositor); @@ -226,7 +223,7 @@ lower_fullscreen_layer(struct desktop_shell *shell); void activate(struct desktop_shell *shell, struct weston_surface *es, - struct weston_seat *seat); + struct weston_seat *seat, bool configure); void exposay_binding(struct weston_seat *seat,