Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
OutputManager: fix disabling outputs
river/Output.zig | 9 +++++----
river/OutputManager.zig | 36 +++++++++++++++++++-----------------
2 files changed, 24 insertions(+), 21 deletions(-)
diff --git a/river/Output.zig b/river/Output.zig
index dba4d3e..2a83e31 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -98,8 +98,10 @@ pub const State = struct {
}
pub fn applyModeset(state: *const State, wlr_state: *wlr.Output.State) void {
+ const enabled = state.state == .enabled;
+ wlr_state.setEnabled(enabled);
+ if (!enabled) return;
state.applyNoModeset(wlr_state);
- wlr_state.setEnabled(state.state == .enabled);
switch (state.mode) {
.standard => |mode| wlr_state.setMode(mode),
.custom => |mode| wlr_state.setCustomMode(mode.width, mode.height, mode.refresh),
@@ -283,7 +285,6 @@ pub fn manageStart(output: *Output) void {
}
output.sent = output.scheduled;
-
output.link_sent.remove();
server.wm.wm_sent.outputs.append(output);
},
@@ -295,8 +296,7 @@ pub fn manageStart(output: *Output) void {
output.object = null;
}
- output.link_sent.remove();
- output.link_sent.init();
+ output.sent = output.scheduled;
if (output.scheduled.state == .destroying) {
{
@@ -316,6 +316,7 @@ pub fn manageStart(output: *Output) void {
}
}
output.link.remove();
+ output.link_sent.remove();
util.gpa.destroy(output);
}
diff --git a/river/OutputManager.zig b/river/OutputManager.zig
index ff2ff27..bce5cbf 100644
--- a/river/OutputManager.zig
+++ b/river/OutputManager.zig
@@ -147,9 +147,13 @@ fn handleManagerApply(_: *wl.Listener(*wlr.OutputConfigurationV1), config: *wlr.
var it = config.heads.iterator(.forward);
while (it.next()) |head| {
const output: *Output = @ptrCast(@alignCast(head.state.output.data));
-
+ if (!head.state.enabled) {
+ // Avoid overwriting and losing all other output state on disable.
+ output.scheduled.state = .disabled_hard;
+ continue;
+ }
output.scheduled = .{
- .state = if (head.state.enabled) .enabled else .disabled_hard,
+ .state = .enabled,
.mode = blk: {
if (head.state.mode) |mode| {
break :blk .{ .standard = mode };
@@ -252,7 +256,6 @@ pub fn autoLayout(om: *OutputManager) void {
pub fn commitOutputState(om: *OutputManager) void {
const wm = &server.wm;
-
{
var it = wm.wm_sent.outputs.iterator(.forward);
while (it.next()) |output| {
@@ -309,6 +312,8 @@ pub fn commitOutputState(om: *OutputManager) void {
};
if (need_modeset) {
+ log.debug("committing output state requires modeset", .{});
+
var states: std.ArrayList(wlr.Backend.OutputState) = .empty;
defer states.deinit(util.gpa);
defer for (states.items) |*s| s.base.finish();
@@ -386,16 +391,6 @@ pub fn commitOutputState(om: *OutputManager) void {
}
swapchain_manager.apply();
-
- {
- var it = wm.wm_sent.outputs.iterator(.forward);
- while (it.next()) |output| {
- const wlr_output = output.wlr_output orelse continue;
- if (!wlr_output.enabled) {
- output.lock_render_state = .blanked;
- }
- }
- }
}
if (wm.wm_sent.output_config) |config| {
@@ -405,13 +400,20 @@ pub fn commitOutputState(om: *OutputManager) void {
}
{
- var it = wm.wm_sent.outputs.iterator(.forward);
+ var it = wm.wm_sent.outputs.safeIterator(.forward);
while (it.next()) |output| {
- output.current = output.sent;
-
if (output.wlr_output) |wlr_output| {
- wlr_output.scheduleFrame();
+ if (wlr_output.enabled) {
+ wlr_output.scheduleFrame();
+ } else {
+ output.lock_render_state = .blanked;
+ }
}
+ if (output.sent.state == .disabled_hard) {
+ output.link_sent.remove();
+ output.link_sent.init();
+ }
+ output.current = output.sent;
}
}