@@ -82,8 +82,10 @@ void Toplevel::map_notify(wl_listener *listener, [[maybe_unused]] void *data) {
8282 } else {
8383 wlr_box output_box = output->layout_geometry ;
8484
85- int32_t x = output_box.x + usable_area.x + (usable_area.width - width) / 2 ;
86- int32_t y = output_box.y + usable_area.y + (usable_area.height - height) / 2 ;
85+ int32_t x =
86+ output_box.x + usable_area.x + (usable_area.width - width) / 2 ;
87+ int32_t y = output_box.y + usable_area.y +
88+ (usable_area.height - height) / 2 ;
8789
8890 // ensure position falls in bounds
8991 x = std::max (x, output_box.x + usable_area.x );
@@ -114,12 +116,21 @@ void Toplevel::map_notify(wl_listener *listener, [[maybe_unused]] void *data) {
114116 if (!xwayland_surface->surface )
115117 return ;
116118
119+ // commit if part of transaction
120+ if (toplevel->in_transaction ) {
121+ Transaction *txn =
122+ toplevel->server ->transaction_manager ->current ();
123+ if (txn && txn->contains (toplevel))
124+ txn->handle_commit (toplevel);
125+ }
126+
117127 wlr_surface_state *state = &xwayland_surface->surface ->current ;
118128 wlr_box *current = &toplevel->geometry ;
119129
120130 // update size if state differs
121- if (current->width != state->width ||
122- current->height != state->height ) {
131+ if (!toplevel->in_transaction &&
132+ (current->width != state->width ||
133+ current->height != state->height )) {
123134 current->width = state->width ;
124135 current->height = state->height ;
125136 toplevel->set_position_size (*current);
@@ -159,9 +170,11 @@ void Toplevel::map_notify(wl_listener *listener, [[maybe_unused]] void *data) {
159170
160171 // center the surface to the focused output if zero
161172 if (!x)
162- x = output->layout_geometry .x + area.x + (area.width - width) / 2 ;
173+ x = output->layout_geometry .x + area.x +
174+ (area.width - width) / 2 ;
163175 if (!y)
164- y = output->layout_geometry .y + area.y + (area.height - height) / 2 ;
176+ y = output->layout_geometry .y + area.y +
177+ (area.height - height) / 2 ;
165178
166179 // send a configure event
167180 wlr_xwayland_surface_configure (xwayland_surface, x, y, width,
@@ -223,6 +236,12 @@ void Toplevel::unmap_notify(wl_listener *listener,
223236 Toplevel *toplevel = wl_container_of (listener, toplevel, unmap);
224237 Server *server = toplevel->server ;
225238
239+ // remove from any active transaction
240+ if (toplevel->in_transaction && server->transaction_manager ) {
241+ server->transaction_manager ->remove_toplevel (toplevel);
242+ toplevel->in_transaction = false ;
243+ }
244+
226245 // deactivate
227246 if (toplevel == server->seat ->grabbed_toplevel )
228247 server->cursor ->reset_mode ();
@@ -297,6 +316,13 @@ Toplevel::Toplevel(Server *server, wlr_xdg_toplevel *xdg_toplevel)
297316 WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE |
298317 WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE );
299318 }
319+
320+ // handle commit if part of transaction
321+ if (toplevel->in_transaction ) {
322+ Transaction *txn = toplevel->server ->transaction_manager ->current ();
323+ if (txn && txn->contains (toplevel))
324+ txn->handle_commit (toplevel);
325+ }
300326 };
301327 wl_signal_add (&xdg_toplevel->base ->surface ->events .commit , &commit);
302328
@@ -313,6 +339,10 @@ Toplevel::Toplevel(Server *server, wlr_xdg_toplevel *xdg_toplevel)
313339 // xdg_toplevel_destroy
314340 destroy.notify = [](wl_listener *listener, [[maybe_unused]] void *data) {
315341 Toplevel *toplevel = wl_container_of (listener, toplevel, destroy);
342+ if (toplevel->in_transaction && toplevel->server ->transaction_manager ) {
343+ toplevel->server ->transaction_manager ->remove_toplevel (toplevel);
344+ toplevel->in_transaction = false ;
345+ }
316346 delete toplevel;
317347 };
318348 wl_signal_add (&xdg_toplevel->events .destroy , &destroy);
@@ -479,6 +509,10 @@ Toplevel::Toplevel(Server *server, wlr_xwayland_surface *xwayland_surface)
479509 // destroy
480510 destroy.notify = [](wl_listener *listener, [[maybe_unused]] void *data) {
481511 Toplevel *toplevel = wl_container_of (listener, toplevel, destroy);
512+ if (toplevel->in_transaction && toplevel->server ->transaction_manager ) {
513+ toplevel->server ->transaction_manager ->remove_toplevel (toplevel);
514+ toplevel->in_transaction = false ;
515+ }
482516 delete toplevel;
483517 };
484518 wl_signal_add (&xwayland_surface->events .destroy , &destroy);
@@ -812,6 +846,12 @@ void Toplevel::begin_interactive(const CursorMode mode, const uint32_t edges) {
812846
813847// set the position and size of a toplevel, send a configure
814848void Toplevel::set_position_size (double x, double y, int width, int height) {
849+ if (Transaction *txn = server->transaction_manager ->current ()) {
850+ txn->add_change (this , static_cast <int >(x), static_cast <int >(y), width,
851+ height);
852+ return ;
853+ }
854+
815855 // xwayland surfaces can call fullscreen and maximize when unmapped so this
816856 // check is necessary
817857#ifdef XWAYLAND
0 commit comments