From 72767e1cc302e7aee9645c1eae3f51abe53fb378 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 24 Apr 2018 14:59:49 +1000 Subject: Implement criteria commands Implements the following commands: * for_window [...] * assign [...] --- sway/commands.c | 2 ++ sway/commands/assign.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++ sway/commands/for_window.c | 41 +++++++++++++++++++++++++++++++++ sway/meson.build | 2 ++ sway/tree/view.c | 27 ++++++++++++++++++++++ 5 files changed, 129 insertions(+) create mode 100644 sway/commands/assign.c create mode 100644 sway/commands/for_window.c diff --git a/sway/commands.c b/sway/commands.c index 6af3c5d0..5827fc13 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -93,12 +93,14 @@ void apply_seat_config(struct seat_config *seat_config) { /* Keep alphabetized */ static struct cmd_handler handlers[] = { + { "assign", cmd_assign }, { "bar", cmd_bar }, { "bindcode", cmd_bindcode }, { "bindsym", cmd_bindsym }, { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, { "focus_follows_mouse", cmd_focus_follows_mouse }, + { "for_window", cmd_for_window }, { "fullscreen", cmd_fullscreen }, { "include", cmd_include }, { "input", cmd_input }, diff --git a/sway/commands/assign.c b/sway/commands/assign.c new file mode 100644 index 00000000..bf0b1f63 --- /dev/null +++ b/sway/commands/assign.c @@ -0,0 +1,57 @@ +#define _XOPEN_SOURCE 700 +#include +#include +#include "sway/commands.h" +#include "sway/criteria.h" +#include "list.h" +#include "log.h" + +struct cmd_results *cmd_assign(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "assign", EXPECTED_AT_LEAST, 2))) { + return error; + } + + char *criteria = *argv++; + + if (strncmp(*argv, "→", strlen("→")) == 0) { + if (argc < 3) { + return cmd_results_new(CMD_INVALID, "assign", "Missing workspace"); + } + argv++; + } + + char *movecmd = "move container to workspace "; + int arglen = strlen(movecmd) + strlen(*argv) + 1; + char *cmdlist = calloc(1, arglen); + if (!cmdlist) { + return cmd_results_new(CMD_FAILURE, "assign", "Unable to allocate command list"); + } + snprintf(cmdlist, arglen, "%s%s", movecmd, *argv); + + struct criteria *crit = malloc(sizeof(struct criteria)); + if (!crit) { + free(cmdlist); + return cmd_results_new(CMD_FAILURE, "assign", "Unable to allocate criteria"); + } + crit->crit_raw = strdup(criteria); + crit->cmdlist = cmdlist; + crit->tokens = create_list(); + char *err_str = extract_crit_tokens(crit->tokens, crit->crit_raw); + + if (err_str) { + error = cmd_results_new(CMD_INVALID, "assign", err_str); + free(err_str); + free_criteria(crit); + } else if (crit->tokens->length == 0) { + error = cmd_results_new(CMD_INVALID, "assign", "Found no name/value pairs in criteria"); + free_criteria(crit); + } else if (list_seq_find(config->criteria, criteria_cmp, crit) != -1) { + wlr_log(L_DEBUG, "assign: Duplicate, skipping."); + free_criteria(crit); + } else { + wlr_log(L_DEBUG, "assign: '%s' -> '%s' added", crit->crit_raw, crit->cmdlist); + list_add(config->criteria, crit); + } + return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/for_window.c b/sway/commands/for_window.c new file mode 100644 index 00000000..a6aa7187 --- /dev/null +++ b/sway/commands/for_window.c @@ -0,0 +1,41 @@ +#define _XOPEN_SOURCE 500 +#include +#include "sway/commands.h" +#include "sway/criteria.h" +#include "list.h" +#include "log.h" +#include "stringop.h" + +struct cmd_results *cmd_for_window(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "for_window", EXPECTED_AT_LEAST, 2))) { + return error; + } + // add command to a criteria/command pair that is run against views when they appear. + char *criteria = argv[0], *cmdlist = join_args(argv + 1, argc - 1); + + struct criteria *crit = malloc(sizeof(struct criteria)); + if (!crit) { + return cmd_results_new(CMD_FAILURE, "for_window", "Unable to allocate criteria"); + } + crit->crit_raw = strdup(criteria); + crit->cmdlist = cmdlist; + crit->tokens = create_list(); + char *err_str = extract_crit_tokens(crit->tokens, crit->crit_raw); + + if (err_str) { + error = cmd_results_new(CMD_INVALID, "for_window", err_str); + free(err_str); + free_criteria(crit); + } else if (crit->tokens->length == 0) { + error = cmd_results_new(CMD_INVALID, "for_window", "Found no name/value pairs in criteria"); + free_criteria(crit); + } else if (list_seq_find(config->criteria, criteria_cmp, crit) != -1) { + wlr_log(L_DEBUG, "for_window: Duplicate, skipping."); + free_criteria(crit); + } else { + wlr_log(L_DEBUG, "for_window: '%s' -> '%s' added", crit->crit_raw, crit->cmdlist); + list_add(config->criteria, crit); + } + return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/meson.build b/sway/meson.build index f3c319ed..a8107e4e 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -26,6 +26,7 @@ sway_sources = files( 'config/seat.c', 'config/input.c', + 'commands/assign.c', 'commands/bar.c', 'commands/bind.c', 'commands/default_orientation.c', @@ -34,6 +35,7 @@ sway_sources = files( 'commands/exec_always.c', 'commands/focus.c', 'commands/focus_follows_mouse.c', + 'commands/for_window.c', 'commands/fullscreen.c', 'commands/kill.c', 'commands/opacity.c', diff --git a/sway/tree/view.c b/sway/tree/view.c index 92767188..7c3b4049 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -2,8 +2,11 @@ #include #include #include "log.h" +#include "sway/criteria.h" +#include "sway/commands.h" #include "sway/ipc-server.h" #include "sway/output.h" +#include "sway/input/seat.h" #include "sway/tree/container.h" #include "sway/tree/layout.h" #include "sway/tree/view.h" @@ -208,6 +211,28 @@ static void view_handle_container_reparent(struct wl_listener *listener, } } +static void view_execute_criteria(struct sway_view *view) { + struct sway_seat *seat = input_manager_current_seat(input_manager); + struct sway_container *prior_workspace = + container_parent(view->swayc, C_WORKSPACE); + list_t *criteria = criteria_for(view->swayc); + for (int i = 0; i < criteria->length; i++) { + struct criteria *crit = criteria->items[i]; + wlr_log(L_DEBUG, "for_window '%s' matches new view %p, cmd: '%s'", + crit->crit_raw, view, crit->cmdlist); + struct cmd_results *res = execute_command(crit->cmdlist, NULL); + if (res->status != CMD_SUCCESS) { + wlr_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); + } + free_cmd_results(res); + // view must be focused for commands to affect it, + // so always refocus in-between command lists + seat_set_focus(seat, view->swayc); + } + list_free(criteria); + seat_set_focus(seat, seat_get_focus_inactive(seat, prior_workspace)); +} + void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { return; @@ -234,6 +259,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { view_damage(view, true); view_handle_container_reparent(&view->container_reparent, NULL); + + view_execute_criteria(view); } void view_unmap(struct sway_view *view) { -- cgit v1.2.3-54-g00ecf From 30a74889366baf4b98bb3d398042508fe07a9906 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 24 Apr 2018 20:06:35 +1000 Subject: Add assert to view_execute_criteria() --- sway/tree/view.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sway/tree/view.c b/sway/tree/view.c index 7c3b4049..3d22d3e4 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -212,6 +212,9 @@ static void view_handle_container_reparent(struct wl_listener *listener, } static void view_execute_criteria(struct sway_view *view) { + if (!sway_assert(view->swayc, "cannot run criteria for unmanaged view")) { + return; + } struct sway_seat *seat = input_manager_current_seat(input_manager); struct sway_container *prior_workspace = container_parent(view->swayc, C_WORKSPACE); -- cgit v1.2.3-54-g00ecf From 689a6a5605fb52f40b2c13f7565e19334fd09842 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 24 Apr 2018 20:07:09 +1000 Subject: Use size_t instead of int and calloc instead of malloc --- sway/commands/assign.c | 2 +- sway/commands/for_window.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/commands/assign.c b/sway/commands/assign.c index bf0b1f63..eb7329aa 100644 --- a/sway/commands/assign.c +++ b/sway/commands/assign.c @@ -22,7 +22,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) { } char *movecmd = "move container to workspace "; - int arglen = strlen(movecmd) + strlen(*argv) + 1; + size_t arglen = strlen(movecmd) + strlen(*argv) + 1; char *cmdlist = calloc(1, arglen); if (!cmdlist) { return cmd_results_new(CMD_FAILURE, "assign", "Unable to allocate command list"); diff --git a/sway/commands/for_window.c b/sway/commands/for_window.c index a6aa7187..dd5461f0 100644 --- a/sway/commands/for_window.c +++ b/sway/commands/for_window.c @@ -14,7 +14,7 @@ struct cmd_results *cmd_for_window(int argc, char **argv) { // add command to a criteria/command pair that is run against views when they appear. char *criteria = argv[0], *cmdlist = join_args(argv + 1, argc - 1); - struct criteria *crit = malloc(sizeof(struct criteria)); + struct criteria *crit = calloc(sizeof(struct criteria), 1); if (!crit) { return cmd_results_new(CMD_FAILURE, "for_window", "Unable to allocate criteria"); } -- cgit v1.2.3-54-g00ecf From dfc26c664f8c1b007f15ff24a3055774af200c69 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 24 Apr 2018 20:14:22 +1000 Subject: Update wording about unmanaged/unmapped views --- include/sway/tree/view.h | 2 +- sway/tree/view.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 648a74c4..7237ea2a 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -39,7 +39,7 @@ struct sway_view { enum sway_view_type type; const struct sway_view_impl *impl; - struct sway_container *swayc; // NULL for unmanaged views + struct sway_container *swayc; // NULL for unmapped views struct wlr_surface *surface; // NULL for unmapped views int width, height; bool is_fullscreen; diff --git a/sway/tree/view.c b/sway/tree/view.c index 3d22d3e4..3eeb1d97 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -212,7 +212,7 @@ static void view_handle_container_reparent(struct wl_listener *listener, } static void view_execute_criteria(struct sway_view *view) { - if (!sway_assert(view->swayc, "cannot run criteria for unmanaged view")) { + if (!sway_assert(view->swayc, "cannot run criteria for unmapped view")) { return; } struct sway_seat *seat = input_manager_current_seat(input_manager); -- cgit v1.2.3-54-g00ecf