[mutter/wip/carlosg/frames-client: 33/39] x11: Add frame synchronization to window frames




commit 22b2cc1f5c01d17caf4ae59ccd97cf974f1981c4
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Sep 9 15:54:28 2022 +0200

    x11: Add frame synchronization to window frames
    
    There's two meanings of "frame" there! Since SSD frames are now
    rendered by an external client, and there are no actual mechanism
    that ensures the frame did already get painted when the client did
    respond to its NET_WM_FRAME_SYNC_REQUEST request, there may be
    artifacts when resizing windows.
    
    In order to get always the best visual result, we should actually
    synchronize rendering with both the client window and the window
    frame window.
    
    This commit adds these mechanisms, so a sync alarm update is
    expected on both windows until further resizes are allowed, this
    ensures window and frame stay in sync, even after moving rendering
    elsewhere.

 src/compositor/meta-window-actor-x11.c | 28 ++++++++++++++++++
 src/core/frame.c                       | 27 +++++++++++++++--
 src/core/frame.h                       |  6 ++++
 src/frames/meta-frame.c                |  2 +-
 src/x11/window-props.c                 |  7 ++++-
 src/x11/window-x11.c                   | 53 +++++++++++++++++++++++++++-------
 6 files changed, 108 insertions(+), 15 deletions(-)
---
diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c
index b34feec5da..f6e18dea72 100644
--- a/src/compositor/meta-window-actor-x11.c
+++ b/src/compositor/meta-window-actor-x11.c
@@ -134,6 +134,13 @@ send_frame_messages_timeout (gpointer data)
 
   sync_counter = meta_window_x11_get_sync_counter (window);
   meta_sync_counter_finish_incomplete (sync_counter);
+
+  if (window->frame)
+    {
+      sync_counter = meta_frame_get_sync_counter (window->frame);
+      meta_sync_counter_finish_incomplete (sync_counter);
+    }
+
   actor_x11->send_frame_messages_timer = 0;
 
   return G_SOURCE_REMOVE;
@@ -210,6 +217,13 @@ assign_frame_counter_to_frames (MetaWindowActorX11 *actor_x11)
   sync_counter = meta_window_x11_get_sync_counter (window);
   meta_sync_counter_assign_counter_to_frames (sync_counter,
                                               clutter_stage_get_frame_counter (stage));
+
+  if (window->frame)
+    {
+      sync_counter = meta_frame_get_sync_counter (window->frame);
+      meta_sync_counter_assign_counter_to_frames (sync_counter,
+                                                  clutter_stage_get_frame_counter (stage));
+    }
 }
 
 static void
@@ -227,6 +241,14 @@ meta_window_actor_x11_frame_complete (MetaWindowActor  *actor,
   meta_sync_counter_complete_frame (sync_counter,
                                     frame_info,
                                     presentation_time);
+
+  if (window->frame)
+    {
+      sync_counter = meta_frame_get_sync_counter (window->frame);
+      meta_sync_counter_complete_frame (sync_counter,
+                                        frame_info,
+                                        presentation_time);
+    }
 }
 
 static MetaSurfaceActor *
