[mutter/wip/carlosg/frames-client: 1002/1005] x11: Add frame synchronization to window frames
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/carlosg/frames-client: 1002/1005] x11: Add frame synchronization to window frames
- Date: Mon, 12 Sep 2022 12:29:21 +0000 (UTC)
commit 47f0bc03040f71297cf3501e0afe1aa5bff44fb4
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/core/frame.c | 27 ++++++++++++++++++++++---
src/core/frame.h | 6 ++++++
src/frames/main.c | 5 -----
src/frames/meta-frame.c | 2 +-
src/x11/window-props.c | 7 ++++++-
src/x11/window-x11.c | 53 +++++++++++++++++++++++++++++++++++++++----------
6 files changed, 80 insertions(+), 20 deletions(-)
---
diff --git a/src/core/frame.c b/src/core/frame.c
index 3261d628f6..4bb3bf72e3 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>
@@ -73,7 +74,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;
@@ -83,6 +84,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",
@@ -95,8 +98,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);
@@ -140,6 +141,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 */
@@ -217,6 +222,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 */
@@ -491,6 +498,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;
}
@@ -616,3 +631,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 84fb037927..d08388de17 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;
@@ -73,4 +77,6 @@ gboolean meta_frame_handle_xevent (MetaFrame *frame,
XEvent *event);
void meta_frame_initialize (MetaDisplay *display);
+MetaSyncCounter * meta_frame_get_sync_counter (MetaFrame *frame);
+
#endif
diff --git a/src/frames/main.c b/src/frames/main.c
index 141ba41b46..bff9c6ec36 100644
--- a/src/frames/main.c
+++ b/src/frames/main.c
@@ -33,11 +33,6 @@ main (int argc,
GMainLoop *loop;
Display *xdisplay;
- /* This seems to be the renderer that works best with
- * frame sync disabled.
- */
- g_setenv ("GSK_RENDERER", "cairo", TRUE);
-
gdk_set_allowed_backends ("x11");
gtk_init ();
diff --git a/src/frames/meta-frame.c b/src/frames/meta-frame.c
index 190e59fd8d..efa4fc78e2 100644
--- a/src/frames/meta-frame.c
+++ b/src/frames/meta-frame.c
@@ -222,7 +222,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 045775302e..74142457dd 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);
}
@@ -3968,6 +3977,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);
}
@@ -3977,6 +3989,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);
}
@@ -4144,6 +4159,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);
}
@@ -4153,12 +4172,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]