wayland-surface: Don't do pending move/resizes on all commits

We assume in meta_window_wayland_move_resize that the next commit that
changes the geometry will always be for our next pending operation, so
if we have a move pending on a resize, the next commit will trigger the
move. This is, of course, fundamentally wrong.

We broke this assumption even more now that we don't fizzle out calls to
meta_window_move_resize_internal and now call it on every commit, which
means that a simple damage and then commit would complete a pending
move.

This was even broken by apps like weston-terminal, which, when clicking
on the maximize button, first redraws the terminal with the maximize
button state back on hover on press, and would only redraw when it got
the configure event with the coordinates.

To track the correct commit to apply the move for, we implement the
ack_configure request and ignore all move/resizes that happen before
that.

Right now, we actually fizzle out the entire move/resize if there's a
future pending configure we're waiting on.
This commit is contained in:
Jasper St. Pierre 2014-07-27 17:23:17 +02:00
parent c844611052
commit 57037a45b8
5 changed files with 59 additions and 19 deletions

View File

@ -243,7 +243,10 @@ toplevel_surface_commit (MetaWaylandSurface *surface,
return; return;
} }
meta_window_wayland_move_resize (window, geom, pending->dx, pending->dy); meta_window_wayland_move_resize (window,
&surface->acked_configure_serial,
geom, pending->dx, pending->dy);
surface->acked_configure_serial.set = FALSE;
} }
} }
@ -906,11 +909,10 @@ xdg_surface_ack_configure (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
uint32_t serial) uint32_t serial)
{ {
/* Do nothing for now. In the future, we'd imagine that MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
* we'd ignore attaches when we have a state pending that
* we haven't had the client ACK'd, to prevent a race surface->acked_configure_serial.set = TRUE;
* condition when we have an in-flight attach when the surface->acked_configure_serial.value = serial;
* client gets the new state. */
} }
static void static void
@ -1811,7 +1813,8 @@ fill_states (struct wl_array *states, MetaWindow *window)
void void
meta_wayland_surface_configure_notify (MetaWaylandSurface *surface, meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int new_width, int new_width,
int new_height) int new_height,
MetaWaylandSerial *sent_serial)
{ {
if (surface->xdg_surface.resource) if (surface->xdg_surface.resource)
{ {
@ -1832,6 +1835,12 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
xdg_surface_send_configure (surface->xdg_surface.resource, new_width, new_height, &states, serial); xdg_surface_send_configure (surface->xdg_surface.resource, new_width, new_height, &states, serial);
wl_array_release (&states); wl_array_release (&states);
if (sent_serial)
{
sent_serial->set = TRUE;
sent_serial->value = serial;
}
} }
else if (surface->wl_shell_surface.resource) else if (surface->wl_shell_surface.resource)
wl_shell_surface_send_configure (surface->wl_shell_surface.resource, wl_shell_surface_send_configure (surface->wl_shell_surface.resource,

View File

@ -31,6 +31,11 @@
#include "meta-wayland-types.h" #include "meta-wayland-types.h"
#include "meta-surface-actor.h" #include "meta-surface-actor.h"
struct _MetaWaylandSerial {
gboolean set;
uint32_t value;
};
struct _MetaWaylandBuffer struct _MetaWaylandBuffer
{ {
struct wl_resource *resource; struct wl_resource *resource;
@ -113,6 +118,8 @@ struct _MetaWaylandSurface
/* All the pending state that wl_surface.commit will apply. */ /* All the pending state that wl_surface.commit will apply. */
MetaWaylandPendingState pending; MetaWaylandPendingState pending;
MetaWaylandSerial acked_configure_serial;
}; };
void meta_wayland_shell_init (MetaWaylandCompositor *compositor); void meta_wayland_shell_init (MetaWaylandCompositor *compositor);
@ -127,7 +134,8 @@ void meta_wayland_surface_set_window (MetaWaylandSurface *surface
void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface, void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int width, int width,
int height); int height,
MetaWaylandSerial *sent_serial);
void meta_wayland_surface_ping (MetaWaylandSurface *surface, void meta_wayland_surface_ping (MetaWaylandSurface *surface,
guint32 serial); guint32 serial);

View File

@ -36,4 +36,6 @@ typedef struct _MetaWaylandBufferReference MetaWaylandBufferReference;
typedef struct _MetaWaylandSurface MetaWaylandSurface; typedef struct _MetaWaylandSurface MetaWaylandSurface;
typedef struct _MetaWaylandSerial MetaWaylandSerial;
#endif #endif

View File

@ -36,6 +36,7 @@ struct _MetaWindowWayland
{ {
MetaWindow parent; MetaWindow parent;
MetaWaylandSerial pending_configure_serial;
gboolean has_pending_move; gboolean has_pending_move;
int pending_move_x; int pending_move_x;
int pending_move_y; int pending_move_y;
@ -126,7 +127,8 @@ surface_state_changed (MetaWindow *window)
meta_wayland_surface_configure_notify (window->surface, meta_wayland_surface_configure_notify (window->surface,
wl_window->last_sent_width, wl_window->last_sent_width,
wl_window->last_sent_height); wl_window->last_sent_height,
&wl_window->pending_configure_serial);
} }
static void static void
@ -214,7 +216,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
meta_wayland_surface_configure_notify (window->surface, meta_wayland_surface_configure_notify (window->surface,
constrained_rect.width, constrained_rect.width,
constrained_rect.height); constrained_rect.height,
&wl_window->pending_configure_serial);
} }
else else
{ {
@ -350,6 +353,7 @@ meta_window_wayland_new (MetaDisplay *display,
*/ */
void void
meta_window_wayland_move_resize (MetaWindow *window, meta_window_wayland_move_resize (MetaWindow *window,
MetaWaylandSerial *acked_configure_serial,
MetaRectangle new_geom, MetaRectangle new_geom,
int dx, int dx,
int dy) int dy)
@ -359,6 +363,22 @@ meta_window_wayland_move_resize (MetaWindow *window,
MetaRectangle rect; MetaRectangle rect;
MetaMoveResizeFlags flags; MetaMoveResizeFlags flags;
if (wl_window->pending_configure_serial.set)
{
/* If we're waiting for a configure and this isn't an ACK for
* any configure, then fizzle it out. */
if (!acked_configure_serial->set)
return;
/* If we're waiting for a configure and this isn't an ACK for
* the configure we're waiting for, then fizzle it out. */
if (acked_configure_serial->value != wl_window->pending_configure_serial.value)
return;
/* OK, this request is going to ACK the pending configure. */
wl_window->pending_configure_serial.set = FALSE;
}
/* XXX: Find a better place to store the window geometry offsets. */ /* XXX: Find a better place to store the window geometry offsets. */
window->custom_frame_extents.left = new_geom.x; window->custom_frame_extents.left = new_geom.x;
window->custom_frame_extents.top = new_geom.y; window->custom_frame_extents.top = new_geom.y;

View File

@ -46,6 +46,7 @@ MetaWindow * meta_window_wayland_new (MetaDisplay *display,
MetaWaylandSurface *surface); MetaWaylandSurface *surface);
void meta_window_wayland_move_resize (MetaWindow *window, void meta_window_wayland_move_resize (MetaWindow *window,
MetaWaylandSerial *acked_configure_serial,
MetaRectangle new_geom, MetaRectangle new_geom,
int dx, int dx,
int dy); int dy);