@@ -1209,6 +1231,12 @@ meta_window_actor_x11_after_paint (MetaWindowActor  *actor,
     {
       sync_counter = meta_window_x11_get_sync_counter (window);
       meta_sync_counter_send_frame_drawn (sync_counter);
+
+      if (window->frame)
+        {
+          sync_counter = meta_frame_get_sync_counter (window->frame);
+          meta_sync_counter_send_frame_drawn (sync_counter);
+        }
     }
 
   /* This is for Xwayland, and a no-op on plain Xorg */
diff --git a/src/core/frame.c b/src/core/frame.c
index f2fa741927..1be05a8ce4 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -30,6 +30,7 @@
 #include "core/keybindings-private.h"
 #include "meta/meta-x11-errors.h"
 #include "x11/meta-x11-display-private.h"
+#include "x11/window-props.h"
 
 #include <X11/Xatom.h>
 
@@ -69,7 +70,7 @@ meta_window_set_frame_xwindow (MetaWindow *window,
   frame = g_new0 (MetaFrame, 1);
 
   frame->window = window;
-  frame->xwindow = None;
+  frame->xwindow = xframe;
 
   frame->rect = window->rect;
   frame->child_x = 0;
@@ -79,6 +80,8 @@ meta_window_set_frame_xwindow (MetaWindow *window,
 
   frame->borders_cached = FALSE;
 
+  meta_sync_counter_init (&frame->sync_counter, window, frame->xwindow);
+
   window->frame = frame;
 
   meta_verbose ("Frame geometry %d,%d  %dx%d",
@@ -91,8 +94,6 @@ meta_window_set_frame_xwindow (MetaWindow *window,
                 frame->rect.x, frame->rect.y,
                 frame->rect.width, frame->rect.height);
 
-  frame->xwindow = xframe;
-
   meta_stack_tracker_record_add (window->display->stack_tracker,
                                  frame->xwindow,
                                  create_serial);
@@ -136,6 +137,10 @@ meta_window_set_frame_xwindow (MetaWindow *window,
   /* stick frame to the window */
   window->frame = frame;
 
+  meta_window_reload_property_from_xwindow (window, frame->xwindow,
+                                            x11_display->atom__NET_WM_SYNC_REQUEST_COUNTER,
+                                            TRUE);
+
   XMapWindow (x11_display->xdisplay, frame->xwindow);
 
   /* Move keybindings to frame instead of window */
@@ -219,6 +224,8 @@ meta_window_destroy_frame (MetaWindow *window)
   /* Move keybindings to window instead of frame */
   meta_window_grab_keys (window);
 
+  meta_sync_counter_clear (&frame->sync_counter);
+
   g_free (frame);
 
   /* Put our state back where it should be */
@@ -493,6 +500,14 @@ meta_frame_handle_xevent (MetaFrame *frame,
       meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
       return TRUE;
     }
+  else if (xevent->xany.type == PropertyNotify &&
+           xevent->xproperty.state == PropertyNewValue &&
+           xevent->xproperty.atom == x11_display->atom__NET_WM_SYNC_REQUEST_COUNTER)
+    {
+      meta_window_reload_property_from_xwindow (window, frame->xwindow,
+                                                xevent->xproperty.atom, FALSE);
+      return TRUE;
+    }
 
   return FALSE;
 }
@@ -560,3 +575,9 @@ meta_frame_type_to_string (MetaFrameType type)
 
   return "<unknown>";
 }
+
+MetaSyncCounter *
+meta_frame_get_sync_counter (MetaFrame *frame)
+{
+  return &frame->sync_counter;
+}
diff --git a/src/core/frame.h b/src/core/frame.h
index fb72d6388b..023e2f4e44 100644
--- a/src/core/frame.h
+++ b/src/core/frame.h
@@ -24,6 +24,8 @@
 
 #include "core/window-private.h"
 
+#include "x11/meta-sync-counter.h"
+
 struct _MetaFrame
 {
   /* window we frame */
@@ -39,6 +41,8 @@ struct _MetaFrame
 
   MetaFrameBorders cached_borders; /* valid if borders_cached is set */
 
+  MetaSyncCounter sync_counter;
+
   /* position of client, size of frame */
   int child_x;
   int child_y;
@@ -75,4 +79,6 @@ gboolean meta_frame_handle_xevent (MetaFrame *frame,
 GSubprocess * meta_frame_launch_client (MetaX11Display *x11_display,
                                         const char     *display_name);
 
+MetaSyncCounter * meta_frame_get_sync_counter (MetaFrame *frame);
+
 #endif
diff --git a/src/frames/meta-frame.c b/src/frames/meta-frame.c
index b137d4f710..2ac27c8edf 100644
--- a/src/frames/meta-frame.c
+++ b/src/frames/meta-frame.c
@@ -249,7 +249,7 @@ meta_frame_new (Window window)
 
   gtk_widget_realize (GTK_WIDGET (frame));
   surface = gtk_native_get_surface (GTK_NATIVE (frame));
-  gdk_x11_surface_set_frame_sync_enabled (surface, FALSE);
+  gdk_x11_surface_set_frame_sync_enabled (surface, TRUE);
 
   gtk_widget_measure (header,
                       GTK_ORIENTATION_VERTICAL, 1,
diff --git a/src/x11/window-props.c b/src/x11/window-props.c
index 1eb3c990a4..bf4d06711f 100644
--- a/src/x11/window-props.c
+++ b/src/x11/window-props.c
@@ -1054,7 +1054,12 @@ reload_update_counter (MetaWindow    *window,
     {
       MetaSyncCounter *sync_counter;
 
-      sync_counter = meta_window_x11_get_sync_counter (window);
+      if (value->source_xwindow == window->xwindow)
+        sync_counter = meta_window_x11_get_sync_counter (window);
+      else if (window->frame && value->source_xwindow == window->frame->xwindow)
+        sync_counter = meta_frame_get_sync_counter (window->frame);
+      else
+        g_assert_not_reached ();
 
       if (value->v.xcounter_list.n_counters == 0)
         {
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index 97fd0c39f5..abacae5b47 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -1459,9 +1459,6 @@ meta_window_x11_move_resize_internal (MetaWindow                *window,
   else
     configure_frame_first = size_dx + size_dy >= 0;
 
-  if (configure_frame_first && window->frame)
-    frame_shape_changed = meta_frame_sync_to_window (window->frame, need_resize_frame);
-
   values.border_width = 0;
   values.x = client_rect.x;
   values.y = client_rect.y;
@@ -1476,25 +1473,33 @@ meta_window_x11_move_resize_internal (MetaWindow                *window,
   if (need_resize_client)
     mask |= (CWWidth | CWHeight);
 
-  if (mask != 0)
+  meta_x11_error_trap_push (window->display->x11_display);
+
+  if (mask != 0 &&
+      window == window->display->grab_window &&
+      meta_grab_op_is_resizing (window->display->grab_op))
     {
-      meta_x11_error_trap_push (window->display->x11_display);
+      meta_sync_counter_send_request (&priv->sync_counter);
+      if (window->frame)
+        meta_sync_counter_send_request (meta_frame_get_sync_counter (window->frame));
+    }
 
-      if (window == window->display->grab_window &&
-          meta_grab_op_is_resizing (window->display->grab_op))
-        meta_sync_counter_send_request (&priv->sync_counter);
+  if (configure_frame_first && window->frame)
+    frame_shape_changed = meta_frame_sync_to_window (window->frame, need_resize_frame);
 
+  if (mask != 0)
+    {
       XConfigureWindow (window->display->x11_display->xdisplay,
                         window->xwindow,
                         mask,
                         &values);
-
-      meta_x11_error_trap_pop (window->display->x11_display);
     }
 
   if (!configure_frame_first && window->frame)
     frame_shape_changed = meta_frame_sync_to_window (window->frame, need_resize_frame);
 
+  meta_x11_error_trap_pop (window->display->x11_display);
+
   if (window->frame)
     window->buffer_rect = window->frame->rect;
   else
@@ -1880,6 +1885,10 @@ meta_window_x11_are_updates_frozen (MetaWindow *window)
   MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
   MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 
+  if (window->frame &&
+      meta_sync_counter_is_waiting (meta_frame_get_sync_counter (window->frame)))
+    return TRUE;
+
   return meta_sync_counter_is_waiting (&priv->sync_counter);
 }
 
@@ -3972,6 +3981,9 @@ meta_window_x11_create_sync_request_alarm (MetaWindow *window)
   MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
   MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 
+  if (window->frame)
+    meta_sync_counter_create_sync_alarm (meta_frame_get_sync_counter (window->frame));
+
   meta_sync_counter_create_sync_alarm (&priv->sync_counter);
 }
 
@@ -3981,6 +3993,9 @@ meta_window_x11_destroy_sync_request_alarm (MetaWindow *window)
   MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
   MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 
+  if (window->frame)
+    meta_sync_counter_destroy_sync_alarm (meta_frame_get_sync_counter (window->frame));
+
   meta_sync_counter_destroy_sync_alarm (&priv->sync_counter);
 }
 
@@ -4148,6 +4163,10 @@ meta_window_x11_has_active_sync_alarms (MetaWindow *window)
   MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
   MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 
+  if (window->frame &&
+      meta_sync_counter_has_sync_alarm (meta_frame_get_sync_counter (window->frame)))
+    return TRUE;
+
   return meta_sync_counter_has_sync_alarm (&priv->sync_counter);
 }
 
@@ -4157,12 +4176,26 @@ meta_window_x11_is_awaiting_sync_response (MetaWindow *window)
   MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
   MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 
+  if (window->frame &&
+      meta_sync_counter_is_waiting_response (meta_frame_get_sync_counter (window->frame)))
+    return TRUE;
+
   return meta_sync_counter_is_waiting_response (&priv->sync_counter);
 }
 
 void
 meta_window_x11_check_update_resize (MetaWindow *window)
 {
+  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
+  MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
+
+  if (window->frame &&
+      meta_sync_counter_is_waiting (meta_frame_get_sync_counter (window->frame)))
+    return;
+
+  if (meta_sync_counter_is_waiting (&priv->sync_counter))
+    return;
+
   meta_window_update_resize (window,
                              window->display->grab_last_edge_resistance_flags,
                              window->display->grab_latest_motion_x,


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