Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
XdgToplevel: handle timed out state in configure()
If a new transaction is started that calls configure() on an xdg
toplevel with a timed_out/timed_out_acked configure_state we currently
leave the configure_state untouched if no new configure is needed.
This can cause an assertion failure in View.commitTransaction() if the
xdg toplevel still hasn't acked/committed by the time the new
transaction completes.
To fix this, update the configure_state as necessary.
river/XdgToplevel.zig | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index dbb3340..653b01c 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -118,6 +118,11 @@ pub fn configure(self: *Self) bool {
.inflight, .acked, .committed => unreachable,
}
+ defer switch (self.configure_state) {
+ .idle, .inflight, .acked => {},
+ .timed_out, .timed_out_acked, .committed => unreachable,
+ };
+
const inflight = &self.view.inflight;
const current = &self.view.current;
@@ -135,7 +140,20 @@ pub fn configure(self: *Self) bool {
inflight.ssd == current.ssd and
inflight.resizing == current.resizing)
{
- return false;
+ // If no new configure is required, continue to track a timed out configure
+ // from the previous transaction if any.
+ switch (self.configure_state) {
+ .idle => return false,
+ .timed_out => |serial| {
+ self.configure_state = .{ .inflight = serial };
+ return true;
+ },
+ .timed_out_acked => {
+ self.configure_state = .acked;
+ return true;
+ },
+ .inflight, .acked, .committed => unreachable,
+ }
}
_ = self.xdg_toplevel.setActivated(inflight.focus != 0);
@@ -160,8 +178,11 @@ pub fn configure(self: *Self) bool {
const configure_serial = self.xdg_toplevel.setSize(inflight.box.width, inflight.box.height);
// Only track configures with the transaction system if they affect the dimensions of the view.
+ // If the configure state is not idle this means we are currently tracking a timed out
+ // configure from a previous transaction and should instead track the newly sent configure.
if (inflight.box.width == current.box.width and
- inflight.box.height == current.box.height)
+ inflight.box.height == current.box.height and
+ self.configure_state == .idle)
{
return false;
}