From db1adab828c8bac2909e1f4ca9a626b0baa6fc9b Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 15 Mar 2018 13:09:23 -0400 Subject: [PATCH] window: track when resize is pending via new flag For Xwayland clients, resizing is an asynchronous operation. First, the window manager part of mutter resizes the frame and client window, then Xwayland waits for damage from the client, and commits a new surface to the display server part of mutter. In order to prevent flicker, we need to know when an initiated resize operation has fully come out the other end of that multi-step process as a new surface. This commit lays the plumbing work for preventing the aforementioned flicker problem, by adding a new resize_pending flag (and associated accessors), and setting the flag appropriately based on when a resize is started and subsequently when a new surface is attached. --- src/compositor/meta-surface-actor-wayland.c | 13 +++++++++++++ src/compositor/meta-surface-actor.c | 4 ++-- src/compositor/meta-surface-actor.h | 2 ++ src/core/window-private.h | 6 ++++++ src/core/window.c | 13 +++++++++++++ src/wayland/meta-wayland-surface.c | 1 + src/wayland/meta-window-xwayland.c | 15 +++++++++++++++ 7 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c index c70e44461..887b848bb 100644 --- a/src/compositor/meta-surface-actor-wayland.c +++ b/src/compositor/meta-surface-actor-wayland.c @@ -125,6 +125,17 @@ meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor) return surface->window; } +static void +meta_surface_actor_wayland_size_changed (MetaSurfaceActor *actor) +{ + MetaWindow *window; + + window = meta_surface_actor_wayland_get_window (actor); + + if (window) + meta_window_set_resize_pending (window, FALSE); +} + static void meta_surface_actor_wayland_get_preferred_width (ClutterActor *actor, gfloat for_height, @@ -237,6 +248,8 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) surface_actor_class->set_frozen = meta_surface_actor_wayland_set_frozen; surface_actor_class->get_window = meta_surface_actor_wayland_get_window; + surface_actor_class->size_changed = meta_surface_actor_wayland_size_changed; + object_class->dispose = meta_surface_actor_wayland_dispose; } diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index 64491ac8c..156a9cf89 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -135,8 +135,8 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass) signals[SIZE_CHANGED] = g_signal_new ("size-changed", G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (MetaSurfaceActorClass, size_changed), NULL, NULL, NULL, G_TYPE_NONE, 0); diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h index f60cbb64f..ef307f0fc 100644 --- a/src/compositor/meta-surface-actor.h +++ b/src/compositor/meta-surface-actor.h @@ -40,6 +40,8 @@ struct _MetaSurfaceActorClass gboolean is_frozen); MetaWindow *(* get_window) (MetaSurfaceActor *actor); + + void (* size_changed) (MetaSurfaceActor *actor); }; struct _MetaSurfaceActor diff --git a/src/core/window-private.h b/src/core/window-private.h index 9545dfc3c..afaa499e5 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -407,6 +407,9 @@ struct _MetaWindow /* whether or not the window is from a program running on another machine */ guint is_remote : 1; + /* if TRUE, the X server hasn't yet committed a new buffer following resize of the frame/client window */ + guint resize_pending : 1; + /* if non-NULL, the bounds of the window frame */ cairo_region_t *frame_bounds; @@ -781,6 +784,9 @@ void meta_window_move_resize_internal (MetaWindow *window, MetaMoveResizeFlags flags, int gravity, MetaRectangle frame_rect); +void meta_window_set_resize_pending (MetaWindow *window, + gboolean is_resize_pending); +gboolean meta_window_resize_is_pending (MetaWindow *window); 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 86f9d69b1..34f48712f 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -6311,6 +6311,19 @@ meta_window_update_resize (MetaWindow *window, update_resize (window, snap, x, y, force); } +void +meta_window_set_resize_pending (MetaWindow *window, + gboolean is_resize_pending) +{ + window->resize_pending = is_resize_pending; +} + +gboolean +meta_window_resize_is_pending (MetaWindow *window) +{ + return window->resize_pending; +} + static void end_grab_op (MetaWindow *window, const ClutterEvent *event) diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 159e6f86e..3038beb86 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -1102,6 +1102,7 @@ meta_wayland_surface_set_window (MetaWaylandSurface *surface, "position-changed", G_CALLBACK (window_position_changed), surface, 0); + meta_window_set_resize_pending (window, FALSE); } } diff --git a/src/wayland/meta-window-xwayland.c b/src/wayland/meta-window-xwayland.c index 6f073893a..08d0649da 100644 --- a/src/wayland/meta-window-xwayland.c +++ b/src/wayland/meta-window-xwayland.c @@ -71,6 +71,20 @@ meta_window_xwayland_shortcuts_inhibited (MetaWindow *window, return meta_wayland_compositor_is_shortcuts_inhibited (compositor, source); } +static void +meta_window_xwayland_move_resize_internal (MetaWindow *window, + int gravity, + MetaRectangle unconstrained_rect, + MetaRectangle constrained_rect, + MetaMoveResizeFlags flags, + MetaMoveResizeResultFlags *result) +{ + META_WINDOW_CLASS (meta_window_xwayland_parent_class)->move_resize_internal (window, gravity, unconstrained_rect, constrained_rect, flags, result); + + if (*result & META_MOVE_RESIZE_RESULT_RESIZED) + meta_window_set_resize_pending (window, TRUE); +} + static void meta_window_xwayland_get_property (GObject *object, guint prop_id, @@ -117,6 +131,7 @@ meta_window_xwayland_class_init (MetaWindowXwaylandClass *klass) window_class->force_restore_shortcuts = meta_window_xwayland_force_restore_shortcuts; window_class->shortcuts_inhibited = meta_window_xwayland_shortcuts_inhibited; + window_class->move_resize_internal = meta_window_xwayland_move_resize_internal; gobject_class->get_property = meta_window_xwayland_get_property; gobject_class->set_property = meta_window_xwayland_set_property;