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;
}
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,
uint32_t serial)
{
/* Do nothing for now. In the future, we'd imagine that
* we'd ignore attaches when we have a state pending that
* we haven't had the client ACK'd, to prevent a race
* condition when we have an in-flight attach when the
* client gets the new state. */
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
surface->acked_configure_serial.set = TRUE;
surface->acked_configure_serial.value = serial;
}
static void
@ -1811,7 +1813,8 @@ fill_states (struct wl_array *states, MetaWindow *window)
void
meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int new_width,
int new_height)
int new_height,
MetaWaylandSerial *sent_serial)
{
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);
wl_array_release (&states);
if (sent_serial)
{
sent_serial->set = TRUE;
sent_serial->value = serial;
}
}
else if (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-surface-actor.h"
struct _MetaWaylandSerial {
gboolean set;
uint32_t value;
};
struct _MetaWaylandBuffer
{
struct wl_resource *resource;
@ -113,6 +118,8 @@ struct _MetaWaylandSurface
/* All the pending state that wl_surface.commit will apply. */
MetaWaylandPendingState pending;
MetaWaylandSerial acked_configure_serial;
};
void meta_wayland_shell_init (MetaWaylandCompositor *compositor);
@ -126,8 +133,9 @@ void meta_wayland_surface_set_window (MetaWaylandSurface *surface
MetaWindow *window);
void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int width,
int height);
int width,
int height,
MetaWaylandSerial *sent_serial);
void meta_wayland_surface_ping (MetaWaylandSurface *surface,
guint32 serial);

View File

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

View File

@ -36,6 +36,7 @@ struct _MetaWindowWayland
{
MetaWindow parent;
MetaWaylandSerial pending_configure_serial;
gboolean has_pending_move;
int pending_move_x;
int pending_move_y;
@ -126,7 +127,8 @@ surface_state_changed (MetaWindow *window)
meta_wayland_surface_configure_notify (window->surface,
wl_window->last_sent_width,
wl_window->last_sent_height);
wl_window->last_sent_height,
&wl_window->pending_configure_serial);
}
static void
@ -214,7 +216,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
meta_wayland_surface_configure_notify (window->surface,
constrained_rect.width,
constrained_rect.height);
constrained_rect.height,
&wl_window->pending_configure_serial);
}
else
{
@ -349,16 +352,33 @@ meta_window_wayland_new (MetaDisplay *display,
* Complete a resize operation from a wayland client.
*/
void
meta_window_wayland_move_resize (MetaWindow *window,
MetaRectangle new_geom,
int dx,
int dy)
meta_window_wayland_move_resize (MetaWindow *window,
MetaWaylandSerial *acked_configure_serial,
MetaRectangle new_geom,
int dx,
int dy)
{
MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
int gravity;
MetaRectangle rect;
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. */
window->custom_frame_extents.left = new_geom.x;
window->custom_frame_extents.top = new_geom.y;

View File

@ -45,9 +45,10 @@ typedef struct _MetaWindowWaylandClass MetaWindowWaylandClass;
MetaWindow * meta_window_wayland_new (MetaDisplay *display,
MetaWaylandSurface *surface);
void meta_window_wayland_move_resize (MetaWindow *window,
MetaRectangle new_geom,
int dx,
int dy);
void meta_window_wayland_move_resize (MetaWindow *window,
MetaWaylandSerial *acked_configure_serial,
MetaRectangle new_geom,
int dx,
int dy);
#endif