[mutter] window/wayland: Always include a size when sending a configuration



commit 251bb45ec0fdfd2f7f4ba4c89bdd74be66141035
Author: Sebastian Keller <skeller gnome org>
Date:   Sun Jan 16 01:44:37 2022 +0100

    window/wayland: Always include a size when sending a configuration
    
    Prior to 67033b0a mutter was accidentally including sizes for
    configurations that were just focus state changes. This was not leading
    to any known problems on the client side, but it was causing issues in
    mutter itself when detecting whether a resize originated from the client
    or the server.
    
    Not including sizes in focus change configurations anymore however
    revealed a bug in gtk. It was storing the window size when in a fixed
    size mode (tiled/maximized/fullscreen), but not on any other server side
    resizes. It was then restoring this stored size whenever there was a new
    configuration without a size while in floating mode, i.e. the focus
    change configurations generated by mutter after 67033b0a.
    
    This change now addresses the issue 67033b0a was fixing in a way that
    restores the previous behavior of always including the size whenever
    sending a configuration.
    
    Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2091
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2238>

 src/wayland/meta-wayland-window-configuration.c | 47 ++++++----------
 src/wayland/meta-wayland-window-configuration.h | 12 ++--
 src/wayland/meta-window-wayland.c               | 74 ++++++++++++++++++++-----
 src/wayland/meta-window-wayland.h               |  4 ++
 4 files changed, 86 insertions(+), 51 deletions(-)
---
diff --git a/src/wayland/meta-wayland-window-configuration.c b/src/wayland/meta-wayland-window-configuration.c
index 702c95a620..fb8657017b 100644
--- a/src/wayland/meta-wayland-window-configuration.c
+++ b/src/wayland/meta-wayland-window-configuration.c
@@ -21,25 +21,10 @@
 #include "config.h"
 
 #include "wayland/meta-wayland-window-configuration.h"
+#include "wayland/meta-window-wayland.h"
 
 static uint32_t global_serial_counter = 0;
 
