[mutter] window/x11: Add `freeze_commits()/thaw_commits()`



commit 845157c11138ed189221f5c8164fb17945d1d493
Author: Olivier Fourdan <ofourdan redhat com>
Date:   Tue Nov 19 14:08:45 2019 +0100

    window/x11: Add `freeze_commits()/thaw_commits()`
    
    Xwayland may post damages for an X11 window as soon as the frame
    callback is triggered, while the X11 window manager/compositor has not
    yet finished updating the windows.
    
    If Xwayland becomes compliant enough to not permit updates after the
    buffer has been committed (see [1]), then the partial redraw of the X11
    window at the time it was posted will show on screen.
    
    To avoid that issue, the X11 window manager can use the X11 property
    `_XWAYLAND_ALLOW_COMMITS` to control when Xwayland should be allowed to
    post the pending damages.
    
    Add `freeze_commits()` and `thaw_commits()` methods to `MetaWindowX11`
    which are a no-op on plain X11, but sets `_XWAYLAND_ALLOW_COMMITS` on
    the toplevel X11 windows running on Xwayland.
    
    [1] https://gitlab.freedesktop.org/xorg/xserver/merge_requests/316
    See-also: https://gitlab.gnome.org/GNOME/mutter/merge_requests/855
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/942

 src/wayland/meta-window-xwayland.c | 64 ++++++++++++++++++++++++++++++++++++++
 src/x11/atomnames.h                |  1 +
 src/x11/window-x11-private.h       |  3 ++
 src/x11/window-x11.c               | 27 ++++++++++++++++
 src/x11/window-x11.h               |  3 ++
 5 files changed, 98 insertions(+)
---
diff --git a/src/wayland/meta-window-xwayland.c b/src/wayland/meta-window-xwayland.c
index 9967f439a..5b1c4198e 100644
--- a/src/wayland/meta-window-xwayland.c
+++ b/src/wayland/meta-window-xwayland.c
@@ -18,6 +18,8 @@
 
 #include "config.h"
 
+#include "core/frame.h"
+#include "meta/meta-x11-errors.h"
 #include "x11/window-x11.h"
 #include "x11/window-x11-private.h"
 #include "x11/xprops.h"
@@ -40,6 +42,7 @@ struct _MetaWindowXwayland
   MetaWindowX11 parent;
 
   gboolean xwayland_may_grab_keyboard;
+  int freeze_count;
 };
 
 struct _MetaWindowXwaylandClass
@@ -159,6 +162,63 @@ meta_window_xwayland_shortcuts_inhibited (MetaWindow         *window,
   return meta_wayland_compositor_is_shortcuts_inhibited (compositor, source);
 }
 
