Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
View: improve transaction timeout handling
This fixes a possible assertion failure in Cursor.updateState() when
trying to start move/resize of a xdg toplevel with the timed_out or
timed_out_acked configure_state.
This also generally improves the UX of transaction timeouts as all
state except for the size change is now applied immediately.
river/View.zig | 34 ++++++++++++++++++----------------
river/XdgToplevel.zig | 10 ++++++----
2 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/river/View.zig b/river/View.zig
index ed7441a..9f7d4bc 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -285,26 +285,28 @@ pub fn commitTransaction(view: *Self) void {
view.foreign_toplevel_handle.update();
- // Tag and output changes must be applied immediately even if the configure sequence times out.
- // This allows Root.commitTransaction() to rely on the fact that all tag and output changes
- // are applied directly by this function.
- view.current.tags = view.inflight.tags;
- view.current.output = view.inflight.output;
-
view.dropSavedSurfaceTree();
switch (view.impl) {
.xdg_toplevel => |*xdg_toplevel| {
switch (xdg_toplevel.configure_state) {
- .inflight => |serial| {
- xdg_toplevel.configure_state = .{ .timed_out = serial };
- },
- .acked => {
- xdg_toplevel.configure_state = .timed_out_acked;
+ .inflight, .acked => {
+ switch (xdg_toplevel.configure_state) {
+ .inflight => |serial| xdg_toplevel.configure_state = .{ .timed_out = serial },
+ .acked => xdg_toplevel.configure_state = .timed_out_acked,
+ else => unreachable,
+ }
+ // The width and height cannot be updated until the client has
+ // committed a new buffer in response to the configure.
+ const old_width = view.current.box.width;
+ const old_height = view.current.box.height;
+ view.current = view.inflight;
+ view.current.box.width = old_width;
+ view.current.box.height = old_height;
},
.idle, .committed => {
xdg_toplevel.configure_state = .idle;
- view.updateCurrent();
+ view.current = view.inflight;
},
.timed_out, .timed_out_acked => unreachable,
}
@@ -322,15 +324,15 @@ pub fn commitTransaction(view: *Self) void {
view.pending.box.width = xwayland_view.xwayland_surface.width;
view.pending.box.height = xwayland_view.xwayland_surface.height;
- view.updateCurrent();
+ view.current = view.inflight;
},
.none => {},
}
-}
-pub fn updateCurrent(view: *Self) void {
- view.current = view.inflight;
+ view.updateSceneState();
+}
+pub fn updateSceneState(view: *Self) void {
const box = &view.current.box;
view.tree.node.setPosition(box.x, box.y);
view.popup_tree.node.setPosition(box.x, box.y);
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 0ae9f5b..6382fb6 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -369,7 +369,8 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
view.inflight.box.height = self.geometry.height;
view.pending.box.width = self.geometry.width;
view.pending.box.height = self.geometry.height;
- view.updateCurrent();
+ view.current = view.inflight;
+ view.updateSceneState();
}
},
// If the client has not yet acked our configure, we need to send a
@@ -377,7 +378,7 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
// buffers won't be rendered since we are still rendering our
// stashed buffer from when the transaction started.
.inflight => view.sendFrameDone(),
- inline .acked, .timed_out_acked => |_, tag| {
+ .acked, .timed_out_acked => {
if (view.inflight.resizing) {
view.resizeUpdatePosition(self.geometry.width, self.geometry.height);
}
@@ -387,14 +388,15 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
view.pending.box.width = self.geometry.width;
view.pending.box.height = self.geometry.height;
- switch (tag) {
+ switch (self.configure_state) {
.acked => {
self.configure_state = .committed;
server.root.notifyConfigured();
},
.timed_out_acked => {
self.configure_state = .idle;
- view.updateCurrent();
+ view.current = view.inflight;
+ view.updateSceneState();
},
else => unreachable,
}