aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--river/LockManager.zig2
-rw-r--r--river/Output.zig41
-rw-r--r--river/render.zig7
3 files changed, 46 insertions, 4 deletions
diff --git a/river/LockManager.zig b/river/LockManager.zig
index cc4b56a..6723bd4 100644
--- a/river/LockManager.zig
+++ b/river/LockManager.zig
@@ -149,7 +149,7 @@ pub fn maybeLock(manager: *LockManager) void {
while (it) |node| : (it = node.next) {
const output = &node.data;
switch (output.lock_render_state) {
- .unlocked => {
+ .unlocked, .pending_blank, .pending_lock_surface => {
all_outputs_blanked = false;
all_outputs_rendered_lock_surface = false;
},
diff --git a/river/Output.zig b/river/Output.zig
index d1469d9..0d5a541 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -70,8 +70,17 @@ views: ViewStack(View) = .{},
lock_surface: ?*LockSurface = null,
lock_render_state: enum {
+ /// Normal, "unlocked" content may be visible.
unlocked,
+ /// Submitted a blank buffer but the buffer has not yet been presented.
+ /// Normal, "unlocked" content may be visible.
+ pending_blank,
+ /// A blank buffer has been presented.
blanked,
+ /// Submitted the lock surface buffer but the buffer has not yet been presented.
+ /// Normal, "unlocked" content may be visible.
+ pending_lock_surface,
+ /// The lock surface buffer has been presented.
lock_surface,
} = .unlocked,
@@ -102,6 +111,7 @@ status_trackers: std.SinglyLinkedList(OutputStatus) = .{},
destroy: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleDestroy),
enable: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleEnable),
mode: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleMode),
+present: wl.Listener(*wlr.Output.event.Present) = wl.Listener(*wlr.Output.event.Present).init(handlePresent),
frame: wl.Listener(*wlr.OutputDamage) = wl.Listener(*wlr.OutputDamage).init(handleFrame),
damage_destroy: wl.Listener(*wlr.OutputDamage) = wl.Listener(*wlr.OutputDamage).init(handleDamageDestroy),
@@ -140,6 +150,7 @@ pub fn init(self: *Self, wlr_output: *wlr.Output) !void {
wlr_output.events.destroy.add(&self.destroy);
wlr_output.events.enable.add(&self.enable);
wlr_output.events.mode.add(&self.mode);
+ wlr_output.events.present.add(&self.present);
self.damage.?.events.frame.add(&self.frame);
self.damage.?.events.destroy.add(&self.damage_destroy);
@@ -478,6 +489,7 @@ fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
self.enable.link.remove();
self.frame.link.remove();
self.mode.link.remove();
+ self.present.link.remove();
// Free all memory and clean up the wlr.Output
if (self.layout_demand) |demand| demand.deinit();
@@ -511,6 +523,35 @@ fn handleMode(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
server.root.startTransaction();
}
+fn handlePresent(
+ listener: *wl.Listener(*wlr.Output.event.Present),
+ event: *wlr.Output.event.Present,
+) void {
+ const self = @fieldParentPtr(Self, "present", listener);
+
+ switch (self.lock_render_state) {
+ .unlocked => return,
+ .pending_blank, .pending_lock_surface => {
+ if (!event.presented) {
+ self.lock_render_state = .unlocked;
+ self.damage.?.addWhole();
+ return;
+ }
+
+ self.lock_render_state = switch (self.lock_render_state) {
+ .pending_blank => .blanked,
+ .pending_lock_surface => .lock_surface,
+ .unlocked, .blanked, .lock_surface => unreachable,
+ };
+
+ if (server.lock_manager.state != .locked) {
+ server.lock_manager.maybeLock();
+ }
+ },
+ .blanked, .lock_surface => unreachable,
+ }
+}
+
fn setTitle(self: Self) void {
const title = fmt.allocPrintZ(util.gpa, "river - {s}", .{self.wlr_output.name}) catch return;
defer util.gpa.free(title);
diff --git a/river/render.zig b/river/render.zig
index adef939..a238cd9 100644
--- a/river/render.zig
+++ b/river/render.zig
@@ -98,9 +98,10 @@ pub fn renderOutput(output: *Output) void {
return;
};
- output.lock_render_state = if (output.lock_surface != null) .lock_surface else .blanked;
- if (server.lock_manager.state != .locked) {
- server.lock_manager.maybeLock();
+ if (output.lock_surface == null) {
+ output.lock_render_state = .pending_blank;
+ } else {
+ output.lock_render_state = .pending_lock_surface;
}
return;