compositor: Move fade animation out of core Weston into shell
Previously, it was impossible to override the fade in/out behavior of
Weston using a different shell, since this was implemented in core
Weston. This also led to complicated interaction between the shell and
the core when displaying lock surfaces and screensavers.
This patch starts to solve this issue by moving the fade animation out
of the core. On compositor.c, besides deleting the fade code, the idle
handler had to be changed to emit the lock signal, since it was called
from the fade_frame() function before. This causes a slight change of
behavior, since before the fade would happen with the compositor being
active, while now it is already in the idle state. That leads to the
dpms state being set when cancelling the fade with mouse movement, and
in turn, to a slight freeze with drm compositor. This problem will be
fixed in a follow up patch.
On the shell side, the fade was re-implemented in a slightly different
manner. Instead of using a custom frame function, the fade animation
from animation.c is used. The interface for starting the fade was also
changed to take the value of an enum instead of a float alpha value,
in order to improve readability.
diff --git a/src/shell.c b/src/shell.c
index da17cfb..0a5c4f0 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -49,6 +49,11 @@
ANIMATION_FADE
};
+enum fade_type {
+ FADE_IN,
+ FADE_OUT
+};
+
struct focus_state {
struct weston_seat *seat;
struct workspace *ws;
@@ -137,6 +142,12 @@
struct wl_list surfaces;
} input_panel;
+ struct {
+ struct weston_surface *surface;
+ struct weston_surface_animation *animation;
+ enum fade_type type;
+ } fade;
+
uint32_t binding_modifier;
enum animation_type win_animation_type;
};
@@ -2754,10 +2765,8 @@
}
static void
-lock(struct wl_listener *listener, void *data)
+lock(struct desktop_shell *shell)
{
- struct desktop_shell *shell =
- container_of(listener, struct desktop_shell, lock_listener);
struct weston_output *output;
struct workspace *ws = get_current_workspace(shell);
@@ -2791,11 +2800,8 @@
}
static void
-unlock(struct wl_listener *listener, void *data)
+unlock(struct desktop_shell *shell)
{
- struct desktop_shell *shell =
- container_of(listener, struct desktop_shell, unlock_listener);
-
if (!shell->locked || shell->lock_surface) {
weston_compositor_wake(shell->compositor);
return;
@@ -2815,6 +2821,91 @@
}
static void
+shell_fade_done(struct weston_surface_animation *animation, void *data)
+{
+ struct desktop_shell *shell = data;
+
+ shell->fade.animation = NULL;
+
+ switch (shell->fade.type) {
+ case FADE_IN:
+ weston_surface_destroy(shell->fade.surface);
+ shell->fade.surface = NULL;
+ break;
+ case FADE_OUT:
+ shell->compositor->state = WESTON_COMPOSITOR_SLEEPING;
+ lock(shell);
+ break;
+ }
+}
+
+static void
+shell_fade(struct desktop_shell *shell, enum fade_type type)
+{
+ struct weston_compositor *compositor = shell->compositor;
+ struct weston_surface *surface;
+ float tint;
+
+ switch (type) {
+ case FADE_IN:
+ tint = 0.0;
+ break;
+ case FADE_OUT:
+ tint = 1.0;
+ break;
+ default:
+ weston_log("shell: invalid fade type\n");
+ return;
+ }
+
+ shell->fade.type = type;
+
+ if (shell->fade.surface == NULL) {
+ surface = weston_surface_create(compositor);
+ if (!surface)
+ return;
+
+ weston_surface_configure(surface, 0, 0, 8192, 8192);
+ weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
+ surface->alpha = 1.0 - tint;
+ wl_list_insert(&compositor->fade_layer.surface_list,
+ &surface->layer_link);
+ weston_surface_update_transform(surface);
+ shell->fade.surface = surface;
+ pixman_region32_init(&surface->input);
+ }
+
+ if (shell->fade.animation)
+ weston_fade_update(shell->fade.animation,
+ shell->fade.surface->alpha, tint, 30.0);
+ else
+ shell->fade.animation =
+ weston_fade_run(shell->fade.surface,
+ 1.0 - tint, tint, 30.0,
+ shell_fade_done, shell);
+}
+
+static void
+lock_handler(struct wl_listener *listener, void *data)
+{
+ struct desktop_shell *shell =
+ container_of(listener, struct desktop_shell, lock_listener);
+
+ shell_fade(shell, FADE_OUT);
+ /* lock() is called from shell_fade_done() */
+}
+
+static void
+unlock_handler(struct wl_listener *listener, void *data)
+{
+ struct desktop_shell *shell =
+ container_of(listener, struct desktop_shell, unlock_listener);
+
+ shell_fade(shell, FADE_IN);
+ unlock(shell);
+}
+
+static void
show_input_panels(struct wl_listener *listener, void *data)
{
struct desktop_shell *shell =
@@ -3216,6 +3307,7 @@
&surface->layer_link);
weston_surface_update_transform(surface);
shell->compositor->idle_time = shell->screensaver.duration;
+ shell_fade(shell, FADE_IN);
weston_compositor_wake(shell->compositor);
shell->compositor->state = WESTON_COMPOSITOR_IDLE;
}
@@ -3972,9 +4064,9 @@
shell->destroy_listener.notify = shell_destroy;
wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
- shell->lock_listener.notify = lock;
+ shell->lock_listener.notify = lock_handler;
wl_signal_add(&ec->lock_signal, &shell->lock_listener);
- shell->unlock_listener.notify = unlock;
+ shell->unlock_listener.notify = unlock_handler;
wl_signal_add(&ec->unlock_signal, &shell->unlock_listener);
shell->show_input_panel_listener.notify = show_input_panels;
wl_signal_add(&ec->show_input_panel_signal, &shell->show_input_panel_listener);
@@ -4048,5 +4140,7 @@
shell_add_bindings(ec, shell);
+ shell_fade(shell, FADE_IN);
+
return 0;
}