From 1039e3a80035d2d71c50e7e06e40b25e44575bd4 Mon Sep 17 00:00:00 2001 From: Harrison DiAmbrosio Date: Sat, 13 Dec 2025 00:30:42 -0500 Subject: [PATCH] still working on migrating to the new SceneNodeData --- src/Cursor.zig | 16 ++++--- src/LayerSurface.zig | 25 ++++++++--- src/Output.zig | 101 +++++++++++++++++++++++++++--------------- src/Root.zig | 38 ++++++++++++---- src/SceneNodeData.zig | 52 ++-------------------- src/Server.zig | 30 ++++++------- src/View.zig | 9 +++- 7 files changed, 148 insertions(+), 123 deletions(-) diff --git a/src/Cursor.zig b/src/Cursor.zig index 557f668..e9386af 100644 --- a/src/Cursor.zig +++ b/src/Cursor.zig @@ -86,8 +86,8 @@ pub fn processCursorMotion(self: *Cursor, time_msec: u32) void { // Exit the switch if no focused output exists if (output == null) return; - const viewAtResult = output.?.viewAt(self.wlr_cursor.x, self.wlr_cursor.y); - if (viewAtResult == null) { + const surfaceAtResult = output.?.surfaceAt(self.wlr_cursor.x, self.wlr_cursor.y); + if (surfaceAtResult == null) { self.wlr_cursor.setXcursor(self.x_cursor_manager, "default"); server.seat.wlr_seat.pointerClearFocus(); @@ -98,10 +98,16 @@ pub fn processCursorMotion(self: *Cursor, time_msec: u32) void { return; } - server.events.exec("ViewPointerMotion", .{viewAtResult.?.view.id, self.wlr_cursor.x, self.wlr_cursor.y}); + switch (surfaceAtResult.?.scene_node_data.*) { + .view => { + server.events.exec("ViewPointerMotion", .{surfaceAtResult.?.scene_node_data.view.id, self.wlr_cursor.x, self.wlr_cursor.y}); + }, + .layer_surface => { }, + else => unreachable + } - server.seat.wlr_seat.pointerNotifyEnter(viewAtResult.?.surface, viewAtResult.?.sx, viewAtResult.?.sy); - server.seat.wlr_seat.pointerNotifyMotion(time_msec, viewAtResult.?.sx, viewAtResult.?.sy); + server.seat.wlr_seat.pointerNotifyEnter(surfaceAtResult.?.surface, surfaceAtResult.?.sx, surfaceAtResult.?.sy); + server.seat.wlr_seat.pointerNotifyMotion(time_msec, surfaceAtResult.?.sx, surfaceAtResult.?.sy); }, .move => { // TODO: Have these behave more like pointer motion if(self.drag.view) |view| { diff --git a/src/LayerSurface.zig b/src/LayerSurface.zig index 395d1f5..968cc74 100644 --- a/src/LayerSurface.zig +++ b/src/LayerSurface.zig @@ -6,12 +6,13 @@ const wlr = @import("wlroots"); const Utils = @import("Utils.zig"); const Output = @import("Output.zig"); -const SceneNodeData = @import("SceneNodeData.zig"); +const SceneNodeData = @import("SceneNodeData.zig").SceneNodeData; const gpa = std.heap.c_allocator; const server = &@import("main.zig").server; output: *Output, +scene_node_data: SceneNodeData, wlr_layer_surface: *wlr.LayerSurfaceV1, scene_layer_surface: *wlr.SceneLayerSurfaceV1, @@ -27,11 +28,26 @@ pub fn init(wlr_layer_surface: *wlr.LayerSurfaceV1) *LayerSurface { const self = try gpa.create(LayerSurface); self.* = .{ - .output = @ptrCast(@alignCast(wlr_layer_surface.output.?.data)), + .output = blk: { + // These block things are dangerous + // There was no need for this + // But I cannot be stopped + // - Powerhungry programmer + const data = wlr_layer_surface.output.?.data; + if(data == null) unreachable; + const scene_node_data: *SceneNodeData = @ptrCast(@alignCast(wlr_layer_surface.output.?.data.?)); + break :blk switch(scene_node_data.*) { + .output => @fieldParentPtr("scene_node_data", scene_node_data), + else => unreachable + }; + }, .wlr_layer_surface = wlr_layer_surface, .scene_layer_surface = undefined, + .scene_node_data = .{ .layer_surface = self } }; + self.wlr_layer_surface.surface.data = &self.scene_node_data; + if(server.seat.focused_output) |output| { self.scene_layer_surface = switch (wlr_layer_surface.current.layer) { .background => try output.layers.background.createSceneLayerSurfaceV1(wlr_layer_surface), @@ -45,11 +61,6 @@ pub fn init(wlr_layer_surface: *wlr.LayerSurfaceV1) *LayerSurface { }; } - try SceneNodeData.setData( - &self.scene_layer_surface.tree.node, - .{ .layer_surface = self }, - ); - self.wlr_layer_surface.surface.data = &self.scene_layer_surface.tree.node; self.wlr_layer_surface.events.destroy.add(&self.destroy); self.wlr_layer_surface.surface.events.map.add(&self.map); diff --git a/src/Output.zig b/src/Output.zig index 56498b2..43b9e42 100644 --- a/src/Output.zig +++ b/src/Output.zig @@ -5,11 +5,13 @@ const zwlr = @import("wayland").server.zwlr; const wlr = @import("wlroots"); const std = @import("std"); -const Server = @import("Server.zig"); const Utils = @import("Utils.zig"); + +const Server = @import("Server.zig"); const View = @import("View.zig"); const LayerSurface = @import("LayerSurface.zig"); -const SceneNodeData = @import("SceneNodeData.zig"); + +const SceneNodeData = @import("SceneNodeData.zig").SceneNodeData; const posix = std.posix; const gpa = std.heap.c_allocator; @@ -21,6 +23,7 @@ id: u64, wlr_output: *wlr.Output, state: wlr.Output.State, tree: *wlr.SceneTree, +scene_node_data: SceneNodeData, scene_output: *wlr.SceneOutput, layers: struct { @@ -59,6 +62,7 @@ pub fn init(wlr_output: *wlr.Output) ?*Output { .overlay = try self.tree.createSceneTree(), }, .scene_output = try server.root.scene.createSceneOutput(wlr_output), + .scene_node_data = SceneNodeData{ .output = self }, .state = wlr.Output.State.init() }; @@ -130,7 +134,6 @@ pub fn configureLayers(self: *Output) void { self.wlr_output.effectiveResolution(&output_box.width, &output_box.height); // Should calculate usable area here for LUA view positioning - for ([_]zwlr.LayerShellV1.Layer{ .background, .bottom, .top, .overlay }) |layer| { const tree = blk: { const trees = [_]*wlr.SceneTree{ @@ -146,43 +149,65 @@ pub fn configureLayers(self: *Output) void { while(it.next()) |node| { if(node.data == null) continue; - const layer_surface: *wlr.LayerSurfaceV1 = @ptrCast(@alignCast(node.data.?)); - _ = layer_surface.configure(@intCast(output_box.width), @intCast(output_box.height)); + const scene_node_data: *SceneNodeData = @ptrCast(@alignCast(node.data.?)); + switch (scene_node_data.*) { + .layer_surface => { + _ = scene_node_data.layer_surface.wlr_layer_surface.configured( + @intCast(output_box.width), + @intCast(output_box.height) + ); + }, + else => { + std.log.err("Something other than a layer surface found in layer surface scene trees", .{}); + unreachable; + } + } } } } -const ViewAtResult = struct { - view: *View, +const SurfaceAtResult = struct { + scene_node_data: *SceneNodeData, surface: *wlr.Surface, sx: f64, sy: f64, }; -pub fn viewAt(self: *Output, lx: f64, ly: f64) ?ViewAtResult { +pub fn surfaceAt(self: *Output, lx: f64, ly: f64) ?SurfaceAtResult { var sx: f64 = undefined; var sy: f64 = undefined; - if(self.layers.content.node.at(lx, ly, &sx, &sy)) |node| { - if (node.type != .buffer) return null; - const scene_buffer = wlr.SceneBuffer.fromNode(node); - const scene_surface = wlr.SceneSurface.tryFromBuffer(scene_buffer) orelse return null; + const layers = [_]*wlr.SceneTree{ + self.layers.top, + self.layers.overlay, + self.layers.fullscreen, + self.layers.content, + self.layers.bottom, + self.layers.background + }; - var it: ?*wlr.SceneTree = node.parent; + for(layers) |layer| { + if(layer.node.at(lx, ly, &sx, &sy)) |node| { + const scene_buffer = wlr.SceneBuffer.fromNode(node); + const scene_surface = wlr.SceneSurface.tryFromBuffer(scene_buffer) orelse continue; - while (it) |n| : (it = n.node.parent) { - if (n.node.data == null) continue; + if (node.data == null) continue; + const scene_node_data: *SceneNodeData = @ptrCast(@alignCast(node.data.?)); - const view: *View = @ptrCast(@alignCast(n.node.data.?)); - - return ViewAtResult{ - .view = view, - .surface = scene_surface.surface, - .sx = sx, - .sy = sy, - }; + switch (scene_node_data.*) { + .layer_surface, .view => { + return SurfaceAtResult{ + .scene_node_data = scene_node_data, + .surface = scene_surface.surface, + .sx = sx, + .sy = sy, + }; + }, + else => continue + } } } + return null; } @@ -247,23 +272,27 @@ pub fn arrangeLayers(self: *Output) void { const layer: *wlr.SceneTree = @field(self.layers, comptime_layer.name); var it = layer.children.safeIterator(.forward); while (it.next()) |node| { - if (@as(?*SceneNodeData, @alignCast(@ptrCast(node.data)))) |node_data| { - const layer_surface = node_data.data.layer_surface; + if(node.data == null) continue; - if (!layer_surface.wlr_layer_surface.initialized) continue; + const scene_node_data: *SceneNodeData = @ptrCast(@alignCast(node.data.?)); + const layer_surface: *LayerSurface = switch(scene_node_data.*) { + .layer_surface => @fieldParentPtr("scene_node_data", scene_node_data), + else => continue + }; - // TEST: river seems to try and prevent clients from taking an - // exclusive size greater than half the screen by killing them. Do we - // need to? Clients can do quite a bit of nasty stuff and taking - // exclusive focus isn't even that bad. + if (!layer_surface.wlr_layer_surface.initialized) continue; - layer_surface.scene_layer_surface.configure(&full_box, &full_box); + // TEST: river seems to try and prevent clients from taking an + // exclusive size greater than half the screen by killing them. Do we + // need to? Clients can do quite a bit of nasty stuff and taking + // exclusive focus isn't even that bad. - // TEST: are these calls useless? - // const x = layer_surface.scene_layer_surface.tree.node.x; - // const y = layer_surface.scene_layer_surface.tree.node.y; - // layer_surface.scene_layer_surface.tree.node.setPosition(x, y); - } + layer_surface.scene_layer_surface.configure(&full_box, &full_box); + + // TEST: are these calls useless? + // const x = layer_surface.scene_layer_surface.tree.node.x; + // const y = layer_surface.scene_layer_surface.tree.node.y; + // layer_surface.scene_layer_surface.tree.node.setPosition(x, y); } } } diff --git a/src/Root.zig b/src/Root.zig index 3614286..bca85ef 100644 --- a/src/Root.zig +++ b/src/Root.zig @@ -1,22 +1,25 @@ /// The root of Mezzaluna is, you guessed it, the root of many of the systems mez needs: -/// - Managing outputs -/// - + const Root = @This(); const std = @import("std"); const wl = @import("wayland").server.wl; const wlr = @import("wlroots"); -const Output = @import("Output.zig"); -const View = @import("View.zig"); -const Utils = @import("Utils.zig"); - const server = &@import("main.zig").server; const gpa = std.heap.c_allocator; +const Output = @import("Output.zig"); +const View = @import("View.zig"); +const LayerSurface = @import("LayerSurface.zig"); +const SceneNodeData = @import("SceneNodeData.zig").SceneNodeData; + +const Utils = @import("Utils.zig"); + xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, scene: *wlr.Scene, + waiting_room: *wlr.SceneTree, scene_output_layout: *wlr.SceneOutputLayout, @@ -48,8 +51,16 @@ pub fn deinit(self: *Root) void { while(it.next()) |node| { if(node.data == null) continue; - const view: *View = @ptrCast(@alignCast(node.data.?)); - view.deinit(); + const scene_node_data: *SceneNodeData = @ptrCast(@alignCast(node.data.?)); + switch(scene_node_data.*) { + .output => { + scene_node_data.output.deinit(); + }, + else => { + std.log.debug("The root has a child that is not an output", .{}); + unreachable; + } + } } self.output_layout.destroy(); @@ -62,7 +73,16 @@ pub fn viewById(self: *Root, id: u64) ?*View { while(output_it.next()) |o| { if(o.output.data == null) continue; - const output: *Output = @ptrCast(@alignCast(o.output.data.?)); + + const scene_node_data: *SceneNodeData = @ptrCast(@alignCast(o.output.data.?)); + const output: *Output = switch (scene_node_data.*) { + .output => |output_ptr| output_ptr, + else => { + std.log.err("Incorrect scene node type found", .{}); + unreachable; + } + }; + var node_it = output.layers.content.children.iterator(.forward); while(node_it.next()) |node| { diff --git a/src/SceneNodeData.zig b/src/SceneNodeData.zig index 3ae95a7..6fadaa5 100644 --- a/src/SceneNodeData.zig +++ b/src/SceneNodeData.zig @@ -1,54 +1,10 @@ -const SceneNodeData = @This(); - -const std = @import("std"); -const wlr = @import("wlroots"); -const wl = @import("wayland").server.wl; - const View = @import("View.zig"); const LayerSurface = @import("LayerSurface.zig"); +const Output = @import("Output.zig"); -const gpa = std.heap.c_allocator; - -pub const Data = union(enum) { +const SceneNodeType = enum { view, layer_surface, output }; +pub const SceneNodeData = union(SceneNodeType) { view: *View, layer_surface: *LayerSurface, + output: *Output }; - -node: *wlr.SceneNode, -data: Data, -destroy: wl.Listener(void) = wl.Listener(void).init(handleDestroy), - -pub fn setData(node: *wlr.SceneNode, data: Data) !void { - const scene_node_data = try gpa.create(SceneNodeData); - - scene_node_data.* = .{ - .node = node, - .data = data, - }; - node.data = scene_node_data; - - node.events.destroy.add(&scene_node_data.destroy); -} - -fn handleDestroy(listener: *wl.Listener(void)) void { - const scene_node_data: *SceneNodeData = @fieldParentPtr("destroy", listener); - - scene_node_data.destroy.link.remove(); - scene_node_data.node.data = null; - - gpa.destroy(scene_node_data); -} - -pub fn getFromNode(node: *wlr.SceneNode) ?*SceneNodeData { - var n = node; - while (true) { - if (@as(?*SceneNodeData, @alignCast(@ptrCast(n.data)))) |scene_node_data| { - return scene_node_data; - } - if (n.parent) |parent_tree| { - n = &parent_tree.node; - } else { - return null; - } - } -} diff --git a/src/Server.zig b/src/Server.zig index e58f44e..3360f9e 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -4,19 +4,19 @@ const std = @import("std"); const wl = @import("wayland").server.wl; const wlr = @import("wlroots"); -const Root = @import("Root.zig"); -const Seat = @import("Seat.zig"); -const Cursor = @import("Cursor.zig"); -const Keyboard = @import("Keyboard.zig"); -const LayerSurface = @import("LayerSurface.zig"); -const Output = @import("Output.zig"); -const View = @import("View.zig"); -const Utils = @import("Utils.zig"); -const Keymap = @import("types/Keymap.zig"); -const Hook = @import("types/Hook.zig"); -const Events = @import("types/Events.zig"); -const Popup = @import("Popup.zig"); -const RemoteLua = @import("RemoteLua.zig"); +const Root = @import("Root.zig"); +const Seat = @import("Seat.zig"); +const Cursor = @import("Cursor.zig"); +const Keyboard = @import("Keyboard.zig"); +const LayerSurface = @import("LayerSurface.zig"); +const Output = @import("Output.zig"); +const View = @import("View.zig"); +const Utils = @import("Utils.zig"); +const Keymap = @import("types/Keymap.zig"); +const Hook = @import("types/Hook.zig"); +const Events = @import("types/Events.zig"); +const Popup = @import("Popup.zig"); +const RemoteLua = @import("RemoteLua.zig"); const RemoteLuaManager = @import("RemoteLuaManager.zig"); const gpa = std.heap.c_allocator; @@ -35,15 +35,13 @@ xdg_shell: *wlr.XdgShell, layer_shell: *wlr.LayerShellV1, xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, -// Input - allocator: *wlr.Allocator, root: Root, seat: Seat, cursor: Cursor, -// lua data +// Lua data keymaps: std.AutoHashMap(u64, Keymap), hooks: std.ArrayList(*Hook), events: Events, diff --git a/src/View.zig b/src/View.zig index ee46aaa..2787b2d 100644 --- a/src/View.zig +++ b/src/View.zig @@ -6,6 +6,8 @@ const wlr = @import("wlroots"); const Popup = @import("Popup.zig"); const Output = @import("Output.zig"); +const SceneNodeData = @import("SceneNodeData.zig").SceneNodeData; + const Utils = @import("Utils.zig"); const gpa = std.heap.c_allocator; @@ -20,6 +22,7 @@ output: ?*Output, xdg_toplevel: *wlr.XdgToplevel, xdg_toplevel_decoration: ?*wlr.XdgToplevelDecorationV1, scene_tree: *wlr.SceneTree, +scene_node_data: SceneNodeData, // Surface Listeners map: wl.Listener(void) = .init(handleMap), @@ -62,6 +65,8 @@ pub fn initFromTopLevel(xdg_toplevel: *wlr.XdgToplevel) *View { .xdg_toplevel = xdg_toplevel, .scene_tree = undefined, .xdg_toplevel_decoration = null, + + .scene_node_data = .{ .view = self } }; self.xdg_toplevel.base.surface.events.unmap.add(&self.unmap); @@ -76,8 +81,8 @@ pub fn initFromTopLevel(xdg_toplevel: *wlr.XdgToplevel) *View { self.scene_tree = try server.root.waiting_room.createSceneXdgSurface(xdg_toplevel.base); } - self.scene_tree.node.data = self; - self.xdg_toplevel.base.data = self.scene_tree; + self.scene_tree.node.data = &self.scene_node_data; + self.xdg_toplevel.base.data = &self.scene_node_data; self.xdg_toplevel.events.destroy.add(&self.destroy); self.xdg_toplevel.base.surface.events.map.add(&self.map);