From d5c915e3cb9967b33b6fb6a9786d13c959dc629a Mon Sep 17 00:00:00 2001 From: dfangx Date: Wed, 11 May 2022 08:14:01 -0400 Subject: idle-inhibit: implement protocol --- river/IdleInhibitor.zig | 34 ++++++++++++++++++++++ river/IdleInhibitorManager.zig | 65 ++++++++++++++++++++++++++++++++++++++++++ river/Root.zig | 1 + river/Server.zig | 4 +++ river/View.zig | 7 +++++ 5 files changed, 111 insertions(+) create mode 100644 river/IdleInhibitor.zig create mode 100644 river/IdleInhibitorManager.zig diff --git a/river/IdleInhibitor.zig b/river/IdleInhibitor.zig new file mode 100644 index 0000000..6482222 --- /dev/null +++ b/river/IdleInhibitor.zig @@ -0,0 +1,34 @@ +const Self = @This(); + +const std = @import("std"); +const wlr = @import("wlroots"); +const wl = @import("wayland").server.wl; + +const server = &@import("main.zig").server; +const util = @import("util.zig"); + +const IdleInhibitorManager = @import("IdleInhibitorManager.zig"); + +inhibitor_manager: *IdleInhibitorManager, +inhibitor: *wlr.IdleInhibitorV1, +destroy: wl.Listener(*wlr.IdleInhibitorV1) = wl.Listener(*wlr.IdleInhibitorV1).init(handleDestroy), + +pub fn init(self: *Self, inhibitor: *wlr.IdleInhibitorV1, inhibitor_manager: *IdleInhibitorManager) !void { + self.inhibitor_manager = inhibitor_manager; + self.inhibitor = inhibitor; + self.destroy.setNotify(handleDestroy); + inhibitor.events.destroy.add(&self.destroy); + + inhibitor_manager.idleInhibitCheckActive(); +} + +fn handleDestroy(listener: *wl.Listener(*wlr.IdleInhibitorV1), _: *wlr.IdleInhibitorV1) void { + const self = @fieldParentPtr(Self, "destroy", listener); + self.destroy.link.remove(); + + const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); + server.idle_inhibitor_manager.inhibitors.remove(node); + util.gpa.destroy(node); + + self.inhibitor_manager.idleInhibitCheckActive(); +} diff --git a/river/IdleInhibitorManager.zig b/river/IdleInhibitorManager.zig new file mode 100644 index 0000000..88ba041 --- /dev/null +++ b/river/IdleInhibitorManager.zig @@ -0,0 +1,65 @@ +const Self = @This(); + +const std = @import("std"); +const wlr = @import("wlroots"); +const wl = @import("wayland").server.wl; + +const server = &@import("main.zig").server; +const util = @import("util.zig"); + +const View = @import("View.zig"); +const IdleInhibitor = @import("IdleInhibitor.zig"); + +idle_inhibit_manager: *wlr.IdleInhibitManagerV1, +new_idle_inhibitor: wl.Listener(*wlr.IdleInhibitorV1), +inhibitors: std.TailQueue(IdleInhibitor) = .{}, +idle: *wlr.Idle, + +pub fn init(self: *Self, idle: *wlr.Idle) !void { + self.idle_inhibit_manager = try wlr.IdleInhibitManagerV1.create(server.wl_server); + self.idle = idle; + self.new_idle_inhibitor.setNotify(handleNewIdleInhibitor); + self.idle_inhibit_manager.events.new_inhibitor.add(&self.new_idle_inhibitor); +} + +pub fn deinit(self: *Self) void { + while (self.inhibitors.pop()) |inhibitor| { + inhibitor.data.destroy.link.remove(); + util.gpa.destroy(inhibitor); + } + self.new_idle_inhibitor.link.remove(); +} + +pub fn idleInhibitCheckActive(self: *Self) void { + var inhibited = false; + var it = self.inhibitors.first; + while (it) |node| : (it = node.next) { + if (View.fromWlrSurface(node.data.inhibitor.surface)) |v| { + // If view is visible, + if (v.current.tags & v.output.current.tags != 0) { + inhibited = true; + break; + } + } else { + // If for whatever reason the inhibitor does not have a view, then + // assume it is visible. + inhibited = true; + break; + } + } + + self.idle.setEnabled(null, !inhibited); +} + +fn handleNewIdleInhibitor(listener: *wl.Listener(*wlr.IdleInhibitorV1), inhibitor: *wlr.IdleInhibitorV1) void { + const self = @fieldParentPtr(Self, "new_idle_inhibitor", listener); + const inhibitor_node = util.gpa.create(std.TailQueue(IdleInhibitor).Node) catch return; + inhibitor_node.data.init(inhibitor, self) catch { + util.gpa.destroy(inhibitor_node); + return; + }; + + self.inhibitors.append(inhibitor_node); + + self.idleInhibitCheckActive(); +} diff --git a/river/Root.zig b/river/Root.zig index 5796421..7175a33 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -395,6 +395,7 @@ fn commitTransaction(self: *Self) void { output.damage.addWhole(); } server.input_manager.updateCursorState(); + server.idle_inhibitor_manager.idleInhibitCheckActive(); } /// Send the new output configuration to all wlr-output-manager clients diff --git a/river/Server.zig b/river/Server.zig index 830f5c9..0a7bd94 100644 --- a/river/Server.zig +++ b/river/Server.zig @@ -36,6 +36,7 @@ const StatusManager = @import("StatusManager.zig"); const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig"); +const IdleInhibitorManager = @import("IdleInhibitorManager.zig"); const log = std.log.scoped(.server); @@ -69,6 +70,7 @@ config: Config, control: Control, status_manager: StatusManager, layout_manager: LayoutManager, +idle_inhibitor_manager: IdleInhibitorManager, pub fn init(self: *Self) !void { self.wl_server = try wl.Server.create(); @@ -123,6 +125,7 @@ pub fn init(self: *Self) !void { try self.control.init(); try self.status_manager.init(); try self.layout_manager.init(); + try self.idle_inhibitor_manager.init(self.input_manager.idle); // These all free themselves when the wl_server is destroyed _ = try wlr.DataDeviceManager.create(self.wl_server); @@ -148,6 +151,7 @@ pub fn deinit(self: *Self) void { self.root.deinit(); self.input_manager.deinit(); + self.idle_inhibitor_manager.deinit(); self.wl_server.destroy(); diff --git a/river/View.zig b/river/View.zig index 99996c9..1a6c0ae 100644 --- a/river/View.zig +++ b/river/View.zig @@ -436,6 +436,13 @@ pub fn fromWlrSurface(surface: *wlr.Surface) ?*Self { return @intToPtr(*Self, xwayland_surface.data); } } + if (surface.isSubsurface()) { + if (wlr.Subsurface.fromWlrSurface(surface)) |ss| { + if (ss.parent) |s| { + return fromWlrSurface(s); + } + } + } return null; } -- cgit v1.2.3