[mutter] window: Throttle resize-grab updates to stage updates



commit 11a50fffa29e601fe654b8123a80c8982130f229
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Wed Oct 5 13:55:59 2022 +0200

    window: Throttle resize-grab updates to stage updates
    
    With high frequency mouse devices, we would send very many configure
    events per each update cycle, which had the end result that some clients
    constantly re-allocating and redrawing their buffers far too often, if
    they did this in direct response to xdg_toplevel configure events.
    
    Lets throttle the interactive resize updates to stage updates, to avoid
    having these clients doing the excessive buffer reallocation.
    
    This also removes some old legacy X11 client resize throttling, that
    throttled a bit arbitrarily on 25 resizes a second; it is probably
    enough to throttle on stage updates for these clients.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2652>

 src/core/display-private.h |   6 +-
 src/core/display.c         |  22 ++++++--
 src/core/window-private.h  |   8 +--
 src/core/window.c          | 134 +++++++++++++++------------------------------
 src/x11/window-x11.c       |   6 +-
 5 files changed, 71 insertions(+), 105 deletions(-)
---
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 145509e913..5757444760 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -183,11 +183,9 @@ struct _MetaDisplay
   MetaRectangle grab_initial_window_pos;
   int         grab_initial_x, grab_initial_y;  /* These are only relevant for */
   gboolean    grab_threshold_movement_reached; /* raise_on_click == FALSE.    */
-  int64_t     grab_last_moveresize_time;
   MetaEdgeResistanceData *grab_edge_resistance_data;
   unsigned int grab_last_edge_resistance_flags;
-
-  int        grab_resize_timeout_id;
+  unsigned int grab_move_resize_later_id;
 
   MetaKeyBindingManager key_binding_manager;
 
@@ -342,6 +340,8 @@ gboolean meta_grab_op_is_resizing (MetaGrabOp op);
 gboolean meta_grab_op_is_mouse    (MetaGrabOp op);
 gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
 
+void meta_display_clear_grab_move_resize_later (MetaDisplay *display);
+
 void meta_display_queue_autoraise_callback  (MetaDisplay *display,
                                              MetaWindow  *window);
 void meta_display_remove_autoraise_callback (MetaDisplay *display);
diff --git a/src/core/display.c b/src/core/display.c
index f10334665c..ce1335b843 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -878,7 +878,6 @@ meta_display_new (MetaContext  *context,
 
   display->current_time = META_CURRENT_TIME;
 
-  display->grab_resize_timeout_id = 0;
   display->grab_have_keyboard = FALSE;
 
   display->grab_op = META_GRAB_OP_NONE;
@@ -1849,6 +1848,21 @@ get_event_route_from_grab_op (MetaGrabOp op)
     }
 }
 
