From b328c0a7c77b24193241b2636192db2ccc7dc7e9 Mon Sep 17 00:00:00 2001 From: Harrison DiAmbrosio Date: Thu, 23 Oct 2025 13:30:59 -0400 Subject: [PATCH] more error handling and oranization --- src/cursor.zig | 5 ++++- src/keyboard.zig | 10 +++++++++- src/main.zig | 2 +- src/output.zig | 5 ++++- src/root.zig | 27 +++++++++++++++---------- src/seat.zig | 6 +++++- src/server.zig | 51 ++++++++++++++++++++++++------------------------ src/view.zig | 26 +++++++++++++----------- 8 files changed, 81 insertions(+), 51 deletions(-) diff --git a/src/cursor.zig b/src/cursor.zig index 29dae24..4ef8b7f 100644 --- a/src/cursor.zig +++ b/src/cursor.zig @@ -5,6 +5,7 @@ const wl = @import("wayland").server.wl; const wlr = @import("wlroots"); const View = @import("view.zig"); +const Utils = @import("utils.zig"); const server = &@import("main.zig").server; @@ -26,7 +27,9 @@ grab_y: f64 = 0, grab_box: wlr.Box = undefined, resize_edges: wlr.Edges = .{}, -pub fn init(self: *Cursor) !void { +pub fn init(self: *Cursor) void { + errdefer Utils.oomPanic(); + self.* = .{ .wlr_cursor = try wlr.Cursor.create(), .x_cursor_manager = try wlr.XcursorManager.create(null, 24), diff --git a/src/keyboard.zig b/src/keyboard.zig index 081fefe..c23b756 100644 --- a/src/keyboard.zig +++ b/src/keyboard.zig @@ -24,19 +24,27 @@ modifiers: wl.Listener(*wlr.Keyboard) = .init(handleModifiers), destroy: wl.Listener(*wlr.InputDevice) = .init(handleDestroy), -pub fn init(self: *Keyboard, device: *wlr.InputDevice) !void { +pub fn init(self: *Keyboard, device: *wlr.InputDevice) void { + errdefer { + std.log.err("Unable to initialize new keyboard, exiting", .{}); + std.process.exit(6); + } + self.* = .{ .wlr_keyboard = device.toKeyboard(), .device = device, }; + // Should handle this error here const context = xkb.Context.new(.no_flags) orelse return error.ContextFailed; defer context.unref(); + // Should handle this error here const keymap = xkb.Keymap.newFromNames(context, null, .no_flags) orelse return error.KeymapFailed; defer keymap.unref(); // TODO: configure this via lua later + // Should handle this error here if (!self.wlr_keyboard.setKeymap(keymap)) return error.SetKeymapFailed; self.wlr_keyboard.setRepeatInfo(25, 600); diff --git a/src/main.zig b/src/main.zig index 03f816f..604a51d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -12,7 +12,7 @@ pub fn main() !void { std.log.info("Starting mezzaluna", .{}); - try server.init(); + server.init(); defer server.deinit(); var buf: [11]u8 = undefined; diff --git a/src/output.zig b/src/output.zig index 30dfb96..f22aca8 100644 --- a/src/output.zig +++ b/src/output.zig @@ -4,6 +4,7 @@ const wl = @import("wayland").server.wl; const wlr = @import("wlroots"); const std = @import("std"); const Server = @import("server.zig"); +const Utils = @import("utils.zig"); const posix = std.posix; const gpa = std.heap.c_allocator; @@ -17,7 +18,9 @@ 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(wlr_output: *wlr.Output) !*Output { +pub fn create(wlr_output: *wlr.Output) *Output { + errdefer Utils.oomPanic(); + const output = try gpa.create(Output); output.* = .{ diff --git a/src/root.zig b/src/root.zig index fb09663..c9ef609 100644 --- a/src/root.zig +++ b/src/root.zig @@ -11,12 +11,15 @@ const Utils = @import("utils.zig"); const server = &@import("main.zig").server; const gpa = std.heap.c_allocator; +// xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, + scene: *wlr.Scene, scene_output_layout: *wlr.SceneOutputLayout, output_layout: *wlr.OutputLayout, +focused_output: ?*Output, -views: std.ArrayList(View) = undefined, +views: std.ArrayList(*View) = undefined, workspaces: std.ArrayList(*wlr.SceneTree) = undefined, pub fn init(self: *Root) void { @@ -33,29 +36,37 @@ pub fn init(self: *Root) void { self.* = .{ .scene = scene, .output_layout = output_layout, + .focused_output = null, + // .xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(server.wl_server), .scene_output_layout = try scene.attachOutputLayout(output_layout), }; - self.views = std.ArrayList(View).initCapacity(gpa, 10); // Should consider number better, prolly won't matter that much though + self.views = try std.ArrayList(*View).initCapacity(gpa, 10); // Should consider number better, prolly won't matter that much though // Even though I would never use a changing amount of workspaces, opens more extensibility - self.workspaces = std.ArrayList(*wlr.SceneTree).initCapacity(gpa, 10); // TODO: change to a configured number of workspaces + self.workspaces = try std.ArrayList(*wlr.SceneTree).initCapacity(gpa, 10); // TODO: change to a configured number of workspaces // TODO: Make configurable for(0..9) |_| { - self.workspaces.append(gpa, try self.scene.tree.createSceneTree()); + try self.workspaces.append(gpa, try self.scene.tree.createSceneTree()); } } pub fn deinit(self: *Root) void { - self.workspaces.deinit(gpa); + for(self.views.items) |view| { + view.deinit(); + } self.views.deinit(gpa); + self.workspaces.deinit(gpa); + self.output_layout.destroy(); self.scene.tree.node.destroy(); } pub fn addOutput(self: *Root, new_output: *Output) void { - _ = self.output_layout.addAuto(new_output.wlr_output) catch Utils.oomPanic(); + errdefer Utils.oomPanic(); + _ = try self.output_layout.addAuto(new_output.wlr_output); + self.focused_output = new_output; } const ViewAtResult = struct { @@ -102,10 +113,6 @@ pub fn focusView(_: *Root, view: *View) void { view.scene_tree.node.raiseToTop(); - // _ = server.root.all_views.append(gpa, view) catch { - // unreachable; - // }; - _ = view.xdg_toplevel.setActivated(true); const wlr_keyboard = server.seat.wlr_seat.getKeyboard() orelse return; diff --git a/src/seat.zig b/src/seat.zig index 1b3e8ae..eb9fa3c 100644 --- a/src/seat.zig +++ b/src/seat.zig @@ -4,6 +4,8 @@ const std = @import("std"); const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; +const Utils = @import("utils.zig"); + const server = &@import("main.zig").server; wlr_seat: *wlr.Seat, @@ -13,7 +15,9 @@ request_set_selection: wl.Listener(*wlr.Seat.event.RequestSetSelection) = .init( // request_set_primary_selection // request_start_drage -pub fn init(self: *Seat) !void { +pub fn init(self: *Seat) void { + errdefer Utils.oomPanic(); + self.* = .{ .wlr_seat = try wlr.Seat.create(server.wl_server, "default"), }; diff --git a/src/server.zig b/src/server.zig index 0185cc2..ea658ca 100644 --- a/src/server.zig +++ b/src/server.zig @@ -10,6 +10,7 @@ const Cursor = @import("cursor.zig"); const Keyboard = @import("keyboard.zig"); const Output = @import("output.zig"); const View = @import("view.zig"); +const Utils = @import("utils.zig"); const gpa = std.heap.c_allocator; const server = &@import("main.zig").server; @@ -23,6 +24,7 @@ session: ?*wlr.Session, shm: *wlr.Shm, xdg_shell: *wlr.XdgShell, +// xdg_toplevel_decoration_manager: *wlr.XdgDecorationManagerV1, // Input @@ -41,14 +43,17 @@ new_output: wl.Listener(*wlr.Output) = .init(handleNewOutput), // 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), // new_xdg_popup // new_xdg_toplevel // Seat listeners -pub fn init(self: *Server) !void { +pub fn init(self: *Server) void { + errdefer Utils.oomPanic(); + const wl_server = wl.Server.create() catch { - std.err.log("Server create failed, exiting with 2", .{}); + std.log.err("Server create failed, exiting with 2", .{}); std.process.exit(2); }; @@ -74,6 +79,7 @@ pub fn init(self: *Server) !void { std.process.exit(5); }, .xdg_shell = try wlr.XdgShell.create(wl_server, 2), + // .xdg_toplevel_decoration_manager = try wlr.XdgDecorationManagerV1.create(self.wl_server), .event_loop = event_loop, .session = session, .compositor = try wlr.Compositor.create(wl_server, 6, renderer), @@ -85,14 +91,14 @@ pub fn init(self: *Server) !void { .keyboard = undefined, }; - try self.renderer.initServer(wl_server) catch { + self.renderer.initServer(wl_server) catch { std.log.err("Renderer init failed, exiting with 6", .{}); std.process.exit(6); }; self.root.init(); - try self.seat.init(); - try self.cursor.init(); + self.seat.init(); + self.cursor.init(); _ = try wlr.Subcompositor.create(self.wl_server); _ = try wlr.DataDeviceManager.create(self.wl_server); @@ -105,6 +111,9 @@ pub fn init(self: *Server) !void { // 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_toplevel_decoration); } pub fn deinit(self: *Server) void { @@ -112,6 +121,7 @@ pub fn deinit(self: *Server) void { self.new_output.link.remove(); self.new_xdg_toplevel.link.remove(); self.new_xdg_popup.link.remove(); + self.new_xdg_toplevel.link.remove(); self.seat.deinit(); self.root.deinit(); @@ -129,9 +139,7 @@ fn handleNewInput( device: *wlr.InputDevice ) void { switch (device.type) { - .keyboard => server.keyboard.init(device) catch { - std.log.err("Unable to create keyboard from device {s}", .{device.name orelse "(null)"}); - }, + .keyboard => server.keyboard.init(device), .pointer => server.cursor.wlr_cursor.attachInputDevice(device), else => { std.log.err( @@ -165,31 +173,16 @@ fn handleNewOutput( } 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; - }; + const new_output = Output.create(wlr_output); server.root.addOutput(new_output); } -fn handleRequestSetSelection( - _: *wl.Listener(*wlr.Seat.event.RequestSetSelection), - event: *wlr.Seat.event.RequestSetSelection, -) void { - server.seat.setSelection(event.source, event.serial); -} - fn handleNewXdgToplevel( _: *wl.Listener(*wlr.XdgToplevel), xdg_toplevel: *wlr.XdgToplevel ) void { - if(View.initFromTopLevel(xdg_toplevel)) |view| { - std.log.debug("Adding new view {s}", .{view.xdg_toplevel.title orelse "(null)"}); - } else { - std.log.err("Unable to allocate new view", .{}); - } + _ = View.initFromTopLevel(xdg_toplevel); } fn handleNewXdgPopup( @@ -198,3 +191,11 @@ fn handleNewXdgPopup( ) void { std.log.err("Unimplemented handle new xdg popup", .{}); } + +// fn handleNewXdgToplevelDecoration( +// _: *wl.Listener(*wlr.XdgToplevelDecorationV1), +// decoration: *wlr.XdgToplevelDecorationV1 +// ) void { +// // TODO: Configured with lua perhaps +// decoration.current.mode = .server_side; +// } diff --git a/src/view.zig b/src/view.zig index bfa3a21..ebcfcc2 100644 --- a/src/view.zig +++ b/src/view.zig @@ -30,30 +30,34 @@ request_move: wl.Listener(*wlr.XdgToplevel.event.Move) = .init(handleRequestMove // Not yet silly // new_popup: wl.Listener(*wlr.XdgPopup) = wl.Listener(*wlr.XdgPopup).init(handleNewPopup), -pub fn initFromTopLevel(xdg_toplevel: *wlr.XdgToplevel) ?*View { +pub fn initFromTopLevel(xdg_toplevel: *wlr.XdgToplevel) *View { errdefer Utils.oomPanic(); - const self = gpa.create(View) catch Utils.oomPanic(); + const self = try gpa.create(View); errdefer gpa.destroy(self); self.* = .{ .xdg_toplevel = xdg_toplevel, .xdg_surface = xdg_toplevel.base, .geometry = &xdg_toplevel.base.geometry, - .scene_tree = try server.root.scene.tree.createSceneXdgSurface(xdg_toplevel.base) + .scene_tree = undefined, + }; + // Add new Toplevel to focused output instead of some random shit + self.scene_tree = try server.root.workspaces.items[0].createSceneXdgSurface(xdg_toplevel.base); + self.scene_tree.node.data = self; self.xdg_surface.data = self.scene_tree; // Attach listeners - xdg_surface.surface.events.map.add(&self.map); - xdg_surface.surface.events.unmap.add(&self.unmap); - xdg_surface.surface.events.commit.add(&self.commit); + self.xdg_surface.surface.events.map.add(&self.map); + self.xdg_surface.surface.events.unmap.add(&self.unmap); + self.xdg_surface.surface.events.commit.add(&self.commit); - xdg_toplevel.events.destroy.add(&self.destroy); - xdg_toplevel.events.request_move.add(&self.request_move); - xdg_toplevel.events.request_resize.add(&self.request_resize); + self.xdg_toplevel.events.destroy.add(&self.destroy); + self.xdg_toplevel.events.request_move.add(&self.request_move); + self.xdg_toplevel.events.request_resize.add(&self.request_resize); // xdg_toplevel.events.request_fullscreen.add(&self.request_fullscreen); // xdg_toplevel.events.request_minimize.add(&self.request_minimize); @@ -65,6 +69,8 @@ pub fn initFromTopLevel(xdg_toplevel: *wlr.XdgToplevel) ?*View { // xdg_toplevel.events.request_show_window_menu.add(&self.request_show_window_menu); + try server.root.views.append(gpa, self); + return self; } @@ -76,8 +82,6 @@ pub fn deinit(self: *View) void { self.destroy.link.remove(); self.request_move.link.remove(); self.request_resize.link.remove(); - - gpa.free(self); } // --------- XdgTopLevel event handlers ---------