Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
OutputManager: tighten asserts, resolve XXX comments
river/Output.zig | 5 +++--
river/OutputManager.zig | 43 ++++++++++++++++++++++---------------------
2 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/river/Output.zig b/river/Output.zig
index 7300a8f..d453df8 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -122,7 +122,6 @@ layer_shell: LayerShellOutput = .{},
/// The output is initially considered blanked:
/// If using the DRM backend it will be blanked with the initial modeset.
/// If using the Wayland or X11 backend nothing will be visible until the first frame is rendered.
-/// XXX set this to blanked on enabled->disabled transition
lock_render_state: enum {
/// Submitted an unlocked buffer but the buffer has not yet been presented.
pending_unlock,
@@ -211,7 +210,7 @@ pub fn create(wlr_output: *wlr.Output) !void {
fn handleDestroy(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
const output: *Output = @fieldParentPtr("destroy", listener);
- log.debug("output '{s}' destroyed", .{wlr_output.name});
+ log.debug("wlr_output '{s}' destroyed", .{wlr_output.name});
{
var it = server.layer_shell.surfaces.iterator();
@@ -285,6 +284,7 @@ pub fn manageStart(output: *Output) void {
}
output.sent = output.scheduled;
+
output.link_sent.remove();
server.wm.sent.outputs.append(output);
},
@@ -299,6 +299,7 @@ pub fn manageStart(output: *Output) void {
output.sent = output.scheduled;
if (output.scheduled.state == .destroying) {
+ assert(output.wlr_output == null);
{
var it = server.wm.windows.iterator();
while (it.next()) |window| {
diff --git a/river/OutputManager.zig b/river/OutputManager.zig
index beb393e..7b09086 100644
--- a/river/OutputManager.zig
+++ b/river/OutputManager.zig
@@ -259,11 +259,10 @@ pub fn commitOutputState(om: *OutputManager) void {
{
var it = wm.sent.outputs.iterator(.forward);
while (it.next()) |output| {
- const wlr_output = output.wlr_output orelse continue;
switch (output.sent.state) {
.enabled, .disabled_soft => {
output.scene_output.?.setPosition(output.sent.x, output.sent.y);
- _ = om.output_layout.add(wlr_output, output.sent.x, output.sent.y) catch {
+ _ = om.output_layout.add(output.wlr_output.?, output.sent.x, output.sent.y) catch {
log.err("out of memory", .{});
continue; // Try again next time
};
@@ -271,10 +270,11 @@ pub fn commitOutputState(om: *OutputManager) void {
lock_surface.tree.node.setPosition(output.sent.x, output.sent.y);
}
},
- .disabled_hard, .destroying => {
- om.output_layout.remove(wlr_output);
+ .disabled_hard => {
+ om.output_layout.remove(output.wlr_output.?);
output.sent_wl_output = false;
},
+ .destroying => unreachable,
}
}
}
@@ -284,14 +284,11 @@ pub fn commitOutputState(om: *OutputManager) void {
const need_modeset = blk: {
var it = wm.sent.outputs.iterator(.forward);
while (it.next()) |output| {
- const wlr_output = output.wlr_output orelse continue;
+ const wlr_output = output.wlr_output.?;
switch (output.sent.state) {
.enabled => if (!wlr_output.enabled) break :blk true,
- // Technically disabling an output does not require a modeset,
- // but handling both enabled and disable here simplifies
- // lock_render_state tracking.
.disabled_soft, .disabled_hard => if (wlr_output.enabled) break :blk true,
- .destroying => unreachable, // output.wlr_output must be null.
+ .destroying => unreachable,
}
switch (output.sent.mode) {
.standard => |mode| {
@@ -321,13 +318,12 @@ pub fn commitOutputState(om: *OutputManager) void {
{
var it = wm.sent.outputs.iterator(.forward);
while (it.next()) |output| {
- const wlr_output = output.wlr_output orelse continue;
const state = states.addOne(util.gpa) catch {
log.err("out of memory", .{});
return;
};
- state.output = wlr_output;
+ state.output = output.wlr_output.?;
state.base = wlr.Output.State.init();
output.sent.applyModeset(&state.base);
@@ -402,22 +398,25 @@ pub fn commitOutputState(om: *OutputManager) void {
{
var it = wm.sent.outputs.safeIterator(.forward);
while (it.next()) |output| {
- if (output.wlr_output) |wlr_output| {
- if (wlr_output.enabled) {
- wlr_output.scheduleFrame();
- } else {
+ switch (output.sent.state) {
+ .enabled => {
+ assert(output.wlr_output.?.enabled);
+ output.wlr_output.?.scheduleFrame();
+ },
+ .disabled_soft, .disabled_hard => {
+ assert(!output.wlr_output.?.enabled);
output.lock_render_state = .blanked;
- }
- }
- if (output.sent.state == .disabled_hard) {
- output.link_sent.remove();
- output.link_sent.init();
+ if (output.sent.state == .disabled_hard) {
+ output.link_sent.remove();
+ output.link_sent.init();
+ }
+ },
+ .destroying => unreachable,
}
output.current = output.sent;
}
}
- // XXX sending this every transaction is too noisy
om.sendConfig() catch {
log.err("out of memory", .{});
};
@@ -447,5 +446,7 @@ fn sendConfig(om: *OutputManager) !void {
head.state.y = output.current.y;
}
+ // wlroots won't send events to clients unless something has changed
+ // compared to the last config set.
om.wlr_output_manager.setConfiguration(config);
}