Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
output-management: fix output destroy handling
Currently we update output-management clients based on changes in the
wlr_output_layout struct. However, this is obviously wrong on closer
inspection due to the fact that not all outputs are tracked by the
wlr_output_layout at all times. I think this aproach was originally
cargo-culted from some other output-management implementation and it
needs to go.
Luckily, the solution is quite simple since the only way to configure
outputs using river is through the wlr-output-management protocol. This
means we need to send a new configuration to the output-management
client in 3 cases:
1. An output is created
2. An output is destroyed
3. A wlr-output-management config from a client is applied
river/Output.zig | 2 ++
river/Root.zig | 21 ++++++---------------
2 files changed, 8 insertions(+), 15 deletions(-)
diff --git a/river/Output.zig b/river/Output.zig
index f731c64..dcd6dfb 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -409,6 +409,8 @@ fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
util.gpa.destroy(output);
+ server.root.sendOutputManagerConfig();
+
server.root.applyPending();
}
diff --git a/river/Root.zig b/river/Root.zig
index b9775d7..f4bf0fe 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -81,7 +81,6 @@ views: wl.list.Head(View, .link),
new_output: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleNewOutput),
output_layout: *wlr.OutputLayout,
-layout_change: wl.Listener(*wlr.OutputLayout) = wl.Listener(*wlr.OutputLayout).init(handleLayoutChange),
output_manager: *wlr.OutputManagerV1,
manager_apply: wl.Listener(*wlr.OutputConfigurationV1) =
@@ -186,7 +185,6 @@ pub fn init(self: *Self) !void {
server.backend.events.new_output.add(&self.new_output);
self.output_manager.events.apply.add(&self.manager_apply);
self.output_manager.events.@"test".add(&self.manager_test);
- self.output_layout.events.change.add(&self.layout_change);
self.power_manager.events.set_mode.add(&self.power_manager_set_mode);
self.gamma_control_manager.events.set_gamma.add(&self.gamma_control_set_gamma);
}
@@ -245,8 +243,11 @@ fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
error.InitRenderFailed => log.err("failed to initialize renderer for output {s}", .{wlr_output.name}),
}
wlr_output.destroy();
+ return;
};
+ server.root.sendOutputManagerConfig();
+
server.input_manager.reconfigureDevices();
}
@@ -711,10 +712,8 @@ fn commitTransaction(root: *Self) void {
}
}
-/// Send the new output configuration to all wlr-output-manager clients
-fn handleLayoutChange(listener: *wl.Listener(*wlr.OutputLayout), _: *wlr.OutputLayout) void {
- const self = @fieldParentPtr(Self, "layout_change", listener);
-
+/// Send the current output configuration to all wlr-output-manager clients
+pub fn sendOutputManagerConfig(self: *Self) void {
const config = self.currentOutputConfig() catch {
std.log.scoped(.output_manager).err("out of memory", .{});
return;
@@ -734,11 +733,7 @@ fn handleManagerApply(
self.processOutputConfig(config, .apply);
// Send the config that was actually applied
- const applied_config = self.currentOutputConfig() catch {
- std.log.scoped(.output_manager).err("out of memory", .{});
- return;
- };
- self.output_manager.setConfiguration(applied_config);
+ self.sendOutputManagerConfig();
}
fn handleManagerTest(
@@ -756,10 +751,6 @@ fn processOutputConfig(
config: *wlr.OutputConfigurationV1,
action: enum { test_only, apply },
) void {
- // Ignore layout change events this function generates while applying the config
- self.layout_change.link.remove();
- defer self.output_layout.events.change.add(&self.layout_change);
-
var success = true;
var it = config.heads.iterator(.forward);