[mutter/gnome-3-28] window: Let implementations finish state changes



commit 2919a7f25f5a88665ff132ed1b0443e05e845f3b
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Tue Apr 17 23:42:33 2018 -0300

    window: Let implementations finish state changes
    
    In the old, synchronous X.org world, we could assume that
    a state change always meant a synchronizing the window
    geometry right after. After firing an operation that
    would change the window state, such as maximizing or
    tiling the window,
    
    With Wayland, however, this is not valid anymore, since
    Wayland is asynchronous. In this scenario, we call
    meta_window_move_resize_internal() twice: when the user
    executes an state-changing operation, and when the server
    ACKs this operation. This breaks the previous assumptions,
    and as a consequence, it breaks the GNOME Shell animations
    in Wayland.
    
    The solution is giving the MetaWindow control over the time
    when the window geometry is synchronized with the compositor.
    That is done by introducing a new result flag. Wayland asks
    for a compositor sync after receiving an ACK from the server,
    while X11 asks for it right away.
    
    Fixes #78

 src/core/window-private.h         |  2 ++
 src/core/window.c                 |  2 +-
 src/wayland/meta-window-wayland.c | 24 ++++++++++++++++++------
 src/x11/window-x11.c              |  2 ++
 4 files changed, 23 insertions(+), 7 deletions(-)
---
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 9545dfc3c..eb86b642c 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -81,6 +81,7 @@ typedef enum
   META_MOVE_RESIZE_STATE_CHANGED = 1 << 5,
   META_MOVE_RESIZE_UNMAXIMIZE = 1 << 6,
   META_MOVE_RESIZE_FORCE_MOVE = 1 << 7,
+  META_MOVE_RESIZE_WAYLAND_STATE_CHANGED = 1 << 8,
 } MetaMoveResizeFlags;
 
 typedef enum
@@ -88,6 +89,7 @@ typedef enum
   META_MOVE_RESIZE_RESULT_MOVED               = 1 << 0,
   META_MOVE_RESIZE_RESULT_RESIZED             = 1 << 1,
   META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
+  META_MOVE_RESIZE_RESULT_STATE_CHANGED       = 1 << 3,
 } MetaMoveResizeResultFlags;
 
 typedef enum
diff --git a/src/core/window.c b/src/core/window.c
index 86f9d69b1..743326c60 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -3997,7 +3997,7 @@ meta_window_move_resize_internal (MetaWindow          *window,
 
   if ((moved_or_resized ||
        did_placement ||
-       (flags & META_MOVE_RESIZE_STATE_CHANGED) != 0) &&
+       (result & META_MOVE_RESIZE_RESULT_STATE_CHANGED) != 0) &&
       window->known_to_compositor)
     {
       meta_compositor_sync_window_geometry (window->display->compositor,
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index 939071e08..b0a7de14c 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -48,6 +48,7 @@ struct _MetaWindowWayland
   int geometry_scale;
 
   MetaWaylandSerial pending_configure_serial;
+  gboolean has_pending_state_change;
   gboolean has_pending_move;
   int pending_move_x;
   int pending_move_y;
@@ -324,6 +325,9 @@ meta_window_wayland_move_resize_internal (MetaWindow                *window,
           window->buffer_rect.x = new_buffer_x;
           window->buffer_rect.y = new_buffer_y;
         }
+
+      if (flags & META_MOVE_RESIZE_WAYLAND_STATE_CHANGED)
+        *result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED;
     }
   else
     {
@@ -336,6 +340,8 @@ meta_window_wayland_move_resize_internal (MetaWindow                *window,
           wl_window->pending_move_x = new_x;
           wl_window->pending_move_y = new_y;
         }
+
+      wl_window->has_pending_state_change = (flags & META_MOVE_RESIZE_STATE_CHANGED) != 0;
     }
 }
 
@@ -629,12 +635,9 @@ meta_window_wayland_new (MetaDisplay        *display,
 }
 
 static gboolean
-should_do_pending_move (MetaWindowWayland *wl_window,
-                        MetaWaylandSerial *acked_configure_serial)
+is_pending_ack_configure (MetaWindowWayland *wl_window,
+                          MetaWaylandSerial *acked_configure_serial)
 {
-  if (!wl_window->has_pending_move)
-    return FALSE;
-
   if (wl_window->pending_configure_serial.set)
     {
       /* If we're waiting for a configure and this isn't an ACK for
@@ -677,6 +680,7 @@ meta_window_wayland_move_resize (MetaWindow        *window,
   int gravity;
   MetaRectangle rect;
   MetaMoveResizeFlags flags;
+  gboolean pending_ack_configure;
 
   /* new_geom is in the logical pixel coordinate space, but MetaWindow wants its
    * rects to represent what in turn will end up on the stage, i.e. we need to
@@ -700,10 +704,12 @@ meta_window_wayland_move_resize (MetaWindow        *window,
 
   flags = META_MOVE_RESIZE_WAYLAND_RESIZE;
 
+  pending_ack_configure = is_pending_ack_configure (wl_window, acked_configure_serial);
+
   /* x/y are ignored when we're doing interactive resizing */
   if (!meta_grab_op_is_resizing (window->display->grab_op))
     {
-      if (wl_window->has_pending_move && should_do_pending_move (wl_window, acked_configure_serial))
+      if (wl_window->has_pending_move && pending_ack_configure)
         {
           rect.x = wl_window->pending_move_x;
           rect.y = wl_window->pending_move_y;
@@ -724,6 +730,12 @@ meta_window_wayland_move_resize (MetaWindow        *window,
         }
     }
 
+  if (wl_window->has_pending_state_change && pending_ack_configure)
+    {
+      flags |= META_MOVE_RESIZE_WAYLAND_STATE_CHANGED;
+      wl_window->has_pending_state_change = FALSE;
+    }
+
   wl_window->pending_configure_serial.set = FALSE;
 
   rect.width = new_geom.width;
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index e819c1b67..e9bd8ae65 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -1282,6 +1282,8 @@ meta_window_x11_move_resize_internal (MetaWindow                *window,
     *result |= META_MOVE_RESIZE_RESULT_MOVED;
   if (need_resize_client || need_resize_frame)
     *result |= META_MOVE_RESIZE_RESULT_RESIZED;
+  if (flags & META_MOVE_RESIZE_STATE_CHANGED)
+    *result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED;
 
   update_gtk_edge_constraints (window);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]