diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h index 7dd58ba8c..b07df355d 100644 --- a/include/sway/desktop/transaction.h +++ b/include/sway/desktop/transaction.h @@ -35,20 +35,26 @@ void transaction_commit_dirty(void); void transaction_commit_dirty_client(void); /** - * Notify the transaction system that a view is ready for the new layout. - * - * When all views in the transaction are ready, the layout will be applied. + * Notify the transaction system that a view has acknowledged a configure. */ -void transaction_notify_view_ready_by_serial(struct sway_view *view, +void transaction_notify_view_acked_by_serial(struct sway_view *view, uint32_t serial); /** - * Notify the transaction system that a view is ready for the new layout, but + * Notify the transaction system that a view has acknowledged a configure, but * identifying the instruction by geometry rather than by serial. * - * This is used by xwayland views, as they don't have serials. + * This is used by Xwayland views, as they don't have serials. */ -void transaction_notify_view_ready_by_geometry(struct sway_view *view, +void transaction_notify_view_acked_by_geometry(struct sway_view *view, double x, double y, int width, int height); +/** + * Notify the transaction system that a view is ready for the new layout. This + * call has no effect if the view hasn't acknowledged a configure yet. + * + * When all views in the transaction are ready, the layout will be applied. + */ +void transaction_notify_view_ready(struct sway_view *view); + #endif diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index bf2f0a789..0f0ace9c1 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -116,6 +116,7 @@ struct sway_view { struct sway_xdg_shell_view { struct sway_view view; + struct wl_listener ack_configure; struct wl_listener commit; struct wl_listener request_move; struct wl_listener request_resize; diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index ebaa16809..a65f4ab20 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -35,6 +35,8 @@ struct sway_transaction_instruction { struct sway_container_state container_state; }; uint32_t serial; + bool acked; + bool ready; bool server_request; bool waiting; }; @@ -444,6 +446,8 @@ static void set_instruction_ready( struct sway_transaction_instruction *instruction) { struct sway_transaction *transaction = instruction->transaction; + instruction->ready = true; + if (debug.txn_timings) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -468,16 +472,16 @@ static void set_instruction_ready( transaction_progress(); } -void transaction_notify_view_ready_by_serial(struct sway_view *view, +void transaction_notify_view_acked_by_serial(struct sway_view *view, uint32_t serial) { struct sway_transaction_instruction *instruction = view->container->node.instruction; if (instruction != NULL && instruction->serial == serial) { - set_instruction_ready(instruction); + instruction->acked = true; } } -void transaction_notify_view_ready_by_geometry(struct sway_view *view, +void transaction_notify_view_acked_by_geometry(struct sway_view *view, double x, double y, int width, int height) { struct sway_transaction_instruction *instruction = view->container->node.instruction; @@ -486,7 +490,17 @@ void transaction_notify_view_ready_by_geometry(struct sway_view *view, (int)instruction->container_state.content_y == (int)y && instruction->container_state.content_width == width && instruction->container_state.content_height == height) { - set_instruction_ready(instruction); + instruction->acked = true; + } +} + +void transaction_notify_view_ready(struct sway_view *view) { + struct sway_transaction_instruction *instruction = + view->container->node.instruction; + if (instruction != NULL && !instruction->ready) { + if (instruction->acked) { + set_instruction_ready(instruction); + } } } diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index d34654fd4..a4b479a22 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -279,6 +279,17 @@ static const struct sway_view_impl view_impl = { .destroy = destroy, }; +static void handle_ack_configure(struct wl_listener *listener, void *data) { + struct sway_xdg_shell_view *xdg_shell_view = + wl_container_of(listener, xdg_shell_view, ack_configure); + struct sway_view *view = &xdg_shell_view->view; + struct wlr_xdg_surface_configure *configure = data; + if (view->container->node.instruction) { + transaction_notify_view_acked_by_serial(view, + configure->serial); + } +} + static void handle_commit(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, commit); @@ -308,8 +319,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { } if (view->container->node.instruction) { - transaction_notify_view_ready_by_serial(view, - xdg_surface->configure_serial); + transaction_notify_view_ready(view); } view_damage_from(view); @@ -418,6 +428,7 @@ static void handle_unmap(struct wl_listener *listener, void *data) { view_unmap(view); + wl_list_remove(&xdg_shell_view->ack_configure.link); wl_list_remove(&xdg_shell_view->commit.link); wl_list_remove(&xdg_shell_view->new_popup.link); wl_list_remove(&xdg_shell_view->request_fullscreen.link); @@ -458,6 +469,10 @@ static void handle_map(struct wl_listener *listener, void *data) { transaction_commit_dirty(); + xdg_shell_view->ack_configure.notify = handle_ack_configure; + wl_signal_add(&xdg_surface->events.ack_configure, + &xdg_shell_view->ack_configure); + xdg_shell_view->commit.notify = handle_commit; wl_signal_add(&xdg_surface->surface->events.commit, &xdg_shell_view->commit); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 66cb3b026..0c28febf6 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -418,8 +418,9 @@ static void handle_commit(struct wl_listener *listener, void *data) { } if (view->container->node.instruction) { - transaction_notify_view_ready_by_geometry(view, - xsurface->x, xsurface->y, state->width, state->height); + transaction_notify_view_acked_by_geometry(view, + xsurface->x, xsurface->y, state->width, state->height); + transaction_notify_view_ready(view); } view_damage_from(view);