diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-08-30 15:49:18 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-08-30 15:49:18 +0200 |
| commit | a46436e58beaaa322c082af5e886f96fd31d7a08 (patch) | |
| tree | 05a05b149c2f18cb0562aef94fe41bd5aaad9fbc | |
| parent | 4feb8c7dab2b0a3492b8248ee12c3f0a475106f1 (diff) | |
| -rw-r--r-- | src/main.zig | 19 | ||||
| -rw-r--r-- | src/object/interface.zig | 68 | ||||
| -rw-r--r-- | src/object/root.zig (renamed from src/object.zig) | 8 | ||||
| -rw-r--r-- | src/root.zig | 3 | ||||
| -rw-r--r-- | src/wl/buffer.zig | 28 | ||||
| -rw-r--r-- | src/wl/callback.zig | 17 | ||||
| -rw-r--r-- | src/wl/compositor.zig | 28 | ||||
| -rw-r--r-- | src/wl/display.zig | 3 | ||||
| -rw-r--r-- | src/wl/output/root.zig | 30 | ||||
| -rw-r--r-- | src/wl/shm/pixel/argb8888.zig | 6 | ||||
| -rw-r--r-- | src/wl/shm/pixel/root.zig | 0 | ||||
| -rw-r--r-- | src/wl/shm/pool.zig | 39 | ||||
| -rw-r--r-- | src/wl/shm/root.zig | 44 | ||||
| -rw-r--r-- | src/wl/surface.zig | 14 | ||||
| -rw-r--r-- | src/xdg/root.zig | 2 | ||||
| -rw-r--r-- | src/xdg/surface.zig | 25 | ||||
| -rw-r--r-- | src/xdg/wm-base.zig | 45 |
17 files changed, 219 insertions, 160 deletions
diff --git a/src/main.zig b/src/main.zig index 400df48..0d5c6bd 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,6 +1,7 @@ const std = @import("std"); const wayland = @import("wayland"); const wl = wayland.wl; +const xdg = wayland.xdg; const log = std.log.scoped(.main); @@ -20,6 +21,7 @@ pub fn main() !void { wl.Output.handler, wl.Compositor.handler, wl.Shm.handler, + xdg.WmBase.handler, }); try display.roundtrip(allocator); @@ -32,19 +34,26 @@ pub fn main() !void { try display.roundtrip(allocator); - for (wl.Output.instances.items) |output| { + for (wl.Output.globals.as_slice()) |output| { log.debug("{}", .{output}); } - for (wl.Compositor.instances.items) |compositor| { + for (wl.Compositor.globals.as_slice()) |compositor| { log.debug("{}", .{compositor}); } - for (wl.Shm.instances.items) |shm| { + for (wl.Shm.globals.as_slice()) |shm| { log.debug("{}", .{shm}); } - const pool = try wl.Shm.instances.items[0].create_pool(ctx, 800 * 600 * (wl.Shm.Format.argb8888).bytes_per_pixel()); + for (xdg.WmBase.globals.as_slice()) |wm_base| { + log.debug("{}", .{wm_base}); + } + + const pool = try wl.Shm + .globals + .get(0).? + .create_pool(ctx, 800 * 600 * (wl.Shm.Format.argb8888).bytes_per_pixel()); defer pool.deinit(ctx); try display.roundtrip(allocator); @@ -52,7 +61,7 @@ pub fn main() !void { const buffer = try pool.create_buffer(ctx, 0, 800, 600, .argb8888); defer ctx.display.request(buffer, .{ .destroy = {} }) catch |e| log.err("error {}", .{e}); - const surface = try wl.Compositor.instances.items[0].create_surface(ctx); + const surface = try wl.Compositor.globals.get(0).?.create_surface(ctx); defer surface.deinit(ctx); try display.roundtrip(allocator); diff --git a/src/object/interface.zig b/src/object/interface.zig new file mode 100644 index 0000000..3098c46 --- /dev/null +++ b/src/object/interface.zig @@ -0,0 +1,68 @@ +const std = @import("std"); +const wayland = @import("../root.zig"); +const wl = wayland.wl; + +pub fn Init(T: type) type { + return struct { + const Self = @This(); + + pub fn default( + self: *Self, + ctx: wayland.Context, + ) !void { + const parent: *T = @alignCast(@fieldParentPtr("init", self)); + + parent.* = .{ + .handle = try ctx.display.registry.add_object( + ctx.allocator, + wayland.Object.from_self(parent), + ), + }; + } + + pub fn with( + self: *Self, + ctx: wayland.Context, + values: T, + ) !void { + const parent: *T = @alignCast(@fieldParentPtr("init", self)); + parent.* = values; + parent.handle = try ctx.display.registry.add_object( + ctx.allocator, + wayland.Object.from_self(parent), + ); + } + }; +} + +pub fn Global(T: type) type { + return struct { + const Self = @This(); + + pub const init = Self { }; + var instances: std.ArrayListUnmanaged(*T) = .empty; + + comptime register: fn (ctx: wayland.Context) ?wayland.Object.Ref = reg, + + pub fn reg(ctx: wayland.Context) ?wayland.Object.Ref { + const interface = ctx.allocator.create(T) catch return null; + interface.init.default(ctx) catch return null; + + instances.append(ctx.allocator, interface) catch return null; + return interface.handle; + } + + pub fn as_slice(self: *Self) []*T { + _ = self; + return instances.items; + } + + pub fn get(self: *Self, index: usize) ?*T { + _ = self; + if (index >= instances.items.len) { + return null; + } + return instances.items[index]; + } + }; +} diff --git a/src/object.zig b/src/object/root.zig index 7820674..1895d3f 100644 --- a/src/object.zig +++ b/src/object/root.zig @@ -1,11 +1,17 @@ const std = @import("std"); -const wayland = @import("root.zig"); +const wayland = @import("../root.zig"); const Self = @This(); +pub const interface = @import("interface.zig"); + pub const Ref = struct { id: u32, + pub const @"null": @This() = .{ + .id = 0, + }; + pub const display: @This() = .{ .id = 1, }; diff --git a/src/root.zig b/src/root.zig index ea9357a..82c62f3 100644 --- a/src/root.zig +++ b/src/root.zig @@ -1,6 +1,7 @@ const std = @import("std"); pub const wl = @import("wl/root.zig"); -pub const Object = @import("object.zig"); +pub const xdg = @import("xdg/root.zig"); +pub const Object = @import("object/root.zig"); pub const EventSet = @import("event-set.zig").EventSet; pub const types = @import("types.zig"); pub const Context = @import("context.zig"); diff --git a/src/wl/buffer.zig b/src/wl/buffer.zig index fe69899..ae52196 100644 --- a/src/wl/buffer.zig +++ b/src/wl/buffer.zig @@ -12,29 +12,13 @@ pub fn Buffer(fmt: wl.Shm.Format) type { pub const Events = wayland.EventSet(Self, .{}); - handle: wayland.Object.Ref, + handle: wayland.Object.Ref = .null, + init: wayland.Object.interface.Init(Self) = .{}, + data: []wl.Shm.Format.Pixel(fmt), width: usize, height: usize, - pub fn init( - self: *Self, - ctx: wayland.Context, - width: usize, - height: usize, - data: []u8, - ) !void { - self.* = .{ - .handle = try ctx.display.registry.add_object( - ctx.allocator, - wayland.Object.from_self(self), - ), - .data = @alignCast(@ptrCast(data)), - .width = width, - .height = height, - }; - } - pub fn format( self: *const Self, comptime f: []const u8, @@ -44,7 +28,11 @@ pub fn Buffer(fmt: wl.Shm.Format) type { _ = f; _ = options; - try writer.print("wl.buffer<{s}> {{ {}x{} }}", .{@tagName(fmt), self.width, self.height}); + try writer.print("wl.buffer<{s}> {{ {}x{} }}", .{ + @tagName(fmt), + self.width, + self.height + }); } }; } diff --git a/src/wl/callback.zig b/src/wl/callback.zig index ad2d192..dc9028d 100644 --- a/src/wl/callback.zig +++ b/src/wl/callback.zig @@ -9,21 +9,8 @@ const Self = @This(); pub const Events = wayland.EventSet(Self, .{done}); is_done: *bool, -handle: wayland.Object.Ref, - -pub fn init( - self: *Self, - ctx: wayland.Context, - is_done: *bool, -) !void { - self.is_done = is_done; - self.handle = try ctx.display.registry.add_object( - ctx.allocator, - wayland.Object.from_self(self), - ); - try ctx.display.request(ctx.display, .{ .sync = .{self.handle} }); - -} +handle: wayland.Object.Ref = .null, +init: wayland.Object.interface.Init(Self) = .{}, pub fn deinit(self: *Self, ctx: wayland.Context) void { ctx.display.registry.disable_object(self.handle); diff --git a/src/wl/compositor.zig b/src/wl/compositor.zig index 166430a..ed8ac6b 100644 --- a/src/wl/compositor.zig +++ b/src/wl/compositor.zig @@ -11,35 +11,15 @@ pub const Request = union(enum) { }; handle: wayland.Object.Ref, +init: wayland.Object.interface.Init(Self) = .{}, -pub var instances: std.ArrayListUnmanaged(*Self) = .empty; - +pub var globals: wayland.Object.interface.Global(Self) = .init; pub const handler: wl.Registry.GlobalHandler = .{ .interface = "wl_compositor", .version = 6, - .handler = register, + .handler = globals.register, }; -pub fn init( - self: *Self, - ctx: wayland.Context -) !void { - self.* = .{ - .handle = try ctx.display.registry.add_object( - ctx.allocator, - wayland.Object.from_self(self), - ), - }; -} - -fn register(ctx: wayland.Context) ?wayland.Object.Ref { - const compositor = ctx.allocator.create(Self) catch return null; - compositor.init(ctx) catch return null; - - instances.append(ctx.allocator, compositor) catch return null; - return compositor.handle; -} - pub fn format( self: *const Self, comptime fmt: []const u8, @@ -60,7 +40,7 @@ pub fn create_surface( const surface = try ctx.allocator.create(wl.Surface); errdefer ctx.allocator.destroy(surface); - try surface.init(ctx); + try surface.init.default(ctx); try ctx.display.request(self, .{ .create_surface = .{ surface.handle } }); diff --git a/src/wl/display.zig b/src/wl/display.zig index fed8bbd..5b31646 100644 --- a/src/wl/display.zig +++ b/src/wl/display.zig @@ -200,7 +200,8 @@ pub fn roundtrip(self: *Self, allocator: std.mem.Allocator) !void { var done = false; var callback: wl.Callback = undefined; - try callback.init(context, &done); + try callback.init.with(context, .{ .is_done = &done }); + try self.request(self, .{ .sync = .{ callback.handle } }); defer callback.deinit(context); errdefer self.read_event(context) catch |e| { diff --git a/src/wl/output/root.zig b/src/wl/output/root.zig index 61c1798..9cffd43 100644 --- a/src/wl/output/root.zig +++ b/src/wl/output/root.zig @@ -30,40 +30,22 @@ pub const Info = struct { description: []const u8, }; -pub var instances: std.ArrayListUnmanaged(*Self) = .empty; staging: Info = undefined, info: ?Info = null, -handle: wayland.Object.Ref, - -pub fn init( - self: *Self, - ctx: wayland.Context, -) !void { - self.* = .{ - .handle = try ctx.display.registry.add_object( - ctx.allocator, - wayland.Object.from_self(self), - ), - }; -} -pub fn deinit(self: *Self, display: *wl.Display) !void { - display.request(self, .{ .release = void{} }); -} +handle: wayland.Object.Ref, +init: wayland.Object.interface.Init(Self) = .{}, +pub var globals: wayland.Object.interface.Global(Self) = .init; pub const handler: wl.Registry.GlobalHandler = .{ .interface = "wl_output", .version = 4, - .handler = register, + .handler = globals.register, }; -fn register(ctx: wayland.Context) ?wayland.Object.Ref { - const output = ctx.allocator.create(Self) catch return null; - output.init(ctx) catch return null; - - instances.append(ctx.allocator, output) catch return null; - return output.handle; +pub fn deinit(self: *Self, display: *wl.Display) !void { + display.request(self, .{ .release = void{} }); } fn geometry( diff --git a/src/wl/shm/pixel/argb8888.zig b/src/wl/shm/pixel/argb8888.zig new file mode 100644 index 0000000..5e5a68e --- /dev/null +++ b/src/wl/shm/pixel/argb8888.zig @@ -0,0 +1,6 @@ +pub const Pixel = packed struct(u32) { + alpha: u8, + red: u8, + green: u8, + blue: u8, +} diff --git a/src/wl/shm/pixel/root.zig b/src/wl/shm/pixel/root.zig new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/wl/shm/pixel/root.zig diff --git a/src/wl/shm/pool.zig b/src/wl/shm/pool.zig index 62b6c18..16ba936 100644 --- a/src/wl/shm/pool.zig +++ b/src/wl/shm/pool.zig @@ -15,29 +15,11 @@ pub const Request = union(enum) { resize: struct { u32 }, }; -handle: wayland.Object.Ref, +handle: wayland.Object.Ref = .null, +init: wayland.Object.interface.Init(Self) = .{}, file: AnonymousFile, buffer: []u8, -pub fn init( - self: *Self, - ctx: wayland.Context, - size: usize, -) !void { - var file = try AnonymousFile.init_random(); - errdefer file.close(); - try file.truncate(size); - - self.* = .{ - .handle = try ctx.display.registry.add_object( - ctx.allocator, - wayland.Object.from_self(self), - ), - .file = file, - .buffer = try file.mmap(), - }; -} - pub fn deinit(self: *Self, ctx: wayland.Context) void { self.file.close(); std.posix.munmap(@alignCast(self.buffer)); @@ -51,9 +33,9 @@ pub fn deinit(self: *Self, ctx: wayland.Context) void { pub fn create_buffer( self: *Self, ctx: wayland.Context, - offset: usize, - width: usize, - height: usize, + offset: u32, + width: u32, + height: u32, comptime format: Format, ) !*wl.Buffer(format) { const stride = width * format.bytes_per_pixel(); @@ -61,12 +43,11 @@ pub fn create_buffer( const buffer = try ctx.allocator.create(wl.Buffer(format)); errdefer ctx.allocator.destroy(buffer); - try buffer.init( - ctx, - width, - height, - data, - ); + try buffer.init.with(ctx, .{ + .width = width, + .height = height, + .data = @alignCast(@ptrCast(data)), + }); try ctx.display.request( self, diff --git a/src/wl/shm/root.zig b/src/wl/shm/root.zig index 741c7df..46388ad 100644 --- a/src/wl/shm/root.zig +++ b/src/wl/shm/root.zig @@ -13,46 +13,34 @@ pub const Request = union(enum) { create_pool: struct { wayland.Object.Ref, wayland.types.Fd, u32 }, }; -pub var instances: std.ArrayListUnmanaged(*Self) = .empty; - -handle: wayland.Object.Ref, +handle: wayland.Object.Ref = .null, +init: wayland.Object.interface.Init(Self) = .{}, formats: std.EnumSet(Format) = .initEmpty(), -pub fn init( - self: *Self, - ctx: wayland.Context, -) !void { - self.* = .{ - .handle = try ctx.display.registry.add_object( - ctx.allocator, - wayland.Object.from_self(self), - ), - }; -} - -fn announce_format(self: * Self, ctx: wayland.Context, fmt: Format) void { - _ = ctx; - self.formats.insert(fmt); -} - +pub var globals: wayland.Object.interface.Global(Self) = .init; pub const handler: wl.Registry.GlobalHandler = .{ .interface = "wl_shm", .version = 1, - .handler = register, + .handler = globals.register, }; -fn register(ctx: wayland.Context) ?wayland.Object.Ref { - const shm = ctx.allocator.create(Self) catch return null; - shm.init(ctx) catch return null; - - instances.append(ctx.allocator, shm) catch return null; - return shm.handle; +fn announce_format(self: * Self, ctx: wayland.Context, fmt: Format) void { + _ = ctx; + self.formats.insert(fmt); } pub fn create_pool(self: *Self, ctx: wayland.Context, size: usize) !*Pool { const pool = try ctx.allocator.create(Pool); errdefer ctx.allocator.destroy(pool); - try pool.init(ctx, size); + + var file = try AnonymousFile.init_random(); + errdefer file.close(); + try file.truncate(size); + + try pool.init.with(ctx, .{ + .file = file, + .buffer = try file.mmap(), + }); try ctx.display.request(self, .{ .create_pool = .{ pool.handle, diff --git a/src/wl/surface.zig b/src/wl/surface.zig index 07cd80b..4405c96 100644 --- a/src/wl/surface.zig +++ b/src/wl/surface.zig @@ -26,21 +26,11 @@ pub const Events = wayland.EventSet(Self, .{ }); handle: wayland.Object.Ref, +init: wayland.Object.interface.Init(Self) = .{}, + preferred_buffer_scale: u32 = 1, preferred_buffer_transform: wl.Output.Transform = .normal, -pub fn init( - self: *Self, - ctx: wayland.Context, -) !void { - self.* = .{ - .handle = try ctx.display.registry.add_object( - ctx.allocator, - wayland.Object.from_self(self), - ), - }; -} - pub fn deinit( self: *Self, ctx: wayland.Context, diff --git a/src/xdg/root.zig b/src/xdg/root.zig new file mode 100644 index 0000000..0d4f0eb --- /dev/null +++ b/src/xdg/root.zig @@ -0,0 +1,2 @@ +pub const WmBase = @import("wm-base.zig"); +pub const Surface = @import("surface.zig"); diff --git a/src/xdg/surface.zig b/src/xdg/surface.zig new file mode 100644 index 0000000..fc9d838 --- /dev/null +++ b/src/xdg/surface.zig @@ -0,0 +1,25 @@ +const wayland = @import("../root.zig"); +const wl = wayland.wl; + +const Self = @This(); + +pub const Request = union(enum) { + destroy: void, + get_toplevel: struct { wayland.Object.Ref }, + get_popup: struct { wayland.Object.Ref, ?wayland.Object.Ref, wayland.Object.Ref }, + set_window_geometry: struct { i32, i32, i32, i32 }, + ack_configure: struct { u32 }, +}; + +pub const Events = wayland.EventSet(Self, .{ configure }); + +handle: wayland.Object.Ref, +init: wayland.Object.interface.Init(Self) = .{}, + +fn configure( + self: *Self, + ctx: wayland.Context, + payload: u32 +) !void { + try ctx.display.request(self, .{ .ack_configure = .{ payload } }); +} diff --git a/src/xdg/wm-base.zig b/src/xdg/wm-base.zig new file mode 100644 index 0000000..6a9df47 --- /dev/null +++ b/src/xdg/wm-base.zig @@ -0,0 +1,45 @@ +const std = @import("std"); +const wayland = @import("../root.zig"); +const wl = wayland.wl; + +const Self = @This(); + +pub const Request = union(enum) { + destroy: void, + create_positioner: struct { wayland.Object.Ref }, + create_xdg_surface: struct { wayland.Object.Ref, wayland.Object.Ref }, + pong: struct { u32 }, +}; + +pub const Events = wayland.EventSet(Self, .{ ping }); + +handle: wayland.Object.Ref, +init: wayland.Object.interface.Init(Self) = .{}, + + +pub var globals: wayland.Object.interface.Global(Self) = .init; +pub const handler: wl.Registry.GlobalHandler = .{ + .interface = "xdg_wm_base", + .version = 6, + .handler = globals.register, +}; + +fn ping( + self: *Self, + ctx: wayland.Context, + payload: u32, +) !void { + try ctx.display.request(self, .{ .pong = .{ payload } }); +} + +pub fn format( + self: *const Self, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, +) !void { + _ = self; + _ = fmt; + _ = options; + try writer.print("xdg.wm-base", .{}); +} |