Surface damage effectively does nothing if the surface is not on any output.
Animations need a repaint to start and workspace switcher was relying on
weston_surface_damage() to do this. If there are no surfaces on the workspace,
nothing will happen until the next repaint. So, in the case of no surfaces in
the workspace layer list, we just do a full damage to kick off the animation.

This bug was exposed by 982387011ff. The scenario is trying to switch workspaces
while there are no surfaces on the current workspace. If no other damage/repaint
is happening, the switch animation wont start until the moving the mouse, for
example.
---
 src/shell.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/src/shell.c b/src/shell.c
index 87e688c..13a7fd0 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -577,9 +577,13 @@ workspace_translate_in(struct workspace *ws, double 
fraction)
 }
 
 static void
-workspace_damage_all_surfaces(struct workspace *ws)
+workspace_damage_all_surfaces(struct desktop_shell *shell, struct workspace 
*ws)
 {
        struct weston_surface *surface;
+       struct weston_compositor *compositor = shell->compositor;
+
+       if (wl_list_empty(&ws->layer.surface_list))
+               weston_compositor_schedule_repaint(compositor);
 
        wl_list_for_each(surface, &ws->layer.surface_list, layer_link)
                weston_surface_damage(surface);
@@ -600,8 +604,8 @@ reverse_workspace_change_animation(struct desktop_shell 
*shell,
 
        restore_focus_state(shell, to);
 
-       workspace_damage_all_surfaces(from);
-       workspace_damage_all_surfaces(to);
+       workspace_damage_all_surfaces(shell, from);
+       workspace_damage_all_surfaces(shell, to);
 }
 
 static void
@@ -623,8 +627,8 @@ finish_workspace_change_animation(struct desktop_shell 
*shell,
                                  struct workspace *from,
                                  struct workspace *to)
 {
-       workspace_damage_all_surfaces(from);
-       workspace_damage_all_surfaces(to);
+       workspace_damage_all_surfaces(shell, from);
+       workspace_damage_all_surfaces(shell, to);
 
        wl_list_remove(&shell->workspaces.animation.link);
        workspace_deactivate_transforms(from);
@@ -673,15 +677,15 @@ animate_workspace_change_frame(struct weston_animation 
*animation,
        y = sin(x);
 
        if (t < DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) {
-               workspace_damage_all_surfaces(from);
-               workspace_damage_all_surfaces(to);
+               workspace_damage_all_surfaces(shell, from);
+               workspace_damage_all_surfaces(shell, to);
 
                workspace_translate_out(from, shell->workspaces.anim_dir * y);
                workspace_translate_in(to, shell->workspaces.anim_dir * y);
                shell->workspaces.anim_current = y;
 
-               workspace_damage_all_surfaces(from);
-               workspace_damage_all_surfaces(to);
+               workspace_damage_all_surfaces(shell, from);
+               workspace_damage_all_surfaces(shell, to);
        }
        else
                finish_workspace_change_animation(shell, from, to);
@@ -721,8 +725,8 @@ animate_workspace_change(struct desktop_shell *shell,
 
        restore_focus_state(shell, to);
 
-       workspace_damage_all_surfaces(from);
-       workspace_damage_all_surfaces(to);
+       workspace_damage_all_surfaces(shell, from);
+       workspace_damage_all_surfaces(shell, to);
 }
 
 static void
-- 
1.7.11.2

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to