aboutsummaryrefslogtreecommitdiff
path: root/src/wl/registry.zig
blob: 0939d172f6c490d73535c53eb8ad3306f7acab9a (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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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: *const 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,
) !wayland.Object.Ref {
    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: *const wayland.Context,
    name: u32,
    interface: []const u8,
    version: u32,
) !void {
    log.debug("global {s} {}", .{interface, version});
    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: *const wayland.Context,
    name: u32,
) void {
    _ = self;
    _ = ctx;
    log.debug("remove_global: {}", .{name});
}