aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2018-04-25 22:52:01 +0100
committerLibravatar GitHub <noreply@github.com>2018-04-25 22:52:01 +0100
commit7ac770f3c0d4aa4b38650ad5ec7d1f5b7e70028a (patch)
treeec248905f4c73d8f52c3e2c08ce26decbda2d704
parentMerge pull request #1861 from emersion/swaybar-memory-leaks (diff)
parentMerge branch 'master' into criteria-commands (diff)
downloadsway-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.h2
-rw-r--r--sway/commands.c2
-rw-r--r--sway/commands/assign.c57
-rw-r--r--sway/commands/for_window.c41
-rw-r--r--sway/meson.build2
-rw-r--r--sway/tree/view.c30
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 */
95static struct cmd_handler handlers[] = { 95static 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
9struct 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
9struct 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
214static 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
211void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { 239void 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
239void view_unmap(struct sway_view *view) { 269void view_unmap(struct sway_view *view) {