From b89684182415d39e083abd727647874e8202641e Mon Sep 17 00:00:00 2001 From: Florian Franzen Date: Thu, 20 Jan 2022 22:12:09 +0100 Subject: [PATCH 1/2] sway/bar: add bindgesture support --- include/sway/commands.h | 2 + include/sway/config.h | 8 +++ sway/commands/bar.c | 2 + sway/commands/bar/gesture.c | 109 ++++++++++++++++++++++++++++++++++++ sway/config/bar.c | 17 ++++++ sway/ipc-json.c | 19 +++++++ sway/meson.build | 1 + sway/sway-bar.5.scd | 11 ++++ 8 files changed, 169 insertions(+) create mode 100644 sway/commands/bar/gesture.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 5f71a79db..5e48b22f1 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -202,6 +202,7 @@ sway_cmd cmd_ws_auto_back_and_forth; sway_cmd cmd_xwayland; sway_cmd bar_cmd_bindcode; +sway_cmd bar_cmd_bindgesture; sway_cmd bar_cmd_binding_mode_indicator; sway_cmd bar_cmd_bindsym; sway_cmd bar_cmd_colors; @@ -228,6 +229,7 @@ sway_cmd bar_cmd_tray_bindsym; sway_cmd bar_cmd_tray_output; sway_cmd bar_cmd_tray_padding; sway_cmd bar_cmd_unbindcode; +sway_cmd bar_cmd_unbindgesture; sway_cmd bar_cmd_unbindsym; sway_cmd bar_cmd_wrap_scroll; sway_cmd bar_cmd_workspace_buttons; diff --git a/include/sway/config.h b/include/sway/config.h index 05678c334..c9b0b26bb 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -355,6 +355,7 @@ struct bar_config { list_t *outputs; char *position; list_t *bindings; + list_t *gestures; char *status_command; enum pango_markup_config pango_markup; char *font; @@ -408,6 +409,11 @@ struct bar_binding { char *command; }; +struct bar_gesture { + struct gesture gesture; + char *command; +}; + #if HAVE_TRAY struct tray_binding { uint32_t button; @@ -717,6 +723,8 @@ void free_bar_config(struct bar_config *bar); void free_bar_binding(struct bar_binding *binding); +void free_bar_gesture(struct bar_gesture *binding); + void free_workspace_config(struct workspace_config *wsc); /** diff --git a/sway/commands/bar.c b/sway/commands/bar.c index 8571d282c..8a47dc34c 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -10,6 +10,7 @@ // Must be in alphabetical order for bsearch static const struct cmd_handler bar_handlers[] = { { "bindcode", bar_cmd_bindcode }, + { "bindgesture", bar_cmd_bindgesture }, { "binding_mode_indicator", bar_cmd_binding_mode_indicator }, { "bindsym", bar_cmd_bindsym }, { "colors", bar_cmd_colors }, @@ -34,6 +35,7 @@ static const struct cmd_handler bar_handlers[] = { { "tray_output", bar_cmd_tray_output }, { "tray_padding", bar_cmd_tray_padding }, { "unbindcode", bar_cmd_unbindcode }, + { "unbindgesture", bar_cmd_unbindgesture }, { "unbindsym", bar_cmd_unbindsym }, { "workspace_buttons", bar_cmd_workspace_buttons }, { "workspace_min_width", bar_cmd_workspace_min_width }, diff --git a/sway/commands/bar/gesture.c b/sway/commands/bar/gesture.c new file mode 100644 index 000000000..9cf48e003 --- /dev/null +++ b/sway/commands/bar/gesture.c @@ -0,0 +1,109 @@ +#define _POSIX_C_SOURCE 200809L +#include "sway/config.h" + +#include +#include "log.h" +#include "stringop.h" +#include "sway/commands.h" + +/** + * Add gesture binding to config + */ +static struct cmd_results *bar_gesture_add( + struct bar_gesture *binding, const char *name) { + list_t *gestures = config->current_bar->gestures; + + // overwrite the binding if it already exists + bool overwritten = false; + for (int i = 0; i < gestures->length; ++i) { + struct bar_gesture *current = gestures->items[i]; + if (gesture_equal(¤t->gesture, &binding->gesture)) { + + overwritten = true; + gestures->items[i] = binding; + free_bar_gesture(current); + sway_log(SWAY_DEBUG, "[bar %s] Updated gesture for %s", + config->current_bar->id, name); + break; + } + } + + if (!overwritten) { + list_add(gestures, binding); + sway_log(SWAY_DEBUG, "[bar %s] Added binding for %s", + config->current_bar->id, name); + } + + return cmd_results_new(CMD_SUCCESS, NULL); +} + +/** + * Remove gesture binding from config + */ +static struct cmd_results *bar_gesture_remove( + struct bar_gesture *binding, const char *name) { + list_t *gestures = config->current_bar->gestures; + + for (int i = 0; i < gestures->length; ++i) { + struct bar_gesture *current = gestures->items[i]; + if (gesture_equal(¤t->gesture, &binding->gesture)) { + sway_log(SWAY_DEBUG, "[bar %s] Unbound binding for %s", + config->current_bar->id, name); + + free_bar_gesture(current); + free_bar_gesture(binding); + list_del(gestures, i); + + return cmd_results_new(CMD_SUCCESS, NULL); + } + } + + free_bar_gesture(binding); + return cmd_results_new(CMD_FAILURE, + "Could not find gesture for [bar %s] %s", + config->current_bar->id, name); +} + +/** + * Parse and execute bindgesture or unbindgesture command. + */ +static struct cmd_results *bar_cmd_gesture(int argc, char **argv, bool unbind) { + int minargs = 2; + char *bindtype = "bindgesture"; + if (unbind) { + minargs--; + bindtype = "unbindgesture"; + } + + struct cmd_results *error = NULL; + if ((error = checkarg(argc, bindtype, EXPECTED_AT_LEAST, minargs))) { + return error; + } + + struct bar_gesture *binding = calloc(1, sizeof(struct bar_gesture)); + if (!binding) { + return cmd_results_new(CMD_FAILURE, "Unable to allocate binding"); + } + char *errmsg = NULL; + if ((errmsg = gesture_parse(argv[0], &binding->gesture))) { + free(binding); + struct cmd_results *final = cmd_results_new( + CMD_FAILURE, "Invalid %s command (%s)", bindtype, errmsg); + free(errmsg); + return final; + } + + if (unbind) { + return bar_gesture_remove(binding, argv[0]); + } + binding->command = join_args(argv + 1, argc - 1); + return bar_gesture_add(binding, argv[0]); +} + +struct cmd_results *bar_cmd_bindgesture(int argc, char **argv) { + return bar_cmd_gesture(argc, argv, false); +} + +struct cmd_results *bar_cmd_unbindgesture(int argc, char **argv) { + return bar_cmd_gesture(argc, argv, true); +} diff --git a/sway/config/bar.c b/sway/config/bar.c index d1b342e69..4c567a397 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -27,6 +27,14 @@ void free_bar_binding(struct bar_binding *binding) { free(binding); } +void free_bar_gesture(struct bar_gesture *gesture) { + if (!gesture) { + return; + } + free(gesture->command); + free(gesture); +} + void free_bar_config(struct bar_config *bar) { if (!bar) { return; @@ -45,6 +53,12 @@ void free_bar_config(struct bar_config *bar) { } } list_free(bar->bindings); + if (bar->gestures) { + for (int i = 0; i < bar->gestures->length; i++) { + free_bar_gesture(bar->gestures->items[i]); + } + } + list_free(bar->gestures); list_free_items_and_destroy(bar->outputs); if (bar->client != NULL) { wl_client_destroy(bar->client); @@ -115,6 +129,9 @@ struct bar_config *default_bar_config(void) { if (!(bar->bindings = create_list())) { goto cleanup; } + if (!(bar->gestures = create_list())) { + goto cleanup; + } // set default colors if (!(bar->colors.background = strndup("#000000ff", 9))) { goto cleanup; diff --git a/sway/ipc-json.c b/sway/ipc-json.c index e682bc362..79cd52f59 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -1241,6 +1241,25 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { json_object_object_add(json, "bindings", bindings); } + if (bar->gestures->length > 0) { + json_object *gestures = json_object_new_array(); + for (int i = 0; i < bar->gestures->length; ++i) { + struct bar_gesture *binding = bar->gestures->items[i]; + struct gesture *gesture = &binding->gesture; + json_object *bind = json_object_new_object(); + json_object_object_add(bind, "type", + json_object_new_int(gesture->type)); + json_object_object_add(bind, "fingers", + json_object_new_int(gesture->fingers)); + json_object_object_add(bind, "directions", + json_object_new_int(gesture->directions)); + json_object_object_add(bind, "command", + json_object_new_string(binding->command)); + json_object_array_add(gestures, bind); + } + json_object_object_add(json, "gestures", gestures); + } + // Add outputs if defined if (bar->outputs && bar->outputs->length > 0) { json_object *outputs = json_object_new_array(); diff --git a/sway/meson.build b/sway/meson.build index 5dd9cad2f..4b10ba6fe 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -128,6 +128,7 @@ sway_sources = files( 'commands/bar/colors.c', 'commands/bar/font.c', 'commands/bar/gaps.c', + 'commands/bar/gesture.c', 'commands/bar/height.c', 'commands/bar/hidden_state.c', 'commands/bar/icon_theme.c', diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd index 42e59d57d..6700ce1eb 100644 --- a/sway/sway-bar.5.scd +++ b/sway/sway-bar.5.scd @@ -27,6 +27,14 @@ runtime. an event code, which can be obtaining from *libinput debug-events*. To disable the default behavior for a button, use the command _nop_. +*bindgesture* [:][:directions] + Executes _command_ when the _gesture_ has been detected. _gesture_ can be + _hold_, _pinch_ or _swipe_. The optional _fingers_ allows you to limit the + binding to gestures with only a certain number of finger. The optional + _directions_ allows you to limit the binding to a gesture in a certain + direction, i.e. either _up_, _down_, _left_ or _right_ as well as + _inward_, _outward_, _clockwise_ and _counterclockwise_. + *bindsym* [--release] button[1-9]| Executes _command_ when the mouse button has been pressed (or if _released_ is given, when the button has been released). The buttons can be given as a @@ -128,6 +136,9 @@ runtime. *unbindcode* [--release] Removes the binding with the given . +*unbindgesture* [:][:directions] + Removes the gesture binding with the given , etc. + *unbindsym* [--release] button[1-9]| Removes the binding with the given