View: fix/simplify logic in applyPending()

In particular, this fixes a crash that can happen if a client is made
non-fullscreen and then, while that transaction is ongoing, made
fullscreen again.
This commit is contained in:
Isaac Freund 2022-02-03 21:23:02 +01:00
parent 79d7775a3d
commit be870e058d
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
3 changed files with 22 additions and 27 deletions

View File

@ -171,26 +171,16 @@ pub fn destroy(self: *Self) void {
/// Handle changes to pending state and start a transaction to apply them
pub fn applyPending(self: *Self) void {
var arrange_output = false;
if (self.current.tags != self.pending.tags) arrange_output = true;
// If switching from float -> layout or layout -> float arrange the output
// to get assigned a new size or fill the hole in the layout left behind.
if (self.current.float != self.pending.float) {
assert(!self.pending.fullscreen); // float state modifed while in fullscreen
arrange_output = true;
if (self.current.float and !self.pending.float) {
// If switching from float to non-float, save the dimensions.
self.float_box = self.current.box;
} else if (!self.current.float and self.pending.float) {
// If switching from non-float to float, apply the saved float dimensions.
self.pending.box = self.float_box;
}
// If switching from float to non-float, save the dimensions.
if (self.current.float and !self.pending.float) self.float_box = self.current.box;
// If switching from non-float to float, apply the saved float dimensions.
if (!self.current.float and self.pending.float) self.pending.box = self.float_box;
// If switching to fullscreen, set the dimensions to the full area of the output
// Since no other views will be visible, we can skip arranging the output.
if (!self.current.fullscreen and self.pending.fullscreen) {
// If switching to fullscreen, set the dimensions to the full area of the output
self.setFullscreen(true);
self.post_fullscreen_box = self.current.box;
const dimensions = self.output.getEffectiveResolution();
@ -200,16 +190,17 @@ pub fn applyPending(self: *Self) void {
.width = dimensions.width,
.height = dimensions.height,
};
}
if (self.current.fullscreen and !self.pending.fullscreen) {
} else if (self.current.fullscreen and !self.pending.fullscreen) {
self.setFullscreen(false);
self.pending.box = self.post_fullscreen_box;
// If switching from fullscreen to layout, we need to arrange the output.
if (!self.pending.float) arrange_output = true;
}
if (arrange_output) self.output.arrangeViews();
// We always need to arrange the output, as there could already be a
// transaction in progress. If we were able to check against the state
// that was pending when that transaction was started, we could in some
// cases avoid the arrangeViews() call here, but we don't store that
// information and it's simpler to always arrange anyways.
self.output.arrangeViews();
server.root.startTransaction();
}

View File

@ -329,8 +329,10 @@ fn handleRequestFullscreen(
event: *wlr.XdgToplevel.event.SetFullscreen,
) void {
const self = @fieldParentPtr(Self, "request_fullscreen", listener);
self.view.pending.fullscreen = event.fullscreen;
self.view.applyPending();
if (self.view.pending.fullscreen != event.fullscreen) {
self.view.pending.fullscreen = event.fullscreen;
self.view.applyPending();
}
}
/// Called when the client asks to be moved via the cursor, for example when the

View File

@ -273,8 +273,10 @@ fn handleSetClass(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.Xwayland
fn handleRequestFullscreen(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wlr.XwaylandSurface) void {
const self = @fieldParentPtr(Self, "request_fullscreen", listener);
self.view.pending.fullscreen = xwayland_surface.fullscreen;
self.view.applyPending();
if (self.view.pending.fullscreen != xwayland_surface.fullscreen) {
self.view.pending.fullscreen = xwayland_surface.fullscreen;
self.view.applyPending();
}
}
/// Some X11 clients will minimize themselves regardless of how we respond.