diff options
author | emersion <contact@emersion.fr> | 2018-04-25 22:52:01 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-25 22:52:01 +0100 |
commit | 7ac770f3c0d4aa4b38650ad5ec7d1f5b7e70028a (patch) | |
tree | ec248905f4c73d8f52c3e2c08ce26decbda2d704 | |
parent | Merge pull request #1861 from emersion/swaybar-memory-leaks (diff) | |
parent | Merge branch 'master' into criteria-commands (diff) | |
download | sway-7ac770f3c0d4aa4b38650ad5ec7d1f5b7e70028a.tar.gz sway-7ac770f3c0d4aa4b38650ad5ec7d1f5b7e70028a.tar.zst sway-7ac770f3c0d4aa4b38650ad5ec7d1f5b7e70028a.zip |
Merge pull request #1852 from RyanDwyer/criteria-commands
Implement criteria commands
-rw-r--r-- | include/sway/tree/view.h | 2 | ||||
-rw-r--r-- | sway/commands.c | 2 | ||||
-rw-r--r-- | sway/commands/assign.c | 57 | ||||
-rw-r--r-- | sway/commands/for_window.c | 41 | ||||
-rw-r--r-- | sway/meson.build | 2 | ||||
-rw-r--r-- | sway/tree/view.c | 30 |
6 files changed, 133 insertions, 1 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 { | |||
39 | enum sway_view_type type; | 39 | enum sway_view_type type; |
40 | const struct sway_view_impl *impl; | 40 | const struct sway_view_impl *impl; |
41 | 41 | ||
42 | struct sway_container *swayc; // NULL for unmanaged views | 42 | struct sway_container *swayc; // NULL for unmapped views |
43 | struct wlr_surface *surface; // NULL for unmapped views | 43 | struct wlr_surface *surface; // NULL for unmapped views |
44 | int width, height; | 44 | int width, height; |
45 | bool is_fullscreen; | 45 | bool is_fullscreen; |
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) { | |||
93 | 93 | ||
94 | /* Keep alphabetized */ | 94 | /* Keep alphabetized */ |
95 | static struct cmd_handler handlers[] = { | 95 | static struct cmd_handler handlers[] = { |
96 | { "assign", cmd_assign }, | ||
96 | { "bar", cmd_bar }, | 97 | { "bar", cmd_bar }, |
97 | { "bindcode", cmd_bindcode }, | 98 | { "bindcode", cmd_bindcode }, |
98 | { "bindsym", cmd_bindsym }, | 99 | { "bindsym", cmd_bindsym }, |
99 | { "exec", cmd_exec }, | 100 | { "exec", cmd_exec }, |
100 | { "exec_always", cmd_exec_always }, | 101 | { "exec_always", cmd_exec_always }, |
101 | { "focus_follows_mouse", cmd_focus_follows_mouse }, | 102 | { "focus_follows_mouse", cmd_focus_follows_mouse }, |
103 | { "for_window", cmd_for_window }, | ||
102 | { "fullscreen", cmd_fullscreen }, | 104 | { "fullscreen", cmd_fullscreen }, |
103 | { "include", cmd_include }, | 105 | { "include", cmd_include }, |
104 | { "input", cmd_input }, | 106 | { "input", cmd_input }, |
diff --git a/sway/commands/assign.c b/sway/commands/assign.c new file mode 100644 index 00000000..eb7329aa --- /dev/null +++ b/sway/commands/assign.c | |||
@@ -0,0 +1,57 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <stdio.h> | ||
3 | #include <string.h> | ||
4 | #include "sway/commands.h" | ||
5 | #include "sway/criteria.h" | ||
6 | #include "list.h" | ||
7 | #include "log.h" | ||
8 | |||
9 | struct cmd_results *cmd_assign(int argc, char **argv) { | ||
10 | struct cmd_results *error = NULL; | ||
11 | if ((error = checkarg(argc, "assign", EXPECTED_AT_LEAST, 2))) { | ||
12 | return error; | ||
13 | } | ||
14 | |||
15 | char *criteria = *argv++; | ||
16 | |||
17 | if (strncmp(*argv, "→", strlen("→")) == 0) { | ||
18 | if (argc < 3) { | ||
19 | return cmd_results_new(CMD_INVALID, "assign", "Missing workspace"); | ||
20 | } | ||
21 | argv++; | ||
22 | } | ||
23 | |||
24 | char *movecmd = "move container to workspace "; | ||
25 | size_t arglen = strlen(movecmd) + strlen(*argv) + 1; | ||
26 | char *cmdlist = calloc(1, arglen); | ||
27 | if (!cmdlist) { | ||
28 | return cmd_results_new(CMD_FAILURE, "assign", "Unable to allocate command list"); | ||
29 | } | ||
30 | snprintf(cmdlist, arglen, "%s%s", movecmd, *argv); | ||
31 | |||
32 | struct criteria *crit = malloc(sizeof(struct criteria)); | ||
33 | if (!crit) { | ||
34 | free(cmdlist); | ||
35 | return cmd_results_new(CMD_FAILURE, "assign", "Unable to allocate criteria"); | ||
36 | } | ||
37 | crit->crit_raw = strdup(criteria); | ||
38 | crit->cmdlist = cmdlist; | ||
39 | crit->tokens = create_list(); | ||
40 | char *err_str = extract_crit_tokens(crit->tokens, crit->crit_raw); | ||
41 | |||
42 | if (err_str) { | ||
43 | error = cmd_results_new(CMD_INVALID, "assign", err_str); | ||
44 | free(err_str); | ||
45 | free_criteria(crit); | ||
46 | } else if (crit->tokens->length == 0) { | ||
47 | error = cmd_results_new(CMD_INVALID, "assign", "Found no name/value pairs in criteria"); | ||
48 | free_criteria(crit); | ||
49 | } else if (list_seq_find(config->criteria, criteria_cmp, crit) != -1) { | ||
50 | wlr_log(L_DEBUG, "assign: Duplicate, skipping."); | ||
51 | free_criteria(crit); | ||
52 | } else { | ||
53 | wlr_log(L_DEBUG, "assign: '%s' -> '%s' added", crit->crit_raw, crit->cmdlist); | ||
54 | list_add(config->criteria, crit); | ||
55 | } | ||
56 | return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
57 | } | ||
diff --git a/sway/commands/for_window.c b/sway/commands/for_window.c new file mode 100644 index 00000000..dd5461f0 --- /dev/null +++ b/sway/commands/for_window.c | |||
@@ -0,0 +1,41 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
2 | #include <string.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/criteria.h" | ||
5 | #include "list.h" | ||
6 | #include "log.h" | ||
7 | #include "stringop.h" | ||
8 | |||
9 | struct cmd_results *cmd_for_window(int argc, char **argv) { | ||
10 | struct cmd_results *error = NULL; | ||
11 | if ((error = checkarg(argc, "for_window", EXPECTED_AT_LEAST, 2))) { | ||
12 | return error; | ||
13 | } | ||
14 | // add command to a criteria/command pair that is run against views when they appear. | ||
15 | char *criteria = argv[0], *cmdlist = join_args(argv + 1, argc - 1); | ||
16 | |||
17 | struct criteria *crit = calloc(sizeof(struct criteria), 1); | ||
18 | if (!crit) { | ||
19 | return cmd_results_new(CMD_FAILURE, "for_window", "Unable to allocate criteria"); | ||
20 | } | ||
21 | crit->crit_raw = strdup(criteria); | ||
22 | crit->cmdlist = cmdlist; | ||
23 | crit->tokens = create_list(); | ||
24 | char *err_str = extract_crit_tokens(crit->tokens, crit->crit_raw); | ||
25 | |||
26 | if (err_str) { | ||
27 | error = cmd_results_new(CMD_INVALID, "for_window", err_str); | ||
28 | free(err_str); | ||
29 | free_criteria(crit); | ||
30 | } else if (crit->tokens->length == 0) { | ||
31 | error = cmd_results_new(CMD_INVALID, "for_window", "Found no name/value pairs in criteria"); | ||
32 | free_criteria(crit); | ||
33 | } else if (list_seq_find(config->criteria, criteria_cmp, crit) != -1) { | ||
34 | wlr_log(L_DEBUG, "for_window: Duplicate, skipping."); | ||
35 | free_criteria(crit); | ||
36 | } else { | ||
37 | wlr_log(L_DEBUG, "for_window: '%s' -> '%s' added", crit->crit_raw, crit->cmdlist); | ||
38 | list_add(config->criteria, crit); | ||
39 | } | ||
40 | return error ? error : cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
41 | } | ||
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( | |||
26 | 'config/seat.c', | 26 | 'config/seat.c', |
27 | 'config/input.c', | 27 | 'config/input.c', |
28 | 28 | ||
29 | 'commands/assign.c', | ||
29 | 'commands/bar.c', | 30 | 'commands/bar.c', |
30 | 'commands/bind.c', | 31 | 'commands/bind.c', |
31 | 'commands/default_orientation.c', | 32 | 'commands/default_orientation.c', |
@@ -34,6 +35,7 @@ sway_sources = files( | |||
34 | 'commands/exec_always.c', | 35 | 'commands/exec_always.c', |
35 | 'commands/focus.c', | 36 | 'commands/focus.c', |
36 | 'commands/focus_follows_mouse.c', | 37 | 'commands/focus_follows_mouse.c', |
38 | 'commands/for_window.c', | ||
37 | 'commands/fullscreen.c', | 39 | 'commands/fullscreen.c', |
38 | 'commands/kill.c', | 40 | 'commands/kill.c', |
39 | 'commands/opacity.c', | 41 | 'commands/opacity.c', |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 92767188..3eeb1d97 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -2,8 +2,11 @@ | |||
2 | #include <wayland-server.h> | 2 | #include <wayland-server.h> |
3 | #include <wlr/types/wlr_output_layout.h> | 3 | #include <wlr/types/wlr_output_layout.h> |
4 | #include "log.h" | 4 | #include "log.h" |
5 | #include "sway/criteria.h" | ||
6 | #include "sway/commands.h" | ||
5 | #include "sway/ipc-server.h" | 7 | #include "sway/ipc-server.h" |
6 | #include "sway/output.h" | 8 | #include "sway/output.h" |
9 | #include "sway/input/seat.h" | ||
7 | #include "sway/tree/container.h" | 10 | #include "sway/tree/container.h" |
8 | #include "sway/tree/layout.h" | 11 | #include "sway/tree/layout.h" |
9 | #include "sway/tree/view.h" | 12 | #include "sway/tree/view.h" |
@@ -208,6 +211,31 @@ static void view_handle_container_reparent(struct wl_listener *listener, | |||
208 | } | 211 | } |
209 | } | 212 | } |
210 | 213 | ||
214 | static void view_execute_criteria(struct sway_view *view) { | ||
215 | if (!sway_assert(view->swayc, "cannot run criteria for unmapped view")) { | ||
216 | return; | ||
217 | } | ||
218 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
219 | struct sway_container *prior_workspace = | ||
220 | container_parent(view->swayc, C_WORKSPACE); | ||
221 | list_t *criteria = criteria_for(view->swayc); | ||
222 | for (int i = 0; i < criteria->length; i++) { | ||
223 | struct criteria *crit = criteria->items[i]; | ||
224 | wlr_log(L_DEBUG, "for_window '%s' matches new view %p, cmd: '%s'", | ||
225 | crit->crit_raw, view, crit->cmdlist); | ||
226 | struct cmd_results *res = execute_command(crit->cmdlist, NULL); | ||
227 | if (res->status != CMD_SUCCESS) { | ||
228 | wlr_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error); | ||
229 | } | ||
230 | free_cmd_results(res); | ||
231 | // view must be focused for commands to affect it, | ||
232 | // so always refocus in-between command lists | ||
233 | seat_set_focus(seat, view->swayc); | ||
234 | } | ||
235 | list_free(criteria); | ||
236 | seat_set_focus(seat, seat_get_focus_inactive(seat, prior_workspace)); | ||
237 | } | ||
238 | |||
211 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | 239 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { |
212 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { | 240 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { |
213 | return; | 241 | return; |
@@ -234,6 +262,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
234 | 262 | ||
235 | view_damage(view, true); | 263 | view_damage(view, true); |
236 | view_handle_container_reparent(&view->container_reparent, NULL); | 264 | view_handle_container_reparent(&view->container_reparent, NULL); |
265 | |||
266 | view_execute_criteria(view); | ||
237 | } | 267 | } |
238 | 268 | ||
239 | void view_unmap(struct sway_view *view) { | 269 | void view_unmap(struct sway_view *view) { |