XdgToplevel: ensure view dimensions match geometry

Some clients (e.g. mpv) do not respond to configures by committing
buffers of the exact size requested. Instead they may commit a buffer of
a smaller size in order to maintain an aspect ratio or not commit a
buffer at all.
This commit is contained in:
Isaac Freund 2023-03-14 12:30:53 +01:00
parent 90f240355e
commit 9db41115a8
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
2 changed files with 26 additions and 6 deletions

View File

@ -247,13 +247,25 @@ pub fn destroy(view: *Self) void {
pub fn updateCurrent(view: *Self) void {
const config = &server.config;
if (view.impl == .xdg_toplevel) {
switch (view.impl.xdg_toplevel.configure_state) {
// If the configure timed out, don't update current to dimensions
// that have not been committed by the client.
.inflight, .acked => {
view.inflight.box.width = view.current.box.width;
view.inflight.box.height = view.current.box.height;
view.pending.box.width = view.current.box.width;
view.pending.box.height = view.current.box.height;
},
.idle, .committed => {},
}
view.impl.xdg_toplevel.configure_state = .idle;
}
view.foreign_toplevel_handle.update();
view.current = view.inflight;
view.dropSavedSurfaceTree();
if (view.impl == .xdg_toplevel) {
view.impl.xdg_toplevel.configure_state = .idle;
}
const color = blk: {
if (view.current.urgent) break :blk &config.border_color_urgent;

View File

@ -50,6 +50,8 @@ configure_state: union(enum) {
inflight: u32,
/// A configure was acked but the surface has not yet been committed.
acked,
/// A configure was acked and the surface was committed.
committed,
} = .idle,
// Listeners that are always active over the view's lifetime
@ -288,7 +290,7 @@ fn handleAckConfigure(
.inflight => |serial| if (acked_configure.serial == serial) {
self.configure_state = .acked;
},
.acked, .idle => {},
.acked, .idle, .committed => {},
}
}
@ -310,7 +312,7 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
self.xdg_toplevel.base.getGeometry(&self.geometry);
switch (self.configure_state) {
.idle => {
.idle, .committed => {
const size_changed = self.geometry.width != old_geometry.width or
self.geometry.height != old_geometry.height;
const no_layout = view.current.output != null and view.current.output.?.layout == null;
@ -334,7 +336,13 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
// stashed buffer from when the transaction started.
.inflight => view.sendFrameDone(),
.acked => {
self.configure_state = .idle;
self.configure_state = .committed;
view.inflight.box.width = self.geometry.width;
view.inflight.box.height = self.geometry.height;
view.pending.box.width = self.geometry.width;
view.pending.box.height = self.geometry.height;
server.root.notifyConfigured();
},
}