desktop-shell: Allow multiple active fullscreen windows on multi-display setup.

Desktop shell demoted all fullscreen shell surfaces on all active
outputs of a multi-display setup whenever any shell surface was
activated anywhere. This made it impossible to have multiple
fullscreen windows on separate outputs active at the same
time, as creating or activating any shell surface would disable
fullscreen status for all existing fullscreen surfaces.

Make lower_fullscreen_layer() more selective, so on request it
only demotes fullscreen surfaces on a specified weston_output.

The activate() method for a specific surface will now only request
demotion of fullscreen surfaces on the target output of the activated
surface, but leave fullscreen surfaces on unrelated outputs alone.

Desktop wide acting functions like the window switcher or exposay
will still demote all fullscreen surfaces on all outputs to
implement their effect as before.

Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
Reviewed-By: Derek Foreman <derekf@osg.samsung.com>
This commit is contained in:
Mario Kleiner 2015-06-21 21:25:08 +02:00 committed by Bryce Harrington
parent 3559f892e4
commit 9f4d655494
3 changed files with 38 additions and 14 deletions

View file

@ -566,7 +566,7 @@ exposay_transition_active(struct desktop_shell *shell)
shell->exposay.clicked = NULL;
wl_list_init(&shell->exposay.surface_list);
lower_fullscreen_layer(shell);
lower_fullscreen_layer(shell, NULL);
shell->exposay.grab_kbd.interface = &exposay_kbd_grab;
weston_keyboard_start_grab(seat->keyboard,
&shell->exposay.grab_kbd);

View file

@ -309,17 +309,29 @@ static bool
shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
{
struct desktop_shell *shell;
struct weston_view *top_fs_ev;
struct weston_view *view;
struct shell_surface *top_fs_shsurf = NULL;
shell = shell_surface_get_shell(shsurf);
if (wl_list_empty(&shell->fullscreen_layer.view_list.link))
return false;
top_fs_ev = container_of(shell->fullscreen_layer.view_list.link.next,
struct weston_view,
layer_link.link);
return (shsurf == get_shell_surface(top_fs_ev->surface));
/* Find topmost shsurf on the same fullscreen output on which shsurf
* is displaying. We don't care about other outputs.
*/
wl_list_for_each(view, &shell->fullscreen_layer.view_list.link,
layer_link.link) {
struct shell_surface *cand_shsurf = get_shell_surface(view->surface);
if (cand_shsurf &&
(cand_shsurf->fullscreen_output == shsurf->fullscreen_output)) {
top_fs_shsurf = cand_shsurf;
break;
}
}
return (shsurf == top_fs_shsurf);
}
static void
@ -4980,10 +4992,14 @@ rotate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
* and this is reversed when such a surface is re-configured, see
* shell_configure_fullscreen() and shell_ensure_fullscreen_black_view().
*
* lowering_output = NULL - Lower on all outputs, else only lower on the
* specified output.
*
* 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)
lower_fullscreen_layer(struct desktop_shell *shell,
struct weston_output *lowering_output)
{
struct workspace *ws;
struct weston_view *view, *prev;
@ -4997,6 +5013,12 @@ lower_fullscreen_layer(struct desktop_shell *shell)
if (!shsurf)
continue;
/* Only lower surfaces which have lowering_output as their fullscreen
* output, unless a NULL output asks for lowering on all outputs.
*/
if (lowering_output && (shsurf->fullscreen_output != lowering_output))
continue;
/* We can have a non-fullscreen popup for a fullscreen surface
* in the fullscreen layer. */
if (shsurf->state.fullscreen) {
@ -5027,9 +5049,13 @@ activate(struct desktop_shell *shell, struct weston_surface *es,
struct weston_surface *old_es;
struct shell_surface *shsurf;
lower_fullscreen_layer(shell);
main_surface = weston_surface_get_main_surface(es);
shsurf = get_shell_surface(main_surface);
assert(shsurf);
/* Only demote fullscreen surfaces on the output of activated shsurf.
* Leave fullscreen surfaces on unrelated outputs alone. */
lower_fullscreen_layer(shell, shsurf->output);
weston_surface_activate(es, seat);
@ -5040,9 +5066,6 @@ activate(struct desktop_shell *shell, struct weston_surface *es,
old_es = state->keyboard_focus;
focus_state_set_focus(state, es);
shsurf = get_shell_surface(main_surface);
assert(shsurf);
if (shsurf->state.fullscreen && configure)
shell_configure_fullscreen(shsurf);
else
@ -6013,7 +6036,7 @@ switcher_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
wl_array_init(&switcher->minimized_array);
restore_all_output_modes(shell->compositor);
lower_fullscreen_layer(switcher->shell);
lower_fullscreen_layer(switcher->shell, NULL);
switcher->grab.interface = &switcher_grab;
weston_keyboard_start_grab(seat->keyboard, &switcher->grab);
weston_keyboard_set_focus(seat->keyboard, NULL);

View file

@ -222,7 +222,8 @@ struct workspace *
get_current_workspace(struct desktop_shell *shell);
void
lower_fullscreen_layer(struct desktop_shell *shell);
lower_fullscreen_layer(struct desktop_shell *shell,
struct weston_output *lowering_output);
void
activate(struct desktop_shell *shell, struct weston_surface *es,