From 6559e124a7f6e1e10f4b19c3e07bf48b02006604 Mon Sep 17 00:00:00 2001 From: Louis Pearson Date: Mon, 15 Jan 2024 13:07:18 -0700 Subject: [PATCH] feat: add registerGlobals --- examples/01_client_connect.zig | 157 ++++----------------------------- src/core.zig | 7 ++ src/main.zig | 66 ++++++++++++++ src/xdg.zig | 3 + src/zxdg.zig | 3 + 5 files changed, 95 insertions(+), 141 deletions(-) diff --git a/examples/01_client_connect.zig b/examples/01_client_connect.zig index 92b8beb..36085bb 100644 --- a/examples/01_client_connect.zig +++ b/examples/01_client_connect.zig @@ -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}); diff --git a/src/core.zig b/src/core.zig index 9ad1a1e..df05c5a 100644 --- a/src/core.zig +++ b/src/core.zig @@ -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, diff --git a/src/main.zig b/src/main.zig index 73fed2c..6fb6e8e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -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; +} diff --git a/src/xdg.zig b/src/xdg.zig index 0e40c4f..001aa22 100644 --- a/src/xdg.zig +++ b/src/xdg.zig @@ -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 { diff --git a/src/zxdg.zig b/src/zxdg.zig index 769dce5..92aae9b 100644 --- a/src/zxdg.zig +++ b/src/zxdg.zig @@ -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 {