aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <mail@isaacfreund.com>2023-03-04 22:41:35 +0100
committerIsaac Freund <mail@isaacfreund.com>2023-03-04 22:41:35 +0100
commit44004e2d28a3a3af5b84f20f859c58ed360ef50d (patch)
tree56b60de96821868f53c6825e1ab0856699e86447
parentea4e589fdcb78f99f7e7cbc041287b9dd42e01d0 (diff)
downloadriver-44004e2d28a3a3af5b84f20f859c58ed360ef50d.tar.gz
river-44004e2d28a3a3af5b84f20f859c58ed360ef50d.tar.xz
SceneNodeData: allow access from wlr_surfaces
This replaces the old View.fromWlrSurface function and is more general. This commit also moves the xdg activation request_activate listener to Server as it has no reason to be in View.
-rw-r--r--river/IdleInhibitorManager.zig30
-rw-r--r--river/LayerSurface.zig2
-rw-r--r--river/LockSurface.zig2
-rw-r--r--river/Root.zig2
-rw-r--r--river/SceneNodeData.zig11
-rw-r--r--river/Server.zig35
-rw-r--r--river/View.zig34
-rw-r--r--river/XdgPopup.zig2
-rw-r--r--river/XdgToplevel.zig1
-rw-r--r--river/XwaylandOverrideRedirect.zig8
-rw-r--r--river/XwaylandView.zig6
11 files changed, 80 insertions, 53 deletions
diff --git a/river/IdleInhibitorManager.zig b/river/IdleInhibitorManager.zig
index e3b198c..945f3f8 100644
--- a/river/IdleInhibitorManager.zig
+++ b/river/IdleInhibitorManager.zig
@@ -7,8 +7,9 @@ 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");
+const SceneNodeData = @import("SceneNodeData.zig");
+const View = @import("View.zig");
idle_inhibit_manager: *wlr.IdleInhibitManagerV1,
new_idle_inhibitor: wl.Listener(*wlr.IdleInhibitorV1),
@@ -32,17 +33,26 @@ 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.output != null and v.current.tags & v.current.output.?.current.tags != 0) {
+ const node_data = SceneNodeData.fromSurface(node.data.inhibitor.surface) orelse continue;
+ switch (node_data.data) {
+ .view => |view| {
+ if (view.current.output != null and
+ view.current.tags & view.current.output.?.current.tags != 0)
+ {
+ inhibited = true;
+ break;
+ }
+ },
+ .layer_surface => |layer_surface| {
+ if (layer_surface.wlr_layer_surface.mapped) {
+ inhibited = true;
+ break;
+ }
+ },
+ .lock_surface, .xwayland_override_redirect => {
inhibited = true;
break;
- }
- } else {
- // If for whatever reason the inhibitor does not have a view, then
- // assume it is visible.
- inhibited = true;
- break;
+ },
}
}
diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig
index 2a8a770..265a4dc 100644
--- a/river/LayerSurface.zig
+++ b/river/LayerSurface.zig
@@ -60,6 +60,8 @@ pub fn create(wlr_layer_surface: *wlr.LayerSurfaceV1) error{OutOfMemory}!void {
try SceneNodeData.attach(&layer_surface.scene_layer_surface.tree.node, .{ .layer_surface = layer_surface });
try SceneNodeData.attach(&layer_surface.popup_tree.node, .{ .layer_surface = layer_surface });
+ wlr_layer_surface.surface.data = @ptrToInt(&layer_surface.scene_layer_surface.tree.node);
+
wlr_layer_surface.events.destroy.add(&layer_surface.destroy);
wlr_layer_surface.events.map.add(&layer_surface.map);
wlr_layer_surface.events.unmap.add(&layer_surface.unmap);
diff --git a/river/LockSurface.zig b/river/LockSurface.zig
index 83f95b3..8f58f45 100644
--- a/river/LockSurface.zig
+++ b/river/LockSurface.zig
@@ -51,6 +51,8 @@ pub fn create(wlr_lock_surface: *wlr.SessionLockSurfaceV1, lock: *wlr.SessionLoc
try SceneNodeData.attach(&tree.node, .{ .lock_surface = lock_surface });
+ wlr_lock_surface.surface.data = @ptrToInt(&tree.node);
+
wlr_lock_surface.output.events.mode.add(&lock_surface.output_mode);
wlr_lock_surface.events.map.add(&lock_surface.map);
wlr_lock_surface.events.destroy.add(&lock_surface.surface_destroy);
diff --git a/river/Root.zig b/river/Root.zig
index cbbfd21..419b392 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -195,7 +195,7 @@ pub fn at(self: Self, lx: f64, ly: f64) ?AtResult {
break :blk null;
};
- if (SceneNodeData.get(node_at)) |scene_node_data| {
+ if (SceneNodeData.fromNode(node_at)) |scene_node_data| {
return .{
.surface = surface,
.sx = sx,
diff --git a/river/SceneNodeData.zig b/river/SceneNodeData.zig
index f79bc59..782351f 100644
--- a/river/SceneNodeData.zig
+++ b/river/SceneNodeData.zig
@@ -50,7 +50,7 @@ pub fn attach(node: *wlr.SceneNode, data: Data) error{OutOfMemory}!void {
node.events.destroy.add(&scene_node_data.destroy);
}
-pub fn get(node: *wlr.SceneNode) ?*SceneNodeData {
+pub fn fromNode(node: *wlr.SceneNode) ?*SceneNodeData {
var it: ?*wlr.SceneNode = node;
while (it) |n| : (it = n.parent) {
if (@intToPtr(?*SceneNodeData, n.data)) |scene_node_data| {
@@ -60,6 +60,15 @@ pub fn get(node: *wlr.SceneNode) ?*SceneNodeData {
return null;
}
+pub fn fromSurface(surface: *wlr.Surface) ?*SceneNodeData {
+ if (surface.getRootSurface()) |root_surface| {
+ if (@intToPtr(?*wlr.SceneNode, root_surface.data)) |node| {
+ return fromNode(node);
+ }
+ }
+ return null;
+}
+
fn handleDestroy(listener: *wl.Listener(void)) void {
const scene_node_data = @fieldParentPtr(SceneNodeData, "destroy", listener);
diff --git a/river/Server.zig b/river/Server.zig
index 291567e..3715f1e 100644
--- a/river/Server.zig
+++ b/river/Server.zig
@@ -27,17 +27,18 @@ const util = @import("util.zig");
const Config = @import("Config.zig");
const Control = @import("Control.zig");
const DecorationManager = @import("DecorationManager.zig");
+const IdleInhibitorManager = @import("IdleInhibitorManager.zig");
const InputManager = @import("InputManager.zig");
const LayerSurface = @import("LayerSurface.zig");
const LayoutManager = @import("LayoutManager.zig");
const LockManager = @import("LockManager.zig");
const Output = @import("Output.zig");
const Root = @import("Root.zig");
+const SceneNodeData = @import("SceneNodeData.zig");
const StatusManager = @import("StatusManager.zig");
const XdgToplevel = @import("XdgToplevel.zig");
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
const XwaylandView = @import("XwaylandView.zig");
-const IdleInhibitorManager = @import("IdleInhibitorManager.zig");
const log = std.log.scoped(.server);
@@ -62,6 +63,7 @@ xwayland: if (build_options.xwayland) *wlr.Xwayland else void,
new_xwayland_surface: if (build_options.xwayland) wl.Listener(*wlr.XwaylandSurface) else void,
xdg_activation: *wlr.XdgActivationV1,
+request_activate: wl.Listener(*wlr.XdgActivationV1.event.RequestActivate),
decoration_manager: DecorationManager,
input_manager: InputManager,
@@ -115,6 +117,8 @@ pub fn init(self: *Self) !void {
}
self.xdg_activation = try wlr.XdgActivationV1.create(self.wl_server);
+ self.xdg_activation.events.request_activate.add(&self.request_activate);
+ self.request_activate.setNotify(handleRequestActivate);
_ = try wlr.PrimarySelectionDeviceManagerV1.create(self.wl_server);
@@ -144,7 +148,14 @@ pub fn deinit(self: *Self) void {
self.sigint_source.remove();
self.sigterm_source.remove();
- if (build_options.xwayland) self.xwayland.destroy();
+ self.new_xdg_surface.link.remove();
+ self.new_layer_surface.link.remove();
+ self.request_activate.link.remove();
+
+ if (build_options.xwayland) {
+ self.new_xwayland_surface.link.remove();
+ self.xwayland.destroy();
+ }
self.wl_server.destroyClients();
@@ -251,3 +262,23 @@ fn handleNewXwaylandSurface(_: *wl.Listener(*wlr.XwaylandSurface), xwayland_surf
};
}
}
+
+fn handleRequestActivate(
+ listener: *wl.Listener(*wlr.XdgActivationV1.event.RequestActivate),
+ event: *wlr.XdgActivationV1.event.RequestActivate,
+) void {
+ const server = @fieldParentPtr(Self, "request_activate", listener);
+
+ std.debug.print("made it here ig\n", .{});
+
+ const node_data = SceneNodeData.fromSurface(event.surface) orelse return;
+ switch (node_data.data) {
+ .view => |view| if (view.current.focus == 0) {
+ view.pending.urgent = true;
+ server.root.applyPending();
+ },
+ else => |tag| {
+ log.info("ignoring xdg-activation-v1 activate request of {s} surface", .{@tagName(tag)});
+ },
+ }
+}
diff --git a/river/View.zig b/river/View.zig
index 3c783a7..24e6652 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -147,9 +147,6 @@ float_box: wlr.Box = undefined,
/// exiting fullscreen if there is no active layout.
post_fullscreen_box: wlr.Box = undefined,
-request_activate: wl.Listener(*wlr.XdgActivationV1.event.RequestActivate) =
- wl.Listener(*wlr.XdgActivationV1.event.RequestActivate).init(handleRequestActivate),
-
pub fn create(impl: Impl) error{OutOfMemory}!*Self {
const view = try util.gpa.create(Self);
errdefer util.gpa.destroy(view);
@@ -383,21 +380,6 @@ pub fn applyConstraints(self: *Self, box: *wlr.Box) void {
box.height = math.clamp(box.height, self.constraints.min_height, self.constraints.max_height);
}
-/// Find and return the view corresponding to a given surface, if any
-pub fn fromWlrSurface(surface: *wlr.Surface) ?*Self {
- if (surface.isXdgSurface()) {
- const xdg_surface = wlr.XdgSurface.fromWlrSurface(surface) orelse return null;
- if (xdg_surface.role == .toplevel) {
- return @intToPtr(*Self, xdg_surface.data);
- }
- }
- if (build_options.xwayland and surface.isXWaylandSurface()) {
- const xwayland_surface = wlr.XwaylandSurface.fromWlrSurface(surface) orelse return null;
- return @intToPtr(?*Self, xwayland_surface.data);
- }
- return null;
-}
-
/// Called by the impl when the surface is ready to be displayed
pub fn map(view: *Self) !void {
log.debug("view '{?s}' mapped", .{view.getTitle()});
@@ -407,8 +389,6 @@ pub fn map(view: *Self) !void {
view.pending.borders = !server.config.csdAllowed(view);
- server.xdg_activation.events.request_activate.add(&view.request_activate);
-
if (server.input_manager.defaultSeat().focused_output) |output| {
// Center the initial pending box on the output
view.pending.box.x = @divTrunc(math.max(0, output.usable_box.width - view.pending.box.width), 2);
@@ -444,8 +424,6 @@ pub fn unmap(view: *Self) void {
server.root.hidden.pending.wm_stack.prepend(view);
}
- view.request_activate.link.remove();
-
assert(view.mapped and !view.destroying);
view.mapped = false;
@@ -468,15 +446,3 @@ pub fn notifyTitle(self: *const Self) void {
pub fn notifyAppId(_: Self) void {
// TODO reimplement foreign-toplevel-management I guess.
}
-
-fn handleRequestActivate(
- _: *wl.Listener(*wlr.XdgActivationV1.event.RequestActivate),
- event: *wlr.XdgActivationV1.event.RequestActivate,
-) void {
- if (fromWlrSurface(event.surface)) |view| {
- if (view.current.focus == 0) {
- view.pending.urgent = true;
- server.root.applyPending();
- }
- }
-}
diff --git a/river/XdgPopup.zig b/river/XdgPopup.zig
index 2bb6d42..c539cc9 100644
--- a/river/XdgPopup.zig
+++ b/river/XdgPopup.zig
@@ -86,7 +86,7 @@ fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_xdg_popup: *wlr.Xdg
fn handleReposition(listener: *wl.Listener(void)) void {
const xdg_popup = @fieldParentPtr(XdgPopup, "reposition", listener);
- const output = switch (SceneNodeData.get(&xdg_popup.root.node).?.data) {
+ const output = switch (SceneNodeData.fromNode(&xdg_popup.root.node).?.data) {
.view => |view| view.current.output orelse return,
.layer_surface => |layer_surface| layer_surface.output,
else => unreachable,
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 64229ad..a3a96ac 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -79,6 +79,7 @@ pub fn create(xdg_toplevel: *wlr.XdgToplevel) error{OutOfMemory}!void {
_ = try view.surface_tree.createSceneXdgSurface(xdg_toplevel.base);
xdg_toplevel.base.data = @ptrToInt(view);
+ xdg_toplevel.base.surface.data = @ptrToInt(&view.tree.node);
// Add listeners that are active over the view's entire lifetime
const self = &view.impl.xdg_toplevel;
diff --git a/river/XwaylandOverrideRedirect.zig b/river/XwaylandOverrideRedirect.zig
index 8a8147b..e0a5f94 100644
--- a/river/XwaylandOverrideRedirect.zig
+++ b/river/XwaylandOverrideRedirect.zig
@@ -91,11 +91,12 @@ pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandS
}
fn mapImpl(self: *Self) error{OutOfMemory}!void {
- self.surface_tree = try server.root.layers.xwayland_override_redirect.createSceneSubsurfaceTree(
- self.xwayland_surface.surface.?,
- );
+ const surface = self.xwayland_surface.surface.?;
+ self.surface_tree = try server.root.layers.xwayland_override_redirect.createSceneSubsurfaceTree(surface);
try SceneNodeData.attach(&self.surface_tree.?.node, .{ .xwayland_override_redirect = self });
+ surface.data = @ptrToInt(&self.surface_tree.?.node);
+
self.surface_tree.?.node.setPosition(self.xwayland_surface.x, self.xwayland_surface.y);
self.xwayland_surface.events.set_geometry.add(&self.set_geometry);
@@ -130,6 +131,7 @@ fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSur
self.set_geometry.link.remove();
+ self.xwayland_surface.surface.?.data = 0;
self.surface_tree.?.node.destroy();
self.surface_tree = null;
diff --git a/river/XwaylandView.zig b/river/XwaylandView.zig
index 3b1b83a..d071e60 100644
--- a/river/XwaylandView.zig
+++ b/river/XwaylandView.zig
@@ -159,8 +159,10 @@ pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface:
const self = @fieldParentPtr(Self, "map", listener);
const view = self.view;
- // Add listeners that are only active while mapped
const surface = xwayland_surface.surface.?;
+ surface.data = @ptrToInt(&view.tree.node);
+
+ // Add listeners that are only active while mapped
xwayland_surface.events.set_title.add(&self.set_title);
xwayland_surface.events.set_class.add(&self.set_class);
xwayland_surface.events.request_fullscreen.add(&self.request_fullscreen);
@@ -206,6 +208,8 @@ pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface:
fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
const self = @fieldParentPtr(Self, "unmap", listener);
+ self.xwayland_surface.surface.?.data = 0;
+
// Remove listeners that are only active while mapped
self.set_title.link.remove();
self.set_class.link.remove();