Add callback to command request for error handling
This commit is contained in:
@ -117,10 +117,21 @@ const str_to_read_fn = [_]Definition{
|
||||
};
|
||||
// zig fmt: on
|
||||
|
||||
pub const Error = error{
|
||||
NoCommand,
|
||||
UnknownCommand,
|
||||
NotEnoughArguments,
|
||||
TooManyArguments,
|
||||
Overflow,
|
||||
InvalidCharacter,
|
||||
InvalidDirection,
|
||||
OutOfMemory,
|
||||
};
|
||||
|
||||
impl: ImplFn,
|
||||
arg: Arg,
|
||||
|
||||
pub fn init(args: []const []const u8, allocator: *std.mem.Allocator) !Self {
|
||||
pub fn init(args: []const []const u8, allocator: *std.mem.Allocator) Error!Self {
|
||||
if (args.len == 0) return error.NoCommand;
|
||||
const name = args[0];
|
||||
|
||||
|
@ -74,7 +74,12 @@ fn resourceDestroy(wl_resource: ?*c.wl_resource) callconv(.C) void {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fn runCommand(wl_client: ?*c.wl_client, wl_resource: ?*c.wl_resource, wl_array: ?*c.wl_array) callconv(.C) void {
|
||||
fn runCommand(
|
||||
wl_client: ?*c.wl_client,
|
||||
wl_resource: ?*c.wl_resource,
|
||||
wl_array: ?*c.wl_array,
|
||||
callback_id: u32,
|
||||
) callconv(.C) void {
|
||||
const self = @ptrCast(*Self, @alignCast(@alignOf(*Self), c.wl_resource_get_user_data(wl_resource)));
|
||||
const allocator = self.server.allocator;
|
||||
|
||||
@ -89,11 +94,34 @@ fn runCommand(wl_client: ?*c.wl_client, wl_resource: ?*c.wl_resource, wl_array:
|
||||
i += slice.len + 1;
|
||||
}
|
||||
|
||||
for (args.items) |x| {
|
||||
std.debug.warn("{}\n", .{x});
|
||||
}
|
||||
const callback_resource = c.wl_resource_create(
|
||||
wl_client,
|
||||
&c.zriver_command_callback_v1_interface,
|
||||
protocol_version,
|
||||
callback_id,
|
||||
) orelse {
|
||||
c.wl_client_post_no_memory(wl_client);
|
||||
return;
|
||||
};
|
||||
|
||||
// TODO: send the error event on failure instead of crashing
|
||||
const command = Command.init(args.items, allocator) catch unreachable;
|
||||
c.wl_resource_set_implementation(callback_resource, null, null, null);
|
||||
|
||||
const command = Command.init(args.items, allocator) catch |err| {
|
||||
c.zriver_command_callback_v1_send_failure(
|
||||
callback_resource,
|
||||
switch (err) {
|
||||
Command.Error.NoCommand => "no command given",
|
||||
Command.Error.UnknownCommand => "unknown command",
|
||||
Command.Error.NotEnoughArguments => "not enough arguments",
|
||||
Command.Error.TooManyArguments => "too many arguments",
|
||||
Command.Error.Overflow => "value out of bounds",
|
||||
Command.Error.InvalidCharacter => "invalid character in argument",
|
||||
Command.Error.InvalidDirection => "invalid direction. Must be 'next' or 'previous'",
|
||||
Command.Error.OutOfMemory => unreachable,
|
||||
},
|
||||
);
|
||||
return;
|
||||
};
|
||||
c.zriver_command_callback_v1_send_success(callback_resource);
|
||||
command.run(self.server.input_manager.default_seat);
|
||||
}
|
||||
|
@ -27,14 +27,20 @@ const wl_registry_listener = c.wl_registry_listener{
|
||||
.global_remove = handleGlobalRemove,
|
||||
};
|
||||
|
||||
const command_callback_listener = c.zriver_command_callback_v1_listener{
|
||||
.success = handleSuccess,
|
||||
.failure = handleFailure,
|
||||
};
|
||||
|
||||
var river_window_manager: ?*c.zriver_window_manager_v1 = null;
|
||||
|
||||
pub fn main() !void {
|
||||
const wl_display = c.wl_display_connect(null) orelse return error.CantConnectToDisplay;
|
||||
const wl_registry = c.wl_display_get_registry(wl_display);
|
||||
|
||||
_ = c.wl_registry_add_listener(wl_registry, &wl_registry_listener, null);
|
||||
if (c.wl_display_roundtrip(wl_display) == -1) return error.RoundtripFailed;
|
||||
if (c.wl_registry_add_listener(wl_registry, &wl_registry_listener, null) < 0)
|
||||
return error.FailedToAddListener;
|
||||
if (c.wl_display_roundtrip(wl_display) < 0) return error.RoundtripFailed;
|
||||
|
||||
const wm = river_window_manager orelse return error.RiverWMNotAdvertised;
|
||||
|
||||
@ -51,8 +57,15 @@ pub fn main() !void {
|
||||
ptr[arg.len] = 0;
|
||||
}
|
||||
|
||||
c.zriver_window_manager_v1_run_command(wm, &command);
|
||||
if (c.wl_display_roundtrip(wl_display) == -1) return error.RoundtripFailed;
|
||||
const command_callback = c.zriver_window_manager_v1_run_command(wm, &command);
|
||||
if (c.zriver_command_callback_v1_add_listener(
|
||||
command_callback,
|
||||
&command_callback_listener,
|
||||
null,
|
||||
) < 0) return error.FailedToAddListener;
|
||||
|
||||
// Loop until our callback is called and we exit.
|
||||
while (true) if (c.wl_display_dispatch(wl_display) < 0) return error.DispatchFailed;
|
||||
}
|
||||
|
||||
fn handleGlobal(
|
||||
@ -77,3 +90,20 @@ fn handleGlobal(
|
||||
|
||||
/// Ignore the event
|
||||
fn handleGlobalRemove(data: ?*c_void, wl_registry: ?*c.wl_registry, name: u32) callconv(.C) void {}
|
||||
|
||||
/// On success we simply exit with a clean exit code
|
||||
fn handleSuccess(data: ?*c_void, callback: ?*c.zriver_command_callback_v1) callconv(.C) void {
|
||||
std.os.exit(0);
|
||||
}
|
||||
|
||||
/// Print the failure message and exit non-zero
|
||||
fn handleFailure(
|
||||
data: ?*c_void,
|
||||
callback: ?*c.zriver_command_callback_v1,
|
||||
failure_message: ?[*:0]const u8,
|
||||
) callconv(.C) void {
|
||||
if (failure_message) |message| {
|
||||
std.debug.warn("Error: {}\n", .{failure_message});
|
||||
}
|
||||
std.os.exit(1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user