[mutter/wip/ssd-black-borders-fix: 21/22] window: ensure window titlebars are drawn in sync during resize



commit 7f4f5f5c4c4d52183a6b3113901c3fcfbdd9e824
Author: Ray Strode <rstrode redhat com>
Date:   Thu Mar 15 18:14:43 2018 -0400

    window: ensure window titlebars are drawn in sync during resize
    
    mutter synchronizes drawing and resizes with Xwayland applications using
    XSYNC counters, but it doesn't synchronize drawing and resizes with its
    own titlebar painting code.
    
    This commit makes mutter wait until the titlebar finishes drawing before
    it unfreezes the corresponding window actor.  This ensures the titlebar
    and client area don't get out of sync with each other.

 src/core/window-private.h |  6 ++++++
 src/core/window.c         | 12 ++++++++++++
 src/ui/frames.c           | 31 +++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)
---
diff --git a/src/core/window-private.h b/src/core/window-private.h
index afaa499e5..9964c8595 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -410,6 +410,9 @@ struct _MetaWindow
   /* if TRUE, the X server hasn't yet committed a new buffer following resize of the frame/client window */
   guint resize_pending : 1;
 
+  /* if TRUE, the window frame has a redraw queued */
+  guint frame_redraw_pending : 1;
+
   /* if non-NULL, the bounds of the window frame */
   cairo_region_t *frame_bounds;
 
@@ -788,6 +791,9 @@ void meta_window_set_resize_pending (MetaWindow *window,
                                      gboolean    is_resize_pending);
 gboolean meta_window_resize_is_pending (MetaWindow  *window);
 
+void meta_window_set_frame_redraw_pending (MetaWindow *window,
+                                           gboolean    is_frame_redraw_pending);
+
 void meta_window_grab_op_began (MetaWindow *window, MetaGrabOp op);
 void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op);
 
diff --git a/src/core/window.c b/src/core/window.c
index 34f48712f..eaab29d2e 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -3730,6 +3730,9 @@ meta_window_updates_are_frozen (MetaWindow *window)
   if (window->sync_request_serial < window->sync_request_wait_serial)
     return TRUE;
 
+  if (window->frame_redraw_pending)
+    return TRUE;
+
   return FALSE;
 }
 
@@ -6324,6 +6327,15 @@ meta_window_resize_is_pending (MetaWindow  *window)
   return window->resize_pending;
 }
 
+void
+meta_window_set_frame_redraw_pending (MetaWindow *window,
+                                      gboolean    is_frame_redraw_pending)
+{
+  window->frame_redraw_pending = is_frame_redraw_pending;
+
+  meta_compositor_sync_updates_frozen (window->display->compositor, window);
+}
+
 static void
 end_grab_op (MetaWindow *window,
              const ClutterEvent *event)
diff --git a/src/ui/frames.c b/src/ui/frames.c
index 129a9e59b..471bfa0c7 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -149,6 +149,7 @@ static void
 invalidate_whole_window (MetaUIFrame *frame)
 {
   gdk_window_invalidate_rect (frame->window, NULL, FALSE);
+  meta_window_set_frame_redraw_pending (frame->meta_window, TRUE);
 }
 
 static MetaStyleInfo *
@@ -484,6 +485,27 @@ meta_ui_frame_attach_style (MetaUIFrame *frame)
                                                                             variant));
 }
 
+static void
+after_paint (GdkFrameClock *frame_clock,
+             MetaUIFrame   *frame)
+{
+  MetaFrames *frames = frame->frames;
+  MetaWindow *window = frame->meta_window;
+
+  /* Make sure the damage is posted to the X server before
+   * we mark the frame redraw finished and unfreeze, so there's
+   * a wayland surface commit waiting for us at unfreeze time
+   */
+  if (meta_is_wayland_compositor ())
+    gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (frames)));
+
+  meta_window_set_frame_redraw_pending (window, FALSE);
+
+  g_signal_handlers_disconnect_by_func (G_OBJECT (gdk_window_get_frame_clock (frame->window)),
+                                        G_CALLBACK (after_paint),
+                                        frame);
+}
+
 MetaUIFrame *
 meta_frames_manage_window (MetaFrames *frames,
                            MetaWindow *meta_window,
@@ -531,6 +553,10 @@ meta_ui_frame_unmanage (MetaUIFrame *frame)
                                frame->xwindow,
                                META_CURSOR_DEFAULT);
 
+  g_signal_handlers_disconnect_by_func (G_OBJECT (gdk_window_get_frame_clock (frame->window)),
+                                        G_CALLBACK (after_paint),
+                                        frame);
+
   gdk_window_set_user_data (frame->window, NULL);
 
   g_hash_table_remove (frames->frames, &frame->xwindow);
@@ -1396,6 +1422,11 @@ meta_frames_draw (GtkWidget *widget,
   meta_ui_frame_paint (frame, cr);
   cairo_region_destroy (region);
 
+  g_signal_connect (G_OBJECT (gdk_window_get_frame_clock (frame->window)),
+                    "after-paint",
+                    G_CALLBACK (after_paint),
+                    frame);
+
   return TRUE;
 }
 


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