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, []const u8, u32, u32 }, }; pub const GlobalHandler = struct { interface: []const u8, version: u32, handler: *const fn (ctx: *wayland.Context) ?wayland.Object.Ref, }; objects: std.ArrayListUnmanaged(?wayland.Object) = .empty, handlers: []const GlobalHandler, handle: wayland.Object.Ref, pub fn init( self: *Self, allocator: std.mem.Allocator, display: *wl.Display, handlers: []const GlobalHandler, ) !void { self.* = .{ .handlers = handlers, .handle = 2, }; try self.objects.append(allocator, null); try self.objects.append(allocator, wayland.Object.from_self(display)); try self.objects.append(allocator, wayland.Object.from_self(self)); display.handle = 1; 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, ) !usize { for (self.objects.items[1..], 1..) |obj, index| { if (obj == null) { self.objects.items[index] = object; return index; } } 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, name: u32, 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_ref| { try ctx.display.request(self, .{ .bind = .{ name, interface, version, @truncate(object_ref), } }); } } } } fn global_remove( self: *Self, ctx: *wayland.Context, name: u32, ) void { _ = self; _ = ctx; log.debug("remove_global: {}", .{name}); }