From 209cd8a540a4b87a3781e2702885f6c2950ef327 Mon Sep 17 00:00:00 2001 From: Harrison DiAmbrosio Date: Sun, 14 Dec 2025 11:48:05 -0500 Subject: [PATCH] xdg_activation works --- ' | 222 ------------------------------------------------- src/Output.zig | 3 - src/Server.zig | 32 ++++--- 3 files changed, 20 insertions(+), 237 deletions(-) delete mode 100644 ' diff --git a/' b/' deleted file mode 100644 index 468b5f6..0000000 --- a/' +++ /dev/null @@ -1,222 +0,0 @@ -/// The root of Mezzaluna is, you guessed it, the root of many of the systems mez needs: - -const Root = @This(); - -const std = @import("std"); -const wl = @import("wayland").server.wl; -const wlr = @import("wlroots"); - -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, - -output_layout: *wlr.OutputLayout, - -pub fn init(self: *Root) void { - std.log.info("Creating root of mezzaluna\n", .{}); - - errdefer Utils.oomPanic(); - - const output_layout = try wlr.OutputLayout.create(server.wl_server); - errdefer output_layout.destroy(); - - const scene = try wlr.Scene.create(); - errdefer scene.tree.node.destroy(); - - self.* = .{ - .scene = scene, - .waiting_room = try scene.tree.createSceneTree(), - .output_layout = output_layout, - .xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(server.wl_server), - .scene_output_layout = try scene.attachOutputLayout(output_layout), - }; -} - -pub fn deinit(self: *Root) void { - var it = self.scene.tree.children.iterator(.forward); - - while(it.next()) |node| { - if(node.data == null) continue; - - 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(); - self.scene.tree.node.destroy(); -} - -// Search output_layout's ouputs, and each outputs views -pub fn viewById(self: *Root, id: u64) ?*View { - var output_it = self.output_layout.outputs.iterator(.forward); - - while(output_it.next()) |o| { - if(o.output.data == null) continue; - - const output_snd: *SceneNodeData = @ptrCast(@alignCast(o.output.data.?)); - const output: *Output = switch (output_snd.*) { - .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| { - if(node.data == null) continue; - - const view_snd: *SceneNodeData = @ptrCast(@alignCast(node.data.?)); - - // TODO: Should we assert that we want only views to be here - // -- Basically should we use switch statements for snd interactions - // -- Or if statements, for simplicity - if(view_snd.* == .view and view_snd.view.id == id) { - return view_snd.view; - } - } - } - - return null; -} - -pub fn outputById(self: *Root, id: u64) ?*Output { - var it = self.scene.outputs.iterator(.forward); - - while(it.next()) |scene_output| { - if(scene_output.output.data == null) continue; - - const output: *Output = @as(*Output, @ptrCast(@alignCast(scene_output.output.data.?))); - if(output.id == id) return output; - } - - return null; -} - -pub fn debugPrintSceneTree(self: *Root) void { - std.log.debug("=== SCENE TREE DEBUG ===", .{}); - printNode(&self.scene.tree.node, 0); - std.log.debug("=== END SCENE TREE ===", .{}); -} - -fn printNode(node: *wlr.SceneNode, depth: usize) void { - errdefer Utils.oomPanic(); - - var indent = gpa.alloc(u8, depth); - for(0..indent.len) |i| { - - } - - // Print node type and position - const type_name = switch (node.type) { - .tree => "TREE", - .rect => "RECT", - .buffer => "BUFFER", - }; - - std.log.debug("{s}{s} @ ({d}, {d}) enabled={} visible={}", .{ - indent, - type_name, - node.x, - node.y, - node.enabled, - node.state.pending.enabled, - }); - - // Print associated data if present - if (node.data) |data| { - const scene_node_data: *SceneNodeData = @ptrCast(@alignCast(data)); - switch (scene_node_data.*) { - .output => |output| { - std.log.debug("{s} → Output: {s} (focused={}, id={})", .{ - indent, - output.wlr_output.name, - output.focused, - output.id, - }); - }, - .view => |view| { - std.log.debug("{s} → View: id={} mapped={} focused={}", .{ - indent, - view.id, - view.xdg_toplevel.base.surface.mapped, - view.focused, - }); - if (view.xdg_toplevel.title) |title| { - std.log.debug("{s} title=\"{s}\"", .{ indent, title }); - } - }, - .layer_surface => |layer| { - const layer_name = switch (layer.wlr_layer_surface.current.layer) { - .background => "background", - .bottom => "bottom", - .top => "top", - .overlay => "overlay", - else => "unknown", - }; - std.log.debug("{s} → LayerSurface: layer={s} mapped={}", .{ - indent, - layer_name, - layer.wlr_layer_surface.surface.mapped, - }); - if (layer.wlr_layer_surface.namespace.len > 0) { - std.log.debug("{s} namespace=\"{s}\"", .{ - indent, - layer.wlr_layer_surface.namespace, - }); - } - }, - } - } - - // Print buffer-specific info - if (node.type == .buffer) { - const scene_buffer = wlr.SceneBuffer.fromNode(node); - std.log.debug("{s} buffer: {d}x{d}", .{ - indent, - scene_buffer.buffer.?.width, - scene_buffer.buffer.?.height, - }); - - // Check if it's a surface - if (wlr.SceneSurface.tryFromBuffer(scene_buffer)) |scene_surface| { - std.log.debug("{s} → Surface: {*}", .{ indent, scene_surface.surface }); - } - } - - // Recursively print children if this is a tree - if (node.type == .tree) { - const tree = wlr.SceneTree.fromNode(node); - var it = tree.children.iterator(.forward); - var child_count: usize = 0; - while (it.next()) |child| { - child_count += 1; - printNode(child, depth + 1); - } - if (child_count == 0) { - std.log.debug("{s} (no children)", .{indent}); - } - } -} diff --git a/src/Output.zig b/src/Output.zig index 2389bc0..f09f3af 100644 --- a/src/Output.zig +++ b/src/Output.zig @@ -305,9 +305,6 @@ fn handleDestroy( } pub fn arrangeLayers(self: *Output) void { - const debug = @import("Debug.zig"); - debug.debugPrintSceneTree(); - var full_box: wlr.Box = .{ .x = 0, .y = 0, diff --git a/src/Server.zig b/src/Server.zig index 257e1f5..a943678 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -11,13 +11,14 @@ 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 Utils = @import("Utils.zig"); +const SceneNodeData = @import("SceneNodeData.zig").SceneNodeData; const gpa = std.heap.c_allocator; const server = &@import("main.zig").server; @@ -34,6 +35,7 @@ shm: *wlr.Shm, xdg_shell: *wlr.XdgShell, layer_shell: *wlr.LayerShellV1, xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, +xdg_activation: *wlr.XdgActivationV1, allocator: *wlr.Allocator, @@ -51,14 +53,11 @@ remote_lua_clients: std.DoublyLinkedList, new_input: wl.Listener(*wlr.InputDevice) = .init(handleNewInput), new_output: wl.Listener(*wlr.Output) = .init(handleNewOutput), // backend.events.destroy - -// XdgShell listeners new_xdg_toplevel: wl.Listener(*wlr.XdgToplevel) = .init(handleNewXdgToplevel), new_xdg_popup: wl.Listener(*wlr.XdgPopup) = .init(handleNewXdgPopup), new_xdg_toplevel_decoration: wl.Listener(*wlr.XdgToplevelDecorationV1) = .init(handleNewXdgToplevelDecoration), - -// LayerShell Listeners new_layer_surface: wl.Listener(*wlr.LayerSurfaceV1) = .init(handleNewLayerSurface), +request_activate: wl.Listener(*wlr.XdgActivationV1.event.RequestActivate) = .init(handleRequestActivate), pub fn init(self: *Server) void { errdefer Utils.oomPanic(); @@ -92,6 +91,7 @@ pub fn init(self: *Server) void { .xdg_shell = try wlr.XdgShell.create(wl_server, 2), .layer_shell = try wlr.LayerShellV1.create(wl_server, 4), .xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(self.wl_server), + .xdg_activation = try wlr.XdgActivationV1.create(self.wl_server), .event_loop = event_loop, .session = session, .compositor = try wlr.Compositor.create(wl_server, 6, renderer), @@ -131,19 +131,13 @@ pub fn init(self: *Server) void { self.root.scene.setGammaControlManagerV1(try wlr.GammaControlManagerV1.create(self.wl_server)); // Add event listeners to events - // Backend events self.backend.events.new_input.add(&self.new_input); self.backend.events.new_output.add(&self.new_output); - - // XdgShell events self.xdg_shell.events.new_toplevel.add(&self.new_xdg_toplevel); self.xdg_shell.events.new_popup.add(&self.new_xdg_popup); - - // XdgDecorationManagerV1 events self.xdg_toplevel_decoration_manager.events.new_toplevel_decoration.add(&self.new_xdg_toplevel_decoration); - - // LayerShell events self.layer_shell.events.new_surface.add(&self.new_layer_surface); + self.xdg_activation.events.request_activate.add(&self.request_activate); self.events.exec("ServerStartPost", .{}); } @@ -236,3 +230,17 @@ fn handleNewLayerSurface( _ = LayerSurface.init(layer_surface); } + +fn handleRequestActivate( + _: *wl.Listener(*wlr.XdgActivationV1.event.RequestActivate), + event: *wlr.XdgActivationV1.event.RequestActivate, +) void { + if(event.surface.data == null) return; + + const scene_node_data: *SceneNodeData = @ptrCast(@alignCast(event.surface.data.?)); + if(scene_node_data.* == .view) { + scene_node_data.view.setFocused(); + } else { + std.log.warn("Ignoring request to activate non-view", .{}); + } +}