feat: add registerGlobals

dev
Louis Pearson 2024-01-15 13:07:18 -07:00
parent 847051ebc3
commit 6559e124a7
5 changed files with 95 additions and 141 deletions

View File

@ -15,132 +15,18 @@ pub fn main() !void {
// Create an id pool to allocate ids for us
var id_pool = wayland.IdPool{};
// reserve an object id for the registry
const registry_id = id_pool.create();
{
var buffer: [5]u32 = undefined;
const message = try wayland.serialize(wayland.core.Display.Request, &buffer, 1, .{ .get_registry = .{ .registry = registry_id } });
try socket.writeAll(std.mem.sliceAsBytes(message));
}
const ids = try wayland.registerGlobals(gpa, &id_pool, socket, &.{
wayland.core.Shm,
wayland.core.Compositor,
wayland.xdg.WmBase,
wayland.core.Seat,
wayland.zxdg.DecorationManagerV1,
});
// create a sync callback so we know when the registry is done listing extensions
const registry_done_id = id_pool.create();
std.debug.print("registry done id: {}\n", .{registry_done_id});
{
var buffer: [5]u32 = undefined;
const message = try wayland.serialize(wayland.core.Display.Request, &buffer, 1, .{ .sync = .{ .callback = registry_done_id } });
try socket.writeAll(std.mem.sliceAsBytes(message));
}
var shm_id_opt: ?u32 = null;
var compositor_id_opt: ?u32 = null;
var xdg_wm_base_id_opt: ?u32 = null;
var zxdg_decoration_manager_id_opt: ?u32 = null;
var wl_seat_id_opt: ?u32 = null;
var message_buffer = std.ArrayList(u32).init(gpa);
defer message_buffer.deinit();
while (true) {
var header: wayland.Header = undefined;
const header_bytes_read = try socket.readAll(std.mem.asBytes(&header));
if (header_bytes_read < @sizeOf(wayland.Header)) {
break;
}
try message_buffer.resize((header.size_and_opcode.size - @sizeOf(wayland.Header)) / @sizeOf(u32));
const bytes_read = try socket.readAll(std.mem.sliceAsBytes(message_buffer.items));
message_buffer.shrinkRetainingCapacity(bytes_read / @sizeOf(u32));
if (header.object_id == registry_id) {
const event = try wayland.deserialize(wayland.core.Registry.Event, header, message_buffer.items);
switch (event) {
.global => |global| {
var buffer: [20]u32 = undefined;
if (std.mem.eql(u8, global.interface, "wl_shm")) {
shm_id_opt = id_pool.create();
const message = try wayland.serialize(
wayland.core.Registry.Request,
&buffer,
registry_id,
.{ .bind = .{
.name = global.name,
.interface = global.interface,
.version = global.version,
.new_id = shm_id_opt.?,
} },
);
try socket.writeAll(std.mem.sliceAsBytes(message));
} else if (std.mem.eql(u8, global.interface, wayland.core.Compositor.INTERFACE)) {
compositor_id_opt = id_pool.create();
const message = try wayland.serialize(
wayland.core.Registry.Request,
&buffer,
registry_id,
.{ .bind = .{
.name = global.name,
.interface = global.interface,
.version = global.version,
.new_id = compositor_id_opt.?,
} },
);
try socket.writeAll(std.mem.sliceAsBytes(message));
} else if (std.mem.eql(u8, global.interface, "xdg_wm_base")) {
xdg_wm_base_id_opt = id_pool.create();
const message = try wayland.serialize(
wayland.core.Registry.Request,
&buffer,
registry_id,
.{ .bind = .{
.name = global.name,
.interface = global.interface,
.version = global.version,
.new_id = xdg_wm_base_id_opt.?,
} },
);
try socket.writeAll(std.mem.sliceAsBytes(message));
} else if (std.mem.eql(u8, global.interface, "zxdg_decoration_manager_v1")) {
zxdg_decoration_manager_id_opt = id_pool.create();
const message = try wayland.serialize(
wayland.core.Registry.Request,
&buffer,
registry_id,
.{ .bind = .{
.name = global.name,
.interface = global.interface,
.version = 1,
.new_id = zxdg_decoration_manager_id_opt.?,
} },
);
try socket.writeAll(std.mem.sliceAsBytes(message));
} else if (std.mem.eql(u8, global.interface, "wl_seat")) {
wl_seat_id_opt = id_pool.create();
const message = try wayland.serialize(
wayland.core.Registry.Request,
&buffer,
registry_id,
.{ .bind = .{
.name = global.name,
.interface = global.interface,
.version = 8,
.new_id = wl_seat_id_opt.?,
} },
);
try socket.writeAll(std.mem.sliceAsBytes(message));
}
},
.global_remove => {},
}
} else if (header.object_id == registry_done_id) {
break;
} else {
std.debug.print("{} {x} \"{}\"\n", .{ header.object_id, header.size_and_opcode.opcode, std.zig.fmtEscapes(std.mem.sliceAsBytes(message_buffer.items)) });
}
}
const shm_id = shm_id_opt orelse return error.NeccessaryWaylandExtensionMissing;
const compositor_id = compositor_id_opt orelse return error.NeccessaryWaylandExtensionMissing;
const xdg_wm_base_id = xdg_wm_base_id_opt orelse return error.NeccessaryWaylandExtensionMissing;
const wl_seat_id = wl_seat_id_opt orelse return error.NeccessaryWaylandExtensionMissing;
const shm_id = ids[0] orelse return error.NeccessaryWaylandExtensionMissing;
const compositor_id = ids[1] orelse return error.NeccessaryWaylandExtensionMissing;
const xdg_wm_base_id = ids[2] orelse return error.NeccessaryWaylandExtensionMissing;
const wl_seat_id = ids[3] orelse return error.NeccessaryWaylandExtensionMissing;
const surface_id = id_pool.create();
{
@ -186,7 +72,7 @@ pub fn main() !void {
}
var zxdg_toplevel_decoration_id_opt: ?u32 = null;
if (zxdg_decoration_manager_id_opt) |zxdg_decoration_manager_id| {
if (ids[4]) |zxdg_decoration_manager_id| {
zxdg_toplevel_decoration_id_opt = id_pool.create();
{
var buffer: [10]u32 = undefined;
@ -214,12 +100,16 @@ pub fn main() !void {
try socket.writeAll(std.mem.sliceAsBytes(message));
}
const registry_done_id = id_pool.create();
{
var buffer: [5]u32 = undefined;
const message = try wayland.serialize(wayland.core.Display.Request, &buffer, 1, .{ .sync = .{ .callback = registry_done_id } });
try socket.writeAll(std.mem.sliceAsBytes(message));
}
var message_buffer = std.ArrayList(u32).init(gpa);
defer message_buffer.deinit();
var done = false;
var surface_configured = false;
var seat_capabilties: ?wayland.core.Seat.Capability = null;
@ -271,21 +161,6 @@ pub fn main() !void {
const cap: wayland.core.Seat.Capability = @bitCast(capabilities.capability);
std.debug.print("<- wl_seat.capabilties = {}\n", .{cap});
seat_capabilties = cap;
// if (cap.keyboard) {
// var buffer: [10]u32 = undefined;
// wl_keyboard_id_opt = id_pool.create();
// std.debug.print("wl keyboard id: {}\n", .{wl_keyboard_id_opt.?});
// const message = try wayland.serialize(
// wayland.core.Seat.Request,
// &buffer,
// wl_seat_id,
// .{ .get_keyboard = .{
// .new_id = wl_keyboard_id_opt.?,
// } },
// );
// try socket.writeAll(std.mem.sliceAsBytes(message));
// }
},
.name => |name| {
std.debug.print("<- wl_seat.name = {s}\n", .{name.name});

View File

@ -53,6 +53,7 @@ pub const Registry = struct {
pub const Compositor = struct {
pub const INTERFACE = "wl_compositor";
pub const VERSION = 5;
pub const Request = union(enum) {
create_surface: struct {
@ -82,6 +83,9 @@ pub const ShmPool = struct {
};
pub const Shm = struct {
pub const INTERFACE = "wl_shm";
pub const VERSION = 1;
pub const Request = union(enum) {
create_pool: struct {
new_id: u32,
@ -172,6 +176,9 @@ pub const Buffer = struct {
};
pub const Seat = struct {
pub const INTERFACE = "wl_seat";
pub const VERSION = 8;
pub const Request = union(enum) {
get_pointer: struct {
new_id: u32,

View File

@ -347,3 +347,69 @@ pub const IdPool = struct {
this.free_ids.append(id) catch {};
}
};
pub fn registerGlobals(alloc: std.mem.Allocator, id_pool: *IdPool, socket: std.net.Stream, comptime T: []const type) ![T.len]?u32 {
const Item = struct { version: u32, index: u32 };
const Pair = struct { []const u8, Item };
comptime var kvs_list: []const Pair = &[_]Pair{};
inline for (T, 0..) |t, i| {
// if (!@hasField(t, "INTERFACE")) @compileError("Missing INTERFACE for " ++ @typeName(t));
// if (!@hasField(t, "VERSION")) @compileError("Missing VERSION for " ++ @typeName(t));
kvs_list = kvs_list ++ &[_]Pair{.{ t.INTERFACE, .{ .version = t.VERSION, .index = i } }};
}
const map = std.ComptimeStringMap(Item, kvs_list);
const registry_id = id_pool.create();
{
var buffer: [5]u32 = undefined;
const message = try serialize(core.Display.Request, &buffer, 1, .{ .get_registry = .{ .registry = registry_id } });
try socket.writeAll(std.mem.sliceAsBytes(message));
}
const registry_done_id = id_pool.create();
{
var buffer: [5]u32 = undefined;
const message = try serialize(core.Display.Request, &buffer, 1, .{ .sync = .{ .callback = registry_done_id } });
try socket.writeAll(std.mem.sliceAsBytes(message));
}
var ids: [T.len]?u32 = [_]?u32{null} ** T.len;
var message_buffer = std.ArrayList(u32).init(alloc);
defer message_buffer.deinit();
while (true) {
var header: Header = undefined;
const header_bytes_read = try socket.readAll(std.mem.asBytes(&header));
if (header_bytes_read < @sizeOf(Header)) break;
try message_buffer.resize((header.size_and_opcode.size - @sizeOf(Header)) / @sizeOf(u32));
const bytes_read = try socket.readAll(std.mem.sliceAsBytes(message_buffer.items));
message_buffer.shrinkRetainingCapacity(bytes_read / @sizeOf(u32));
if (header.object_id == registry_id) {
const event = try deserialize(core.Registry.Event, header, message_buffer.items);
switch (event) {
.global => |global| {
var buffer: [20]u32 = undefined;
if (map.get(global.interface)) |item| {
const new_id = id_pool.create();
ids[item.index] = new_id;
const message = try serialize(core.Registry.Request, &buffer, registry_id, .{ .bind = .{
.name = global.name,
.interface = global.interface,
.version = item.version,
.new_id = new_id,
} });
try socket.writeAll(std.mem.sliceAsBytes(message));
}
},
.global_remove => {},
}
} else if (header.object_id == registry_done_id) {
break;
} else {
std.log.info("{} {x} \"{}\"", .{ header.object_id, header.size_and_opcode.opcode, std.zig.fmtEscapes(std.mem.sliceAsBytes(message_buffer.items)) });
}
}
return ids;
}

View File

@ -1,4 +1,7 @@
pub const WmBase = struct {
pub const INTERFACE = "xdg_wm_base";
pub const VERSION = 4;
pub const Request = union(Request.Tag) {
destroy: void,
create_positioner: struct {

View File

@ -1,4 +1,7 @@
pub const DecorationManagerV1 = struct {
pub const INTERFACE = "zxdg_decoration_manager_v1";
pub const VERSION = 1;
pub const Request = union(Request.Tag) {
destroy: void,
get_toplevel_decoration: struct {