From 275f96615b61f466e2113469e7dc9c2a015978b2 Mon Sep 17 00:00:00 2001 From: Harrison DiAmbrosio Date: Sat, 18 Oct 2025 17:27:23 -0400 Subject: [PATCH] starting of root module refactor --- src/main.zig | 9 ++++-- src/output.zig | 81 +++++++++++++++++++++++--------------------------- src/root.zig | 71 +++++++++++++++++++++++++++++++++++++++++++ src/scene.zig | 50 ------------------------------- src/server.zig | 30 ++++--------------- 5 files changed, 121 insertions(+), 120 deletions(-) create mode 100644 src/root.zig delete mode 100644 src/scene.zig diff --git a/src/main.zig b/src/main.zig index e142957..6ebd8cf 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5,11 +5,14 @@ const Server = @import("server.zig").Server; const gpa = std.heap.c_allocator; + +pub var server: Server = undefined; + pub fn main() !void { wlr.log.init(.debug, null); - std.debug.print("Starting mezzaluna", .{}); - var server: Server = undefined; + std.log.info("Starting mezzaluna", .{}); + try server.init(); var buf: [11]u8 = undefined; @@ -25,10 +28,12 @@ pub fn main() !void { try child.spawn(); } + std.log.info("Starting backend", .{}); server.backend.start() catch |err| { std.debug.panic("Failed to start backend: {}", .{err}); return; }; + std.log.info("Starting server", .{}); server.wl_server.run(); } diff --git a/src/output.zig b/src/output.zig index 8001cb9..73ae2fe 100644 --- a/src/output.zig +++ b/src/output.zig @@ -5,60 +5,55 @@ const gpa = std.heap.c_allocator; const wl = @import("wayland").server.wl; const wlr = @import("wlroots"); -const Server = @import("server.zig").Server; +const server = &@import("main.zig").server; pub const Output = struct { - server: *Server, - wlr_output: *wlr.Output, + wlr_output: *wlr.Output, + scene_output: *wlr.SceneOutput, - frame: wl.Listener(*wlr.Output) = .init(handleFrame), - request_state: wl.Listener(*wlr.Output.event.RequestState) = .init(handleRequestState), - destroy: wl.Listener(*wlr.Output) = .init(handleDestroy), + frame: wl.Listener(*wlr.Output) = .init(handleFrame), + request_state: wl.Listener(*wlr.Output.event.RequestState) = .init(handleRequestState), + 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) !void { - const output = try gpa.create(Output); + // The wlr.Output should be destroyed by the caller on failure to trigger cleanup. + 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); - wlr_output.events.request_state.add(&output.request_state); - wlr_output.events.destroy.add(&output.destroy); + output.* = .{ + .wlr_output = wlr_output, + .scene_output = try server.root.scene.createSceneOutput(wlr_output) + }; + wlr_output.events.frame.add(&output.frame); + wlr_output.events.request_state.add(&output.request_state); + wlr_output.events.destroy.add(&output.destroy); - const layout_output = try server.output_layout.addAuto(wlr_output); + return output; + } - const scene_output = try server.scene.createSceneOutput(wlr_output); - server.scene_output_layout.addOutput(layout_output, scene_output); - } + pub fn handleFrame(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { + const scene_output = server.scene.getSceneOutput(wlr_output).?; + _ = scene_output.commit(null); - pub fn handleFrame(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { - const output: *Output = @fieldParentPtr("frame", listener); + var now = posix.clock_gettime(posix.CLOCK.MONOTONIC) catch @panic("CLOCK_MONOTONIC not supported"); + scene_output.sendFrameDone(&now); + } - const scene_output = output.server.scene.getSceneOutput(output.wlr_output).?; - _ = scene_output.commit(null); + pub fn handleRequestState( + listener: *wl.Listener(*wlr.Output.event.RequestState), + event: *wlr.Output.event.RequestState, +) void { + const output: *Output = @fieldParentPtr("request_state", listener); - var now = posix.clock_gettime(posix.CLOCK.MONOTONIC) catch @panic("CLOCK_MONOTONIC not supported"); - scene_output.sendFrameDone(&now); - } + _ = output.wlr_output.commitState(event.state); + } - pub fn handleRequestState( - listener: *wl.Listener(*wlr.Output.event.RequestState), - event: *wlr.Output.event.RequestState, - ) void { - const output: *Output = @fieldParentPtr("request_state", listener); + pub fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { + const output: *Output = @fieldParentPtr("destroy", listener); - _ = output.wlr_output.commitState(event.state); - } + output.frame.link.remove(); + output.request_state.link.remove(); + output.destroy.link.remove(); - pub fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { - const output: *Output = @fieldParentPtr("destroy", listener); - - output.frame.link.remove(); - output.request_state.link.remove(); - output.destroy.link.remove(); - - gpa.destroy(output); - } + gpa.destroy(output); + } }; diff --git a/src/root.zig b/src/root.zig new file mode 100644 index 0000000..fd915d4 --- /dev/null +++ b/src/root.zig @@ -0,0 +1,71 @@ +const std = @import("std"); + +const wl = @import("wayland").server.wl; +const wlr = @import("wlroots"); + +const Output = @import("output.zig").Output; + +const server = &@import("main.zig").server; + +pub const Root = struct { + scene: *wlr.Scene, + + output_layout: *wlr.OutputLayout, + + new_output: wl.Listener(*wlr.Output), + + pub fn init(root: *Root) !void { + std.log.info("Creating root of mezzaluna", .{}); + + 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(); + + root.* = .{ + .scene = scene, + .output_layout = output_layout, + + .new_output = .init(handleNewOutput), + }; + + 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; + }; + + _ = self.scene.createSceneOutput(new_output.wlr_output) catch { + std.log.err("failed to create scene output for new output", .{}); + return; + }; + } +}; + +fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { + std.log.info("Handling a new output - {s}", .{wlr_output.name}); + + if (!wlr_output.initRender(server.allocator, server.renderer)) return; + + var state = wlr.Output.State.init(); + defer state.finish(); + + state.setEnabled(true); + + if (wlr_output.preferredMode()) |mode| { + state.setMode(mode); + } + if (!wlr_output.commitState(&state)) return; + + const new_output = Output.create(wlr_output) catch { + std.log.err("failed to allocate new output", .{}); + wlr_output.destroy(); + return; + }; + + server.root.addOutput(new_output); +} diff --git a/src/scene.zig b/src/scene.zig deleted file mode 100644 index da3dd3f..0000000 --- a/src/scene.zig +++ /dev/null @@ -1,50 +0,0 @@ -const wl = @import("wayland").server.wl; -const wlr = @import("wlroots"); - -// server owns -// - compositor -// -// wlr_compositor owms -// - a list of wlr_surfaces -// -// wlr_surfaces own_buffers -// -// struct wl_resource *_surface; -// wl_resource_for_each(_surface, &server->compositor->surfaces) { -// struct wlr_surface *surface = wlr_surface_from_resource(_surface); -// if (!wlr_surface_has_buffer(surface)) { -// continue; -// } -// struct wlr_box render_box = { -// .x = 20, .y = 20, -// .width = surface->current->width, -// .height = surface->current->height -// }; -// float matrix[16]; -// wlr_matrix_project_box(&matrix, &render_box, -// surface->current->transform, -// 0, &wlr_output->transform_matrix); -// wlr_render_with_matrix(renderer, surface->texture, &matrix, 1.0f); -// wlr_surface_send_frame_done(surface, &now); -// } -// -// -// -// wlr_scene owns -// - list of outputs -// - wlr_scene_tree -// -// wlr_scene_tree owns -// - its own wlr_scene_node -// - list of its children wlr_scene_node -// -// wlr_scene_node can be TREE, RECT or BUFFER and owns -// - its own type -// - a pointer to its parent wlr_scene_tree -// - a list of children as wlr_scene_trees -// - boolean if enabled -// - x, y position relative to parent -// - wl signal for destroy -// - *void arbitrary data - - diff --git a/src/server.zig b/src/server.zig index 85b5e76..263eb09 100644 --- a/src/server.zig +++ b/src/server.zig @@ -5,6 +5,7 @@ const wl = @import("wayland").server.wl; const wlr = @import("wlroots"); const Output = @import("output.zig").Output; +const Root = @import("root.zig").Root; pub const Server = struct { allocator: *wlr.Allocator, @@ -14,7 +15,6 @@ pub const Server = struct { shm: *wlr.Shm, scene: *wlr.Scene, output_layout: *wlr.OutputLayout, - scene_output_layout: *wlr.SceneOutputLayout, xdg_shell: *wlr.XdgShell, seat: *wlr.Seat, @@ -24,7 +24,7 @@ pub const Server = struct { compositor: *wlr.Compositor, - new_output: wl.Listener(*wlr.Output) = .init(newOutput), + root: Root, pub fn init(server: *Server) !void { const wl_server = try wl.Server.create(); @@ -45,13 +45,14 @@ pub const Server = struct { .allocator = try wlr.Allocator.autocreate(backend, renderer), .scene = scene, .output_layout = output_layout, - .scene_output_layout = try scene.attachOutputLayout(output_layout), .xdg_shell = try wlr.XdgShell.create(wl_server, 2), .event_loop = event_loop, .session = session, .compositor = try wlr.Compositor.create(wl_server, 6, renderer), .shm = try wlr.Shm.createWithRenderer(wl_server, 1, renderer), .seat = try wlr.Seat.create(wl_server, "default"), + + .root = undefined, }; try server.renderer.initServer(wl_server); @@ -60,27 +61,6 @@ pub const Server = struct { _ = try wlr.Subcompositor.create(server.wl_server); _ = try wlr.DataDeviceManager.create(server.wl_server); - server.backend.events.new_output.add(&server.new_output); - } - - fn newOutput(listener: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void { - const server: *Server = @fieldParentPtr("new_output", listener); - - if (!wlr_output.initRender(server.allocator, server.renderer)) return; - - var state = wlr.Output.State.init(); - defer state.finish(); - - state.setEnabled(true); - if (wlr_output.preferredMode()) |mode| { - state.setMode(mode); - } - if (!wlr_output.commitState(&state)) return; - - Output.create(server, wlr_output) catch { - std.log.err("failed to allocate new output", .{}); - wlr_output.destroy(); - return; - }; + try Root.init(&server.root); } };