summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2022-09-09 15:54:28 +0200
committerMarge Bot <marge-bot@gnome.org>2022-12-01 20:10:53 +0000
commitf2237fa0c8359acdbf4ff08966efa0986dea3be8 (patch)
tree72cb53250538155885868bff9c7f3a2300ab1ad1
parent782d200d6c2566aa50fbbed7cbe7bf65a2bea312 (diff)
downloadmutter-f2237fa0c8359acdbf4ff08966efa0986dea3be8.tar.gz
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. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
-rw-r--r--src/compositor/meta-window-actor-x11.c28
-rw-r--r--src/core/frame.c27
-rw-r--r--src/core/frame.h6
-rw-r--r--src/frames/meta-frame.c2
-rw-r--r--src/x11/window-props.c7
-rw-r--r--src/x11/window-x11.c53
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 de0cb9219..f5c6de376 100644
--- a/src/compositor/meta-window-actor-x11.c
+++ b/src/compositor/meta-window-actor-x11.c
@@ -132,6 +132,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;
@@ -208,6 +215,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
@@ -225,6 +239,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 *
@@ -1207,6 +1229,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 a3a0e5cf1..a2bb00421 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 */
@@ -222,6 +227,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 */
@@ -496,6 +503,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;
}
@@ -572,3 +587,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 fb72d6388..023e2f4e4 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 26d0e1f1a..c66d8b660 100644
--- a/src/frames/meta-frame.c
+++ b/src/frames/meta-frame.c
@@ -250,7 +250,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 1eb3c990a..bf4d06711 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 f2df2904f..637f7a3dc 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -1479,9 +1479,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;
@@ -1496,25 +1493,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
@@ -1900,6 +1905,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);
}
@@ -4111,6 +4120,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);
}
@@ -4120,6 +4132,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);
}
@@ -4276,6 +4291,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);
}
@@ -4285,12 +4304,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,