From 956ecb061b1862a4b632c8d5d6b6fa4318e1f640 Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Fri, 22 Aug 2025 20:12:56 +0200 Subject: object refactor and add wl output Now the Object is held by the registry instead of the struct its referencing and the struct only has a `handle` which is a usize. --- src/event-set.zig | 8 +-- src/main.zig | 6 +- src/object.zig | 9 ++- src/wl/callback.zig | 19 ++--- src/wl/display.zig | 128 ++++++++++++++++++++------------- src/wl/output.zig | 171 -------------------------------------------- src/wl/output/geometry.zig | 12 ++++ src/wl/output/mode.zig | 26 +++++++ src/wl/output/root.zig | 156 ++++++++++++++++++++++++++++++++++++++++ src/wl/output/subpixel.zig | 8 +++ src/wl/output/transform.zig | 10 +++ src/wl/registry.zig | 52 +++++++++----- src/wl/root.zig | 2 +- 13 files changed, 352 insertions(+), 255 deletions(-) delete mode 100644 src/wl/output.zig create mode 100644 src/wl/output/geometry.zig create mode 100644 src/wl/output/mode.zig create mode 100644 src/wl/output/root.zig create mode 100644 src/wl/output/subpixel.zig create mode 100644 src/wl/output/transform.zig diff --git a/src/event-set.zig b/src/event-set.zig index 5721a4e..27c28bf 100644 --- a/src/event-set.zig +++ b/src/event-set.zig @@ -4,7 +4,6 @@ const wayland = @import("root.zig"); pub fn EventSet(T: type, events: anytype) type { return struct { pub fn on_event(ptr: *anyopaque, ctx: *wayland.Context, opcode: u16, args: []const u8) void { - std.debug.print("event {} {}\n", .{T, opcode}); var offset: usize = 0; inline for (events, 0..) |event, index| { if (@TypeOf(event) != @TypeOf(null) and index == opcode) { @@ -31,7 +30,7 @@ pub fn EventSet(T: type, events: anytype) type { }, *wayland.Object => { const result = std.mem.readPackedIntNative(u32, args, offset * 8); - fn_args[arg_index] = ctx.display.registry.objects.items[result] orelse unreachable; + fn_args[arg_index] = ctx.display.registry.get(result) orelse unreachable; offset += @sizeOf(u32); }, else => |t| switch (@typeInfo(t)) { @@ -67,7 +66,7 @@ test { a: u32 = 0, b: u32 = 0, - pub fn something(self: *@This(), a: u32, b: u32) void { + pub fn something(self: *@This(), _: *wayland.Context, a: u32, b: u32) void { self.a = a; self.b = b; } @@ -75,8 +74,9 @@ test { var dummy = Dummy{}; const Events = EventSet(Dummy, .{null, Dummy.something }); + var ctx: wayland.Context = undefined; - Events.on_event(&dummy, 1, &(std.mem.toBytes(@as(u32, 1)) ++ std.mem.toBytes(@as(u32, 2)))); + Events.on_event(&dummy, &ctx, 1, &(std.mem.toBytes(@as(u32, 1)) ++ std.mem.toBytes(@as(u32, 2)))); try std.testing.expectEqual(dummy.a, 1); try std.testing.expectEqual(dummy.b, 2); diff --git a/src/main.zig b/src/main.zig index 7e27f94..a9a5ef6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -7,9 +7,13 @@ pub fn main() !void { const allocator = gpa.allocator(); var display: wl.Display = try .open_default(allocator); - defer display.close(); + defer display.deinit(allocator); try display.init(allocator, &.{wl.Output.handler}); try display.roundtrip(allocator); try display.roundtrip(allocator); + + for (wl.Output.all()) |output| { + std.debug.print("{}\n", .{output}); + } } diff --git a/src/object.zig b/src/object.zig index 0751859..14089c1 100644 --- a/src/object.zig +++ b/src/object.zig @@ -3,11 +3,12 @@ const wayland = @import("root.zig"); const Self = @This(); +pub const Ref = usize; + const VTable = struct { on_event: *const fn (ptr: *anyopaque, ctx: *wayland.Context, opcode: u16, args: []const u8) void, }; -id: ?u32 = null, ptr: ?*anyopaque, vtable: VTable, @@ -28,6 +29,10 @@ pub inline fn from_self(ptr: anytype) Self { }; } +pub fn disable(self: *Self) void { + self.ptr = null; +} + pub fn format( self: *const Self, comptime fmt: []const u8, @@ -37,5 +42,5 @@ pub fn format( _ = fmt; _ = options; - try writer.print("Object {{ {?} }}", .{self.id}); + try writer.print("Object {{ {?} }}", .{self.ptr}); } diff --git a/src/wl/callback.zig b/src/wl/callback.zig index 0e7ea5b..c17e190 100644 --- a/src/wl/callback.zig +++ b/src/wl/callback.zig @@ -9,23 +9,26 @@ const Self = @This(); pub const Events = wayland.EventSet(Self, .{done}); is_done: *bool, -interface: wayland.Object, +handle: wayland.Object.Ref, pub fn init( self: *Self, - allocator: std.mem.Allocator, - display: *wl.Display, + ctx: *wayland.Context, is_done: *bool, ) !void { self.is_done = is_done; - self.interface = wayland.Object.from_self(self); - try display.registry.add_object(allocator, &self.interface); - std.debug.print("ids {any}\n", .{display.registry.objects.items}); - std.debug.print("callback #{?}\n", .{self.interface.id}); - try display.request(display, .{ .sync = .{&self.interface} }); + self.handle = try ctx.display.registry.add_object( + ctx.allocator, + wayland.Object.from_self(self), + ); + try ctx.display.request(ctx.display, .{ .sync = .{self.handle} }); } +pub fn deinit(self: *Self, ctx: *wayland.Context) void { + ctx.display.registry.disable_object(self.handle); +} + fn done(self: *Self, ctx: *wayland.Context, value: u32) void { _ = value; _ = ctx; diff --git a/src/wl/display.zig b/src/wl/display.zig index 4f04746..db5ed3c 100644 --- a/src/wl/display.zig +++ b/src/wl/display.zig @@ -14,8 +14,8 @@ pub const Error = enum(u32) { }; pub const Request = union(enum) { - sync: struct { *wayland.Object }, - get_registry: struct { *wayland.Object }, + sync: struct { wayland.Object.Ref }, + get_registry: struct { wayland.Object.Ref }, }; pub const Events = wayland.EventSet(Self, .{ @@ -24,19 +24,23 @@ pub const Events = wayland.EventSet(Self, .{ }); stream: std.net.Stream, -interface: wayland.Object, registry: wl.Registry, +handle: wayland.Object.Ref, pub fn init( self: *Self, allocator: std.mem.Allocator, handlers: []const wl.Registry.GlobalHandler, ) !void { - self.interface = wayland.Object.from_self(self); try self.registry.init(allocator, self, handlers); } -pub fn from_fd(fd: std.posix.fd_t) void { +pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { + self.close(); + self.registry.deinit(allocator); +} + +pub fn from_fd(fd: std.posix.fd_t) Self { var self: Self = undefined; self.stream = std.net.Stream{ .handle = fd }; return self; @@ -65,8 +69,12 @@ pub fn default_path(allocator: std.mem.Allocator) ![]const u8 { return std.fmt.allocPrint(allocator, "{s}/{s}", .{ xdg_runtime_dir, wayland_display }); } +fn padding_len(T: type, length: usize) usize { + return @mod(@as(usize, @bitCast(-@as(isize, @intCast(length * @sizeOf(T))))), 4); +} + pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !void { - comptime std.debug.assert(@FieldType(@TypeOf(object.*), "interface") == wayland.Object); + comptime std.debug.assert(@FieldType(@TypeOf(object.*), "handle") == wayland.Object.Ref); comptime std.debug.assert(@typeInfo(@TypeOf(object.*).Request) == .@"union"); const tag_type = @typeInfo(@TypeOf(args)).@"union".tag_type.?; const opcode: u32 = @intFromEnum(args); @@ -74,21 +82,21 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v inline for (@typeInfo(tag_type).@"enum".fields) |f| { if (f.value == opcode) { const data = @field(args, f.name); - const id = object.interface.id orelse return error.UnregisteredObject; + const id: u32 = @truncate(object.handle); var size: u32 = 8; inline for (data) |value| { switch (@TypeOf(value)) { u32, i32 => |t| size += @sizeOf(t), - *wayland.Object => size += @sizeOf(u32), + wayland.Object.Ref => size += @sizeOf(u32), []const u8, []u8 => { - const padding_size: usize = @mod(@as(usize, @bitCast(-@as(isize, @intCast(value.len + 1)))), 4); + const padding_size: usize = padding_len(u8, value.len + 1); size += @as(u32, @intCast(@sizeOf(u32) + (value.len + 1) + padding_size)); }, else => |t| switch (@typeInfo(t)) { .pointer => |ptr| if (ptr.size == .slice) { - const padding_size: usize = @mod(@as(usize, @bitCast(-@as(isize, @intCast(value.len * @sizeOf(ptr.child))))), 4); + const padding_size: usize = padding_len(ptr.child, value.len); size += @intCast(@sizeOf(u32) + (value.len * @sizeOf(ptr.child)) + padding_size); } else @compileError(std.fmt.comptimePrint("size: unsupported type {}", .{t})), else => @compileError(std.fmt.comptimePrint("size: unsupported type {}", .{t})), @@ -102,9 +110,9 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v inline for (data) |value| { switch (@TypeOf(value)) { u32, i32 => _ = try self.stream.writeAll(std.mem.asBytes(&value)), - *wayland.Object => try self.stream.writeAll(std.mem.asBytes(&(value.id orelse return error.UnregisteredObject))), + wayland.Object.Ref => try self.stream.writeAll(std.mem.asBytes(&(@as(u32, @truncate(value))))), []const u8, []u8 => { - const padding_size: usize = @mod(@as(usize, @bitCast(-@as(isize, @intCast(value.len + 1)))), 4); + const padding_size: usize = padding_len(u8, value.len + 1); _ = try self.stream.writeAll(std.mem.asBytes(&@as(u32, @truncate(value.len + 1)))); _ = try self.stream.writeAll(value); for (0..padding_size + 1) |_| { @@ -131,41 +139,51 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v return error.InvalidOpcode; } -pub fn roundtrip(self: *Self, allocator: std.mem.Allocator) !void { - var done = false; - var callback: wl.Callback = undefined; - try callback.init(allocator, self, &done); +fn read_event(self: *Self, ctx: *wayland.Context) !void { + const endian = @import("builtin").target.cpu.arch.endian(); + const reader = self.stream.reader(); + + const object_id = try reader.readInt(u32, endian); + const message_info = try reader.readInt(u32, endian); + + const opcode: u16 = @truncate(message_info & 0xffff); + const size: u16 = @truncate(((message_info >> 16) & 0xffff)); + const body_size = size - 2 * @sizeOf(u32); + + const body = try ctx.allocator.alloc(u8, body_size); + defer ctx.allocator.free(body); + _ = try reader.readAll(body); + + if (object_id >= self.registry.objects.items.len) { + return error.UnregisteredObject; + } + + if (self.registry.get(object_id)) |object| { + try object.on_event(ctx, opcode, body); + } else { + return error.UnregisteredObject; + } +} + +pub fn roundtrip(self: *Self, allocator: std.mem.Allocator) !void { var context: wayland.Context = .{ .display = self, .allocator = allocator, }; - while (!done) { - const endian = @import("builtin").target.cpu.arch.endian(); - const reader = self.stream.reader(); - - const object_id = try reader.readInt(u32, endian); - - const message_info = try reader.readInt(u32, endian); - - const opcode: u16 = @truncate(message_info & 0xffff); - const size: u16 = @truncate(((message_info >> 16) & 0xffff)); - const body_size = size - 2 * @sizeOf(u32); + var done = false; - const body = try allocator.alloc(u8, body_size); - defer allocator.free(body); - _ = try reader.readAll(body); + var callback: wl.Callback = undefined; + try callback.init(&context, &done); + defer callback.deinit(&context); - if (object_id >= self.registry.objects.items.len) { - return error.UnregisteredObject; - } + errdefer self.read_event(&context) catch |e| { + log.err("cleanup error: {}", .{e}); + }; - if (self.registry.objects.items[object_id]) |object| { - try object.on_event(&context, opcode, body); - } else { - return error.UnregisteredObject; - } + while (!done) { + try self.read_event(&context); } } @@ -194,17 +212,17 @@ test "request" { const Sample = struct { pub const Request = union(enum) { req1: struct { u32 }, - req2: struct { *wayland.Object }, + req2: struct { wayland.Object.Ref }, req3: struct { []const u8 }, req4: struct { []const u16 }, }; pub const Events = wayland.EventSet(@This(), .{}); - interface: wayland.Object, + handle: wayland.Object.Ref, - pub fn init(self: *@This()) void { - self.interface = wayland.Object.from_self(self); + pub fn init() @This() { + return .{ .handle = 42 }; } }; @@ -212,21 +230,29 @@ test "request" { defer std.posix.close(in); { - var sample: Sample = undefined; - sample.init(); - sample.interface.id = 42; + var sample: Sample = .init(); var displ: Self = .from_fd(out); - defer displ.close(); - try displ.init(); - try displ.request(sample, .{ .req1 = .{432} }); - try displ.request(sample, .{ .req2 = .{&sample.interface} }); - try displ.request(sample, .{ .req3 = .{"abcd"} }); - try displ.request(sample, .{ .req4 = .{&[_]u16{ 1, 32, 4, 5, 5 }} }); + defer displ.deinit(std.testing.allocator); + try displ.init(std.testing.allocator, &.{}); + try displ.request(&sample, .{ .req1 = .{432} }); + try displ.request(&sample, .{ .req2 = .{sample.handle} }); + try displ.request(&sample, .{ .req3 = .{"abcd"} }); + try displ.request(&sample, .{ .req4 = .{&[_]u16{ 1, 32, 4, 5, 5 }} }); } const file = std.fs.File{ .handle = in }; + var test_buffer: [64]u8 = undefined; + _ = try file.readAll(test_buffer[0..12]); + try std.testing.expectEqualSlices( + u8, + &(std.mem.toBytes(@as(u32, 1)) ++ + std.mem.toBytes(@as(u32, (12 << 16) | 1)) ++ + std.mem.toBytes(@as(u32, 2))), + test_buffer[0..12], + ); + _ = try file.readAll(test_buffer[0..12]); try std.testing.expectEqualSlices( u8, diff --git a/src/wl/output.zig b/src/wl/output.zig deleted file mode 100644 index 99e8ca1..0000000 --- a/src/wl/output.zig +++ /dev/null @@ -1,171 +0,0 @@ -const std = @import("std"); -const wayland = @import("../root.zig"); -const wl = wayland.wl; - -const Self = @This(); - -pub const Requests = union(enum) { - release: struct {}, -}; - -pub const Events = wayland.EventSet(Self, .{ - geometry, - mode, - done, - scale, - name, - description, -}); - -pub const Subpixel = enum(u32) { - unkown = 0, - none = 1, - orizontal_rgb = 2, - orizontal_bgr = 3, - vertical_rgb = 4, - vertical_bgr = 5, -}; - -pub const Transform = enum(u32) { - normal = 0, - normal_90 = 1, - normal_180 = 2, - normal_270 = 3, - flipped = 4, - flipped_90 = 5, - flipped_180 = 6, - flipped_270 = 7, -}; - -pub const Geometry = struct { - x: u32, - y: u32, - physical_width: u32, - physical_height: u32, - subpixel: Subpixel, - make: []const u8, - model: []const u8, - transform: Transform, -}; - -pub const Mode = struct { - pub const Kind = enum(u32) { - current = 1, - preferred = 2, - }; - - kind: Kind, - width: u32, - height: u32, - refresh: u32, -}; - -pub const Info = struct { - geometry: Geometry, - mode: Mode, - scale: u32, - name: []const u8, - description: []const u8, -}; - -var outputs: std.ArrayListUnmanaged(*Self) = .empty; - -staging: Info = undefined, -info: ?Info = null, -interface: wayland.Object, - -pub fn init( - self: *Self, - allocator: std.mem.Allocator, - display: *wl.Display, -) !void { - self.* = .{ .interface = wayland.Object.from_self(self) }; - try display.registry.add_object(allocator, &self.interface); -} - -pub fn deinit(self: *Self, display: *wl.Display) !void { - display.request(self, .{ .release = void{} }); -} - -pub const handler: wl.Registry.GlobalHandler = .{ - .interface = "wl_output", - .version = 4, - .handler = register, -}; - -pub fn register(ctx: *wayland.Context) ?wayland.Object { - const output = ctx.allocator.create(Self) catch return null; - output.init(ctx.allocator, ctx.display) catch return null; - outputs.append(ctx.allocator, output) catch return null; - return output.interface; -} - -fn geometry( - self: *Self, - ctx: *wayland.Context, - x: u32, - y: u32, - physical_width: u32, - physical_height: u32, - subpixel: Subpixel, - make: []const u8, - model: []const u8, - transform: Transform, -) void { - _ = ctx; - self.staging.geometry = .{ - .x = x, - .y = y, - .physical_width = physical_width, - .physical_height = physical_height, - .subpixel = subpixel, - .make = make, - .model = model, - .transform = transform, - }; -} - -fn mode( - self: *Self, - ctx: *wayland.Context, - flags: Mode.Kind, - width: u32, - height: u32, - refresh: u32, -) void { - _ = ctx; - self.staging.mode = .{ - .kind = flags, - .width = width, - .height = height, - .refresh = refresh, - }; -} - -fn done(self: *Self, ctx: *wayland.Context) void { - if (self.info) |info| { - ctx.allocator.free(info.name); - ctx.allocator.free(info.description); - } - - self.info = self.staging; -} - -fn scale(self: *Self, ctx: *wayland.Context, factor: u32) void { - _ = ctx; - self.staging.scale = factor; -} - -fn name(self: *Self, ctx: *wayland.Context, n: []const u8) !void { - self.staging.name = try ctx.allocator.alloc(u8, n.len); - @memcpy(@constCast(self.staging.name), n); -} - -fn description(self: *Self, ctx: *wayland.Context, d: []const u8) !void { - self.staging.description = try ctx.allocator.alloc(u8, d.len); - @memcpy(@constCast(self.staging.description), d); -} - -pub fn get(index: usize) *Self { - return &outputs.items[index]; -} diff --git a/src/wl/output/geometry.zig b/src/wl/output/geometry.zig new file mode 100644 index 0000000..2dfcf2f --- /dev/null +++ b/src/wl/output/geometry.zig @@ -0,0 +1,12 @@ +const Subpixel = @import("root.zig").Subpixel; +const Transform = @import("root.zig").Transform; + +x: u32, +y: u32, +physical_width: u32, +physical_height: u32, +subpixel: Subpixel, +make: []const u8, +model: []const u8, +transform: Transform, + diff --git a/src/wl/output/mode.zig b/src/wl/output/mode.zig new file mode 100644 index 0000000..a21e8e0 --- /dev/null +++ b/src/wl/output/mode.zig @@ -0,0 +1,26 @@ +const std = @import("std"); + +const Self = @This(); + +pub const Kind = enum(u32) { + current = 1, + preferred = 2, +}; + +kind: Kind, +width: u32, +height: u32, +refresh: u32, + + +pub fn format( + self: *const Self, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, +) !void { + _ = fmt; + _ = options; + const ghz: f32 = @as(f32, @floatFromInt(self.refresh)) / 1000.0; + try writer.print("{}x{}@{d:.2}", .{ self.width, self.height, ghz}); +} diff --git a/src/wl/output/root.zig b/src/wl/output/root.zig new file mode 100644 index 0000000..fca2ecc --- /dev/null +++ b/src/wl/output/root.zig @@ -0,0 +1,156 @@ +const std = @import("std"); +const wayland = @import("../../root.zig"); +const wl = wayland.wl; + +pub const Subpixel = @import("subpixel.zig").Subpixel; +pub const Transform = @import("transform.zig").Transform; +pub const Geometry = @import("geometry.zig"); +pub const Mode = @import("mode.zig"); + +const Self = @This(); + +pub const Requests = union(enum) { + release: struct {}, +}; + +pub const Events = wayland.EventSet(Self, .{ + geometry, + mode, + done, + scale, + name, + description, +}); + +pub const Info = struct { + geometry: Geometry, + mode: Mode, + scale: u32, + name: []const u8, + description: []const u8, +}; + +var outputs: std.ArrayListUnmanaged(*Self) = .empty; + +staging: Info = undefined, +info: ?Info = null, +handle: wayland.Object.Ref, + +pub fn init( + self: *Self, + allocator: std.mem.Allocator, + display: *wl.Display, +) !void { + self.* = .{ + .handle = try display.registry.add_object( + allocator, + wayland.Object.from_self(self), + ), + }; +} + +pub fn deinit(self: *Self, display: *wl.Display) !void { + display.request(self, .{ .release = void{} }); +} + +pub const handler: wl.Registry.GlobalHandler = .{ + .interface = "wl_output", + .version = 4, + .handler = register, +}; + +pub fn register(ctx: *wayland.Context) ?wayland.Object.Ref { + const output = ctx.allocator.create(Self) catch return null; + output.init(ctx.allocator, ctx.display) catch return null; + outputs.append(ctx.allocator, output) catch return null; + return output.handle; +} + +fn geometry( + self: *Self, + ctx: *wayland.Context, + x: u32, + y: u32, + physical_width: u32, + physical_height: u32, + subpixel: Subpixel, + make: []const u8, + model: []const u8, + transform: Transform, +) void { + _ = ctx; + self.staging.geometry = .{ + .x = x, + .y = y, + .physical_width = physical_width, + .physical_height = physical_height, + .subpixel = subpixel, + .make = make, + .model = model, + .transform = transform, + }; +} + +fn mode( + self: *Self, + ctx: *wayland.Context, + flags: Mode.Kind, + width: u32, + height: u32, + refresh: u32, +) void { + _ = ctx; + self.staging.mode = .{ + .kind = flags, + .width = width, + .height = height, + .refresh = refresh, + }; +} + +fn done(self: *Self, ctx: *wayland.Context) void { + if (self.info) |info| { + ctx.allocator.free(info.name); + ctx.allocator.free(info.description); + } + + self.info = self.staging; +} + +fn scale(self: *Self, ctx: *wayland.Context, factor: u32) void { + _ = ctx; + self.staging.scale = factor; +} + +fn name(self: *Self, ctx: *wayland.Context, n: []const u8) !void { + self.staging.name = try ctx.allocator.alloc(u8, n.len); + @memcpy(@constCast(self.staging.name), n); +} + +fn description(self: *Self, ctx: *wayland.Context, d: []const u8) !void { + self.staging.description = try ctx.allocator.alloc(u8, d.len); + @memcpy(@constCast(self.staging.description), d); +} + +pub fn get(index: usize) *Self { + return outputs.items[index]; +} + +pub fn all() []*Self { + return outputs.items; +} + +pub fn format( + self: *const Self, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, +) !void { + _ = fmt; + _ = options; + if (self.info) |info| { + try writer.print("output({s}) [ {} ]", .{ info.name, info.mode}); + } else { + try writer.print("output(?)", .{}); + } +} diff --git a/src/wl/output/subpixel.zig b/src/wl/output/subpixel.zig new file mode 100644 index 0000000..f6d3bba --- /dev/null +++ b/src/wl/output/subpixel.zig @@ -0,0 +1,8 @@ +pub const Subpixel = enum(u32) { + unkown = 0, + none = 1, + orizontal_rgb = 2, + orizontal_bgr = 3, + vertical_rgb = 4, + vertical_bgr = 5, +}; diff --git a/src/wl/output/transform.zig b/src/wl/output/transform.zig new file mode 100644 index 0000000..f41ea9a --- /dev/null +++ b/src/wl/output/transform.zig @@ -0,0 +1,10 @@ +pub const Transform = enum(u32) { + normal = 0, + normal_90 = 1, + normal_180 = 2, + normal_270 = 3, + flipped = 4, + flipped_90 = 5, + flipped_180 = 6, + flipped_270 = 7, +}; diff --git a/src/wl/registry.zig b/src/wl/registry.zig index e4eb3a8..9d91952 100644 --- a/src/wl/registry.zig +++ b/src/wl/registry.zig @@ -12,18 +12,18 @@ pub const Events = wayland.EventSet(Self, .{ }); pub const Request = union(enum) { - bind: struct { u32, u32 }, + bind: struct { u32, []const u8, u32, u32 }, }; pub const GlobalHandler = struct { interface: []const u8, version: u32, - handler: *const fn (ctx: *wayland.Context) ?wayland.Object, + handler: *const fn (ctx: *wayland.Context) ?wayland.Object.Ref, }; -objects: std.ArrayListUnmanaged(?*wayland.Object) = .empty, -interface: wayland.Object, +objects: std.ArrayListUnmanaged(?wayland.Object) = .empty, handlers: []const GlobalHandler, +handle: wayland.Object.Ref, pub fn init( self: *Self, @@ -32,40 +32,55 @@ pub fn init( handlers: []const GlobalHandler, ) !void { self.* = .{ - .interface = wayland.Object.from_self(self), .handlers = handlers, + .handle = 2, }; try self.objects.append(allocator, null); - try self.objects.append(allocator, &display.interface); - try self.objects.append(allocator, &self.interface); + try self.objects.append(allocator, wayland.Object.from_self(display)); + try self.objects.append(allocator, wayland.Object.from_self(self)); - display.interface.id = 1; - self.interface.id = 2; + display.handle = 1; - try display.request(display, .{ .get_registry = .{&self.interface} }); + try display.request(display, .{ .get_registry = .{ self.handle } }); +} + +pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { + self.objects.deinit(allocator); } pub fn add_object( self: *Self, allocator: std.mem.Allocator, - object: *wayland.Object, -) !void { + object: wayland.Object, +) !usize { for (self.objects.items[1..], 1..) |obj, index| { if (obj == null) { - object.id = @truncate(index); self.objects.items[index] = object; - return; + return index; } } - object.id = @truncate(self.objects.items.len); try self.objects.append(allocator, object); + return self.objects.items.len - 1; +} + +pub fn disable_object(self: *Self, id: usize) void { + if (self.objects.items[id]) |*object| { + object.disable(); + } } pub fn release_object(self: *Self, id: u32) void { self.objects.items[id] = null; } +pub fn get(self: *Self, handle: usize) ?*wayland.Object { + if (self.objects.items[handle]) |*objects| { + return objects; + } + return null; +} + fn global( self: *Self, ctx: *wayland.Context, @@ -73,12 +88,15 @@ fn global( interface: []const u8, version: u32, ) !void { + log.debug("global {s}", .{interface}); for (self.handlers) |handler| { if (version == handler.version and std.mem.eql(u8, interface, handler.interface)) { - if (handler.handler(ctx)) |object| { + if (handler.handler(ctx)) |object_ref| { try ctx.display.request(self, .{ .bind = .{ name, - object.id orelse return error.UnregisteredObject, + interface, + version, + @truncate(object_ref), } }); } } diff --git a/src/wl/root.zig b/src/wl/root.zig index b9e149f..778b085 100644 --- a/src/wl/root.zig +++ b/src/wl/root.zig @@ -1,4 +1,4 @@ pub const Display = @import("display.zig"); pub const Registry = @import("registry.zig"); pub const Callback = @import("callback.zig"); -pub const Output = @import("output.zig"); +pub const Output = @import("output/root.zig"); -- cgit v1.2.3-70-g09d2