window: Let implementations finish state changes

In the old, synchronous X.org world, we could assume that
a state change always meant a synchronizing the window
geometry right after. After firing an operation that
would change the window state, such as maximizing or
tiling the window,

With Wayland, however, this is not valid anymore, since
Wayland is asynchronous. In this scenario, we call
meta_window_move_resize_internal() twice: when the user
executes an state-changing operation, and when the server
ACKs this operation. This breaks the previous assumptions,
and as a consequence, it breaks the GNOME Shell animations
in Wayland.

The solution is giving the MetaWindow control over the time
when the window geometry is synchronized with the compositor.
That is done by introducing a new result flag. Wayland asks
for a compositor sync after receiving an ACK from the server,
while X11 asks for it right away.

Fixes #78
This commit is contained in:
Georges Basile Stavracas Neto 2018-04-17 23:42:33 -03:00
parent b412e6c493
commit 822c2666f5
4 changed files with 23 additions and 7 deletions

View File

@ -81,6 +81,7 @@ typedef enum
META_MOVE_RESIZE_STATE_CHANGED = 1 << 5,
META_MOVE_RESIZE_UNMAXIMIZE = 1 << 6,
META_MOVE_RESIZE_FORCE_MOVE = 1 << 7,
META_MOVE_RESIZE_WAYLAND_STATE_CHANGED = 1 << 8,
} MetaMoveResizeFlags;
typedef enum
@ -88,6 +89,7 @@ typedef enum
META_MOVE_RESIZE_RESULT_MOVED = 1 << 0,
META_MOVE_RESIZE_RESULT_RESIZED = 1 << 1,
META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
META_MOVE_RESIZE_RESULT_STATE_CHANGED = 1 << 3,
} MetaMoveResizeResultFlags;
typedef enum

View File

@ -3997,7 +3997,7 @@ meta_window_move_resize_internal (MetaWindow *window,
if ((moved_or_resized ||
did_placement ||
(flags & META_MOVE_RESIZE_STATE_CHANGED) != 0) &&
(result & META_MOVE_RESIZE_RESULT_STATE_CHANGED) != 0) &&
window->known_to_compositor)
{
meta_compositor_sync_window_geometry (window->display->compositor,

View File

@ -48,6 +48,7 @@ struct _MetaWindowWayland
int geometry_scale;
MetaWaylandSerial pending_configure_serial;
gboolean has_pending_state_change;
gboolean has_pending_move;
int pending_move_x;
int pending_move_y;
@ -324,6 +325,9 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
window->buffer_rect.x = new_buffer_x;
window->buffer_rect.y = new_buffer_y;
}
if (flags & META_MOVE_RESIZE_WAYLAND_STATE_CHANGED)
*result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED;
}
else
{
@ -336,6 +340,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
wl_window->pending_move_x = new_x;
wl_window->pending_move_y = new_y;
}
wl_window->has_pending_state_change = (flags & META_MOVE_RESIZE_STATE_CHANGED) != 0;
}
}
@ -629,12 +635,9 @@ meta_window_wayland_new (MetaDisplay *display,
}
static gboolean
should_do_pending_move (MetaWindowWayland *wl_window,
is_pending_ack_configure (MetaWindowWayland *wl_window,
MetaWaylandSerial *acked_configure_serial)
{
if (!wl_window->has_pending_move)
return FALSE;
if (wl_window->pending_configure_serial.set)
{
/* If we're waiting for a configure and this isn't an ACK for
@ -677,6 +680,7 @@ meta_window_wayland_move_resize (MetaWindow *window,
int gravity;
MetaRectangle rect;
MetaMoveResizeFlags flags;
gboolean pending_ack_configure;
/* new_geom is in the logical pixel coordinate space, but MetaWindow wants its
* rects to represent what in turn will end up on the stage, i.e. we need to
@ -700,10 +704,12 @@ meta_window_wayland_move_resize (MetaWindow *window,
flags = META_MOVE_RESIZE_WAYLAND_RESIZE;
pending_ack_configure = is_pending_ack_configure (wl_window, acked_configure_serial);
/* x/y are ignored when we're doing interactive resizing */
if (!meta_grab_op_is_resizing (window->display->grab_op))
{
if (wl_window->has_pending_move && should_do_pending_move (wl_window, acked_configure_serial))
if (wl_window->has_pending_move && pending_ack_configure)
{
rect.x = wl_window->pending_move_x;
rect.y = wl_window->pending_move_y;
@ -724,6 +730,12 @@ meta_window_wayland_move_resize (MetaWindow *window,
}
}
if (wl_window->has_pending_state_change && pending_ack_configure)
{
flags |= META_MOVE_RESIZE_WAYLAND_STATE_CHANGED;
wl_window->has_pending_state_change = FALSE;
}
wl_window->pending_configure_serial.set = FALSE;
rect.width = new_geom.width;

View File

@ -1282,6 +1282,8 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
*result |= META_MOVE_RESIZE_RESULT_MOVED;
if (need_resize_client || need_resize_frame)
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
if (flags & META_MOVE_RESIZE_STATE_CHANGED)
*result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED;
update_gtk_edge_constraints (window);
}