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: *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});
}
|