aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordfangx <github.oxfrj2ct@bged98.anonaddy.com>2022-05-11 08:14:01 -0400
committerGitHub <noreply@github.com>2022-05-11 14:14:01 +0200
commitd5c915e3cb9967b33b6fb6a9786d13c959dc629a (patch)
treef9c7532a948a098541029a448bca2290066bfab6
parent90b37645cf7744d8cc2a000fd3d74caf95bce204 (diff)
downloadriver-d5c915e3cb9967b33b6fb6a9786d13c959dc629a.tar.gz
river-d5c915e3cb9967b33b6fb6a9786d13c959dc629a.tar.xz
idle-inhibit: implement protocol
-rw-r--r--river/IdleInhibitor.zig34
-rw-r--r--river/IdleInhibitorManager.zig65
-rw-r--r--river/Root.zig1
-rw-r--r--river/Server.zig4
-rw-r--r--river/View.zig7
5 files changed, 111 insertions, 0 deletions
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;
}