diff options
-rw-r--r-- | include/sway/commands.h | 1 | ||||
-rw-r--r-- | include/sway/server.h | 8 | ||||
-rw-r--r-- | protocols/ext-action-binder-v1.xml | 148 | ||||
-rw-r--r-- | protocols/meson.build | 1 | ||||
-rw-r--r-- | sway/action-binder-v1.c | 15 | ||||
-rw-r--r-- | sway/commands.c | 1 | ||||
-rw-r--r-- | sway/commands/action.c | 18 | ||||
-rw-r--r-- | sway/meson.build | 2 | ||||
-rw-r--r-- | sway/server.c | 11 |
9 files changed, 205 insertions, 0 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index 27058587..d9b07d79 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -104,6 +104,7 @@ struct sway_container *container_find_resize_parent(struct sway_container *con, sway_cmd cmd_exec_validate; sway_cmd cmd_exec_process; +sway_cmd cmd_action; sway_cmd cmd_assign; sway_cmd cmd_bar; sway_cmd cmd_bindcode; diff --git a/include/sway/server.h b/include/sway/server.h index b2eb2c36..39a8f557 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -113,6 +113,11 @@ struct sway_server { struct wl_listener request_set_cursor_shape; + struct wlr_action_binder_v1 *action_binder; + struct wl_listener action_binder_bind; + struct wl_listener action_binder_unbind; + struct wl_listener action_binder_destroy; + struct wl_list pending_launcher_ctxs; // launcher_ctx::link // The timeout for transactions, after which a transaction is applied @@ -174,6 +179,9 @@ void xdg_activation_v1_handle_request_activate(struct wl_listener *listener, void *data); void xdg_activation_v1_handle_new_token(struct wl_listener *listener, void *data); +void action_binder_v1_bind(struct wl_listener *listener, void *data); +void action_binder_v1_unbind(struct wl_listener *listener, void *data); +void action_binder_v1_delete(struct wl_listener *listener, void *data); void set_rr_scheduling(void); diff --git a/protocols/ext-action-binder-v1.xml b/protocols/ext-action-binder-v1.xml new file mode 100644 index 00000000..a32c4638 --- /dev/null +++ b/protocols/ext-action-binder-v1.xml @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="action_binder_v1"> + <copyright> + Copyright © 2015-2017 Quentin “Sardem FF7” Glidic, 2023 Anna "navi" Figueiredo Gomes + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, 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="ext_action_binder_v1" version="1"> + <description summary="action binder"> + This interface is designed to allow any application to bind + an action. + + An action is an arbitrary couple of a namespace and a name describing the + wanted behaviour. These two strings are not meant to be user-visible. + Some namespaces are well-known and shared by applications while each + application can have its own namespaces for internal actions. + It is possible to have the same action in several namespaces, e.g. to + allow application-specific bindings in addition to global actions. + + It is left to the compositor to determine which client will get events. + The choice can be based on policy, heuristic, user configuration, or any + other mechanism that may be relevant. + Here are some examples of dispatching choice: all applications, last + focused, user-defined preference order, latest fullscreened application. + + This interface is exposed as global + </description> + + <request name="destroy" type="destructor"> + <description summary="unbind the actions"> + The client no longer wants to receive events for any action. + </description> + </request> + + <request name="create_binding"> + <description summary="create a binding"/> + <arg name="binding" type="new_id" interface="ext_action_binding_v1" summary="the new binding" /> + </request> + </interface> + + <interface name="ext_action_binding_v1" version="1"> + <request name="destroy" type="destructor"> + <description summary="unbind the actions"> + The client no longer wants to receive events for this binding. + </description> + </request> + + <request name="set_name"> + <description summary="sets the namespace:name of a binding"> + Sets the namespace:name of the binding. This a kind of action. + </description> + <arg name="action_namespace" type="string" summary="the action namespace" /> + <arg name="action_name" type="string" summary="the action name" /> + </request> + + <request name="set_description"> + <description summary="sets the human-readable description of a binding"> + This description may be used by the compositor to render a ui for bindings. + </description> + <arg name="description" type="string" summary="a human-readable description of what the binding does" /> + </request> + + <request name="set_trigger_hint"> + <description summary="sets the machine-readable trigger of a binding"> + The trigger is a suggestion to the compositor, and the action should not rely + to being set to that specific trigger. + The client does not know which trigger was actually set, but when a binding is + bound, it recieves from the compositor a human readable string describing the trigger, + if any, so it could show it in a ui. + </description> + <arg name="preferred_trigger" type="string" summary="a trigger that the client would like to trigger the action" /> + </request> + + <request name="bind"> + <description summary="binds an action"> + Bind an action to the object. this is a one-time request. + After calling bind, either the "bound" or "rejected" event is sent. + Subsequent calls to bind should be ignored. + If no action has been set for the binding, the error "invalid_action" is raised. + </description> + </request> + + <enum name="error"> + <entry name="invalid_action" value="0" summary="the binding has no action set"/> + </enum> + + <event name="bound"> + <description summary="the compositor bound the binding to an action"> + After the compositor processes a bind request, if the action was + bound to this binding, it calls this event to notify the client of the result. + </description> + <arg name="trigger" type="string" summary="human-readable string describing the trigger for the action" /> + </event> + + <event name="rejected"> + <description summary="the compositor rejected the binding"> + After the compositor processes a bind request, if the binding was + rejected, it calls this event to notify the client of the result. + This event may be sent after a binding was bound, should the compositor + want to remove the binding. + After this event, the binding is destroyed and can't be used anymore. + </description> + </event> + + <enum name="trigger_type"> + <description summary="type of binding triggered"> + Depending on the user configuration, an action can be either one-off or + sustained. The client must handle all the three event types and either make + sense of them or ignore them properly. + </description> + <entry name="one_shot" value="0" + summary="a one shot action was triggered" /> + <entry name="pressed" value="1" + summary="a sustained action was started" /> + <entry name="released" value="2" + summary="a sustained action ended" /> + </enum> + + <event name="triggered"> + <description summary="the action triggered"> + This event is sent when actions are triggered. + If a binding would trigger both triggered and started events, the + started event must be sent first. + </description> + <arg name="type" type="uint" enum="trigger_type" summary="the type of trigger that was sent" /> + </event> + </interface> +</protocol> diff --git a/protocols/meson.build b/protocols/meson.build index 81edb584..3143fd0f 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -14,6 +14,7 @@ protocols = [ wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml', wl_protocol_dir / 'staging/content-type/content-type-v1.xml', wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', + 'ext-action-binder-v1.xml', 'wlr-layer-shell-unstable-v1.xml', 'idle.xml', 'wlr-output-power-management-unstable-v1.xml', diff --git a/sway/action-binder-v1.c b/sway/action-binder-v1.c new file mode 100644 index 00000000..bf6ffef5 --- /dev/null +++ b/sway/action-binder-v1.c @@ -0,0 +1,15 @@ +#include <wlr/types/wlr_action_binder_v1.h> + +void action_binder_v1_bind(struct wl_listener *listener, void *data) { + struct wlr_action_binder_v1_state *state = data; + struct wlr_action_binding_v1 *binding = NULL, *tmp = NULL; + wl_list_for_each_safe(binding, tmp, &state->bind_queue, link) { + wlr_action_binder_v1_bind(binding, ""); + } +} + +void action_binder_v1_unbind(struct wl_listener *listener, void *data) { +} + +void action_binder_v1_delete(struct wl_listener *listener, void *data) { +} diff --git a/sway/commands.c b/sway/commands.c index 8d003dfa..68879af7 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -112,6 +112,7 @@ static const struct cmd_handler config_handlers[] = { /* Runtime-only commands. Keep alphabetized */ static const struct cmd_handler command_handlers[] = { + { "action", cmd_action }, { "border", cmd_border }, { "create_output", cmd_create_output }, { "exit", cmd_exit }, diff --git a/sway/commands/action.c b/sway/commands/action.c new file mode 100644 index 00000000..96cb3b59 --- /dev/null +++ b/sway/commands/action.c @@ -0,0 +1,18 @@ +#include "log.h" +#include <wlr/types/wlr_action_binder_v1.h> +#include "ext-action-binder-v1-protocol.h" +#include "sway/commands.h" +#include "sway/server.h" +#include "sway/input/input-manager.h" + +struct cmd_results *cmd_action(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "action", EXPECTED_EQUAL_TO, 2))) { + return error; + } + + wlr_action_binder_v1_trigger(server.action_binder, argv[0], argv[1], + EXT_ACTION_BINDING_V1_TRIGGER_TYPE_ONE_SHOT); + + return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/meson.build b/sway/meson.build index d937e425..b24d8fbc 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -1,4 +1,5 @@ sway_sources = files( + 'action-binder-v1.c', 'commands.c', 'config.c', 'criteria.c', @@ -41,6 +42,7 @@ sway_sources = files( 'config/seat.c', 'config/input.c', + 'commands/action.c', 'commands/assign.c', 'commands/bar.c', 'commands/bind.c', diff --git a/sway/server.c b/sway/server.c index 684b1dbd..573a018b 100644 --- a/sway/server.c +++ b/sway/server.c @@ -350,6 +350,17 @@ bool server_init(struct sway_server *server) { wl_list_init(&server->pending_launcher_ctxs); + server->action_binder = wlr_action_binder_v1_create(server->wl_display); + server->action_binder_bind.notify = action_binder_v1_bind; + wl_signal_add(&server->action_binder->events.bind, + &server->action_binder_bind); + server->action_binder_unbind.notify = action_binder_v1_unbind; + wl_signal_add(&server->action_binder->events.unbind, + &server->action_binder_unbind); + server->action_binder_destroy.notify = action_binder_v1_delete; + wl_signal_add(&server->action_binder->events.destroy, + &server->action_binder_destroy); + // Avoid using "wayland-0" as display socket char name_candidate[16]; for (unsigned int i = 1; i <= 32; ++i) { |