diff --git a/build.zig b/build.zig index 3bf74dd..6737f5f 100644 --- a/build.zig +++ b/build.zig @@ -28,6 +28,20 @@ pub fn build(b: *zbs.Builder) void { test_step.dependOn(&t.step); } + + { + const ref_all = b.addTest("src/ref_all.zig"); + ref_all.setTarget(target); + ref_all.setBuildMode(mode); + + ref_all.step.dependOn(&scanner.step); + ref_all.addPackage(scanner.getPkg()); + scanner.addCSource(ref_all); + ref_all.linkLibC(); + ref_all.linkSystemLibrary("wayland-client"); + ref_all.linkSystemLibrary("wayland-server"); + test_step.dependOn(&ref_all.step); + } } pub const ScanProtocolsStep = struct { diff --git a/example/seats.zig b/example/seats.zig index 865d28a..2ecbe78 100644 --- a/example/seats.zig +++ b/example/seats.zig @@ -15,7 +15,7 @@ pub fn main() !void { fn listener(registry: *wl.Registry, event: wl.Registry.Event, running: *bool) void { switch (event) { .global => |global| { - if (std.cstr.cmp(global.interface, wl.Seat.interface().name) == 0) { + if (std.cstr.cmp(global.interface, wl.Seat.getInterface().name) == 0) { const seat = registry.bind(global.name, wl.Seat, 1) catch return; seat.setListener(*bool, seatListener, running) catch return; } diff --git a/src/client_display_functions.zig b/src/client_display_functions.zig index 3942bb8..fc6eb1f 100644 --- a/src/client_display_functions.zig +++ b/src/client_display_functions.zig @@ -119,7 +119,7 @@ pub fn roundtripQueue(display: *Display, queue: *client.wl.EventQueue) !u32 { extern fn wl_display_flush(display: *Display) c_int; pub fn flush(display: *Display) error{WouldBlock}!u32 { - const rc = wl_display_dispatch_queue_pending(display, queue); + const rc = wl_display_flush(display); return switch (os.errno(rc)) { 0 => @intCast(u32, rc), os.EAGAIN => error.WouldBlock, @@ -127,7 +127,7 @@ pub fn flush(display: *Display) error{WouldBlock}!u32 { }; } -extern fn wl_display_create_queue(display: *Display) *client.wl.EventQueue; +extern fn wl_display_create_queue(display: *Display) ?*client.wl.EventQueue; pub fn createQueue(display: *Display) error{OutOfMemory}!*client.wl.EventQueue { return wl_display_create_queue(display) orelse error.OutOfMemory; } diff --git a/src/ref_all.zig b/src/ref_all.zig new file mode 100644 index 0000000..d0d9665 --- /dev/null +++ b/src/ref_all.zig @@ -0,0 +1,21 @@ +// 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")); +} diff --git a/src/scanner.zig b/src/scanner.zig index 6e0e00a..b5a8683 100644 --- a/src/scanner.zig +++ b/src/scanner.zig @@ -253,7 +253,7 @@ const Interface = struct { try writer.print( \\pub const {} = opaque {{ - \\ pub const interface = common.{}.{}.interface; + \\ pub const getInterface = common.{}.{}.getInterface; , .{ title_case, namespace, snake_case }); for (interface.enums.items) |e| { @@ -294,12 +294,30 @@ const Interface = struct { \\}} , .{ title_case, title_case, title_case }); - for ([_][]const u8{ "destroy", "getId", "fromLink", "getLink", "getClient", "getVersion" }) |func| + try writer.print( + \\pub fn destroy({}: *{}) void {{ + \\ return @ptrCast(*server.wl.Resource, {}).destroy(); + \\}} + , .{ snake_case, title_case, snake_case }); + + try writer.print( + \\pub fn fromLink(link: *server.wl.list.Link) *{} {{ + \\ return @ptrCast(*{}, server.wl.Resource.fromLink(link)); + \\}} + , .{ title_case, title_case }); + + for ([_][2][]const u8{ + .{ "getLink", "*server.wl.list.Link" }, + .{ "getClient", "*server.wl.Client" }, + .{ "getId", "u32" }, + .{ "getVersion", "u32" }, + }) |func| try writer.print( - \\pub fn {}({}: *{}) void {{ - \\ @ptrCast(*server.wl.Resource, {}).{}(); + \\pub fn {}({}: *{}) {} {{ + \\ return @ptrCast(*server.wl.Resource, {}).{}(); \\}} - , .{ func, snake_case, title_case, snake_case, func }); + , .{ func[0], snake_case, title_case, func[1], snake_case, func[0] }); + if (interface.requests.items.len > 0) { try writer.writeAll("pub const Request = union(enum) {"); for (interface.requests.items) |request| try request.emitField(.server, writer); @@ -400,7 +418,7 @@ const Interface = struct { try writer.print( \\ = struct {{ \\ extern const {}_interface: common.Interface; - \\ pub inline fn interface() *const common.Interface {{ + \\ pub inline fn getInterface() *const common.Interface {{ \\ return &{}_interface; \\ }} , .{ interface.name, interface.name }); @@ -465,34 +483,35 @@ const Message = struct { return error.UnexpectedEndOfFile; } - fn emitMessage(message: Message, writer: anytype) !void { - try writer.print(".{{ .name = \"{}\", .signature = \"", .{message.name}); - for (message.args.items) |arg| try arg.emitSignature(writer); - try writer.writeAll("\", .types = "); - if (message.args.items.len > 0) { - try writer.writeAll("&[_]?*const common.Interface{"); - for (message.args.items) |arg| { - switch (arg.kind) { - .object, .new_id => |interface| if (interface) |i| - try writer.print("&common.{}.{}.interface,", .{ prefix(i), trimPrefix(i) }) - else - try writer.writeAll("null,"), - else => try writer.writeAll("null,"), - } - } - try writer.writeAll("},"); - } else { - try writer.writeAll("null,"); - } - try writer.writeAll("},"); - } + // TODO: restore this code when zig issue #131 is resoleved + //fn emitMessage(message: Message, writer: anytype) !void { + // try writer.print(".{{ .name = \"{}\", .signature = \"", .{message.name}); + // for (message.args.items) |arg| try arg.emitSignature(writer); + // try writer.writeAll("\", .types = "); + // if (message.args.items.len > 0) { + // try writer.writeAll("&[_]?*const common.Interface{"); + // for (message.args.items) |arg| { + // switch (arg.kind) { + // .object, .new_id => |interface| if (interface) |i| + // try writer.print("&common.{}.{}.interface,", .{ prefix(i), trimPrefix(i) }) + // else + // try writer.writeAll("null,"), + // else => try writer.writeAll("null,"), + // } + // } + // try writer.writeAll("},"); + // } else { + // try writer.writeAll("null,"); + // } + // try writer.writeAll("},"); + //} fn emitField(message: Message, side: Side, writer: anytype) !void { try printIdentifier(writer, message.name); try writer.writeAll(": struct {"); for (message.args.items) |arg| { if (side == .server and arg.kind == .new_id and arg.kind.new_id == null) { - try writer.writeAll("interface: [*:0]const u8, version: u32,"); + try writer.writeAll("interface_name: [*:0]const u8, version: u32,"); try printIdentifier(writer, arg.name); try writer.writeAll(": u32"); } else if (side == .client and arg.kind == .new_id) { @@ -601,7 +620,7 @@ const Message = struct { } else { if (new_iface == null) { try writer.writeAll( - \\.{ .s = T.interface().name }, + \\.{ .s = T.getInterface().name }, \\.{ .u = version }, ); } @@ -626,9 +645,9 @@ const Message = struct { try printIdentifier(writer, case(.title, trimPrefix(i))); try writer.print(", try proxy.marshalConstructor({}, &args, ", .{opcode}); try printIdentifier(writer, case(.title, trimPrefix(i))); - try writer.writeAll(".interface()));"); + try writer.writeAll(".getInterface()));"); } else { - try writer.print("return @ptrCast(*T, try proxy.marshalConstructorVersioned({}, &args, T.interface(), version));", .{opcode}); + try writer.print("return @ptrCast(*T, try proxy.marshalConstructorVersioned({}, &args, T.getInterface(), version));", .{opcode}); } }, } diff --git a/src/wayland_client_core.zig b/src/wayland_client_core.zig index 790bbb5..e5d373f 100644 --- a/src/wayland_client_core.zig +++ b/src/wayland_client_core.zig @@ -7,9 +7,9 @@ pub const Fixed = common.Fixed; pub const Argument = common.Argument; pub const Proxy = opaque { - extern fn wl_proxy_create(factory: *Proxy, interface: *const Interface) *Proxy; + extern fn wl_proxy_create(factory: *Proxy, interface: *const Interface) ?*Proxy; pub fn create(factory: *Proxy, interface: *const Interface) error{OutOfMemory}!*Proxy { - return wl_proxy_create(factory.impl, interface) orelse error.OutOfMemory; + return wl_proxy_create(factory, interface) orelse error.OutOfMemory; } extern fn wl_proxy_destroy(proxy: *Proxy) void; diff --git a/src/wayland_server_core.zig b/src/wayland_server_core.zig index f81b5cd..0b9a692 100644 --- a/src/wayland_server_core.zig +++ b/src/wayland_server_core.zig @@ -76,12 +76,13 @@ pub const Server = opaque { extern fn wl_display_add_client_created_listener(server: *Server, listener: *Listener(*Client)) void; pub const addClientCreatedListener = wl_display_add_client_created_listener; - extern fn wl_display_get_destroy_listener(server: *Server, notify: @TypeOf(Listener(*Server).notify)) ?*Listener(*Server); - pub const getDestroyListener = wl_display_get_destroy_listener; + // Doesn't really make sense with our Listener API as we would need to + // pass a pointer to the wrapper function + //extern fn wl_display_get_destroy_listener(server: *Server, notify: @TypeOf(Listener(*Server).notify)) ?*Listener(*Server); extern fn wl_display_set_global_filter( server: *Server, - filter: fn (client: *const Client, global: *const Global, data: ?*c_void) bool, + filter: fn (client: *const Client, global: *const Global, data: ?*c_void) callconv(.C) bool, data: ?*c_void, ) void; pub fn setGlobalFilter( @@ -98,24 +99,23 @@ pub const Server = opaque { extern fn wl_display_init_shm(server: *Server) c_int; pub fn initShm(server: *Server) !void { - if (wl_display_init_shm(display) == -1) - return error.GlobalCreateFailed; + if (wl_display_init_shm(server) == -1) return error.OutOfMemory; } extern fn wl_display_add_shm_format(server: *Server, format: u32) ?*u32; pub fn addShmFormat(server: *Server, format: u32) !*u32 { - return wl_display_add_shm_format(display, format) orelse error.OutOfMemory; + return wl_display_add_shm_format(server, format) orelse error.OutOfMemory; } extern fn wl_display_add_protocol_logger( server: *Server, - func: fn (data: ?*c_void, direction: ProtocolLogger.Type, message: *const ProtocolLogger.Message) void, + func: fn (data: ?*c_void, direction: ProtocolLogger.Type, message: *const ProtocolLogger.LogMessage) callconv(.C) void, data: ?*c_void, ) void; pub fn addProtocolLogger( server: *Server, comptime T: type, - func: fn (data: T, direction: ProtocolLogger.Type, message: *const ProtocolLogger.Message) callconv(.C) void, + func: fn (data: T, direction: ProtocolLogger.Type, message: *const ProtocolLogger.LogMessage) callconv(.C) void, data: T, ) void { wl_display_add_protocol_logger(display, func, data); @@ -153,8 +153,9 @@ pub const Client = opaque { extern fn wl_client_add_destroy_listener(client: *Client, listener: *Listener(*Client)) void; pub const addDestroyListener = wl_client_add_destroy_listener; - extern fn wl_client_get_destroy_listener(client: *Client, notify: @TypeOf(Listener(*Client).notify)) ?*Listener(*Client); - pub const getDestroyListener = wl_client_get_destroy_listener; + // Doesn't really make sense with our Listener API as we would need to + // pass a pointer to the wrapper function + //extern fn wl_client_get_destroy_listener(client: *Client, notify: @TypeOf(Listener(*Client).notify)) ?*Listener(*Client); extern fn wl_client_get_object(client: *Client, id: u32) ?*Resource; pub const getObject = wl_client_get_object; @@ -171,7 +172,7 @@ pub const Client = opaque { const IteratorResult = extern enum { stop, cont }; extern fn wl_client_for_each_resource( client: *Client, - iterator: fn (resource: *Resource, data: ?*c_void) IteratorResult, + iterator: fn (resource: *Resource, data: ?*c_void) callconv(.C) IteratorResult, data: ?*c_void, ) void; pub fn forEachResource( @@ -206,7 +207,7 @@ pub const Global = opaque { data: T, bind: fn (client: *Client, data: T, version: u32, id: u32) callconv(.C) void, ) !*Global { - return wl_global_create(display, Object.interface, version, data, bind) orelse + return wl_global_create(display, Object.getInterface(), version, data, bind) orelse error.GlobalCreateFailed; } @@ -228,19 +229,19 @@ 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 fn create(client: *Client, comptime Object: type, version: u32, id: u32) !*Resource { + pub fn create(client: *Client, comptime T: type, version: u32, id: u32) !*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, Object.interface, @intCast(c_int, version), id) orelse error.ResourceCreateFailed; + return wl_resource_create(client, T.getInterface(), @intCast(c_int, version), id) orelse error.ResourceCreateFailed; } extern fn wl_resource_destroy(resource: *Resource) void; pub const destroy = wl_resource_destroy; - extern fn wl_resource_post_event_array(resource: *Resource, opcode: u32, args: [*]Argument) void; + extern fn wl_resource_post_event_array(resource: *Resource, opcode: u32, args: ?[*]Argument) void; pub const postEvent = wl_resource_post_event_array; - extern fn wl_resource_queue_event_array(resource: *Resource, opcode: u32, args: [*]Argument) void; + extern fn wl_resource_queue_event_array(resource: *Resource, opcode: u32, args: ?[*]Argument) void; pub const queueEvent = wl_resource_queue_event_array; extern fn wl_resource_post_error(resource: *Resource, code: u32, message: [*:0]const u8, ...) void; @@ -262,14 +263,14 @@ pub const Resource = opaque { dispatcher: ?DispatcherFn, implementation: ?*const c_void, data: ?*c_void, - destroy: ?DestroyFn, + destroy_fn: ?DestroyFn, ) void; pub fn setDispatcher( resource: *Resource, dispatcher: ?DispatcherFn, implementation: ?*const c_void, data: ?*c_void, - destroy: ?DestroyFn, + destroy_fn: ?DestroyFn, ) void { wl_resource_set_dispatcher(resource, dispatcher, implementation, data, destroy); } @@ -312,8 +313,9 @@ pub const Resource = opaque { extern fn wl_resource_add_destroy_listener(resource: *Resource, listener: *Listener(*Resource)) void; pub const addDestroyListener = wl_resource_add_destroy_listener; - extern fn wl_resource_get_destroy_listener(resource: *Resource, notify: @TypeOf(Listener(*Resource).notify)) ?*Listener(*Resource); - pub const getDestroyListener = wl_resource_get_destroy_listener; + // Doesn't really make sense with our Listener API as we would need to + // pass a pointer to the wrapper function + //extern fn wl_resource_get_destroy_listener(resource: *Resource, notify: @TypeOf(Listener(*Resource).notify)) ?*Listener(*Resource); }; pub const ProtocolLogger = opaque { @@ -322,7 +324,7 @@ pub const ProtocolLogger = opaque { event, }; - pub const Message = extern struct { + pub const LogMessage = extern struct { resource: *Resource, message_opcode: c_int, message: *Message, @@ -512,7 +514,7 @@ pub fn Signal(comptime T: type) type { pub const EventLoop = opaque { extern fn wl_event_loop_create() ?*EventLoop; - pub fn create() *EventLoop { + pub fn create() !*EventLoop { return wl_event_loop_create() orelse error.EventLoopCreateFailed; } @@ -523,7 +525,7 @@ pub const EventLoop = opaque { loop: *EventLoop, fd: os.fd_t, mask: u32, - func: fn (fd: os.fd_t, mask: u32, data: ?*c_void) c_int, + func: fn (fd: os.fd_t, mask: u32, data: ?*c_void) callconv(.C) c_int, data: ?*c_void, ) ?*EventSource; pub fn addFd( @@ -539,7 +541,7 @@ pub const EventLoop = opaque { extern fn wl_event_loop_add_timer( loop: *EventLoop, - func: fn (data: ?*c_void) c_int, + func: fn (data: ?*c_void) callconv(.C) c_int, data: ?*c_void, ) ?*EventSource; pub fn addTimer( @@ -554,7 +556,7 @@ pub const EventLoop = opaque { extern fn wl_event_loop_add_signal( loop: *EventLoop, signal_number: c_int, - func: fn (c_int, ?*c_void) c_int, + func: fn (c_int, ?*c_void) callconv(.C) c_int, data: ?*c_void, ) ?*EventSource; pub fn addSignal( @@ -569,7 +571,7 @@ pub const EventLoop = opaque { extern fn wl_event_loop_add_idle( loop: *EventLoop, - func: fn (data: ?*c_void) c_int, + func: fn (data: ?*c_void) callconv(.C) c_int, data: ?*c_void, ) ?*EventSource; pub fn addIdle( @@ -587,7 +589,7 @@ pub const EventLoop = opaque { switch (os.errno(rc)) { 0 => return, // TODO - else => |err| os.unexpectedErrno(err), + else => |err| return os.unexpectedErrno(err), } } @@ -600,8 +602,8 @@ pub const EventLoop = opaque { extern fn wl_event_loop_add_destroy_listener(loop: *EventLoop, listener: *Listener(*EventLoop)) void; pub const addDestroyListener = wl_event_loop_add_destroy_listener; - extern fn wl_event_loop_get_destroy_listener(loop: *EventLoop, notify: @TypeOf(Listener(*EventLoop).notify)) ?*Listener; - pub const getDestroyListener = wl_event_loop_get_destroy_listener; + //extern fn wl_event_loop_get_destroy_listener(loop: *EventLoop, notify: @TypeOf(Listener(*EventLoop).notify)) ?*Listener; + //pub const getDestroyListener = wl_event_loop_get_destroy_listener; }; pub const EventSource = opaque { @@ -619,7 +621,7 @@ pub const EventSource = opaque { switch (os.errno(rc)) { 0 => return, // TODO - else => |err| os.unexpectedErrno(err), + else => |err| return os.unexpectedErrno(err), } } @@ -629,7 +631,7 @@ pub const EventSource = opaque { switch (os.errno(rc)) { 0 => return, // TODO - else => |err| os.unexpectedErrno(err), + else => |err| return os.unexpectedErrno(err), } } };