aboutsummaryrefslogtreecommitdiff
path: root/src/wl
diff options
context:
space:
mode:
Diffstat (limited to 'src/wl')
-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
8 files changed, 186 insertions, 50 deletions
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,