[PATCH 3/6] desktop-shell: Allow multiple active fullscreen windows on multi-display setup.

Mario Kleiner mario.kleiner.de at gmail.com
Wed Apr 1 22:10:51 PDT 2015


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 at gmail.com>
---
 desktop-shell/exposay.c |  2 +-
 desktop-shell/shell.c   | 47 +++++++++++++++++++++++++++++++++++------------
 desktop-shell/shell.h   |  3 ++-
 3 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c
index 4b65cbd..a15fc7a 100644
--- a/desktop-shell/exposay.c
+++ b/desktop-shell/exposay.c
@@ -563,7 +563,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);
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index f7c928e..7d0e403 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -303,17 +303,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
@@ -5000,10 +5012,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;
@@ -5017,6 +5033,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) {
@@ -5047,9 +5069,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);
 
@@ -5060,9 +5086,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
@@ -6119,7 +6142,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);
diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
index 2cfd1d6..0f8e16d 100644
--- a/desktop-shell/shell.h
+++ b/desktop-shell/shell.h
@@ -227,7 +227,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,
-- 
1.9.1



More information about the wayland-devel mailing list