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.
This commit is contained in:
parent
ea4e589fdc
commit
44004e2d28
@ -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,18 +33,27 @@ 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;
|
||||
}
|
||||
} else {
|
||||
// If for whatever reason the inhibitor does not have a view, then
|
||||
// assume it is visible.
|
||||
},
|
||||
.layer_surface => |layer_surface| {
|
||||
if (layer_surface.wlr_layer_surface.mapped) {
|
||||
inhibited = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
.lock_surface, .xwayland_override_redirect => {
|
||||
inhibited = true;
|
||||
break;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
server.input_manager.idle_notifier.setInhibited(inhibited);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user