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.
This commit is contained in:
Ray Strode 2018-03-15 13:09:23 -04:00 committed by Ray Strode
parent 8369fde7f8
commit db1adab828
7 changed files with 52 additions and 2 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -40,6 +40,8 @@ struct _MetaSurfaceActorClass
gboolean is_frozen);
MetaWindow *(* get_window) (MetaSurfaceActor *actor);
void (* size_changed) (MetaSurfaceActor *actor);
};
struct _MetaSurfaceActor

View File

@ -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);

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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;