aboutsummaryrefslogtreecommitdiff
path: root/src/wl/registry.zig
blob: e4eb3a89e0a00ce3a539bb3cb2d2e5c8f8d70937 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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});
}