From 60b06a67413ac041a5ed6a0828a57ab38bca8f25 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sun, 25 Feb 2024 13:42:58 +0100 Subject: [PATCH] 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);