Make Dispatcher work for server as well

This commit is contained in:
Isaac Freund
2020-10-07 00:04:35 +02:00
parent 85bef02e7b
commit 40232ae394
3 changed files with 38 additions and 36 deletions
+1 -1
View File
@@ -87,7 +87,7 @@ const Interface = struct {
\\ data: T,
\\ ) !void {{
\\ const proxy = @ptrCast(*client.Proxy, {});
\\ try proxy.addDispatcher(client.Dispatcher({}, T).dispatcher, listener, data);
\\ try proxy.addDispatcher(common.Dispatcher({}, T).dispatcher, listener, data);
\\ }}
\\
, .{ snake_case, title_case, snake_case, title_case, snake_case, title_case });
-35
View File
@@ -102,38 +102,3 @@ pub const EventQueue = opaque {
wl_event_queue_destroy(event_queue);
}
};
pub fn Dispatcher(comptime Object: type, comptime Data: type) type {
return struct {
pub fn dispatcher(
implementation: ?*const c_void,
proxy: *Proxy,
opcode: u32,
message: *const common.Message,
args: [*]common.Argument,
) callconv(.C) c_int {
inline for (@typeInfo(Object.Event).Union.fields) |event_field, event_num| {
if (event_num == opcode) {
var event_data: event_field.field_type = undefined;
inline for (@typeInfo(event_field.field_type).Struct.fields) |f, i| {
@field(event_data, f.name) = switch (@sizeOf(f.field_type)) {
4 => @bitCast(f.field_type, args[i].u),
8 => @ptrCast(f.field_type, args[i].s),
else => unreachable,
};
}
const listener = @ptrCast(fn (object: *Object, event: Object.Event, data: Data) void, implementation);
listener(
@ptrCast(*Object, proxy),
@unionInit(Object.Event, event_field.name, event_data),
@intToPtr(Data, @ptrToInt(proxy.getUserData())),
);
return 0;
}
}
unreachable;
}
};
}
+37
View File
@@ -1,4 +1,5 @@
const std = @import("std");
const wayland = @import("wayland.zig");
pub const Object = opaque {};
@@ -51,3 +52,39 @@ pub const Argument = extern union {
a: ?*Array,
h: std.os.fd_t,
};
pub fn Dispatcher(comptime Obj: type, comptime Data: type) type {
const client = @hasDecl(Obj, "Event");
const Payload = if (client) Obj.Event else Obj.Request;
return struct {
pub fn dispatcher(
implementation: ?*const c_void,
object: if (client) *wayland.client.Proxy else *wayland.server.Resource,
opcode: u32,
message: *const Message,
args: [*]Argument,
) callconv(.C) c_int {
inline for (@typeInfo(Payload).Union.fields) |payload_field, payload_num| {
if (payload_num == opcode) {
var payload_data: payload_field.field_type = undefined;
inline for (@typeInfo(payload_field.field_type).Struct.fields) |f, i| {
@field(payload_data, f.name) = switch (@sizeOf(f.field_type)) {
4 => @bitCast(f.field_type, args[i].u),
8 => @ptrCast(f.field_type, args[i].s),
else => unreachable,
};
}
@ptrCast(fn (*Obj, Payload, Data) void, implementation)(
@ptrCast(*Obj, object),
@unionInit(Payload, payload_field.name, payload_data),
@intToPtr(Data, @ptrToInt(object.getUserData())),
);
return 0;
}
}
unreachable;
}
};
}