summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/river.h19
-rw-r--r--protocols/meson.build3
-rw-r--r--protocols/river-control-unstable-v1.xml86
-rw-r--r--src/river.c38
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);