Add callback to command request for error handling
This commit is contained in:
parent
9f35984c62
commit
4d68043045
4 changed files with 105 additions and 15 deletions
|
@ -29,12 +29,10 @@
|
|||
</description>
|
||||
<arg name="command" type="array" summary="the command to run as a series
|
||||
of null-terminated strings"/>
|
||||
<arg name="callback" type="new_id" interface="zriver_command_callback_v1"
|
||||
summary="callback object to recieve success/error events"/>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_command" value="0" summary="the command is invalid"/>
|
||||
</enum>
|
||||
|
||||
<event name="focus">
|
||||
<description summary="sent when a view gains focus">
|
||||
</description>
|
||||
|
@ -56,4 +54,27 @@
|
|||
summary="the current tags of each view on the output"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zriver_command_callback_v1" version="1">
|
||||
<description summary="callback object">
|
||||
Exactly one of the success or failure events will be sent.
|
||||
</description>
|
||||
|
||||
<event name="success">
|
||||
<description summary="command successful">
|
||||
Send when the command has been successfully received and validated by
|
||||
the server and will be carried out.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="failure">
|
||||
<description summary="command failed">
|
||||
Sent when the command could not be carried out. This could be due to
|
||||
sending a non-existent command, no command, not enough arguments, too
|
||||
many arguments, invalid arguments, etc.
|
||||
</description>
|
||||
<arg name="failure_message" type="string"
|
||||
summary="a message explaining why failure occurred"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue