From f10906f0fc7e94651db5623746a333d2b00dadb4 Mon Sep 17 00:00:00 2001 From: Harrison DiAmbrosio Date: Sat, 18 Oct 2025 23:45:13 -0400 Subject: [PATCH] some basic xdg surface stuff --- src/output.zig | 15 ++++++----- src/root.zig | 69 +++++++++++++++++++++++++++--------------------- src/server.zig | 23 +++++++++++++++- src/toplevel.zig | 35 ++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 38 deletions(-) create mode 100644 src/toplevel.zig diff --git a/src/output.zig b/src/output.zig index 8f4aca6..77a48cb 100644 --- a/src/output.zig +++ b/src/output.zig @@ -3,13 +3,13 @@ const Output = @This(); const std = @import("std"); const posix = std.posix; const gpa = std.heap.c_allocator; +const server = &@import("main.zig").server; const wl = @import("wayland").server.wl; const wlr = @import("wlroots"); const Server = @import("server.zig"); -server: *Server, wlr_output: *wlr.Output, frame: wl.Listener(*wlr.Output) = .init(handleFrame), @@ -17,11 +17,10 @@ request_state: wl.Listener(*wlr.Output.event.RequestState) = .init(handleRequest destroy: wl.Listener(*wlr.Output) = .init(handleDestroy), // The wlr.Output should be destroyed by the caller on failure to trigger cleanup. -pub fn create(server: *Server, wlr_output: *wlr.Output) !*Output { +pub fn create(wlr_output: *wlr.Output) !*Output { const output = try gpa.create(Output); output.* = .{ - .server = server, .wlr_output = wlr_output, }; wlr_output.events.frame.add(&output.frame); @@ -42,6 +41,7 @@ pub fn handleRequestState( listener: *wl.Listener(*wlr.Output.event.RequestState), event: *wlr.Output.event.RequestState, ) void { + std.log.debug("Handling request state", .{}); const output: *Output = @fieldParentPtr("request_state", listener); if (!output.wlr_output.commitState(event.state)) { @@ -49,13 +49,13 @@ event: *wlr.Output.event.RequestState, } } -pub fn handleFrame(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { - const output: *Output = @fieldParentPtr("destroy", listener); +pub fn handleFrame(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { + std.log.debug("Handling frame for {s}", .{wlr_output.name}); - const scene_output = output.*.server.*.scene.*.getSceneOutput(wlr_output); + const scene_output = server.scene.*.getSceneOutput(wlr_output); if(scene_output) |so| { - std.log.info("Rendering commitin scene output\n", .{}); + std.log.info("Rendering commited scene output\n", .{}); _ = so.commit(null); var now = posix.clock_gettime(posix.CLOCK.MONOTONIC) catch @panic("CLOCK_MONOTONIC not supported"); @@ -65,6 +65,7 @@ pub fn handleFrame(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) } pub fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { + std.log.debug("Handling destroy", .{}); const output: *Output = @fieldParentPtr("destroy", listener); std.log.debug("removing output: {s}", .{output.*.wlr_output.*.name}); diff --git a/src/root.zig b/src/root.zig index be6b7f1..0b460a3 100644 --- a/src/root.zig +++ b/src/root.zig @@ -1,50 +1,58 @@ -const std = @import("std"); +const Root = @This(); +const std = @import("std"); const wl = @import("wayland").server.wl; const wlr = @import("wlroots"); const Output = @import("output.zig"); +const TopLevel = @import("toplevel.zig"); const server = &@import("main.zig").server; +const gpa = std.heap.c_allocator; -pub const Root = struct { - scene: *wlr.Scene, +scene: *wlr.Scene, - output_layout: *wlr.OutputLayout, +output_layout: *wlr.OutputLayout, - new_output: wl.Listener(*wlr.Output), +new_output: wl.Listener(*wlr.Output), - pub fn init(root: *Root) !void { - std.log.info("Creating root of mezzaluna\n", .{}); +all_top_levels: std.ArrayList(*TopLevel), - const output_layout = try wlr.OutputLayout.create(server.wl_server); - errdefer output_layout.destroy(); +pub fn init(root: *Root) !void { + std.log.info("Creating root of mezzaluna\n", .{}); - const scene = try wlr.Scene.create(); - errdefer scene.tree.node.destroy(); + const output_layout = try wlr.OutputLayout.create(server.wl_server); + errdefer output_layout.destroy(); - root.* = .{ - .scene = scene, - .output_layout = output_layout, + const scene = try wlr.Scene.create(); + errdefer scene.tree.node.destroy(); - .new_output = .init(handleNewOutput), - }; + root.* = .{ + .scene = scene, + .output_layout = output_layout, - server.backend.events.new_output.add(&root.new_output); - } + .new_output = .init(handleNewOutput), - pub fn addOutput(self: *Root, new_output: *Output) void { - _ = self.output_layout.addAuto(new_output.wlr_output) catch { - std.log.err("failed to add new output to output layout\n", .{}); - return; - }; + .all_top_levels = try .initCapacity(gpa, 10), + }; - // _ = self.scene.createSceneOutput(new_output.wlr_output) catch { - // std.log.err("failed to create scene output for new output", .{}); - // return; - // }; - } -}; + server.backend.events.new_output.add(&root.new_output); +} + +pub fn addOutput(self: *Root, new_output: *Output) void { + _ = self.output_layout.addAuto(new_output.wlr_output) catch { + std.log.err("failed to add new output to output layout\n", .{}); + return; + }; +} + +pub fn addTopLevel(self: *Root, top_level: *TopLevel) void { + self.all_top_levels.append(gpa, top_level) catch { + std.log.err("Out of memory to append top level", .{}); + }; + + // self.scene.tree.children.append(wlr.SceneNode) +} fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { std.log.info("Handling a new output - {s}", .{wlr_output.name}); @@ -61,7 +69,7 @@ fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { } if (!wlr_output.commitState(&state)) return; - const new_output = Output.create(server, wlr_output) catch { + const new_output = Output.create(wlr_output) catch { std.log.err("failed to allocate new output", .{}); wlr_output.destroy(); return; @@ -69,3 +77,4 @@ fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { server.root.addOutput(new_output); } + diff --git a/src/server.zig b/src/server.zig index 13b917d..bbf89b8 100644 --- a/src/server.zig +++ b/src/server.zig @@ -8,7 +8,8 @@ const wlr = @import("wlroots"); const Output = @import("output.zig"); const Keyboard = @import("keyboard.zig"); -const Root = @import("root.zig").Root; +const TopLevel = @import("toplevel.zig"); +const Root = @import("root.zig"); allocator: *wlr.Allocator, backend: *wlr.Backend, @@ -32,6 +33,9 @@ cursor_mgr: *wlr.XcursorManager, // Listeners new_input: wl.Listener(*wlr.InputDevice) = .init(newInput), + +new_xdg_surface: wl.Listener(*wlr.XdgSurface) = .init(handleNewXdgSurface), + cursor_motion: wl.Listener(*wlr.Pointer.event.Motion) = .init(cursorMotion), cursor_motion_absolute: wl.Listener(*wlr.Pointer.event.MotionAbsolute) = .init(cursorMotionAbsolute), cursor_button: wl.Listener(*wlr.Pointer.event.Button) = .init(cursorButton), @@ -75,9 +79,13 @@ pub fn init(server: *Server) !void { try server.renderer.initServer(wl_server); try Root.init(&server.root); + server.xdg_shell.events.new_surface.add(&server.new_xdg_surface); + server.backend.events.new_input.add(&server.new_input); + server.seat.events.request_set_cursor.add(&server.request_set_cursor); server.seat.events.request_set_selection.add(&server.request_set_selection); + server.keyboards.init(); server.cursor.attachOutputLayout(server.output_layout); @@ -237,3 +245,16 @@ fn requestSetSelection( const server: *Server = @fieldParentPtr("request_set_selection", listener); server.seat.setSelection(event.source, event.serial); } + +fn handleNewXdgSurface(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurface) void { + const server: *Server = @fieldParentPtr("new_xdg_surface", listener); + + std.log.info("New xdg_toplevel added", .{}); + + const top_level = TopLevel.init(xdg_surface) catch { + std.log.err("Unable to allocate a top level", .{}); + return; + }; + + server.root.addTopLevel(top_level); +} diff --git a/src/toplevel.zig b/src/toplevel.zig new file mode 100644 index 0000000..8de9bf6 --- /dev/null +++ b/src/toplevel.zig @@ -0,0 +1,35 @@ +const TopLevel = @This(); + +const std = @import("std"); +const wl = @import("wayland").server.wl; +const wlr = @import("wlroots"); + +const gpa = std.heap.c_allocator; +const server = &@import("main.zig").server; + +xdg_toplevel: *wlr.XdgToplevel, +box: *wlr.Box, + +pub fn init(xdg_surface: *wlr.XdgSurface) !*TopLevel { + const top_level = gpa.create(TopLevel) catch |err| { + std.log.err("Unable to allocate memory for new XdgTopLevel", .{}); + return err; + }; + + if(xdg_surface.role_data.toplevel) |xgd_toplevel| { + top_level.* = .{ + .xdg_toplevel = xgd_toplevel, + .box = undefined, + }; + + top_level.box.x = 0; + top_level.box.y = 0; + top_level.box.width = 640; + top_level.box.height = 360; + } + + // Listen to important toplevel events + // top_level.xdg_toplevel.events.set_title.add(listener: *Listener(void)) + + return top_level; +}