diff --git a/README.md b/README.md index 8fbf747..321321b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # zig-wayland -Zig 0.9 bindings and protocol scanner for libwayland. +Zig 0.10 bindings and protocol scanner for libwayland. ## Usage @@ -39,7 +39,7 @@ pub fn build(b: *Builder) void { exe.addPackage(.{ .name = "wayland", - .path = .{ .generated = &scanner.result }, + .source = .{ .generated = &scanner.result }, }); exe.step.dependOn(&scanner.step); exe.linkLibC(); diff --git a/build.zig b/build.zig index 473cc28..93a8686 100644 --- a/build.zig +++ b/build.zig @@ -10,7 +10,7 @@ pub fn build(b: *zbs.Builder) void { const scanner = ScanProtocolsStep.create(b); const wayland = zbs.Pkg{ .name = "wayland", - .path = .{ .generated = &scanner.result }, + .source = .{ .generated = &scanner.result }, }; scanner.generate("wl_compositor", 1); diff --git a/src/common_core.zig b/src/common_core.zig index f234496..e406f58 100644 --- a/src/common_core.zig +++ b/src/common_core.zig @@ -100,7 +100,7 @@ pub fn Dispatcher(comptime Obj: type, comptime Data: type) type { } } - @ptrCast(fn (*Obj, Payload, Data) void, implementation)( + @ptrCast(*const fn (*Obj, Payload, Data) void, implementation)( @ptrCast(*Obj, object), @unionInit(Payload, payload_field.name, payload_data), @intToPtr(Data, @ptrToInt(object.getUserData())), diff --git a/src/ref_all.zig b/src/ref_all.zig index d0d9665..7e40f9a 100644 --- a/src/ref_all.zig +++ b/src/ref_all.zig @@ -1,21 +1,4 @@ -// Note: this requires the fix made in https://github.com/ziglang/zig/pull/7178 -// to work properly with zig-wayland's use of usingnamespace -fn refAllDeclsRecursive(comptime T: type) void { - const decls = switch (@typeInfo(T)) { - .Struct => |info| info.decls, - .Union => |info| info.decls, - .Enum => |info| info.decls, - .Opaque => |info| info.decls, - else => return, - }; - inline for (decls) |decl| { - switch (decl.data) { - .Type => |T2| refAllDeclsRecursive(T2), - else => _ = decl, - } - } -} - -test "" { - refAllDeclsRecursive(@import("wayland")); +const std = @import("std"); +test { + std.testing.refAllDeclsRecursive(@import("wayland")); } diff --git a/src/scanner.zig b/src/scanner.zig index 2da7378..3849e0f 100644 --- a/src/scanner.zig +++ b/src/scanner.zig @@ -598,7 +598,7 @@ const Interface = struct { \\pub inline fn setListener( \\ _{[interface]}: *{[type]}, \\ comptime T: type, - \\ _listener: fn ({[interface]}: *{[type]}, event: Event, data: T) void, + \\ _listener: *const fn ({[interface]}: *{[type]}, event: Event, data: T) void, \\ _data: T, \\) void {{ \\ const _proxy = @ptrCast(*client.wl.Proxy, _{[interface]}); @@ -695,7 +695,7 @@ const Interface = struct { \\pub inline fn setHandler( \\ _{[interface]}: *{[type]}, \\ comptime T: type, - \\ handle_request: fn (_{[interface]}: *{[type]}, request: Request, data: T) void, + \\ handle_request: *const fn (_{[interface]}: *{[type]}, request: Request, data: T) void, \\ comptime handle_destroy: ?fn (_{[interface]}: *{[type]}, data: T) void, \\ _data: T, \\) void {{ @@ -1161,29 +1161,18 @@ const Enum = struct { if (e.bitfield) { var entries_emitted: u8 = 0; - try writer.writeAll(" = packed struct {"); + try writer.writeAll(" = packed struct(u32) {"); for (e.entries) |entry| { if (entry.since <= target_version) { const value = entry.intValue(); if (value != 0 and std.math.isPowerOfTwo(value)) { - try writer.print("{s}", .{entry.name}); - if (entries_emitted == 0) { - // Align the first field to ensure the entire packed - // struct matches the alignment of a u32. This allows - // using the packed struct as the field of an extern - // struct where a u32 is expected. - try writer.writeAll(": bool align(@alignOf(u32)) = false,"); - } else { - try writer.writeAll(": bool = false,"); - } + try writer.print("{s}: bool = false,", .{entry.name}); entries_emitted += 1; } } } - // Pad to 32 bits. Use only bools to avoid zig stage1 packed - // struct bugs. - while (entries_emitted < 32) : (entries_emitted += 1) { - try writer.print("_paddding{}: bool = false,\n", .{entries_emitted}); + if (entries_emitted < 32) { + try writer.print("_padding: u{d} = 0,\n", .{32 - entries_emitted}); } // Emit the normal C abi enum as well as it may be needed to interface @@ -1260,7 +1249,7 @@ fn trimPrefix(s: []const u8) []const u8 { const Case = enum { title, camel }; -fn formatCaseImpl(case: Case, comptime trim: bool) type { +fn formatCaseImpl(comptime case: Case, comptime trim: bool) type { return struct { pub fn f( bytes: []const u8, @@ -1311,7 +1300,7 @@ test "parsing" { var arena = std.heap.ArenaAllocator.init(testing.allocator); defer arena.deinit(); - const protocol = try Protocol.parseXML(arena.allocator(), @embedFile("../protocol/wayland.xml")); + const protocol = try Protocol.parseXML(arena.allocator(), @embedFile("test_data/wayland.xml")); try testing.expectEqualSlices(u8, "wayland", protocol.name); try testing.expectEqual(@as(usize, 7), protocol.globals.len); diff --git a/protocol/wayland.xml b/src/test_data/wayland.xml similarity index 100% rename from protocol/wayland.xml rename to src/test_data/wayland.xml diff --git a/src/wayland_client_core.zig b/src/wayland_client_core.zig index ca3354a..9fdbc88 100644 --- a/src/wayland_client_core.zig +++ b/src/wayland_client_core.zig @@ -63,13 +63,13 @@ pub const Proxy = opaque { ) callconv(.C) c_int; extern fn wl_proxy_add_dispatcher( proxy: *Proxy, - dispatcher: DispatcherFn, + dispatcher: *const DispatcherFn, implementation: ?*const anyopaque, data: ?*anyopaque, ) c_int; pub fn addDispatcher( proxy: *Proxy, - dispatcher: DispatcherFn, + dispatcher: *const DispatcherFn, implementation: ?*const anyopaque, data: ?*anyopaque, ) void { diff --git a/src/wayland_server_core.zig b/src/wayland_server_core.zig index 44d10d1..a43f77c 100644 --- a/src/wayland_server_core.zig +++ b/src/wayland_server_core.zig @@ -82,16 +82,24 @@ pub const Server = opaque { extern fn wl_display_set_global_filter( server: *Server, - filter: fn (client: *const Client, global: *const Global, data: ?*anyopaque) callconv(.C) bool, + filter: *const fn (client: *const Client, global: *const Global, data: ?*anyopaque) callconv(.C) bool, data: ?*anyopaque, ) void; pub inline fn setGlobalFilter( server: *Server, comptime T: type, - filter: fn (client: *const Client, global: *const Global, data: T) callconv(.C) bool, + comptime filter: fn (client: *const Client, global: *const Global, data: T) bool, data: T, ) void { - wl_display_set_global_filter(server, filter, data); + wl_display_set_global_filter( + server, + struct { + fn wrapper(_client: *const Client, _global: *const Global, _data: ?*anyopaque) callconv(.C) bool { + filter(_client, _global, @ptrCast(T, @alignCast(@alignOf(T), _data))); + } + }._wrapper, + data, + ); } extern fn wl_display_get_client_list(server: *Server) *list.Head(Client, null); @@ -109,16 +117,24 @@ pub const Server = opaque { extern fn wl_display_add_protocol_logger( server: *Server, - func: fn (data: ?*anyopaque, direction: ProtocolLogger.Type, message: *const ProtocolLogger.LogMessage) callconv(.C) void, + func: *const fn (data: ?*anyopaque, direction: ProtocolLogger.Type, message: *const ProtocolLogger.LogMessage) callconv(.C) void, data: ?*anyopaque, ) void; pub inline fn addProtocolLogger( server: *Server, comptime T: type, - func: fn (data: T, direction: ProtocolLogger.Type, message: *const ProtocolLogger.LogMessage) callconv(.C) void, + comptime func: fn (data: T, direction: ProtocolLogger.Type, message: *const ProtocolLogger.LogMessage) void, data: T, ) void { - wl_display_add_protocol_logger(server, func, data); + wl_display_add_protocol_logger( + server, + struct { + fn _wrapper(_data: ?*anyopaque, _direction: ProtocolLogger.Type, _message: *const ProtocolLogger.LogMessage) callconv(.C) void { + func(@ptrCast(T, @alignCast(@alignOf(T), _data)), _direction, _message); + } + }, + data, + ); } }; @@ -172,16 +188,24 @@ pub const Client = opaque { const IteratorResult = enum(c_int) { stop, cont }; extern fn wl_client_for_each_resource( client: *Client, - iterator: fn (resource: *Resource, data: ?*anyopaque) callconv(.C) IteratorResult, + iterator: *const fn (resource: *Resource, data: ?*anyopaque) callconv(.C) IteratorResult, data: ?*anyopaque, ) void; pub inline fn forEachResource( client: *Client, comptime T: type, - iterator: fn (resource: *Resource, data: T) callconv(.C) IteratorResult, + comptime iterator: fn (resource: *Resource, data: T) IteratorResult, data: T, ) void { - wl_client_for_each_resource(client, iterator, data); + wl_client_for_each_resource( + client, + struct { + fn _wrapper(_resource: *Resource, _data: ?*anyopaque) callconv(.C) IteratorResult { + return iterator(_resource, @ptrCast(T, @alignCast(@alignOf(T), _data))); + } + }._wrapper, + data, + ); } extern fn wl_client_get_fd(client: *Client) c_int; @@ -197,7 +221,7 @@ pub const Global = opaque { interface: *const Interface, version: c_int, data: ?*anyopaque, - bind: fn (client: *Client, data: ?*anyopaque, version: u32, id: u32) callconv(.C) void, + bind: *const fn (client: *Client, data: ?*anyopaque, version: u32, id: u32) callconv(.C) void, ) ?*Global; pub inline fn create( server: *Server, @@ -205,14 +229,18 @@ pub const Global = opaque { version: u32, comptime DataT: type, data: DataT, - bind: fn (client: *Client, data: DataT, version: u32, id: u32) callconv(.C) void, - ) !*Global { + comptime bind: fn (client: *Client, data: DataT, version: u32, id: u32) void, + ) error{GlobalCreateFailed}!*Global { return wl_global_create( server, T.getInterface(), @intCast(c_int, version), data, - @ptrCast(fn (client: *Client, data: ?*anyopaque, version: u32, id: u32) callconv(.C) void, bind), + struct { + fn _wrapper(_client: *Client, _data: ?*anyopaque, _version: u32, _id: u32) callconv(.C) void { + bind(_client, @ptrCast(DataT, @alignCast(@alignOf(DataT), _data)), _version, _id); + } + }._wrapper, ) orelse error.GlobalCreateFailed; } @@ -231,7 +259,7 @@ pub const Global = opaque { pub const Resource = opaque { extern fn wl_resource_create(client: *Client, interface: *const Interface, version: c_int, id: u32) ?*Resource; - pub inline fn create(client: *Client, comptime T: type, version: u32, id: u32) !*Resource { + pub inline fn create(client: *Client, comptime T: type, version: u32, id: u32) error{ResourceCreateFailed}!*Resource { // This is only a c_int because of legacy libwayland reasons. Negative versions are invalid. // Version is a u32 on the wire and for wl_global, wl_proxy, etc. return wl_resource_create(client, T.getInterface(), @intCast(c_int, version), id) orelse error.ResourceCreateFailed; @@ -262,17 +290,17 @@ pub const Resource = opaque { pub const DestroyFn = fn (resource: *Resource) callconv(.C) void; extern fn wl_resource_set_dispatcher( resource: *Resource, - dispatcher: ?DispatcherFn, + dispatcher: ?*const DispatcherFn, implementation: ?*const anyopaque, data: ?*anyopaque, - destroy_fn: ?DestroyFn, + destroy_fn: ?*const DestroyFn, ) void; pub fn setDispatcher( resource: *Resource, - dispatcher: ?DispatcherFn, + dispatcher: ?*const DispatcherFn, implementation: ?*const anyopaque, data: ?*anyopaque, - destroy_fn: ?DestroyFn, + destroy_fn: ?*const DestroyFn, ) void { wl_resource_set_dispatcher(resource, dispatcher, implementation, data, destroy_fn); } @@ -471,7 +499,7 @@ pub fn Listener(comptime T: type) type { fn (listener: *Self, data: T) void; link: list.Link, - notify: fn (listener: *Self, data: ?*anyopaque) callconv(.C) void, + notify: *const fn (listener: *Self, data: ?*anyopaque) callconv(.C) void, pub fn init(comptime notify: NotifyFn) Self { var self: Self = undefined; @@ -569,7 +597,7 @@ pub const EventLoop = opaque { loop: *EventLoop, fd: c_int, mask: u32, - func: fn (fd: c_int, mask: u32, data: ?*anyopaque) callconv(.C) c_int, + func: *const fn (fd: c_int, mask: u32, data: ?*anyopaque) callconv(.C) c_int, data: ?*anyopaque, ) ?*EventSource; pub inline fn addFd( @@ -577,32 +605,40 @@ pub const EventLoop = opaque { comptime T: type, fd: c_int, mask: u32, - func: fn (fd: c_int, mask: u32, data: T) callconv(.C) c_int, + comptime func: fn (fd: c_int, mask: u32, data: T) c_int, data: T, - ) !*EventSource { + ) error{AddFdFailed}!*EventSource { return wl_event_loop_add_fd( loop, fd, mask, - @ptrCast(fn (fd: c_int, mask: u32, data: ?*anyopaque) callconv(.C) c_int, func), + struct { + fn _wrapper(_fd: c_int, _mask: u32, _data: ?*anyopaque) callconv(.C) c_int { + return func(_fd, _mask, @ptrCast(T, @alignCast(@alignOf(T), _data))); + } + }._wrapper, data, ) orelse error.AddFdFailed; } extern fn wl_event_loop_add_timer( loop: *EventLoop, - func: fn (data: ?*anyopaque) callconv(.C) c_int, + func: *const fn (data: ?*anyopaque) callconv(.C) c_int, data: ?*anyopaque, ) ?*EventSource; pub inline fn addTimer( loop: *EventLoop, comptime T: type, - func: fn (data: T) callconv(.C) c_int, + comptime func: fn (data: T) c_int, data: T, - ) !*EventSource { + ) error{AddTimerFailed}!*EventSource { return wl_event_loop_add_timer( loop, - @ptrCast(fn (?*anyopaque) callconv(.C) c_int, func), + struct { + fn _wrapper(_data: ?*anyopaque) callconv(.C) c_int { + return func(@ptrCast(T, @alignCast(@alignOf(T), _data))); + } + }._wrapper, data, ) orelse error.AddTimerFailed; } @@ -610,38 +646,46 @@ pub const EventLoop = opaque { extern fn wl_event_loop_add_signal( loop: *EventLoop, signal_number: c_int, - func: fn (c_int, ?*anyopaque) callconv(.C) c_int, + func: *const fn (c_int, ?*anyopaque) callconv(.C) c_int, data: ?*anyopaque, ) ?*EventSource; pub inline fn addSignal( loop: *EventLoop, comptime T: type, signal_number: c_int, - func: fn (signal_number: c_int, data: T) callconv(.C) c_int, + comptime func: fn (signal_number: c_int, data: T) c_int, data: T, - ) !*EventSource { + ) error{AddSignalFailed}!*EventSource { return wl_event_loop_add_signal( loop, signal_number, - @ptrCast(fn (c_int, ?*anyopaque) callconv(.C) c_int, func), + struct { + fn _wrapper(_signal_number: c_int, _data: ?*anyopaque) callconv(.C) c_int { + return func(_signal_number, @ptrCast(T, @alignCast(@alignOf(T), _data))); + } + }._wrapper, data, ) orelse error.AddSignalFailed; } extern fn wl_event_loop_add_idle( loop: *EventLoop, - func: fn (data: ?*anyopaque) callconv(.C) void, + func: *const fn (data: ?*anyopaque) callconv(.C) void, data: ?*anyopaque, ) ?*EventSource; pub inline fn addIdle( loop: *EventLoop, comptime T: type, - func: fn (data: T) callconv(.C) void, + comptime func: fn (data: T) void, data: T, ) error{OutOfMemory}!*EventSource { return wl_event_loop_add_idle( loop, - @ptrCast(fn (?*anyopaque) callconv(.C) void, func), + struct { + fn _wrapper(_data: ?*anyopaque) callconv(.C) c_int { + return func(@ptrCast(T, @alignCast(@alignOf(T), _data))); + } + }._wrapper, data, ) orelse error.OutOfMemory; }