[PATCH weston v3 8/8] desktop-shell: Enable per-output fade animations

Bryce Harrington bryce at osg.samsung.com
Thu Apr 7 23:44:23 UTC 2016


Instead of creating a single global fade surface across all outputs,
create a separate surface for each output.  This lets us individually
fade each output (or block fading if the output has an inhibiting
surface).

When there are client surfaces with valid idle inhibits present, fade
out only the outputs those surfaces are not visible on.  Then fade those
out too, if the client terminates for some reason while the system is in
sleep/idle/offscreen mode.

This also fixes a potential issue if on multihead layout spanning a
desktop wider than 8096 (or higher than 8096), the fade animation may
not completely cover all surfaces.

This assumes the output geometry doesn't change larger during the course
of the fade animation.

Signed-off-by: Bryce Harrington <bryce at osg.samsung.com>
---
v3: Fix failure to resume fade-out animation when inhibiting client exits

 desktop-shell/shell.c | 166 +++++++++++++++++++++++++++++++-------------------
 desktop-shell/shell.h |  14 ++---
 2 files changed, 109 insertions(+), 71 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 48e4e30..78ec665 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -3545,10 +3545,23 @@ destroy_shell_surface(struct shell_surface *shsurf)
 }
 
 static void
+shell_fade(struct desktop_shell *shell, enum fade_type type);
+
+static void
 shell_destroy_shell_surface(struct wl_resource *resource)
 {
 	struct shell_surface *shsurf = wl_resource_get_user_data(resource);
 
+	/* Re-queue the fade animation to be evaluated if client had been inhibiting */
+	if (shsurf->surface->inhibit_idling &&
+	    (shsurf->shell->compositor->state == WESTON_COMPOSITOR_IDLE
+	     || shsurf->shell->compositor->state == WESTON_COMPOSITOR_OFFSCREEN
+	     || shsurf->shell->compositor->state == WESTON_COMPOSITOR_SLEEPING))
+	{
+		shsurf->surface->inhibit_idling = false;
+		shell_fade(shsurf->shell, FADE_OUT);
+	}
+
 	if (!wl_list_empty(&shsurf->popup.grab_link))
 		remove_popup_grab(shsurf);
 	wl_list_remove(wl_resource_get_link(shsurf->resource));
@@ -4285,9 +4298,6 @@ xdg_shell_unversioned_dispatch(const void *implementation,
 /***********************************/
 
 static void
-shell_fade(struct desktop_shell *shell, enum fade_type type);
-
-static void
 configure_static_view(struct weston_view *ev, struct weston_layer *layer)
 {
 	struct weston_view *v, *next;
@@ -5224,24 +5234,27 @@ static void
 shell_fade_done(struct weston_view_animation *animation, void *data)
 {
 	struct desktop_shell *shell = data;
+	struct shell_output *shell_output;
 
-	shell->fade.animation = NULL;
+	wl_list_for_each(shell_output, &shell->output_list, link) {
+		shell_output->fade.animation = NULL;
 
-	switch (shell->fade.type) {
-	case FADE_IN:
-		weston_surface_destroy(shell->fade.view->surface);
-		shell->fade.view = NULL;
-		break;
-	case FADE_OUT:
-		lock(shell);
-		break;
-	default:
-		break;
+		switch (shell_output->fade.type) {
+		case FADE_IN:
+			weston_surface_destroy(shell_output->fade.view->surface);
+			shell_output->fade.view = NULL;
+			break;
+		case FADE_OUT:
+			lock(shell);
+			break;
+		default:
+			break;
+		}
 	}
 }
 
 static struct weston_view *
-shell_fade_create_surface(struct desktop_shell *shell)
+shell_fade_create_surface_for_output(struct desktop_shell *shell, struct shell_output *shell_output)
 {
 	struct weston_compositor *compositor = shell->compositor;
 	struct weston_surface *surface;
@@ -5257,8 +5270,8 @@ shell_fade_create_surface(struct desktop_shell *shell)
 		return NULL;
 	}
 
-	weston_surface_set_size(surface, 8192, 8192);
-	weston_view_set_position(view, 0, 0);
+	weston_surface_set_size(surface, shell_output->output->width, shell_output->output->height);
+	weston_view_set_position(view, shell_output->output->x, shell_output->output->y);
 	weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
 	weston_layer_entry_insert(&compositor->fade_layer.view_list,
 				  &view->layer_link);
@@ -5271,6 +5284,8 @@ static void
 shell_fade(struct desktop_shell *shell, enum fade_type type)
 {
 	float tint;
+	struct shell_output *shell_output;
+	uint32_t inhibit_mask = weston_output_inhibited_outputs(shell->compositor);
 
 	switch (type) {
 	case FADE_IN:
@@ -5280,36 +5295,41 @@ shell_fade(struct desktop_shell *shell, enum fade_type type)
 		tint = 1.0;
 		break;
 	default:
-		weston_log("shell: invalid fade type\n");
 		return;
 	}
 
-	shell->fade.type = type;
+	/* Create a separate fade surface for each output */
+        wl_list_for_each(shell_output, &shell->output_list, link) {
+		if (inhibit_mask & (1 << shell_output->output->id))
+			continue;
 
-	if (shell->fade.view == NULL) {
-		shell->fade.view = shell_fade_create_surface(shell);
-		if (!shell->fade.view)
-			return;
+		shell_output->fade.type = type;
 
-		shell->fade.view->alpha = 1.0 - tint;
-		weston_view_update_transform(shell->fade.view);
-	}
+		if (shell_output->fade.view == NULL) {
+			shell_output->fade.view = shell_fade_create_surface_for_output(shell, shell_output);
+			if (!shell_output->fade.view)
+				return;
 
-	if (shell->fade.view->output == NULL) {
-		/* If the black view gets a NULL output, we lost the
-		 * last output and we'll just cancel the fade.  This
-		 * happens when you close the last window under the
-		 * X11 or Wayland backends. */
-		shell->locked = false;
-		weston_surface_destroy(shell->fade.view->surface);
-		shell->fade.view = NULL;
-	} else if (shell->fade.animation) {
-		weston_fade_update(shell->fade.animation, tint);
-	} else {
-		shell->fade.animation =
-			weston_fade_run(shell->fade.view,
-					1.0 - tint, tint, 300.0,
-					shell_fade_done, shell);
+			shell_output->fade.view->alpha = 1.0 - tint;
+			weston_view_update_transform(shell_output->fade.view);
+		}
+
+		if (shell_output->fade.view->output == NULL) {
+			/* If the black view gets a NULL output, we lost the
+			 * last output and we'll just cancel the fade.  This
+			 * happens when you close the last window under the
+			 * X11 or Wayland backends. */
+			shell->locked = false;
+			weston_surface_destroy(shell_output->fade.view->surface);
+			shell_output->fade.view = NULL;
+		} else if (shell_output->fade.animation) {
+			weston_fade_update(shell_output->fade.animation, tint);
+		} else {
+			shell_output->fade.animation =
+				weston_fade_run(shell_output->fade.view,
+						1.0 - tint, tint, 300.0,
+						shell_fade_done, shell);
+		}
 	}
 }
 
@@ -5317,6 +5337,7 @@ static void
 do_shell_fade_startup(void *data)
 {
 	struct desktop_shell *shell = data;
+	struct shell_output *shell_output;
 
 	if (shell->startup_animation_type == ANIMATION_FADE) {
 		shell_fade(shell, FADE_IN);
@@ -5324,8 +5345,10 @@ do_shell_fade_startup(void *data)
 		weston_log("desktop shell: "
 			   "unexpected fade-in animation type %d\n",
 			   shell->startup_animation_type);
-		weston_surface_destroy(shell->fade.view->surface);
-		shell->fade.view = NULL;
+		wl_list_for_each(shell_output, &shell->output_list, link) {
+			weston_surface_destroy(shell_output->fade.view->surface);
+			shell_output->fade.view = NULL;
+		}
 	}
 }
 
@@ -5333,15 +5356,22 @@ static void
 shell_fade_startup(struct desktop_shell *shell)
 {
 	struct wl_event_loop *loop;
+	struct shell_output *shell_output;
+	bool has_fade = false;
 
-	if (!shell->fade.startup_timer)
-		return;
+        wl_list_for_each(shell_output, &shell->output_list, link) {
+		if (!shell_output->fade.startup_timer)
+			continue;
 
-	wl_event_source_remove(shell->fade.startup_timer);
-	shell->fade.startup_timer = NULL;
+		wl_event_source_remove(shell_output->fade.startup_timer);
+		shell_output->fade.startup_timer = NULL;
+		has_fade = true;
+	}
 
-	loop = wl_display_get_event_loop(shell->compositor->wl_display);
-	wl_event_loop_add_idle(loop, do_shell_fade_startup, shell);
+	if (has_fade) {
+		loop = wl_display_get_event_loop(shell->compositor->wl_display);
+		wl_event_loop_add_idle(loop, do_shell_fade_startup, shell);
+	}
 }
 
 static int
@@ -5362,27 +5392,35 @@ shell_fade_init(struct desktop_shell *shell)
 	 */
 
 	struct wl_event_loop *loop;
-
-	if (shell->fade.view != NULL) {
-		weston_log("%s: warning: fade surface already exists\n",
-			   __func__);
-		return;
-	}
+	struct shell_output *shell_output;
 
 	if (shell->startup_animation_type == ANIMATION_NONE)
 		return;
 
-	shell->fade.view = shell_fade_create_surface(shell);
-	if (!shell->fade.view)
-		return;
+	wl_list_for_each(shell_output, &shell->output_list, link) {
+		uint32_t inhibit_mask = weston_output_inhibited_outputs(shell->compositor);
+
+		if (shell_output->fade.view != NULL) {
+			weston_log("%s: warning: fade surface already exists\n",
+				   __func__);
+			continue;
+		}
+
+		if (inhibit_mask & (1 << shell_output->output->id))
+			continue;
 
-	weston_view_update_transform(shell->fade.view);
-	weston_surface_damage(shell->fade.view->surface);
+		shell_output->fade.view = shell_fade_create_surface_for_output(shell, shell_output);
+		if (!shell_output->fade.view)
+			return;
+
+		weston_view_update_transform(shell_output->fade.view);
+		weston_surface_damage(shell_output->fade.view->surface);
 
-	loop = wl_display_get_event_loop(shell->compositor->wl_display);
-	shell->fade.startup_timer =
-		wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
-	wl_event_source_timer_update(shell->fade.startup_timer, 15000);
+		loop = wl_display_get_event_loop(shell->compositor->wl_display);
+		shell_output->fade.startup_timer =
+			wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
+		wl_event_source_timer_update(shell_output->fade.startup_timer, 15000);
+	}
 }
 
 static void
diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
index 2ef23f4..0e5a4d1 100644
--- a/desktop-shell/shell.h
+++ b/desktop-shell/shell.h
@@ -114,6 +114,13 @@ struct shell_output {
 	struct exposay_output eoutput;
 	struct wl_listener    destroy_listener;
 	struct wl_list        link;
+
+	struct {
+		struct weston_view *view;
+		struct weston_view_animation *animation;
+		enum fade_type type;
+		struct wl_event_source *startup_timer;
+	} fade;
 };
 
 struct desktop_shell {
@@ -179,13 +186,6 @@ struct desktop_shell {
 		struct wl_list surfaces;
 	} input_panel;
 
-	struct {
-		struct weston_view *view;
-		struct weston_view_animation *animation;
-		enum fade_type type;
-		struct wl_event_source *startup_timer;
-	} fade;
-
 	struct exposay exposay;
 
 	uint32_t binding_modifier;
-- 
1.9.1



More information about the wayland-devel mailing list