+static void
+apply_allow_commits_x11_property (MetaWindowXwayland *xwayland_window,
+                                  gboolean            allow_commits)
+{
+  MetaWindow *window = META_WINDOW (xwayland_window);
+  MetaDisplay *display = window->display;
+  MetaX11Display *x11_display = display->x11_display;
+  Display *xdisplay = x11_display->xdisplay;
+  MetaFrame *frame;
+  Window xwin;
+  guint32 property[1];
+
+  frame = meta_window_get_frame (window);
+  if (!frame)
+    xwin = window->xwindow;
+  else
+    xwin = meta_frame_get_xwindow (frame);
+
+  if (!xwin)
+    return;
+
+  property[0] = !!allow_commits;
+
+  meta_x11_error_trap_push (x11_display);
+  XChangeProperty (xdisplay, xwin,
+                   x11_display->atom__XWAYLAND_ALLOW_COMMITS,
+                   XA_CARDINAL, 32, PropModeReplace,
+                   (guchar*) &property, 1);
+  meta_x11_error_trap_pop (x11_display);
+  XFlush (xdisplay);
+}
+
+static void
+meta_window_xwayland_freeze_commits (MetaWindow *window)
+{
+  MetaWindowXwayland *xwayland_window = META_WINDOW_XWAYLAND (window);
+
+  if (xwayland_window->freeze_count == 0)
+    apply_allow_commits_x11_property (xwayland_window, FALSE);
+
+  xwayland_window->freeze_count++;
+}
+
+static void
+meta_window_xwayland_thaw_commits (MetaWindow *window)
+{
+  MetaWindowXwayland *xwayland_window = META_WINDOW_XWAYLAND (window);
+
+  g_return_if_fail (xwayland_window->freeze_count > 0);
+
+  xwayland_window->freeze_count--;
+  if (xwayland_window->freeze_count > 0)
+    return;
+
+  apply_allow_commits_x11_property (xwayland_window, TRUE);
+}
+
 static void
 meta_window_xwayland_get_property (GObject    *object,
                                    guint       prop_id,
@@ -201,12 +261,16 @@ static void
 meta_window_xwayland_class_init (MetaWindowXwaylandClass *klass)
 {
   MetaWindowClass *window_class = META_WINDOW_CLASS (klass);
+  MetaWindowX11Class *window_x11_class = META_WINDOW_X11_CLASS (klass);
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   window_class->adjust_fullscreen_monitor_rect = meta_window_xwayland_adjust_fullscreen_monitor_rect;
   window_class->force_restore_shortcuts = meta_window_xwayland_force_restore_shortcuts;
   window_class->shortcuts_inhibited = meta_window_xwayland_shortcuts_inhibited;
 
+  window_x11_class->freeze_commits = meta_window_xwayland_freeze_commits;
+  window_x11_class->thaw_commits = meta_window_xwayland_thaw_commits;
+
   gobject_class->get_property = meta_window_xwayland_get_property;
   gobject_class->set_property = meta_window_xwayland_set_property;
 
diff --git a/src/x11/atomnames.h b/src/x11/atomnames.h
index 4099d5d31..4c1b49ede 100644
--- a/src/x11/atomnames.h
+++ b/src/x11/atomnames.h
@@ -82,6 +82,7 @@ item(_XKB_RULES_NAMES)
 item(WL_SURFACE_ID)
 item(_XWAYLAND_MAY_GRAB_KEYBOARD)
 item(_XWAYLAND_RANDR_EMU_MONITOR_RECTS)
+item(_XWAYLAND_ALLOW_COMMITS)
 
 /* Oddities: These are used, and we need atoms for them,
  * but when we need all _NET_WM hints (i.e. when we're making
diff --git a/src/x11/window-x11-private.h b/src/x11/window-x11-private.h
index c582118c7..a073a5b8a 100644
--- a/src/x11/window-x11-private.h
+++ b/src/x11/window-x11-private.h
@@ -33,6 +33,9 @@ typedef struct _MetaWindowX11Private MetaWindowX11Private;
 struct _MetaWindowX11Class
 {
   MetaWindowClass parent_class;
+
+  void (*freeze_commits) (MetaWindow *window);
+  void (*thaw_commits)   (MetaWindow *window);
 };
 
 struct _MetaWindowX11
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index 6378111b5..9caf75ad6 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -1973,6 +1973,16 @@ meta_window_x11_calculate_layer (MetaWindow *window)
   return layer;
 }
 
+static void
+meta_window_x11_impl_freeze_commits (MetaWindow *window)
+{
+}
+
+static void
+meta_window_x11_impl_thaw_commits (MetaWindow *window)
+{
+}
+
 static void
 meta_window_x11_map (MetaWindow *window)
 {
@@ -2024,6 +2034,9 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
   window_class->calculate_layer = meta_window_x11_calculate_layer;
   window_class->map = meta_window_x11_map;
   window_class->unmap = meta_window_x11_unmap;
+
+  klass->freeze_commits = meta_window_x11_impl_freeze_commits;
+  klass->thaw_commits = meta_window_x11_impl_thaw_commits;
 }
 
 void
@@ -3995,3 +4008,17 @@ meta_window_x11_get_toplevel_xwindow (MetaWindow *window)
 {
   return window->frame ? window->frame->xwindow : window->xwindow;
 }
+
+void
+meta_window_x11_freeze_commits (MetaWindow *window)
+{
+  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
+  META_WINDOW_X11_GET_CLASS (window_x11)->freeze_commits (window);
+}
+
+void
+meta_window_x11_thaw_commits (MetaWindow *window)
+{
+  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
+  META_WINDOW_X11_GET_CLASS (window_x11)->thaw_commits (window);
+}
diff --git a/src/x11/window-x11.h b/src/x11/window-x11.h
index f3f3f1de1..2180ce976 100644
--- a/src/x11/window-x11.h
+++ b/src/x11/window-x11.h
@@ -81,4 +81,7 @@ void     meta_window_x11_configure_notify        (MetaWindow      *window,
 
 Window   meta_window_x11_get_toplevel_xwindow    (MetaWindow *window);
 
+void     meta_window_x11_freeze_commits          (MetaWindow *window);
+void     meta_window_x11_thaw_commits            (MetaWindow *window);
+
 #endif


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