desktop-shell: Enable per-output fade animations
Instead of creating a single global fade surface across all outputs,
create a separate surface for each output. This will permit
e.g. individual fades for each output (or blocking the fade-outs if
inhibiting idling as will come in a later patch.)
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 to become larger during
the course of the fade animation.
Signed-off-by: Bryce Harrington <bryce@osg.samsung.com>
Reviewed-by: Quentin Glidic <sardemff7+git@sardemff7.net>
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 6b1876d..f1577c1 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -202,6 +202,9 @@
static void
shell_fade_startup(struct desktop_shell *shell);
+static void
+shell_fade(struct desktop_shell *shell, enum fade_type type);
+
static struct shell_seat *
get_shell_seat(struct weston_seat *seat);
@@ -2847,9 +2850,6 @@
* end of libweston-desktop *
* ************************ */
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, int x, int y)
{
struct weston_view *v, *next;
@@ -3845,16 +3845,16 @@
}
static void
-shell_fade_done(struct weston_view_animation *animation, void *data)
+shell_fade_done_for_output(struct weston_view_animation *animation, void *data)
{
- struct desktop_shell *shell = data;
+ struct shell_output *shell_output = data;
+ struct desktop_shell *shell = shell_output->shell;
- shell->fade.animation = NULL;
-
- switch (shell->fade.type) {
+ shell_output->fade.animation = NULL;
+ switch (shell_output->fade.type) {
case FADE_IN:
- weston_surface_destroy(shell->fade.view->surface);
- shell->fade.view = NULL;
+ weston_surface_destroy(shell_output->fade.view->surface);
+ shell_output->fade.view = NULL;
break;
case FADE_OUT:
lock(shell);
@@ -3865,7 +3865,7 @@
}
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;
@@ -3881,8 +3881,8 @@
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);
@@ -3897,6 +3897,7 @@
shell_fade(struct desktop_shell *shell, enum fade_type type)
{
float tint;
+ struct shell_output *shell_output;
switch (type) {
case FADE_IN:
@@ -3910,32 +3911,35 @@
return;
}
- shell->fade.type = type;
+ /* Create a separate fade surface for each output */
+ wl_list_for_each(shell_output, &shell->output_list, link) {
+ shell_output->fade.type = type;
- if (shell->fade.view == NULL) {
- shell->fade.view = shell_fade_create_surface(shell);
- if (!shell->fade.view)
- return;
+ if (shell_output->fade.view == NULL) {
+ shell_output->fade.view = shell_fade_create_surface_for_output(shell, shell_output);
+ if (!shell_output->fade.view)
+ continue;
- shell->fade.view->alpha = 1.0 - tint;
- weston_view_update_transform(shell->fade.view);
- }
+ shell_output->fade.view->alpha = 1.0 - tint;
+ weston_view_update_transform(shell_output->fade.view);
+ }
- 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);
+ 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_for_output, shell_output);
+ }
}
}
@@ -3943,6 +3947,7 @@
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);
@@ -3950,8 +3955,10 @@
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;
+ }
}
}
@@ -3959,15 +3966,22 @@
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
@@ -3988,27 +4002,30 @@
*/
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) {
+ if (shell_output->fade.view != NULL) {
+ weston_log("%s: warning: fade surface already exists\n",
+ __func__);
+ 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)
+ continue;
- 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);
+ 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_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
@@ -4023,7 +4040,7 @@
weston_seat_break_desktop_grabs(seat);
shell_fade(shell, FADE_OUT);
- /* lock() is called from shell_fade_done() */
+ /* lock() is called from shell_fade_done_for_output() */
}
static void