+void
+meta_display_clear_grab_move_resize_later (MetaDisplay *display)
+{
+  if (display->grab_move_resize_later_id)
+    {
+      MetaCompositor *compositor;
+      MetaLaters *laters;
+
+      compositor = meta_display_get_compositor (display);
+      laters = meta_compositor_get_laters (compositor);
+      meta_laters_remove (laters, display->grab_move_resize_later_id);
+      display->grab_move_resize_later_id = 0;
+    }
+}
+
 gboolean
 meta_display_begin_grab_op (MetaDisplay *display,
                             MetaWindow  *window,
@@ -1955,13 +1969,12 @@ meta_display_begin_grab_op (MetaDisplay *display,
   display->grab_anchor_root_y = root_y;
   display->grab_latest_motion_x = root_x;
   display->grab_latest_motion_y = root_y;
-  display->grab_last_moveresize_time = 0;
   display->grab_last_edge_resistance_flags = META_EDGE_RESISTANCE_DEFAULT;
   display->grab_frame_action = frame_action;
 
   meta_display_update_cursor (display);
 
-  g_clear_handle_id (&display->grab_resize_timeout_id, g_source_remove);
+  meta_display_clear_grab_move_resize_later (display);
 
   meta_topic (META_DEBUG_WINDOW_OPS,
               "Grab op %u on window %s successful",
@@ -2046,13 +2059,12 @@ meta_display_end_grab_op (MetaDisplay *display,
   display->grab_anchor_root_y = 0;
   display->grab_latest_motion_x = 0;
   display->grab_latest_motion_y = 0;
-  display->grab_last_moveresize_time = 0;
   display->grab_last_edge_resistance_flags = META_EDGE_RESISTANCE_DEFAULT;
   display->grab_frame_action = FALSE;
 
   meta_display_update_cursor (display);
 
-  g_clear_handle_id (&display->grab_resize_timeout_id, g_source_remove);
+  meta_display_clear_grab_move_resize_later (display);
 
   if (meta_is_wayland_compositor ())
     meta_display_sync_wayland_input_focus (display);
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 473e162565..568d3d1d8b 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -865,10 +865,10 @@ cairo_surface_t * meta_window_get_mini_icon (MetaWindow *window);
 void meta_window_set_urgent (MetaWindow *window,
                              gboolean    urgent);
 
-void meta_window_update_resize (MetaWindow *window,
-                                MetaEdgeResistanceFlags flags,
-                                int x, int y,
-                                gboolean force);
+void meta_window_update_resize (MetaWindow              *window,
+                                MetaEdgeResistanceFlags  flags,
+                                int                      x,
+                                int                      y);
 
 void meta_window_move_resize_internal (MetaWindow          *window,
                                        MetaMoveResizeFlags  flags,
diff --git a/src/core/window.c b/src/core/window.c
index 660bf010ea..9666617b4c 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -136,11 +136,6 @@ static void     update_move           (MetaWindow              *window,
                                        MetaEdgeResistanceFlags  flags,
                                        int                      x,
                                        int                      y);
-static void     update_resize         (MetaWindow              *window,
-                                       MetaEdgeResistanceFlags  flags,
-                                       int                      x,
-                                       int                      y,
-                                       gboolean                 force);
 static gboolean should_be_on_all_workspaces (MetaWindow *window);
 
 static void meta_window_flush_calc_showing   (MetaWindow *window);
@@ -5765,44 +5760,6 @@ meta_window_titlebar_is_onscreen (MetaWindow *window)
   return is_onscreen;
 }
 
-static gboolean
-check_moveresize_frequency (MetaWindow *window,
-                           gdouble    *remaining)
-{
-  int64_t current_time;
-  const double max_resizes_per_second = 25.0;
-  const double ms_between_resizes = 1000.0 / max_resizes_per_second;
-  double elapsed;
-
-  current_time = g_get_real_time ();
-
-  /* If we are throttling via _NET_WM_SYNC_REQUEST, we don't need
-   * an artificial timeout-based throttled */
-  if (!window->disable_sync &&
-      window->sync_request_alarm != None)
-    return TRUE;
-
-  elapsed = (current_time - window->display->grab_last_moveresize_time) / 1000;
-
-  if (elapsed >= 0.0 && elapsed < ms_between_resizes)
-    {
-      meta_topic (META_DEBUG_RESIZING,
-                  "Delaying move/resize as only %g of %g ms elapsed",
-                  elapsed, ms_between_resizes);
-
-      if (remaining)
-        *remaining = (ms_between_resizes - elapsed);
-
-      return FALSE;
-    }
-
-  meta_topic (META_DEBUG_RESIZING,
-              " Checked moveresize freq, allowing move/resize now (%g of %g seconds elapsed)",
-              elapsed / 1000.0, 1.0 / max_resizes_per_second);
-
-  return TRUE;
-}
-
 static void
 update_move_maybe_tile (MetaWindow *window,
                         int         shake_threshold,
@@ -6042,35 +5999,22 @@ update_move (MetaWindow              *window,
   meta_window_move_frame (window, TRUE, new_x, new_y);
 }
 
-static gboolean
-update_resize_timeout (gpointer data)
-{
-  MetaWindow *window = data;
-
-  update_resize (window,
-                 window->display->grab_last_edge_resistance_flags,
-                 window->display->grab_latest_motion_x,
-                 window->display->grab_latest_motion_y,
-                 TRUE);
-  return FALSE;
-}
-
 static void
 update_resize (MetaWindow              *window,
                MetaEdgeResistanceFlags  flags,
                int                      x,
-               int                      y,
-               gboolean                 force)
+               int                      y)
 {
   int dx, dy;
   MetaGravity gravity;
   MetaRectangle new_rect;
   MetaRectangle old_rect;
-  double remaining = 0;
 
   window->display->grab_latest_motion_x = x;
   window->display->grab_latest_motion_y = y;
 
+  meta_display_clear_grab_move_resize_later (window->display);
+
   dx = x - window->display->grab_anchor_root_x;
   dy = y - window->display->grab_anchor_root_y;
 
@@ -6132,27 +6076,6 @@ update_resize (MetaWindow              *window,
   if (window->sync_request_timeout_id != 0)
     return;
 
-  if (!check_moveresize_frequency (window, &remaining) && !force)
-    {
-      /* we are ignoring an event here, so we schedule a
-       * compensation event when we would otherwise not ignore
-       * an event. Otherwise we can become stuck if the user never
-       * generates another event.
-       */
-      if (!window->display->grab_resize_timeout_id)
-       {
-         window->display->grab_resize_timeout_id =
-           g_timeout_add ((int)remaining, update_resize_timeout, window);
-         g_source_set_name_by_id (window->display->grab_resize_timeout_id,
-                                   "[mutter] update_resize_timeout");
-       }
-
-      return;
-    }
-
-  /* Remove any scheduled compensation events */
-  g_clear_handle_id (&window->display->grab_resize_timeout_id, g_source_remove);
-
   meta_window_get_frame_rect (window, &old_rect);
 
   /* One sided resizing ought to actually be one-sided, despite the fact that
@@ -6180,11 +6103,45 @@ update_resize (MetaWindow              *window,
   meta_window_resize_frame_with_gravity (window, TRUE,
                                          new_rect.width, new_rect.height,
                                          gravity);
+}
+
+static gboolean
+update_resize_cb (gpointer user_data)
+{
+  MetaWindow *window = user_data;
+
+  window->display->grab_move_resize_later_id = 0;
+
+  update_resize (window,
+                 window->display->grab_last_edge_resistance_flags,
+                 window->display->grab_latest_motion_x,
+                 window->display->grab_latest_motion_y);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+queue_update_resize (MetaWindow              *window,
+                     MetaEdgeResistanceFlags  flags,
+                     int                      x,
+                     int                      y)
+{
+  MetaCompositor *compositor;
+  MetaLaters *laters;
+
+  window->display->grab_latest_motion_x = x;
+  window->display->grab_latest_motion_y = y;
+
+  if (window->display->grab_move_resize_later_id)
+    return;
 
-  /* Store the latest resize time, if we actually resized. */
-  if (window->rect.width != old_rect.width ||
-      window->rect.height != old_rect.height)
-    window->display->grab_last_moveresize_time = g_get_real_time ();
+  compositor = meta_display_get_compositor (window->display);
+  laters = meta_compositor_get_laters (compositor);
+  window->display->grab_move_resize_later_id =
+    meta_laters_add (laters,
+                     META_LATER_BEFORE_REDRAW,
+                     update_resize_cb,
+                     window, NULL);
 }
 
 static void
@@ -6208,10 +6165,9 @@ maybe_maximize_tiled_window (MetaWindow *window)
 void
 meta_window_update_resize (MetaWindow *window,
                            MetaEdgeResistanceFlags flags,
-                           int x, int y,
-                           gboolean force)
+                           int x, int y)
 {
-  update_resize (window, flags, x, y, force);
+  update_resize (window, flags, x, y);
 }
 
 static void
@@ -6255,7 +6211,7 @@ end_grab_op (MetaWindow *window,
           if (window->tile_match != NULL)
             flags |= (META_EDGE_RESISTANCE_SNAP | META_EDGE_RESISTANCE_WINDOWS);
 
-          update_resize (window, flags, x, y, TRUE);
+          update_resize (window, flags, x, y);
           maybe_maximize_tiled_window (window);
         }
     }
@@ -6339,7 +6295,7 @@ meta_window_handle_mouse_grab_op_event  (MetaWindow         *window,
           if (window->tile_match != NULL)
             flags |= (META_EDGE_RESISTANCE_SNAP | META_EDGE_RESISTANCE_WINDOWS);
 
-          update_resize (window, flags, x, y, FALSE);
+          queue_update_resize (window, flags, x, y);
         }
       return TRUE;
 
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index 5e11472033..7f152ff42f 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -1235,8 +1235,7 @@ sync_request_timeout (gpointer data)
       meta_window_update_resize (window,
                                  window->display->grab_last_edge_resistance_flags,
                                  window->display->grab_latest_motion_x,
-                                 window->display->grab_latest_motion_y,
-                                 TRUE);
+                                 window->display->grab_latest_motion_y);
     }
 
   return FALSE;
@@ -4160,8 +4159,7 @@ meta_window_x11_update_sync_request_counter (MetaWindow *window,
           meta_window_update_resize (window,
                                      window->display->grab_last_edge_resistance_flags,
                                      window->display->grab_latest_motion_x,
-                                     window->display->grab_latest_motion_y,
-                                     TRUE);
+                                     window->display->grab_latest_motion_y);
         }
     }
 


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