diff options
Diffstat (limited to 'sway/criteria.c')
-rw-r--r-- | sway/criteria.c | 58 |
1 files changed, 51 insertions, 7 deletions
diff --git a/sway/criteria.c b/sway/criteria.c index 04683f66..f5fe40cb 100644 --- a/sway/criteria.c +++ b/sway/criteria.c | |||
@@ -12,9 +12,12 @@ | |||
12 | 12 | ||
13 | enum criteria_type { // *must* keep in sync with criteria_strings[] | 13 | enum criteria_type { // *must* keep in sync with criteria_strings[] |
14 | CRIT_CLASS, | 14 | CRIT_CLASS, |
15 | CRIT_CON_ID, | ||
15 | CRIT_CON_MARK, | 16 | CRIT_CON_MARK, |
17 | CRIT_FLOATING, | ||
16 | CRIT_ID, | 18 | CRIT_ID, |
17 | CRIT_INSTANCE, | 19 | CRIT_INSTANCE, |
20 | CRIT_TILING, | ||
18 | CRIT_TITLE, | 21 | CRIT_TITLE, |
19 | CRIT_URGENT, | 22 | CRIT_URGENT, |
20 | CRIT_WINDOW_ROLE, | 23 | CRIT_WINDOW_ROLE, |
@@ -25,9 +28,12 @@ enum criteria_type { // *must* keep in sync with criteria_strings[] | |||
25 | 28 | ||
26 | static const char * const criteria_strings[CRIT_LAST] = { | 29 | static const char * const criteria_strings[CRIT_LAST] = { |
27 | [CRIT_CLASS] = "class", | 30 | [CRIT_CLASS] = "class", |
31 | [CRIT_CON_ID] = "con_id", | ||
28 | [CRIT_CON_MARK] = "con_mark", | 32 | [CRIT_CON_MARK] = "con_mark", |
33 | [CRIT_FLOATING] = "floating", | ||
29 | [CRIT_ID] = "id", | 34 | [CRIT_ID] = "id", |
30 | [CRIT_INSTANCE] = "instance", | 35 | [CRIT_INSTANCE] = "instance", |
36 | [CRIT_TILING] = "tiling", | ||
31 | [CRIT_TITLE] = "title", | 37 | [CRIT_TITLE] = "title", |
32 | [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ... | 38 | [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ... |
33 | [CRIT_WINDOW_ROLE] = "window_role", | 39 | [CRIT_WINDOW_ROLE] = "window_role", |
@@ -108,6 +114,7 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str | |||
108 | 114 | ||
109 | char **argv = *buf = calloc(max_tokens, sizeof(char*)); | 115 | char **argv = *buf = calloc(max_tokens, sizeof(char*)); |
110 | argv[0] = base; // this needs to be freed by caller | 116 | argv[0] = base; // this needs to be freed by caller |
117 | bool quoted = true; | ||
111 | 118 | ||
112 | *argc = 1; // uneven = name, even = value | 119 | *argc = 1; // uneven = name, even = value |
113 | while (*head && *argc < max_tokens) { | 120 | while (*head && *argc < max_tokens) { |
@@ -128,7 +135,8 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str | |||
128 | if (*(namep) == ' ') { | 135 | if (*(namep) == ' ') { |
129 | namep = strrchr(namep, ' ') + 1; | 136 | namep = strrchr(namep, ' ') + 1; |
130 | } | 137 | } |
131 | argv[(*argc)++] = namep; | 138 | argv[*argc] = namep; |
139 | *argc += 1; | ||
132 | } | 140 | } |
133 | } else if (*head == '"') { | 141 | } else if (*head == '"') { |
134 | if (*argc % 2 != 0) { | 142 | if (*argc % 2 != 0) { |
@@ -137,21 +145,38 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str | |||
137 | "Found quoted value where it was not expected"); | 145 | "Found quoted value where it was not expected"); |
138 | } else if (!valp) { // value starts here | 146 | } else if (!valp) { // value starts here |
139 | valp = head + 1; | 147 | valp = head + 1; |
148 | quoted = true; | ||
140 | } else { | 149 | } else { |
141 | // value ends here | 150 | // value ends here |
142 | argv[(*argc)++] = valp; | 151 | argv[*argc] = valp; |
152 | *argc += 1; | ||
143 | *head = '\0'; | 153 | *head = '\0'; |
144 | valp = NULL; | 154 | valp = NULL; |
145 | namep = head + 1; | 155 | namep = head + 1; |
146 | } | 156 | } |
147 | } else if (*argc % 2 == 0 && !valp && *head != ' ') { | 157 | } else if (*argc % 2 == 0 && *head != ' ') { |
148 | // We're expecting a quoted value, haven't found one yet, and this | 158 | // parse unquoted values |
149 | // is not an empty space. | 159 | if (!valp) { |
150 | return strdup("Unable to parse criteria: " | 160 | quoted = false; |
151 | "Names must be unquoted, values must be quoted"); | 161 | valp = head; // value starts here |
162 | } | ||
163 | } else if (valp && !quoted && *head == ' ') { | ||
164 | // value ends here | ||
165 | argv[*argc] = valp; | ||
166 | *argc += 1; | ||
167 | *head = '\0'; | ||
168 | valp = NULL; | ||
169 | namep = head + 1; | ||
152 | } | 170 | } |
153 | head++; | 171 | head++; |
154 | } | 172 | } |
173 | |||
174 | // catch last unquoted value if needed | ||
175 | if (valp && !quoted && !*head) { | ||
176 | argv[*argc] = valp; | ||
177 | *argc += 1; | ||
178 | } | ||
179 | |||
155 | return NULL; | 180 | return NULL; |
156 | } | 181 | } |
157 | 182 | ||
@@ -263,6 +288,15 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) { | |||
263 | matches++; | 288 | matches++; |
264 | } | 289 | } |
265 | break; | 290 | break; |
291 | case CRIT_CON_ID: { | ||
292 | char *endptr; | ||
293 | size_t crit_id = strtoul(crit->raw, &endptr, 10); | ||
294 | |||
295 | if (*endptr == 0 && cont->id == crit_id) { | ||
296 | ++matches; | ||
297 | } | ||
298 | break; | ||
299 | } | ||
266 | case CRIT_CON_MARK: | 300 | case CRIT_CON_MARK: |
267 | if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) { | 301 | if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) { |
268 | // Make sure it isn't matching the NUL string | 302 | // Make sure it isn't matching the NUL string |
@@ -271,6 +305,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) { | |||
271 | } | 305 | } |
272 | } | 306 | } |
273 | break; | 307 | break; |
308 | case CRIT_FLOATING: | ||
309 | if (cont->is_floating) { | ||
310 | matches++; | ||
311 | } | ||
312 | break; | ||
274 | case CRIT_ID: | 313 | case CRIT_ID: |
275 | if (!cont->app_id) { | 314 | if (!cont->app_id) { |
276 | // ignore | 315 | // ignore |
@@ -290,6 +329,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) { | |||
290 | matches++; | 329 | matches++; |
291 | } | 330 | } |
292 | break; | 331 | break; |
332 | case CRIT_TILING: | ||
333 | if (!cont->is_floating) { | ||
334 | matches++; | ||
335 | } | ||
336 | break; | ||
293 | case CRIT_TITLE: | 337 | case CRIT_TITLE: |
294 | if (!cont->name) { | 338 | if (!cont->name) { |
295 | // ignore | 339 | // ignore |