diff options
-rw-r--r-- | include/river.h | 19 | ||||
-rw-r--r-- | protocols/meson.build | 3 | ||||
-rw-r--r-- | protocols/river-control-unstable-v1.xml | 86 | ||||
-rw-r--r-- | src/river.c | 38 |
4 files changed, 144 insertions, 2 deletions
diff --git a/include/river.h b/include/river.h index 881ca75..7e2bd59 100644 --- a/include/river.h +++ b/include/river.h @@ -132,6 +132,25 @@ gchar* astal_river_river_get_focused_output(AstalRiverRiver *self); gchar* astal_river_river_get_mode(AstalRiverRiver *self); +/** + * AstalRiverCommandCallback: + * @success: a #gboolean. + * @msg: a string. + * + * A callback function that gets a #GObject, a #gboolean, and a string. + */ +typedef void (*AstalRiverCommandCallback)(gboolean success, const gchar *msg); + +/** + * astal_river_river_run_command_async: + * @self: the AstalRiverRiver object + * @length: the length of the cmd array + * @cmd: (array length=length): the command to execute + * @callback: (scope async) (nullable): the callback to invoke. + * + * Calls the given callback with the provided parameters. + */ +void astal_river_river_run_command_async(AstalRiverRiver *self, gint length, const gchar **cmd, AstalRiverCommandCallback callback); diff --git a/protocols/meson.build b/protocols/meson.build index f936e37..69f01bb 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -3,6 +3,7 @@ wayland_scanner = find_program('wayland-scanner') protocols = [ 'river-status-unstable-v1.xml', + 'river-control-unstable-v1.xml' ] gen_client_header = generator(wayland_scanner, @@ -19,4 +20,4 @@ foreach protocol : protocols client_header = gen_client_header.process(protocol) code = gen_private_code.process(protocol) client_protocol_srcs += [client_header, code] -endforeach
\ No newline at end of file +endforeach diff --git a/protocols/river-control-unstable-v1.xml b/protocols/river-control-unstable-v1.xml new file mode 100644 index 0000000..c431901 --- /dev/null +++ b/protocols/river-control-unstable-v1.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="river_control_unstable_v1"> + <copyright> + Copyright 2020 The River Developers + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + </copyright> + + <interface name="zriver_control_v1" version="1"> + <description summary="run compositor commands"> + This interface allows clients to run compositor commands and receive a + success/failure response with output or a failure message respectively. + + Each command is built up in a series of add_argument requests and + executed with a run_command request. The first argument is the command + to be run. + + A complete list of commands should be made available in the man page of + the compositor. + </description> + + <request name="destroy" type="destructor"> + <description summary="destroy the river_control object"> + This request indicates that the client will not use the + river_control object any more. Objects that have been created + through this instance are not affected. + </description> + </request> + + <request name="add_argument"> + <description summary="add an argument to the current command"> + Arguments are stored by the server in the order they were sent until + the run_command request is made. + </description> + <arg name="argument" type="string" summary="the argument to add"/> + </request> + + <request name="run_command"> + <description summary="run the current command"> + Execute the command built up using the add_argument request for the + given seat. + </description> + <arg name="seat" type="object" interface="wl_seat"/> + <arg name="callback" type="new_id" interface="zriver_command_callback_v1" + summary="callback object"/> + </request> + </interface> + + <interface name="zriver_command_callback_v1" version="1"> + <description summary="callback object"> + This object is created by the run_command request. Exactly one of the + success or failure events will be sent. This object will be destroyed + by the compositor after one of the events is sent. + </description> + + <event name="success" type="destructor"> + <description summary="command successful"> + Sent when the command has been successfully received and executed by + the compositor. Some commands may produce output, in which case the + output argument will be a non-empty string. + </description> + <arg name="output" type="string" summary="the output of the command"/> + </event> + + <event name="failure" type="destructor"> + <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> + diff --git a/src/river.c b/src/river.c index 61c5c9d..e6fc26c 100644 --- a/src/river.c +++ b/src/river.c @@ -6,6 +6,7 @@ #include <wayland-client-protocol.h> #include <wayland-client.h> #include "river-status-unstable-v1-client.h" +#include "river-control-unstable-v1-client.h" #include "wayland-source.h" #include <json-glib/json-glib.h> @@ -26,6 +27,7 @@ typedef struct { struct wl_display *display; WLSource *wl_source; struct zriver_status_manager_v1 *river_status_manager; + struct zriver_control_v1 *river_control;; struct zriver_seat_status_v1 *river_seat_status; } AstalRiverRiverPrivate; @@ -224,14 +226,48 @@ static void global_registry_handler(void* data, } else if (strcmp(interface, zriver_status_manager_v1_interface.name) == 0) { priv->river_status_manager = wl_registry_bind( registry, id, &zriver_status_manager_v1_interface, 4); + } else if (strcmp(interface, zriver_control_v1_interface.name) == 0) { + priv->river_control = wl_registry_bind( + registry, id, &zriver_control_v1_interface, 1); } } +static void astal_river_river_callback_success(void *data, + struct zriver_command_callback_v1 *cb, + const char *msg) { + AstalRiverCommandCallback callback = (AstalRiverCommandCallback)(data); + callback(TRUE, msg); +} + +static void astal_river_river_callback_failure(void *data, + struct zriver_command_callback_v1 *cb, + const char *msg) { + AstalRiverCommandCallback callback = (AstalRiverCommandCallback)(data); + callback(FALSE, msg); +} + +const struct zriver_command_callback_v1_listener cb_listener = { + .success = astal_river_river_callback_success, + .failure = astal_river_river_callback_failure +}; + +void astal_river_river_run_command_async(AstalRiverRiver *self, gint length, const gchar **cmd, AstalRiverCommandCallback callback) { + AstalRiverRiverPrivate *priv = astal_river_river_get_instance_private(self); + + for(gint i = 0; i < length; ++i) { + zriver_control_v1_add_argument(priv->river_control, cmd[i]); + } + + struct zriver_command_callback_v1 *cb = zriver_control_v1_run_command(priv->river_control, priv->seat); + if(callback != NULL) + zriver_command_callback_v1_add_listener(cb, &cb_listener, callback); +} + static void global_registry_remover(void* data, struct wl_registry* registry, uint32_t id) { AstalRiverRiver *self = ASTAL_RIVER_RIVER (data); AstalRiverRiverPrivate *priv = astal_river_river_get_instance_private (self); AstalRiverOutput *output = find_output_by_id(self, id); - if ( output != NULL ) { + if ( output != NULL ) { guint signal_id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->signal_ids, GUINT_TO_POINTER (id))); g_hash_table_remove (priv->signal_ids, GUINT_TO_POINTER(id)); g_signal_handler_disconnect (output, signal_id); |