transaction: split acking and committing

This fixes the problems with e.g. wlr_xdg_toplevel_set_resizing()
interfering with serial checking and causing false timeouts.
This commit is contained in:
Kirill Primak 2021-07-30 11:58:04 +03:00
parent 258f167528
commit ce8dae9328
5 changed files with 52 additions and 15 deletions

View file

@ -35,20 +35,26 @@ void transaction_commit_dirty(void);
void transaction_commit_dirty_client(void); void transaction_commit_dirty_client(void);
/** /**
* Notify the transaction system that a view is ready for the new layout. * Notify the transaction system that a view has acknowledged a configure.
*
* When all views in the transaction are ready, the layout will be applied.
*/ */
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); 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. * 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); 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 #endif

View file

@ -116,6 +116,7 @@ struct sway_view {
struct sway_xdg_shell_view { struct sway_xdg_shell_view {
struct sway_view view; struct sway_view view;
struct wl_listener ack_configure;
struct wl_listener commit; struct wl_listener commit;
struct wl_listener request_move; struct wl_listener request_move;
struct wl_listener request_resize; struct wl_listener request_resize;

View file

@ -35,6 +35,8 @@ struct sway_transaction_instruction {
struct sway_container_state container_state; struct sway_container_state container_state;
}; };
uint32_t serial; uint32_t serial;
bool acked;
bool ready;
bool server_request; bool server_request;
bool waiting; bool waiting;
}; };
@ -444,6 +446,8 @@ static void set_instruction_ready(
struct sway_transaction_instruction *instruction) { struct sway_transaction_instruction *instruction) {
struct sway_transaction *transaction = instruction->transaction; struct sway_transaction *transaction = instruction->transaction;
instruction->ready = true;
if (debug.txn_timings) { if (debug.txn_timings) {
struct timespec now; struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
@ -468,16 +472,16 @@ static void set_instruction_ready(
transaction_progress(); 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) { uint32_t serial) {
struct sway_transaction_instruction *instruction = struct sway_transaction_instruction *instruction =
view->container->node.instruction; view->container->node.instruction;
if (instruction != NULL && instruction->serial == serial) { 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) { double x, double y, int width, int height) {
struct sway_transaction_instruction *instruction = struct sway_transaction_instruction *instruction =
view->container->node.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 && (int)instruction->container_state.content_y == (int)y &&
instruction->container_state.content_width == width && instruction->container_state.content_width == width &&
instruction->container_state.content_height == height) { 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);
}
} }
} }

View file

@ -279,6 +279,17 @@ static const struct sway_view_impl view_impl = {
.destroy = destroy, .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) { static void handle_commit(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_view *xdg_shell_view = struct sway_xdg_shell_view *xdg_shell_view =
wl_container_of(listener, xdg_shell_view, commit); 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) { if (view->container->node.instruction) {
transaction_notify_view_ready_by_serial(view, transaction_notify_view_ready(view);
xdg_surface->configure_serial);
} }
view_damage_from(view); view_damage_from(view);
@ -418,6 +428,7 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
view_unmap(view); 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->commit.link);
wl_list_remove(&xdg_shell_view->new_popup.link); wl_list_remove(&xdg_shell_view->new_popup.link);
wl_list_remove(&xdg_shell_view->request_fullscreen.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(); 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; xdg_shell_view->commit.notify = handle_commit;
wl_signal_add(&xdg_surface->surface->events.commit, wl_signal_add(&xdg_surface->surface->events.commit,
&xdg_shell_view->commit); &xdg_shell_view->commit);

View file

@ -418,8 +418,9 @@ static void handle_commit(struct wl_listener *listener, void *data) {
} }
if (view->container->node.instruction) { if (view->container->node.instruction) {
transaction_notify_view_ready_by_geometry(view, transaction_notify_view_acked_by_geometry(view,
xsurface->x, xsurface->y, state->width, state->height); xsurface->x, xsurface->y, state->width, state->height);
transaction_notify_view_ready(view);
} }
view_damage_from(view); view_damage_from(view);