[gtk/wip/carlosg/for-master: 2/3] gdk/surface: Delay gdk_surface_request_motion() requests internally




commit 80d4a08e306e36486e45542af0cdc58f5ad21e45
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Dec 8 21:33:06 2020 +0100

    gdk/surface: Delay gdk_surface_request_motion() requests internally
    
    Those requests are received while dealing with the ::layout frame
    clock phase, this has the unintended side effect of making the
    frame clock "rewind" to handle ::flush-events again during this
    frame, which delays everything and practically halves the frame
    rate.
    
    We do intend to make the motion events dispatches on the next frame,
    so do this in an idle at a slightly lower priority than layout/draw,
    so the ::flush-events phase is actually requested for the next frame.
    
    Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3264

 gdk/gdksurface.c        | 28 ++++++++++++++++++++++------
 gdk/gdksurfaceprivate.h |  2 ++
 2 files changed, 24 insertions(+), 6 deletions(-)
---
diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c
index 012864479a..b6f739c5c0 100644
--- a/gdk/gdksurface.c
+++ b/gdk/gdksurface.c
@@ -681,6 +681,8 @@ gdk_surface_finalize (GObject *object)
 {
   GdkSurface *surface = GDK_SURFACE (object);
 
+  g_clear_handle_id (&surface->request_motion_id, g_source_remove);
+
   g_signal_handlers_disconnect_by_func (surface->display,
                                         seat_removed_cb, surface);
 
@@ -2408,6 +2410,19 @@ gdk_surface_flush_events (GdkFrameClock *clock,
   surface->frame_clock_events_paused = TRUE;
 }
 
+static gboolean
+request_motion_cb (void *data)
+{
+  GdkSurface *surface = GDK_SURFACE (data);
+  GdkFrameClock *clock = gdk_surface_get_frame_clock (surface);
+
+  if (clock)
+    gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
+  surface->request_motion_id = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
 static void
 gdk_surface_resume_events (GdkFrameClock *clock,
                            void          *data)
@@ -2419,6 +2434,13 @@ gdk_surface_resume_events (GdkFrameClock *clock,
       _gdk_display_unpause_events (surface->display);
       surface->frame_clock_events_paused = FALSE;
     }
+
+  if (surface->request_motion)
+    {
+      surface->request_motion_id =
+        g_idle_add_full (GDK_PRIORITY_REDRAW + 1,
+                         request_motion_cb, surface, NULL);
+    }
 }
 
 static void
@@ -2912,13 +2934,7 @@ gdk_surface_handle_event (GdkEvent *event)
 void
 gdk_surface_request_motion (GdkSurface *surface)
 {
-  GdkFrameClock *frame_clock;
-
   surface->request_motion = TRUE;
-
-  frame_clock = gdk_surface_get_frame_clock (surface);
-  if (frame_clock)
-    gdk_frame_clock_request_phase (frame_clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
 }
 
 /**
diff --git a/gdk/gdksurfaceprivate.h b/gdk/gdksurfaceprivate.h
index 27a3966fe7..2126371853 100644
--- a/gdk/gdksurfaceprivate.h
+++ b/gdk/gdksurfaceprivate.h
@@ -80,6 +80,8 @@ struct _GdkSurface
   guint shortcuts_inhibited : 1;
   guint request_motion : 1;
 
+  guint request_motion_id;
+
   struct {
     GdkGravity surface_anchor;
     GdkGravity rect_anchor;


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