-static gboolean
-is_window_size_fixed (MetaWindow *window)
-{
-  if (meta_window_is_fullscreen (window))
-    return TRUE;
-
-  if (meta_window_get_maximized (window) &
-      (META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL))
-    return TRUE;
-
-  if (meta_window_get_tile_mode (window) != META_TILE_NONE)
-    return TRUE;
-
-  return FALSE;
-}
-
 MetaWaylandWindowConfiguration *
 meta_wayland_window_configuration_new (MetaWindow          *window,
                                        MetaRectangle        rect,
@@ -49,6 +34,7 @@ meta_wayland_window_configuration_new (MetaWindow          *window,
                                        MetaMoveResizeFlags  flags,
                                        MetaGravity          gravity)
 {
+  MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
   MetaWaylandWindowConfiguration *configuration;
 
   configuration = g_new0 (MetaWaylandWindowConfiguration, 1);
@@ -72,26 +58,24 @@ meta_wayland_window_configuration_new (MetaWindow          *window,
       configuration->y = rect.y;
     }
 
-  if (flags & META_MOVE_RESIZE_RESIZE_ACTION ||
-      is_window_size_fixed (window) ||
-      window->rect.width != rect.width ||
-      window->rect.height != rect.height)
-    {
-      configuration->has_size = TRUE;
-      configuration->width = rect.width;
-      configuration->height = rect.height;
-    }
+  configuration->has_size = (rect.width != 0 && rect.height != 0);
+  configuration->is_resizing = flags & META_MOVE_RESIZE_RESIZE_ACTION ||
+    meta_window_wayland_is_resize (wl_window, rect.width, rect.height);
+  configuration->width = rect.width;
+  configuration->height = rect.height;
 
   return configuration;
 }
 
 MetaWaylandWindowConfiguration *
-meta_wayland_window_configuration_new_relative (int rel_x,
-                                                int rel_y,
-                                                int width,
-                                                int height,
-                                                int scale)
+meta_wayland_window_configuration_new_relative (MetaWindow *window,
+                                                int         rel_x,
+                                                int         rel_y,
+                                                int         width,
+                                                int         height,
+                                                int         scale)
 {
+  MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
   MetaWaylandWindowConfiguration *configuration;
 
   configuration = g_new0 (MetaWaylandWindowConfiguration, 1);
@@ -102,7 +86,8 @@ meta_wayland_window_configuration_new_relative (int rel_x,
     .rel_x = rel_x,
     .rel_y = rel_y,
 
-    .has_size = TRUE,
+    .has_size = (width != 0 && height != 0),
+    .is_resizing = meta_window_wayland_is_resize (wl_window, width, height),
     .width = width,
     .height = height,
 
diff --git a/src/wayland/meta-wayland-window-configuration.h b/src/wayland/meta-wayland-window-configuration.h
index c4c0f2e55e..a3d184bd83 100644
--- a/src/wayland/meta-wayland-window-configuration.h
+++ b/src/wayland/meta-wayland-window-configuration.h
@@ -40,6 +40,7 @@ struct _MetaWaylandWindowConfiguration
   int rel_y;
 
   gboolean has_size;
+  gboolean is_resizing;
   int width;
   int height;
 
@@ -59,11 +60,12 @@ MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new (MetaWind
                                                                         MetaMoveResizeFlags  flags,
                                                                         MetaGravity          gravity);
 
-MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_relative (int rel_x,
-                                                                                 int rel_y,
-                                                                                 int width,
-                                                                                 int height,
-                                                                                 int scale);
+MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_relative (MetaWindow *window,
+                                                                                 int         rel_x,
+                                                                                 int         rel_y,
+                                                                                 int         width,
+                                                                                 int         height,
+                                                                                 int         scale);
 
 MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_empty (int bounds_width,
                                                                               int bounds_height);
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index d0fbde8438..2b389bfbf8 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -321,7 +321,8 @@ meta_window_wayland_move_resize_internal (MetaWindow                *window,
                     MetaWaylandWindowConfiguration *configuration;
 
                     configuration =
-                      meta_wayland_window_configuration_new_relative (rel_x,
+                      meta_wayland_window_configuration_new_relative (window,
+                                                                      rel_x,
                                                                       rel_y,
                                                                       configured_rect.width,
                                                                       configured_rect.height,
@@ -824,9 +825,39 @@ meta_window_wayland_peek_configuration (MetaWindowWayland *wl_window,
 
 static MetaWaylandWindowConfiguration *
 acquire_acked_configuration (MetaWindowWayland       *wl_window,
-                             MetaWaylandSurfaceState *pending)
+                             MetaWaylandSurfaceState *pending,
+                             gboolean                *is_client_resize)
 {
   GList *l;
+  gboolean has_pending_resize = FALSE;
+
+  /* There can be 3 different cases where a resizing configurations can be found
+   * in the list of pending configurations. We consider resizes in any of these
+   * cases to be requested by the server:
+   * 1. Acked serial is resizing. This is obviously a server requested resize.
+   * 2. Acked serial is larger than the serial of a pending resizing
+   *    configuration. This means there was a server requested resize in the
+   *    past that has not been acked yet. This covers cases such as a resizing
+   *    configure followed by a status change configure before the client had
+   *    time to ack the former.
+   * 3. Acked serial is smaller than the serial of a pending resizing
+   *    configuration. This means there will be a server requested resize in the
+   *    future. In this case we want to avoid marking this as a client resize,
+   *    because it will change in the future again anyway and considering it
+   *    a client resize could trigger another move_resize on the server due to
+   *    enforcing constraints based on an already outdated size. */
+  for (l = wl_window->pending_configurations; l; l = l->next)
+    {
+      MetaWaylandWindowConfiguration *configuration = l->data;
+
+      if (configuration->is_resizing)
+        {
+          has_pending_resize = TRUE;
+          break;
+        }
+    }
+
+  *is_client_resize = !has_pending_resize;
 
   if (!pending->has_acked_configure_serial)
     return NULL;
@@ -869,20 +900,30 @@ acquire_acked_configuration (MetaWindowWayland       *wl_window,
   return NULL;
 }
 
-static gboolean
-has_pending_resize (MetaWindowWayland *wl_window)
+gboolean
+meta_window_wayland_is_resize (MetaWindowWayland *wl_window,
+                               int                width,
+                               int                height)
 {
-  GList *l;
+  int old_width;
+  int old_height;
 
-  for (l = wl_window->pending_configurations; l; l = l->next)
+  if (wl_window->pending_configurations)
     {
-      MetaWaylandWindowConfiguration *configuration = l->data;
+      old_width = wl_window->last_sent_rect.width;
+      old_height = wl_window->last_sent_rect.height;
+    }
+  else
+    {
+      MetaWindow *window = META_WINDOW (wl_window);
 
-      if (configuration->has_size)
-        return TRUE;
+      old_width = window->rect.width;
+      old_height = window->rect.height;
     }
 
-  return FALSE;
+  return !wl_window->has_last_sent_configuration ||
+         old_width != width ||
+         old_height != height;
 }
 
 int
@@ -945,6 +986,7 @@ meta_window_wayland_finish_move_resize (MetaWindow              *window,
   MetaMoveResizeFlags flags;
   MetaWaylandWindowConfiguration *acked_configuration;
   gboolean is_window_being_resized;
+  gboolean is_client_resize;
 
   /* 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
@@ -968,10 +1010,8 @@ meta_window_wayland_finish_move_resize (MetaWindow              *window,
 
   flags = META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE;
 
-  if (!has_pending_resize (wl_window))
-    flags |= META_MOVE_RESIZE_WAYLAND_CLIENT_RESIZE;
-
-  acked_configuration = acquire_acked_configuration (wl_window, pending);
+  acked_configuration = acquire_acked_configuration (wl_window, pending,
+                                                     &is_client_resize);
 
   /* x/y are ignored when we're doing interactive resizing */
   is_window_being_resized = (meta_grab_op_is_resizing (display->grab_op) &&
@@ -1021,7 +1061,11 @@ meta_window_wayland_finish_move_resize (MetaWindow              *window,
     }
 
   if (rect.width != window->rect.width || rect.height != window->rect.height)
-    flags |= META_MOVE_RESIZE_RESIZE_ACTION;
+    {
+      flags |= META_MOVE_RESIZE_RESIZE_ACTION;
+      if (is_client_resize)
+        flags |= META_MOVE_RESIZE_WAYLAND_CLIENT_RESIZE;
+    }
 
   if (window->display->grab_window == window)
     gravity = meta_resize_gravity_from_grab_op (window->display->grab_op);
diff --git a/src/wayland/meta-window-wayland.h b/src/wayland/meta-window-wayland.h
index db152daaa7..154e9a6f21 100644
--- a/src/wayland/meta-window-wayland.h
+++ b/src/wayland/meta-window-wayland.h
@@ -77,4 +77,8 @@ void meta_window_wayland_get_max_size (MetaWindow *window,
                                        int        *width,
                                        int        *height);
 
+gboolean meta_window_wayland_is_resize (MetaWindowWayland *wl_window,
+                                        int                width,
+                                        int                height);
+
 #endif


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