summaryrefslogtreecommitdiffstats
path: root/sway/criteria.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/criteria.c')
-rw-r--r--sway/criteria.c156
1 files changed, 75 insertions, 81 deletions
diff --git a/sway/criteria.c b/sway/criteria.c
index e8978ebe..22e9a49b 100644
--- a/sway/criteria.c
+++ b/sway/criteria.c
@@ -4,13 +4,15 @@
4#include <stdbool.h> 4#include <stdbool.h>
5#include <pcre.h> 5#include <pcre.h>
6#include "sway/criteria.h" 6#include "sway/criteria.h"
7#include "sway/container.h" 7#include "sway/tree/container.h"
8#include "sway/config.h" 8#include "sway/config.h"
9#include "sway/tree/view.h"
9#include "stringop.h" 10#include "stringop.h"
10#include "list.h" 11#include "list.h"
11#include "log.h" 12#include "log.h"
12 13
13enum criteria_type { // *must* keep in sync with criteria_strings[] 14enum criteria_type { // *must* keep in sync with criteria_strings[]
15 CRIT_APP_ID,
14 CRIT_CLASS, 16 CRIT_CLASS,
15 CRIT_CON_ID, 17 CRIT_CON_ID,
16 CRIT_CON_MARK, 18 CRIT_CON_MARK,
@@ -27,6 +29,7 @@ enum criteria_type { // *must* keep in sync with criteria_strings[]
27}; 29};
28 30
29static const char * const criteria_strings[CRIT_LAST] = { 31static const char * const criteria_strings[CRIT_LAST] = {
32 [CRIT_APP_ID] = "app_id",
30 [CRIT_CLASS] = "class", 33 [CRIT_CLASS] = "class",
31 [CRIT_CON_ID] = "con_id", 34 [CRIT_CON_ID] = "con_id",
32 [CRIT_CON_MARK] = "con_mark", 35 [CRIT_CON_MARK] = "con_mark",
@@ -100,8 +103,9 @@ static int countchr(char *str, char c) {
100// of buf. 103// of buf.
101// 104//
102// Returns error string or NULL if successful. 105// Returns error string or NULL if successful.
103static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str) { 106static char *crit_tokens(int *argc, char ***buf,
104 sway_log(L_DEBUG, "Parsing criteria: '%s'", criteria_str); 107 const char * const criteria_str) {
108 wlr_log(L_DEBUG, "Parsing criteria: '%s'", criteria_str);
105 char *base = criteria_from(criteria_str); 109 char *base = criteria_from(criteria_str);
106 char *head = base; 110 char *head = base;
107 char *namep = head; // start of criteria name 111 char *namep = head; // start of criteria name
@@ -247,13 +251,13 @@ char *extract_crit_tokens(list_t *tokens, const char * const criteria) {
247 free_crit_token(token); 251 free_crit_token(token);
248 goto ect_cleanup; 252 goto ect_cleanup;
249 } else if (token->type == CRIT_URGENT || crit_is_focused(value)) { 253 } else if (token->type == CRIT_URGENT || crit_is_focused(value)) {
250 sway_log(L_DEBUG, "%s -> \"%s\"", name, value); 254 wlr_log(L_DEBUG, "%s -> \"%s\"", name, value);
251 list_add(tokens, token); 255 list_add(tokens, token);
252 } else if((error = generate_regex(&token->regex, value))) { 256 } else if((error = generate_regex(&token->regex, value))) {
253 free_crit_token(token); 257 free_crit_token(token);
254 goto ect_cleanup; 258 goto ect_cleanup;
255 } else { 259 } else {
256 sway_log(L_DEBUG, "%s -> /%s/", name, value); 260 wlr_log(L_DEBUG, "%s -> /%s/", name, value);
257 list_add(tokens, token); 261 list_add(tokens, token);
258 } 262 }
259 } 263 }
@@ -268,8 +272,8 @@ static int regex_cmp(const char *item, const pcre *regex) {
268} 272}
269 273
270// test a single view if it matches list of criteria tokens (all of them). 274// test a single view if it matches list of criteria tokens (all of them).
271static bool criteria_test(swayc_t *cont, list_t *tokens) { 275static bool criteria_test(struct sway_container *cont, list_t *tokens) {
272 if (cont->type != C_VIEW) { 276 if (cont->type != C_CONTAINER && cont->type != C_VIEW) {
273 return false; 277 return false;
274 } 278 }
275 int matches = 0; 279 int matches = 0;
@@ -277,94 +281,85 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
277 struct crit_token *crit = tokens->items[i]; 281 struct crit_token *crit = tokens->items[i];
278 switch (crit->type) { 282 switch (crit->type) {
279 case CRIT_CLASS: 283 case CRIT_CLASS:
280 if (!cont->class) { 284 {
281 // ignore 285 const char *class = view_get_class(cont->sway_view);
282 } else if (crit_is_focused(crit->raw)) { 286 if (!class) {
283 swayc_t *focused = get_focused_view(&root_container); 287 break;
284 if (focused->class && strcmp(cont->class, focused->class) == 0) { 288 }
289 if (crit->regex && regex_cmp(class, crit->regex) == 0) {
285 matches++; 290 matches++;
286 } 291 }
287 } else if (crit->regex && regex_cmp(cont->class, crit->regex) == 0) { 292 break;
288 matches++;
289 } 293 }
290 break; 294 case CRIT_CON_ID:
291 case CRIT_CON_ID: { 295 {
292 char *endptr; 296 char *endptr;
293 size_t crit_id = strtoul(crit->raw, &endptr, 10); 297 size_t crit_id = strtoul(crit->raw, &endptr, 10);
294 298
295 if (*endptr == 0 && cont->id == crit_id) { 299 if (*endptr == 0 && cont->id == crit_id) {
296 ++matches;
297 }
298 break;
299 }
300 case CRIT_CON_MARK:
301 if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) {
302 // Make sure it isn't matching the NUL string
303 if ((strcmp(crit->raw, "") == 0) == (list_seq_find(cont->marks, (int (*)(const void *, const void *))strcmp, "") != -1)) {
304 ++matches; 300 ++matches;
305 } 301 }
302 break;
306 } 303 }
304 case CRIT_CON_MARK:
305 // TODO
307 break; 306 break;
308 case CRIT_FLOATING: 307 case CRIT_FLOATING:
309 if (cont->is_floating) { 308 // TODO
310 matches++;
311 }
312 break; 309 break;
313 case CRIT_ID: 310 case CRIT_ID:
314 if (!cont->app_id) { 311 // TODO
315 // ignore
316 } else if (crit->regex && regex_cmp(cont->app_id, crit->regex) == 0) {
317 matches++;
318 }
319 break; 312 break;
313 case CRIT_APP_ID:
314 {
315 const char *app_id = view_get_app_id(cont->sway_view);
316 if (!app_id) {
317 break;
318 }
319
320 if (crit->regex && regex_cmp(app_id, crit->regex) == 0) {
321 matches++;
322 }
323 break;
324 }
320 case CRIT_INSTANCE: 325 case CRIT_INSTANCE:
321 if (!cont->instance) { 326 {
322 // ignore 327 const char *instance = view_get_instance(cont->sway_view);
323 } else if (crit_is_focused(crit->raw)) { 328 if (!instance) {
324 swayc_t *focused = get_focused_view(&root_container); 329 break;
325 if (focused->instance && strcmp(cont->instance, focused->instance) == 0) { 330 }
331
332 if (crit->regex && regex_cmp(instance, crit->regex) == 0) {
326 matches++; 333 matches++;
327 } 334 }
328 } else if (crit->regex && regex_cmp(cont->instance, crit->regex) == 0) { 335 break;
329 matches++;
330 } 336 }
331 break;
332 case CRIT_TILING: 337 case CRIT_TILING:
333 if (!cont->is_floating) { 338 // TODO
334 matches++;
335 }
336 break; 339 break;
337 case CRIT_TITLE: 340 case CRIT_TITLE:
338 if (!cont->name) { 341 {
339 // ignore 342 const char *title = view_get_title(cont->sway_view);
340 } else if (crit_is_focused(crit->raw)) { 343 if (!title) {
341 swayc_t *focused = get_focused_view(&root_container); 344 break;
342 if (focused->name && strcmp(cont->name, focused->name) == 0) { 345 }
346
347 if (crit->regex && regex_cmp(title, crit->regex) == 0) {
343 matches++; 348 matches++;
344 } 349 }
345 } else if (crit->regex && regex_cmp(cont->name, crit->regex) == 0) { 350 break;
346 matches++;
347 } 351 }
348 break; 352 case CRIT_URGENT:
349 case CRIT_URGENT: // "latest" or "oldest" 353 // TODO "latest" or "oldest"
350 break; 354 break;
351 case CRIT_WINDOW_ROLE: 355 case CRIT_WINDOW_ROLE:
356 // TODO
352 break; 357 break;
353 case CRIT_WINDOW_TYPE: 358 case CRIT_WINDOW_TYPE:
354 // TODO wlc indeed exposes this information 359 // TODO
355 break; 360 break;
356 case CRIT_WORKSPACE: ; 361 case CRIT_WORKSPACE:
357 swayc_t *cont_ws = swayc_parent_by_type(cont, C_WORKSPACE); 362 // TODO
358 if (!cont_ws || !cont_ws->name) {
359 // ignore
360 } else if (crit_is_focused(crit->raw)) {
361 swayc_t *focused_ws = swayc_active_workspace();
362 if (focused_ws->name && strcmp(cont_ws->name, focused_ws->name) == 0) {
363 matches++;
364 }
365 } else if (crit->regex && regex_cmp(cont_ws->name, crit->regex) == 0) {
366 matches++;
367 }
368 break; 363 break;
369 default: 364 default:
370 sway_abort("Invalid criteria type (%i)", crit->type); 365 sway_abort("Invalid criteria type (%i)", crit->type);
@@ -403,7 +398,7 @@ void free_criteria(struct criteria *crit) {
403 free(crit); 398 free(crit);
404} 399}
405 400
406bool criteria_any(swayc_t *cont, list_t *criteria) { 401bool criteria_any(struct sway_container *cont, list_t *criteria) {
407 for (int i = 0; i < criteria->length; i++) { 402 for (int i = 0; i < criteria->length; i++) {
408 struct criteria *bc = criteria->items[i]; 403 struct criteria *bc = criteria->items[i];
409 if (criteria_test(cont, bc->tokens)) { 404 if (criteria_test(cont, bc->tokens)) {
@@ -413,7 +408,7 @@ bool criteria_any(swayc_t *cont, list_t *criteria) {
413 return false; 408 return false;
414} 409}
415 410
416list_t *criteria_for(swayc_t *cont) { 411list_t *criteria_for(struct sway_container *cont) {
417 list_t *criteria = config->criteria, *matches = create_list(); 412 list_t *criteria = config->criteria, *matches = create_list();
418 for (int i = 0; i < criteria->length; i++) { 413 for (int i = 0; i < criteria->length; i++) {
419 struct criteria *bc = criteria->items[i]; 414 struct criteria *bc = criteria->items[i];
@@ -429,23 +424,22 @@ struct list_tokens {
429 list_t *tokens; 424 list_t *tokens;
430}; 425};
431 426
432static void container_match_add(swayc_t *container, struct list_tokens *list_tokens) { 427static void container_match_add(struct sway_container *container,
428 struct list_tokens *list_tokens) {
433 if (criteria_test(container, list_tokens->tokens)) { 429 if (criteria_test(container, list_tokens->tokens)) {
434 list_add(list_tokens->list, container); 430 list_add(list_tokens->list, container);
435 } 431 }
436} 432}
437 433
438list_t *container_for(list_t *tokens) { 434list_t *container_for_crit_tokens(list_t *tokens) {
439 struct list_tokens list_tokens = (struct list_tokens){create_list(), tokens}; 435 struct list_tokens list_tokens =
436 (struct list_tokens){create_list(), tokens};
440 437
441 container_map(&root_container, (void (*)(swayc_t *, void *))container_match_add, &list_tokens); 438 container_for_each_descendant_dfs(&root_container,
442 439 (void (*)(struct sway_container *, void *))container_match_add,
443 for (int i = 0; i < scratchpad->length; ++i) { 440 &list_tokens);
444 swayc_t *c = scratchpad->items[i];
445 if (criteria_test(c, tokens)) {
446 list_add(list_tokens.list, c);
447 }
448 }
449 441
442 // TODO look in the scratchpad
443
450 return list_tokens.list; 444 return list_tokens.list;
451} 445}