[mutter] wayland-surface: Don't do pending move/resizes on all commits



commit 57037a45b8bc6aa5137e256456a7b1a1a554fd8e
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sun Jul 27 17:23:17 2014 +0200

    wayland-surface: Don't do pending move/resizes on all commits
    
    We assume in meta_window_wayland_move_resize that the next commit that
    changes the geometry will always be for our next pending operation, so
    if we have a move pending on a resize, the next commit will trigger the
    move. This is, of course, fundamentally wrong.
    
    We broke this assumption even more now that we don't fizzle out calls to
    meta_window_move_resize_internal and now call it on every commit, which
    means that a simple damage and then commit would complete a pending
    move.
    
    This was even broken by apps like weston-terminal, which, when clicking
    on the maximize button, first redraws the terminal with the maximize
    button state back on hover on press, and would only redraw when it got
    the configure event with the coordinates.
    
    To track the correct commit to apply the move for, we implement the
    ack_configure request and ignore all move/resizes that happen before
    that.
    
    Right now, we actually fizzle out the entire move/resize if there's a
    future pending configure we're waiting on.

 src/wayland/meta-wayland-surface.c |   23 ++++++++++++++++-------
 src/wayland/meta-wayland-surface.h |   12 ++++++++++--
 src/wayland/meta-wayland-types.h   |    2 ++
 src/wayland/window-wayland.c       |   32 ++++++++++++++++++++++++++------
 src/wayland/window-wayland.h       |    9 +++++----
 5 files changed, 59 insertions(+), 19 deletions(-)
---
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 4b9e5b2..57aed65 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -243,7 +243,10 @@ toplevel_surface_commit (MetaWaylandSurface      *surface,
           return;
         }
 
-      meta_window_wayland_move_resize (window, geom, pending->dx, pending->dy);
+      meta_window_wayland_move_resize (window,
+                                       &surface->acked_configure_serial,
+                                       geom, pending->dx, pending->dy);
+      surface->acked_configure_serial.set = FALSE;
     }
 }
 
@@ -906,11 +909,10 @@ xdg_surface_ack_configure (struct wl_client *client,
                            struct wl_resource *resource,
                            uint32_t serial)
 {
-  /* Do nothing for now. In the future, we'd imagine that
-   * we'd ignore attaches when we have a state pending that
-   * we haven't had the client ACK'd, to prevent a race
-   * condition when we have an in-flight attach when the
-   * client gets the new state. */
+  MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
+
+  surface->acked_configure_serial.set = TRUE;
+  surface->acked_configure_serial.value = serial;
 }
 
 static void
@@ -1811,7 +1813,8 @@ fill_states (struct wl_array *states, MetaWindow *window)
 void
 meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
                                        int                 new_width,
-                                       int                 new_height)
+                                       int                 new_height,
+                                       MetaWaylandSerial  *sent_serial)
 {
   if (surface->xdg_surface.resource)
     {
@@ -1832,6 +1835,12 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
       xdg_surface_send_configure (surface->xdg_surface.resource, new_width, new_height, &states, serial);
 
       wl_array_release (&states);
+
+      if (sent_serial)
+        {
+          sent_serial->set = TRUE;
+          sent_serial->value = serial;
+        }
     }
   else if (surface->wl_shell_surface.resource)
     wl_shell_surface_send_configure (surface->wl_shell_surface.resource,
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 582d07d..98a344c 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -31,6 +31,11 @@
 #include "meta-wayland-types.h"
 #include "meta-surface-actor.h"
 
+struct _MetaWaylandSerial {
+  gboolean set;
+  uint32_t value;
+};
+
 struct _MetaWaylandBuffer
 {
   struct wl_resource *resource;
@@ -113,6 +118,8 @@ struct _MetaWaylandSurface
 
   /* All the pending state that wl_surface.commit will apply. */
   MetaWaylandPendingState pending;
+
+  MetaWaylandSerial acked_configure_serial;
 };
 
 void                meta_wayland_shell_init     (MetaWaylandCompositor *compositor);
@@ -126,8 +133,9 @@ void                meta_wayland_surface_set_window (MetaWaylandSurface *surface
                                                      MetaWindow         *window);
 
 void                meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
-                                                          int                 width,
-                                                          int                 height);
+                                                           int                 width,
+                                                           int                 height,
+                                                           MetaWaylandSerial  *sent_serial);
 
 void                meta_wayland_surface_ping (MetaWaylandSurface *surface,
                                                guint32             serial);
diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h
index 9d85d5b..7217431 100644
--- a/src/wayland/meta-wayland-types.h
+++ b/src/wayland/meta-wayland-types.h
@@ -36,4 +36,6 @@ typedef struct _MetaWaylandBufferReference MetaWaylandBufferReference;
 
 typedef struct _MetaWaylandSurface MetaWaylandSurface;
 
+typedef struct _MetaWaylandSerial MetaWaylandSerial;
+
 #endif
diff --git a/src/wayland/window-wayland.c b/src/wayland/window-wayland.c
index 9d10a67..31df759 100644
--- a/src/wayland/window-wayland.c
+++ b/src/wayland/window-wayland.c
@@ -36,6 +36,7 @@ struct _MetaWindowWayland
 {
   MetaWindow parent;
 
+  MetaWaylandSerial pending_configure_serial;
   gboolean has_pending_move;
   int pending_move_x;
   int pending_move_y;
@@ -126,7 +127,8 @@ surface_state_changed (MetaWindow *window)
 
   meta_wayland_surface_configure_notify (window->surface,
                                          wl_window->last_sent_width,
-                                         wl_window->last_sent_height);
+                                         wl_window->last_sent_height,
+                                         &wl_window->pending_configure_serial);
 }
 
 static void
@@ -214,7 +216,8 @@ meta_window_wayland_move_resize_internal (MetaWindow                *window,
 
       meta_wayland_surface_configure_notify (window->surface,
                                              constrained_rect.width,
-                                             constrained_rect.height);
+                                             constrained_rect.height,
+                                             &wl_window->pending_configure_serial);
     }
   else
     {
@@ -349,16 +352,33 @@ meta_window_wayland_new (MetaDisplay        *display,
  * Complete a resize operation from a wayland client.
  */
 void
-meta_window_wayland_move_resize (MetaWindow    *window,
-                                 MetaRectangle  new_geom,
-                                 int            dx,
-                                 int            dy)
+meta_window_wayland_move_resize (MetaWindow        *window,
+                                 MetaWaylandSerial *acked_configure_serial,
+                                 MetaRectangle      new_geom,
+                                 int                dx,
+                                 int                dy)
 {
   MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
   int gravity;
   MetaRectangle rect;
   MetaMoveResizeFlags flags;
 
+  if (wl_window->pending_configure_serial.set)
+    {
+      /* If we're waiting for a configure and this isn't an ACK for
+       * any configure, then fizzle it out. */
+      if (!acked_configure_serial->set)
+        return;
+
+      /* If we're waiting for a configure and this isn't an ACK for
+       * the configure we're waiting for, then fizzle it out. */
+      if (acked_configure_serial->value != wl_window->pending_configure_serial.value)
+        return;
+
+      /* OK, this request is going to ACK the pending configure. */
+      wl_window->pending_configure_serial.set = FALSE;
+    }
+
   /* XXX: Find a better place to store the window geometry offsets. */
   window->custom_frame_extents.left = new_geom.x;
   window->custom_frame_extents.top = new_geom.y;
diff --git a/src/wayland/window-wayland.h b/src/wayland/window-wayland.h
index 3c32685..eb2e8de 100644
--- a/src/wayland/window-wayland.h
+++ b/src/wayland/window-wayland.h
@@ -45,9 +45,10 @@ typedef struct _MetaWindowWaylandClass MetaWindowWaylandClass;
 MetaWindow * meta_window_wayland_new       (MetaDisplay        *display,
                                             MetaWaylandSurface *surface);
 
-void meta_window_wayland_move_resize (MetaWindow    *window,
-                                      MetaRectangle  new_geom,
-                                      int            dx,
-                                      int            dy);
+void meta_window_wayland_move_resize (MetaWindow        *window,
+                                      MetaWaylandSerial *acked_configure_serial,
+                                      MetaRectangle      new_geom,
+                                      int                dx,
+                                      int                dy);
 
 #endif


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