summaryrefslogtreecommitdiffstats
path: root/sway/criteria.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/criteria.c')
-rw-r--r--sway/criteria.c89
1 files changed, 57 insertions, 32 deletions
diff --git a/sway/criteria.c b/sway/criteria.c
index bc0523ce..ee6d4d1c 100644
--- a/sway/criteria.c
+++ b/sway/criteria.c
@@ -2,7 +2,7 @@
2#include <stdlib.h> 2#include <stdlib.h>
3#include <stdio.h> 3#include <stdio.h>
4#include <stdbool.h> 4#include <stdbool.h>
5#include <regex.h> 5#include <pcre.h>
6#include "sway/criteria.h" 6#include "sway/criteria.h"
7#include "sway/container.h" 7#include "sway/container.h"
8#include "sway/config.h" 8#include "sway/config.h"
@@ -12,6 +12,7 @@
12 12
13enum criteria_type { // *must* keep in sync with criteria_strings[] 13enum criteria_type { // *must* keep in sync with criteria_strings[]
14 CRIT_CLASS, 14 CRIT_CLASS,
15 CRIT_CON_MARK,
15 CRIT_ID, 16 CRIT_ID,
16 CRIT_INSTANCE, 17 CRIT_INSTANCE,
17 CRIT_TITLE, 18 CRIT_TITLE,
@@ -22,16 +23,16 @@ enum criteria_type { // *must* keep in sync with criteria_strings[]
22 CRIT_LAST 23 CRIT_LAST
23}; 24};
24 25
25// this *must* match the ordering in criteria_type enum 26static const char * const criteria_strings[CRIT_LAST] = {
26static const char * const criteria_strings[] = { 27 [CRIT_CLASS] = "class",
27 "class", 28 [CRIT_CON_MARK] = "con_mark",
28 "id", 29 [CRIT_ID] = "id",
29 "instance", 30 [CRIT_INSTANCE] = "instance",
30 "title", 31 [CRIT_TITLE] = "title",
31 "urgent", // either "latest" or "oldest" ... 32 [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ...
32 "window_role", 33 [CRIT_WINDOW_ROLE] = "window_role",
33 "window_type", 34 [CRIT_WINDOW_TYPE] = "window_type",
34 "workspace" 35 [CRIT_WORKSPACE] = "workspace"
35}; 36};
36 37
37/** 38/**
@@ -40,18 +41,13 @@ static const char * const criteria_strings[] = {
40 */ 41 */
41struct crit_token { 42struct crit_token {
42 enum criteria_type type; 43 enum criteria_type type;
43 regex_t *regex; 44 pcre *regex;
44 char *raw; 45 char *raw;
45}; 46};
46 47
47static void free_crit_token(struct crit_token *crit) { 48static void free_crit_token(struct crit_token *crit) {
48 if (crit->regex) { 49 pcre_free(crit->regex);
49 regfree(crit->regex); 50 free(crit->raw);
50 free(crit->regex);
51 }
52 if (crit->raw) {
53 free(crit->raw);
54 }
55 free(crit); 51 free(crit);
56} 52}
57 53
@@ -188,18 +184,17 @@ static char *parse_criteria_name(enum criteria_type *type, char *name) {
188} 184}
189 185
190// Returns error string on failure or NULL otherwise. 186// Returns error string on failure or NULL otherwise.
191static char *generate_regex(regex_t **regex, char *value) { 187static char *generate_regex(pcre **regex, char *value) {
192 *regex = calloc(1, sizeof(regex_t)); 188 const char *reg_err;
193 int err = regcomp(*regex, value, REG_NOSUB); 189 int offset;
194 if (err != 0) { 190
195 char *reg_err = malloc(64); 191 *regex = pcre_compile(value, PCRE_UTF8 | PCRE_UCP, &reg_err, &offset, NULL);
196 regerror(err, *regex, reg_err, 64);
197 192
193 if (!*regex) {
198 const char *fmt = "Regex compilation (for '%s') failed: %s"; 194 const char *fmt = "Regex compilation (for '%s') failed: %s";
199 int len = strlen(fmt) + strlen(value) + strlen(reg_err) - 3; 195 int len = strlen(fmt) + strlen(value) + strlen(reg_err) - 3;
200 char *error = malloc(len); 196 char *error = malloc(len);
201 snprintf(error, len, fmt, value, reg_err); 197 snprintf(error, len, fmt, value, reg_err);
202 free(reg_err);
203 return error; 198 return error;
204 } 199 }
205 return NULL; 200 return NULL;
@@ -243,6 +238,10 @@ ect_cleanup:
243 return error; 238 return error;
244} 239}
245 240
241static int regex_cmp(const char *item, const pcre *regex) {
242 return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0);
243}
244
246// test a single view if it matches list of criteria tokens (all of them). 245// test a single view if it matches list of criteria tokens (all of them).
247static bool criteria_test(swayc_t *cont, list_t *tokens) { 246static bool criteria_test(swayc_t *cont, list_t *tokens) {
248 if (cont->type != C_VIEW) { 247 if (cont->type != C_VIEW) {
@@ -260,26 +259,34 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
260 if (focused->class && strcmp(cont->class, focused->class) == 0) { 259 if (focused->class && strcmp(cont->class, focused->class) == 0) {
261 matches++; 260 matches++;
262 } 261 }
263 } else if (crit->regex && regexec(crit->regex, cont->class, 0, NULL, 0) == 0) { 262 } else if (crit->regex && regex_cmp(cont->class, crit->regex) == 0) {
264 matches++; 263 matches++;
265 } 264 }
266 break; 265 break;
266 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)) {
268 // Make sure it isn't matching the NUL string
269 if ((strcmp(crit->raw, "") == 0) == (list_seq_find(cont->marks, (int (*)(const void *, const void *))strcmp, "") != -1)) {
270 ++matches;
271 }
272 }
273 break;
267 case CRIT_ID: 274 case CRIT_ID:
268 if (!cont->app_id) { 275 if (!cont->app_id) {
269 // ignore 276 // ignore
270 } else if (crit->regex && regexec(crit->regex, cont->app_id, 0, NULL, 0) == 0) { 277 } else if (crit->regex && regex_cmp(cont->app_id, crit->regex) == 0) {
271 matches++; 278 matches++;
272 } 279 }
273 break; 280 break;
274 case CRIT_INSTANCE: 281 case CRIT_INSTANCE:
275 if (!cont->instance) { 282 if (!cont->instance) {
276 // ignore 283 // ignore
277 } else if (strcmp(crit->raw, "focused") == 0) { 284 } else if (crit_is_focused(crit->raw)) {
278 swayc_t *focused = get_focused_view(&root_container); 285 swayc_t *focused = get_focused_view(&root_container);
279 if (focused->instance && strcmp(cont->instance, focused->instance) == 0) { 286 if (focused->instance && strcmp(cont->instance, focused->instance) == 0) {
280 matches++; 287 matches++;
281 } 288 }
282 } else if (crit->regex && regexec(crit->regex, cont->instance, 0, NULL, 0) == 0) { 289 } else if (crit->regex && regex_cmp(cont->instance, crit->regex) == 0) {
283 matches++; 290 matches++;
284 } 291 }
285 break; 292 break;
@@ -291,7 +298,7 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
291 if (focused->name && strcmp(cont->name, focused->name) == 0) { 298 if (focused->name && strcmp(cont->name, focused->name) == 0) {
292 matches++; 299 matches++;
293 } 300 }
294 } else if (crit->regex && regexec(crit->regex, cont->name, 0, NULL, 0) == 0) { 301 } else if (crit->regex && regex_cmp(cont->name, crit->regex) == 0) {
295 matches++; 302 matches++;
296 } 303 }
297 break; 304 break;
@@ -311,7 +318,7 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
311 if (focused_ws->name && strcmp(cont_ws->name, focused_ws->name) == 0) { 318 if (focused_ws->name && strcmp(cont_ws->name, focused_ws->name) == 0) {
312 matches++; 319 matches++;
313 } 320 }
314 } else if (crit->regex && regexec(crit->regex, cont_ws->name, 0, NULL, 0) == 0) { 321 } else if (crit->regex && regex_cmp(cont_ws->name, crit->regex) == 0) {
315 matches++; 322 matches++;
316 } 323 }
317 break; 324 break;
@@ -362,3 +369,21 @@ list_t *criteria_for(swayc_t *cont) {
362 } 369 }
363 return matches; 370 return matches;
364} 371}
372
373struct list_tokens {
374 list_t *list;
375 list_t *tokens;
376};
377
378static void container_match_add(swayc_t *container, struct list_tokens *list_tokens) {
379 if (criteria_test(container, list_tokens->tokens)) {
380 list_add(list_tokens->list, container);
381 }
382}
383list_t *container_for(list_t *tokens) {
384 struct list_tokens list_tokens = (struct list_tokens){create_list(), tokens};
385
386 container_map(&root_container, (void (*)(swayc_t *, void *))container_match_add, &list_tokens);
387
388 return list_tokens.list;
389}