From 57037a45b8bc6aa5137e256456a7b1a1a554fd8e Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sun, 27 Jul 2014 17:23:17 +0200 Subject: [PATCH] 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. --- src/wayland/meta-wayland-surface.c | 23 ++++++++++++++------- src/wayland/meta-wayland-surface.h | 12 +++++++++-- src/wayland/meta-wayland-types.h | 2 ++ src/wayland/window-wayland.c | 32 ++++++++++++++++++++++++------ src/wayland/window-wayland.h | 9 +++++---- 5 files changed, 59 insertions(+), 19 deletions(-) diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 4b9e5b2b6..57aed653a 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -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, diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 582d07d4e..98a344c26 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -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); diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h index 9d85d5b4f..72174310a 100644 --- a/src/wayland/meta-wayland-types.h +++ b/src/wayland/meta-wayland-types.h @@ -36,4 +36,6 @@ typedef struct _MetaWaylandBufferReference MetaWaylandBufferReference; typedef struct _MetaWaylandSurface MetaWaylandSurface; +typedef struct _MetaWaylandSerial MetaWaylandSerial; + #endif diff --git a/src/wayland/window-wayland.c b/src/wayland/window-wayland.c index 9d10a6783..31df759c6 100644 --- a/src/wayland/window-wayland.c +++ b/src/wayland/window-wayland.c @@ -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; diff --git a/src/wayland/window-wayland.h b/src/wayland/window-wayland.h index 3c326850c..eb2e8deb5 100644 --- a/src/wayland/window-wayland.h +++ b/src/wayland/window-wayland.h @@ -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