mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
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>
This commit is contained in:
parent
782d200d6c
commit
f2237fa0c8
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -1054,7 +1054,12 @@ reload_update_counter (MetaWindow *window,
|
||||
{
|
||||
MetaSyncCounter *sync_counter;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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 (window == window->display->grab_window &&
|
||||
if (mask != 0 &&
|
||||
window == window->display->grab_window &&
|
||||
meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
meta_sync_counter_send_request (&priv->sync_counter);
|
||||
if (window->frame)
|
||||
meta_sync_counter_send_request (meta_frame_get_sync_counter (window->frame));
|
||||
}
|
||||
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user