aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2025-08-27 09:02:43 +0200
committerNathan Reiner <nathan@nathanreiner.xyz>2025-08-27 09:03:21 +0200
commit8a7392dea729d3ed49a8bf8eee25906c4fd616ac (patch)
tree09e0b2fa96c60a2e0c8b0cae9e631bd2dc66f52f /src
parentc217e7ec5cddfc002c4582fb5d52727aee843a7d (diff)
Add ancillary data mechanism to send fds to compositor.
Currently we are just attaching the fds to the object id. In theory this is not a valid implementation, since if we have more than MAX_FD file descriptors this will not work. But since this wont be the case in basically all cases of the wayland protocol, we can just ignore that for now.
Diffstat (limited to 'src')
-rw-r--r--src/ancillary-data.zig38
-rw-r--r--src/event-set.zig4
-rw-r--r--src/main.zig26
-rw-r--r--src/object.zig22
-rw-r--r--src/wl/callback.zig6
-rw-r--r--src/wl/compositor.zig4
-rw-r--r--src/wl/display.zig87
-rw-r--r--src/wl/output/root.zig16
-rw-r--r--src/wl/registry.zig8
-rw-r--r--src/wl/shm/anonymous-file.zig53
-rw-r--r--src/wl/shm/pool.zig37
-rw-r--r--src/wl/shm/root.zig25
12 files changed, 248 insertions, 78 deletions
diff --git a/src/ancillary-data.zig b/src/ancillary-data.zig
index 0754720..667ba1f 100644
--- a/src/ancillary-data.zig
+++ b/src/ancillary-data.zig
@@ -18,47 +18,47 @@ const ControlMessage = extern struct {
};
header: Header,
- payload: union {
+ payload: extern union {
fd: [255]std.posix.fd_t,
},
pub fn alignment(length: usize) usize {
- return (length + @sizeOf(usize) - 1) & ~(@sizeOf(usize) - 1);
+ return (length + @sizeOf(usize) - 1) & ~(@as(usize, @sizeOf(usize) - 1));
}
- pub fn space(self: @This()) usize {
- return self.alignment(self.length) + self.alignment(@sizeOf(Header));
+ pub fn space(length: usize) usize {
+ return alignment(length) + alignment(@sizeOf(Header));
}
pub fn from_fds(fds: []std.posix.fd_t) @This() {
- var self: @This() = .{
- };
+ var self: @This() = undefined;
- self.level = .socket;
- self.kind = .rights;
- self.length = self.alignment(@sizeOf(Header)) + (fds.len * @sizeOf(std.posix.fd_t));
+ self.header.level = .socket;
+ self.header.kind = .rights;
+ self.header.length = alignment(@sizeOf(Header)) + (fds.len * @sizeOf(std.posix.fd_t));
- @memcpy(self.payload, fds);
+ @memcpy(self.payload.fd[0..fds.len], fds);
+
+ return self;
}
};
-pub fn send_fds(socket: std.posix.socket_t, fds: []std.posix.fd_t) !void {
- var iobuf: [1]u8 = std.mem.zeroes([1]u8);
+pub fn send_fds(socket: std.posix.socket_t, fds: []std.posix.fd_t, data: []const u8) !void {
+ var cmsg: ControlMessage = .from_fds(fds);
const io = std.posix.iovec {
- .base = &iobuf,
- .len = iobuf.len,
+ .base = @constCast(@ptrCast(data)),
+ .len = data.len,
};
- var cmsg: ControlMessage = .from_fds(fds);
-
const msghdr = std.posix.msghdr_const {
.name = null,
.namelen = 0,
- .iov = &io,
- .iolen = 1,
+ .iov = @ptrCast(&io),
+ .iovlen = 1,
.control = &cmsg,
- .controllen = cmsg.control_length(),
+ .controllen = @intCast(ControlMessage.space(fds.len)),
+ .flags = 0,
};
_ = try std.posix.sendmsg(socket, &msghdr, 0);
diff --git a/src/event-set.zig b/src/event-set.zig
index 27c28bf..da17734 100644
--- a/src/event-set.zig
+++ b/src/event-set.zig
@@ -3,7 +3,7 @@ const wayland = @import("root.zig");
pub fn EventSet(T: type, events: anytype) type {
return struct {
- pub fn on_event(ptr: *anyopaque, ctx: *wayland.Context, opcode: u16, args: []const u8) void {
+ pub fn on_event(ptr: *anyopaque, ctx: *const wayland.Context, opcode: u16, args: []const u8) void {
var offset: usize = 0;
inline for (events, 0..) |event, index| {
if (@TypeOf(event) != @TypeOf(null) and index == opcode) {
@@ -66,7 +66,7 @@ test {
a: u32 = 0,
b: u32 = 0,
- pub fn something(self: *@This(), _: *wayland.Context, a: u32, b: u32) void {
+ pub fn something(self: *@This(), _: *const wayland.Context, a: u32, b: u32) void {
self.a = a;
self.b = b;
}
diff --git a/src/main.zig b/src/main.zig
index b6806be..b822109 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -2,6 +2,14 @@ const std = @import("std");
const wayland = @import("wayland");
const wl = wayland.wl;
+const log = std.log.scoped(.main);
+
+pub const std_options = std.Options{
+ .log_scope_levels = &.{
+ .{ .scope = .registry, .level = .info },
+ }
+};
+
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
@@ -17,15 +25,27 @@ pub fn main() !void {
try display.roundtrip(allocator);
try display.roundtrip(allocator);
+ const ctx: wayland.Context = .{
+ .allocator = allocator,
+ .display = &display,
+ };
+
+ try display.roundtrip(allocator);
+
for (wl.Output.instances.items) |output| {
- std.debug.print("{}\n", .{output});
+ log.debug("{}", .{output});
}
for (wl.Compositor.instances.items) |compositor| {
- std.debug.print("{}\n", .{compositor});
+ log.debug("{}", .{compositor});
}
for (wl.Shm.instances.items) |shm| {
- std.debug.print("{}\n", .{shm});
+ log.debug("{}", .{shm});
}
+
+ const pool = try wl.Shm.instances.items[0].create_pool(&ctx, 1024);
+ defer pool.deinit(&ctx);
+
+ try display.roundtrip(allocator);
}
diff --git a/src/object.zig b/src/object.zig
index 14089c1..5502d3d 100644
--- a/src/object.zig
+++ b/src/object.zig
@@ -6,13 +6,24 @@ const Self = @This();
pub const Ref = usize;
const VTable = struct {
- on_event: *const fn (ptr: *anyopaque, ctx: *wayland.Context, opcode: u16, args: []const u8) void,
+ on_event: *const fn (
+ ptr: *anyopaque,
+ ctx: *const wayland.Context,
+ opcode: u16,
+ args: []const u8,
+ ) void,
};
ptr: ?*anyopaque,
vtable: VTable,
+name: []const u8,
-pub inline fn on_event(self: *Self, ctx: *wayland.Context, opcode: u16, args: []const u8) !void {
+pub inline fn on_event(
+ self: *Self,
+ ctx: *const wayland.Context,
+ opcode: u16,
+ args: []const u8,
+) !void {
if (self.ptr) |ptr| {
self.vtable.on_event(ptr, ctx, opcode, args);
} else {
@@ -21,11 +32,14 @@ pub inline fn on_event(self: *Self, ctx: *wayland.Context, opcode: u16, args: []
}
pub inline fn from_self(ptr: anytype) Self {
+ const T = @TypeOf(ptr.*);
+
return .{
.ptr = ptr,
.vtable = VTable{
- .on_event = @TypeOf(ptr.*).Events.on_event,
+ .on_event = T.Events.on_event,
},
+ .name = @typeName(T),
};
}
@@ -42,5 +56,5 @@ pub fn format(
_ = fmt;
_ = options;
- try writer.print("Object {{ {?} }}", .{self.ptr});
+ try writer.print("Object<{s}> {{ {?} }}", .{self.name, self.ptr});
}
diff --git a/src/wl/callback.zig b/src/wl/callback.zig
index c17e190..24927b4 100644
--- a/src/wl/callback.zig
+++ b/src/wl/callback.zig
@@ -13,7 +13,7 @@ handle: wayland.Object.Ref,
pub fn init(
self: *Self,
- ctx: *wayland.Context,
+ ctx: *const wayland.Context,
is_done: *bool,
) !void {
self.is_done = is_done;
@@ -25,11 +25,11 @@ pub fn init(
}
-pub fn deinit(self: *Self, ctx: *wayland.Context) void {
+pub fn deinit(self: *Self, ctx: *const wayland.Context) void {
ctx.display.registry.disable_object(self.handle);
}
-fn done(self: *Self, ctx: *wayland.Context, value: u32) void {
+fn done(self: *Self, ctx: *const wayland.Context, value: u32) void {
_ = value;
_ = ctx;
self.is_done.* = true;
diff --git a/src/wl/compositor.zig b/src/wl/compositor.zig
index 6951446..18db0f0 100644
--- a/src/wl/compositor.zig
+++ b/src/wl/compositor.zig
@@ -22,7 +22,7 @@ pub const handler: wl.Registry.GlobalHandler = .{
pub fn init(
self: *Self,
- ctx: *wayland.Context
+ ctx: *const wayland.Context
) !void {
self.* = .{
.handle = try ctx.display.registry.add_object(
@@ -32,7 +32,7 @@ pub fn init(
};
}
-fn register(ctx: *wayland.Context) ?wayland.Object.Ref {
+fn register(ctx: *const wayland.Context) ?wayland.Object.Ref {
const compositor = ctx.allocator.create(Self) catch return null;
compositor.init(ctx) catch return null;
diff --git a/src/wl/display.zig b/src/wl/display.zig
index 3b5087d..c9e2e6e 100644
--- a/src/wl/display.zig
+++ b/src/wl/display.zig
@@ -86,7 +86,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
const id: u32 = @truncate(object.handle);
var size: u32 = 8;
- comptime var fds: []std.posix.fd_t = &.{};
+ comptime var count_fds = 0;
inline for (data) |value| {
switch (@TypeOf(value)) {
@@ -97,7 +97,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
const padding_size: usize = padding_len(u8, value.len + 1);
size += @as(u32, @intCast(@sizeOf(u32) + (value.len + 1) + padding_size));
},
- wayland.types.Fd => |fd| fds = fds ++ .{ fd },
+ wayland.types.Fd => count_fds += 1,
else => |t| switch (@typeInfo(t)) {
.pointer => |ptr| if (ptr.size == .slice) {
const padding_size: usize = padding_len(ptr.child, value.len);
@@ -108,14 +108,30 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
}
}
- _ = try self.stream.writeAll(&std.mem.toBytes(id));
+ {
+ var fds: [count_fds]std.posix.fd_t = undefined;
+ comptime var current_fd_index = 0;
+
+ inline for (data) |value| {
+ switch (@TypeOf(value)) {
+ wayland.types.Fd => {
+ fds[current_fd_index] = value.fd;
+ current_fd_index += 1;
+ },
+ else => {},
+ }
+ }
+
+ try ancillary_data.send_fds(self.stream.handle, &fds, std.mem.asBytes(&id));
+ }
+
_ = try self.stream.writeAll(&std.mem.toBytes((size << 16) | opcode));
inline for (data) |value| {
switch (@TypeOf(value)) {
u32, i32 => _ = try self.stream.writeAll(std.mem.asBytes(&value)),
wayland.Object.Ref => try self.stream.writeAll(std.mem.asBytes(&(@as(u32, @truncate(value))))),
- ?wayland.Object.Ref => try self.stream.writeAll(std.mem.asBytes(&(@as(u32, 0)))),
+ ?wayland.Object.Ref => try self.stream.writeAll(std.mem.asBytes(&(@as(u32, @truncate(if (value) |v| v else 0))))),
[]const u8, []u8 => {
const padding_size: usize = padding_len(u8, value.len + 1);
_ = try self.stream.writeAll(std.mem.asBytes(&@as(u32, @truncate(value.len + 1))));
@@ -124,10 +140,10 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
_ = try self.stream.writeAll(std.mem.asBytes(&@as(u8, 0)));
}
},
- wayland.types.Fd => {},
+ wayland.types.Fd => { },
else => |t| switch (@typeInfo(t)) {
.pointer => |ptr| if (ptr.size == .slice) {
- const padding_size: usize = @mod(@as(usize, @bitCast(-@as(isize, @intCast(value.len * @sizeOf(ptr.child))))), 4);
+ const padding_size: usize = padding_len(ptr.child, value.len);
_ = try self.stream.writeAll(std.mem.asBytes(&@as(u32, @truncate(value.len))));
_ = try self.stream.writeAll(std.mem.sliceAsBytes(value));
for (0..padding_size) |_| {
@@ -139,10 +155,6 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
}
}
- if (fds.len > 0) {
- try ancillary_data.send_fds(self.stream.handle, fds);
- }
-
return;
}
}
@@ -150,7 +162,7 @@ pub fn request(self: *Self, object: anytype, args: @TypeOf(object.*).Request) !v
return error.InvalidOpcode;
}
-fn read_event(self: *Self, ctx: *wayland.Context) !void {
+fn read_event(self: *Self, ctx: *const wayland.Context) !void {
const endian = @import("builtin").target.cpu.arch.endian();
const reader = self.stream.reader();
@@ -200,7 +212,7 @@ pub fn roundtrip(self: *Self, allocator: std.mem.Allocator) !void {
fn err(
self: *Self,
- ctx: *wayland.Context,
+ ctx: *const wayland.Context,
object: *wayland.Object,
code: u32,
message: []const u8,
@@ -212,7 +224,7 @@ fn err(
fn delete_id(
self: *Self,
- ctx: *wayland.Context,
+ ctx: *const wayland.Context,
id: u32,
) void {
_ = ctx;
@@ -226,6 +238,7 @@ test "request" {
req2: struct { wayland.Object.Ref },
req3: struct { []const u8 },
req4: struct { []const u16 },
+ req5: struct { wayland.types.Fd },
};
pub const Events = wayland.EventSet(@This(), .{});
@@ -237,66 +250,86 @@ test "request" {
}
};
- const in, const out = try std.posix.pipe();
- defer std.posix.close(in);
+ var tmpdir = std.testing.tmpDir(.{});
+ defer tmpdir.cleanup();
+
+ var pathbuf: [std.fs.max_path_bytes]u8 = undefined;
+ var dirbuf: [std.fs.max_path_bytes]u8 = undefined;
+ const path = try std.fmt.bufPrint(&pathbuf, "{s}/testing", .{try tmpdir.dir.realpath(".", &dirbuf)});
+
+ const address = try std.net.Address.initUnix(path);
+ var server = try address.listen(.{});
{
var sample: Sample = .init();
- var displ: Self = .from_fd(out);
+ var displ: Self = try .open(path);
defer displ.deinit(std.testing.allocator);
try displ.init(std.testing.allocator, &.{});
try displ.request(&sample, .{ .req1 = .{432} });
try displ.request(&sample, .{ .req2 = .{sample.handle} });
try displ.request(&sample, .{ .req3 = .{"abcd"} });
try displ.request(&sample, .{ .req4 = .{&[_]u16{ 1, 32, 4, 5, 5 }} });
+ try displ.request(&sample, .{ .req5 = .{ .{ .fd = displ.stream.handle } } });
}
- const file = std.fs.File{ .handle = in };
+ const conn = try server.accept();
+ const file = conn.stream;
var test_buffer: [64]u8 = undefined;
- _ = try file.readAll(test_buffer[0..12]);
+ var size = try file.readAll(test_buffer[0..12]);
try std.testing.expectEqualSlices(
u8,
&(std.mem.toBytes(@as(u32, 1)) ++
std.mem.toBytes(@as(u32, (12 << 16) | 1)) ++
std.mem.toBytes(@as(u32, 2))),
- test_buffer[0..12],
+ test_buffer[0..size],
);
- _ = try file.readAll(test_buffer[0..12]);
+ size = try file.readAll(test_buffer[0..12]);
try std.testing.expectEqualSlices(
u8,
&(std.mem.toBytes(@as(u32, 42)) ++
std.mem.toBytes(@as(u32, (12 << 16) | 0)) ++
std.mem.toBytes(@as(u32, 432))),
- test_buffer[0..12],
+ test_buffer[0..size],
);
- _ = try file.readAll(test_buffer[0..12]);
+ size = try file.readAll(test_buffer[0..12]);
try std.testing.expectEqualSlices(
u8,
&(std.mem.toBytes(@as(u32, 42)) ++
std.mem.toBytes(@as(u32, (12 << 16) | 1)) ++
std.mem.toBytes(@as(u32, 42))),
- test_buffer[0..12],
+ test_buffer[0..size],
);
- _ = try file.readAll(test_buffer[0..20]);
+ size = try file.readAll(test_buffer[0..20]);
try std.testing.expectEqualSlices(
u8,
&(std.mem.toBytes(@as(u32, 42)) ++
std.mem.toBytes(@as(u32, (20 << 16) | 2)) ++
std.mem.toBytes(@as(u32, 5))) ++ "abcd\x00\x00\x00\x00",
- test_buffer[0..20],
+ test_buffer[0..size],
);
- _ = try file.readAll(test_buffer[0..24]);
+ size = try file.readAll(test_buffer[0..24]);
try std.testing.expectEqualSlices(
u8,
&(std.mem.toBytes(@as(u32, 42)) ++
std.mem.toBytes(@as(u32, (24 << 16) | 3)) ++
std.mem.toBytes(@as(u32, 5))) ++ std.mem.toBytes([_]u16{ 1, 32, 4, 5, 5, 0 }),
- test_buffer[0..24],
+ test_buffer[0..size],
+ );
+
+ size = try file.readAll(test_buffer[0..8]);
+ try std.testing.expectEqualSlices(
+ u8,
+ &(std.mem.toBytes(@as(u32, 42)) ++
+ std.mem.toBytes(@as(u32, (8 << 16) | 4))),
+ test_buffer[0..size],
);
+
+ size = try file.readAll(test_buffer[0..]);
+ try std.testing.expectEqual(0, size);
}
diff --git a/src/wl/output/root.zig b/src/wl/output/root.zig
index ce2169f..f4ca36d 100644
--- a/src/wl/output/root.zig
+++ b/src/wl/output/root.zig
@@ -38,7 +38,7 @@ handle: wayland.Object.Ref,
pub fn init(
self: *Self,
- ctx: *wayland.Context,
+ ctx: *const wayland.Context,
) !void {
self.* = .{
.handle = try ctx.display.registry.add_object(
@@ -58,7 +58,7 @@ pub const handler: wl.Registry.GlobalHandler = .{
.handler = register,
};
-fn register(ctx: *wayland.Context) ?wayland.Object.Ref {
+fn register(ctx: *const wayland.Context) ?wayland.Object.Ref {
const output = ctx.allocator.create(Self) catch return null;
output.init(ctx) catch return null;
@@ -68,7 +68,7 @@ fn register(ctx: *wayland.Context) ?wayland.Object.Ref {
fn geometry(
self: *Self,
- ctx: *wayland.Context,
+ ctx: *const wayland.Context,
x: u32,
y: u32,
physical_width: u32,
@@ -93,7 +93,7 @@ fn geometry(
fn mode(
self: *Self,
- ctx: *wayland.Context,
+ ctx: *const wayland.Context,
flags: Mode.Kind,
width: u32,
height: u32,
@@ -108,7 +108,7 @@ fn mode(
};
}
-fn done(self: *Self, ctx: *wayland.Context) void {
+fn done(self: *Self, ctx: *const wayland.Context) void {
if (self.info) |info| {
ctx.allocator.free(info.name);
ctx.allocator.free(info.description);
@@ -117,17 +117,17 @@ fn done(self: *Self, ctx: *wayland.Context) void {
self.info = self.staging;
}
-fn scale(self: *Self, ctx: *wayland.Context, factor: u32) void {
+fn scale(self: *Self, ctx: *const wayland.Context, factor: u32) void {
_ = ctx;
self.staging.scale = factor;
}
-fn name(self: *Self, ctx: *wayland.Context, n: []const u8) !void {
+fn name(self: *Self, ctx: *const wayland.Context, n: []const u8) !void {
self.staging.name = try ctx.allocator.alloc(u8, n.len);
@memcpy(@constCast(self.staging.name), n);
}
-fn description(self: *Self, ctx: *wayland.Context, d: []const u8) !void {
+fn description(self: *Self, ctx: *const wayland.Context, d: []const u8) !void {
self.staging.description = try ctx.allocator.alloc(u8, d.len);
@memcpy(@constCast(self.staging.description), d);
}
diff --git a/src/wl/registry.zig b/src/wl/registry.zig
index 6c8ebdc..0939d17 100644
--- a/src/wl/registry.zig
+++ b/src/wl/registry.zig
@@ -18,7 +18,7 @@ pub const Request = union(enum) {
pub const GlobalHandler = struct {
interface: []const u8,
version: u32,
- handler: *const fn (ctx: *wayland.Context) ?wayland.Object.Ref,
+ handler: *const fn (ctx: *const wayland.Context) ?wayland.Object.Ref,
};
objects: std.ArrayListUnmanaged(?wayland.Object) = .empty,
@@ -52,7 +52,7 @@ pub fn add_object(
self: *Self,
allocator: std.mem.Allocator,
object: wayland.Object,
-) !usize {
+) !wayland.Object.Ref {
for (self.objects.items[1..], 1..) |obj, index| {
if (obj == null) {
self.objects.items[index] = object;
@@ -83,7 +83,7 @@ pub fn get(self: *Self, handle: usize) ?*wayland.Object {
fn global(
self: *Self,
- ctx: *wayland.Context,
+ ctx: *const wayland.Context,
name: u32,
interface: []const u8,
version: u32,
@@ -105,7 +105,7 @@ fn global(
fn global_remove(
self: *Self,
- ctx: *wayland.Context,
+ ctx: *const wayland.Context,
name: u32,
) void {
_ = self;
diff --git a/src/wl/shm/anonymous-file.zig b/src/wl/shm/anonymous-file.zig
new file mode 100644
index 0000000..f73fbc9
--- /dev/null
+++ b/src/wl/shm/anonymous-file.zig
@@ -0,0 +1,53 @@
+const std = @import("std");
+
+const Self = @This();
+
+size: usize = 0,
+name: [24]u8 = undefined,
+fd: std.posix.fd_t = undefined,
+
+pub fn init_random() !Self {
+ var buf: [8]u8 = undefined;
+ try std.posix.getrandom(&buf);
+
+ var self: Self = .{};
+
+ const name = std.fmt.bufPrint(&self.name, "/wl.shm.{x}{x}{x}{x}{x}{x}{x}{x}", .{
+ buf[0],
+ buf[1],
+ buf[2],
+ buf[3],
+ buf[4],
+ buf[5],
+ buf[6],
+ buf[7],
+ }) catch unreachable;
+
+ self.fd = try std.posix.memfd_create(name, 0);
+
+ return self;
+}
+
+pub fn truncate(self: *Self, size: usize) !void {
+ try std.posix.ftruncate(self.fd, size);
+ self.size = size;
+}
+
+pub fn mmap(self: *Self) ![]u8 {
+ return std.posix.mmap(
+ null,
+ self.size,
+ std.os.linux.PROT.READ | std.os.linux.PROT.WRITE,
+ .{
+ .TYPE = .SHARED,
+ .ANONYMOUS = true,
+ },
+ self.fd,
+ 0,
+ );
+}
+
+pub fn close(self: *Self) void {
+ std.posix.close(self.fd);
+ self.* = undefined;
+}
diff --git a/src/wl/shm/pool.zig b/src/wl/shm/pool.zig
index dc30d1b..1f42a17 100644
--- a/src/wl/shm/pool.zig
+++ b/src/wl/shm/pool.zig
@@ -1,5 +1,10 @@
+const std = @import("std");
const wayland = @import("../../root.zig");
-const Format = @import("root.zig").Format;
+const wl = wayland.wl;
+const Format = wl.Shm.Format;
+const AnonymousFile = wl.Shm.AnonymousFile;
+
+const Self = @This();
pub const Events = wayland.EventSet(@This(), .{});
pub const Requests = union(enum) {
@@ -7,3 +12,33 @@ pub const Requests = union(enum) {
destroy: struct {},
resize: struct { u32 },
};
+
+handle: wayland.Object.Ref,
+file: AnonymousFile,
+buffer: []u8,
+
+pub fn init(
+ self: *Self,
+ ctx: *const wayland.Context,
+ size: usize,
+) !void {
+ var file = try AnonymousFile.init_random();
+ errdefer file.close();
+ try file.truncate(size);
+
+ self.* = .{
+ .handle = try ctx.display.registry.add_object(
+ ctx.allocator,
+ wayland.Object.from_self(self),
+ ),
+ .file = file,
+ .buffer = try file.mmap(),
+ };
+}
+
+pub fn deinit(self: *Self, ctx: *const wayland.Context) void {
+ self.file.close();
+ std.posix.munmap(@alignCast(self.buffer));
+ ctx.display.registry.disable_object(self.handle);
+ self.* = undefined;
+}
diff --git a/src/wl/shm/root.zig b/src/wl/shm/root.zig
index 2d24aca..fd96727 100644
--- a/src/wl/shm/root.zig
+++ b/src/wl/shm/root.zig
@@ -4,12 +4,13 @@ const wl = wayland.wl;
pub const Pool = @import("pool.zig");
pub const Format = @import("format.zig").Format;
+pub const AnonymousFile = @import("anonymous-file.zig");
const Self = @This();
pub const Events = wayland.EventSet(Self, .{ announce_format });
-pub const Requests = union(enum) {
- create_pool: struct { u32, wayland.types.Fd, u32 },
+pub const Request = union(enum) {
+ create_pool: struct { wayland.Object.Ref, wayland.types.Fd, u32 },
};
pub var instances: std.ArrayListUnmanaged(*Self) = .empty;
@@ -19,7 +20,7 @@ formats: std.EnumSet(Format) = .initEmpty(),
pub fn init(
self: *Self,
- ctx: *wayland.Context,
+ ctx: *const wayland.Context,
) !void {
self.* = .{
.handle = try ctx.display.registry.add_object(
@@ -29,7 +30,7 @@ pub fn init(
};
}
-fn announce_format(self: * Self, ctx: *wayland.Context, fmt: Format) void {
+fn announce_format(self: * Self, ctx: *const wayland.Context, fmt: Format) void {
_ = ctx;
self.formats.insert(fmt);
}
@@ -40,7 +41,7 @@ pub const handler: wl.Registry.GlobalHandler = .{
.handler = register,
};
-fn register(ctx: *wayland.Context) ?wayland.Object.Ref {
+fn register(ctx: *const wayland.Context) ?wayland.Object.Ref {
const shm = ctx.allocator.create(Self) catch return null;
shm.init(ctx) catch return null;
@@ -48,6 +49,20 @@ fn register(ctx: *wayland.Context) ?wayland.Object.Ref {
return shm.handle;
}
+pub fn create_pool(self: *Self, ctx: *const wayland.Context, size: usize) !*Pool {
+ const pool = try ctx.allocator.create(Pool);
+ errdefer ctx.allocator.destroy(pool);
+ try pool.init(ctx, size);
+
+ try ctx.display.request(self, .{ .create_pool = .{
+ pool.handle,
+ .{ .fd = pool.file.fd },
+ @truncate(size)
+ } });
+
+ return pool;
+}
+
pub fn format(
self: *const Self,
comptime fmt: []const u8,