const std = @import("std"); const wayland = @import("../root.zig"); const wl = wayland.wl; const log = std.log.scoped(.registry); const Self = @This(); pub const Events = wayland.EventSet(Self, .{ global, global_remove, }); pub const Request = union(enum) { bind: struct { u32, u32 }, }; pub const GlobalHandler = struct { interface: []const u8, version: u32, handler: *const fn (ctx: *wayland.Context) ?wayland.Object, }; objects: std.ArrayListUnmanaged(?*wayland.Object) = .empty, interface: wayland.Object, handlers: []const GlobalHandler, pub fn init( self: *Self, allocator: std.mem.Allocator, display: *wl.Display, handlers: []const GlobalHandler, ) !void { self.* = .{ .interface = wayland.Object.from_self(self), .handlers = handlers, }; try self.objects.append(allocator, null); try self.objects.append(allocator, &display.interface); try self.objects.append(allocator, &self.interface); display.interface.id = 1; self.interface.id = 2; try display.request(display, .{ .get_registry = .{&self.interface} }); } pub fn add_object( self: *Self, allocator: std.mem.Allocator, object: *wayland.Object, ) !void { for (self.objects.items[1..], 1..) |obj, index| { if (obj == null) { object.id = @truncate(index); self.objects.items[index] = object; return; } } object.id = @truncate(self.objects.items.len); try self.objects.append(allocator, object); } pub fn release_object(self: *Self, id: u32) void { self.objects.items[id] = null; } fn global( self: *Self, ctx: *wayland.Context, name: u32, interface: []const u8, version: u32, ) !void { for (self.handlers) |handler| { if (version == handler.version and std.mem.eql(u8, interface, handler.interface)) { if (handler.handler(ctx)) |object| { try ctx.display.request(self, .{ .bind = .{ name, object.id orelse return error.UnregisteredObject, } }); } } } } fn global_remove( self: *Self, ctx: *wayland.Context, name: u32, ) void { _ = self; _ = ctx; log.debug("remove_global: {}", .{name}); }