diff options
-rw-r--r-- | include/sway/criteria.h | 1 | ||||
-rw-r--r-- | sway/criteria.c | 71 |
2 files changed, 50 insertions, 22 deletions
diff --git a/include/sway/criteria.h b/include/sway/criteria.h index f7e788c8..8a1d9e5e 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h | |||
@@ -20,6 +20,7 @@ struct criteria { | |||
20 | char *cmdlist; | 20 | char *cmdlist; |
21 | char *target; // workspace or output name for `assign` criteria | 21 | char *target; // workspace or output name for `assign` criteria |
22 | 22 | ||
23 | bool autofail; // __focused__ while no focus or n/a for focused view | ||
23 | pcre *title; | 24 | pcre *title; |
24 | pcre *shell; | 25 | pcre *shell; |
25 | pcre *app_id; | 26 | pcre *app_id; |
diff --git a/sway/criteria.c b/sway/criteria.c index f2db6c18..11b41f35 100644 --- a/sway/criteria.c +++ b/sway/criteria.c | |||
@@ -16,7 +16,8 @@ | |||
16 | #include "config.h" | 16 | #include "config.h" |
17 | 17 | ||
18 | bool criteria_is_empty(struct criteria *criteria) { | 18 | bool criteria_is_empty(struct criteria *criteria) { |
19 | return !criteria->title | 19 | return !criteria->autofail |
20 | && !criteria->title | ||
20 | && !criteria->shell | 21 | && !criteria->shell |
21 | && !criteria->app_id | 22 | && !criteria->app_id |
22 | && !criteria->con_mark | 23 | && !criteria->con_mark |
@@ -98,6 +99,10 @@ static void find_urgent_iterator(struct sway_container *con, void *data) { | |||
98 | 99 | ||
99 | static bool criteria_matches_view(struct criteria *criteria, | 100 | static bool criteria_matches_view(struct criteria *criteria, |
100 | struct sway_view *view) { | 101 | struct sway_view *view) { |
102 | if (criteria->autofail) { | ||
103 | return false; | ||
104 | } | ||
105 | |||
101 | if (criteria->title) { | 106 | if (criteria->title) { |
102 | const char *title = view_get_title(view); | 107 | const char *title = view_get_title(view); |
103 | if (!title || regex_cmp(title, criteria->title) != 0) { | 108 | if (!title || regex_cmp(title, criteria->title) != 0) { |
@@ -366,50 +371,66 @@ static enum criteria_token token_from_name(char *name) { | |||
366 | * using criteria via IPC. Using __focused__ in config is not useful because | 371 | * using criteria via IPC. Using __focused__ in config is not useful because |
367 | * criteria is only executed once per view. | 372 | * criteria is only executed once per view. |
368 | */ | 373 | */ |
369 | static char *get_focused_prop(enum criteria_token token) { | 374 | static char *get_focused_prop(enum criteria_token token, bool *autofail) { |
370 | struct sway_seat *seat = input_manager_current_seat(); | 375 | struct sway_seat *seat = input_manager_current_seat(); |
371 | struct sway_container *focus = seat_get_focused_container(seat); | 376 | struct sway_container *focus = seat_get_focused_container(seat); |
372 | 377 | ||
373 | if (!focus || !focus->view) { | 378 | struct sway_view *view = focus ? focus->view : NULL; |
374 | return NULL; | ||
375 | } | ||
376 | struct sway_view *view = focus->view; | ||
377 | const char *value = NULL; | 379 | const char *value = NULL; |
378 | 380 | ||
379 | switch (token) { | 381 | switch (token) { |
380 | case T_APP_ID: | 382 | case T_APP_ID: |
381 | value = view_get_app_id(view); | 383 | *autofail = true; |
384 | if (view) { | ||
385 | value = view_get_app_id(view); | ||
386 | } | ||
382 | break; | 387 | break; |
383 | case T_SHELL: | 388 | case T_SHELL: |
384 | value = view_get_shell(view); | 389 | *autofail = true; |
390 | if (view) { | ||
391 | value = view_get_shell(view); | ||
392 | } | ||
385 | break; | 393 | break; |
386 | case T_TITLE: | 394 | case T_TITLE: |
387 | value = view_get_title(view); | 395 | *autofail = true; |
396 | if (view) { | ||
397 | value = view_get_title(view); | ||
398 | } | ||
388 | break; | 399 | break; |
389 | case T_WORKSPACE: | 400 | case T_WORKSPACE: |
390 | if (focus->workspace) { | 401 | *autofail = true; |
402 | if (focus && focus->workspace) { | ||
391 | value = focus->workspace->name; | 403 | value = focus->workspace->name; |
392 | } | 404 | } |
393 | break; | 405 | break; |
394 | case T_CON_ID: | 406 | case T_CON_ID: |
395 | if (view->container == NULL) { | 407 | *autofail = true; |
396 | return NULL; | 408 | if (view && view->container) { |
397 | } | 409 | size_t id = view->container->node.id; |
398 | size_t id = view->container->node.id; | 410 | size_t id_size = snprintf(NULL, 0, "%zu", id) + 1; |
399 | size_t id_size = snprintf(NULL, 0, "%zu", id) + 1; | 411 | char *id_str = malloc(id_size); |
400 | char *id_str = malloc(id_size); | 412 | snprintf(id_str, id_size, "%zu", id); |
401 | snprintf(id_str, id_size, "%zu", id); | 413 | value = id_str; |
402 | value = id_str; | 414 | } |
403 | break; | 415 | break; |
404 | #if HAVE_XWAYLAND | 416 | #if HAVE_XWAYLAND |
405 | case T_CLASS: | 417 | case T_CLASS: |
406 | value = view_get_class(view); | 418 | *autofail = true; |
419 | if (view) { | ||
420 | value = view_get_class(view); | ||
421 | } | ||
407 | break; | 422 | break; |
408 | case T_INSTANCE: | 423 | case T_INSTANCE: |
409 | value = view_get_instance(view); | 424 | *autofail = true; |
425 | if (view) { | ||
426 | value = view_get_instance(view); | ||
427 | } | ||
410 | break; | 428 | break; |
411 | case T_WINDOW_ROLE: | 429 | case T_WINDOW_ROLE: |
412 | value = view_get_window_role(view); | 430 | *autofail = true; |
431 | if (view) { | ||
432 | value = view_get_window_role(view); | ||
433 | } | ||
413 | break; | 434 | break; |
414 | case T_WINDOW_TYPE: // These do not support __focused__ | 435 | case T_WINDOW_TYPE: // These do not support __focused__ |
415 | case T_ID: | 436 | case T_ID: |
@@ -419,6 +440,7 @@ static char *get_focused_prop(enum criteria_token token) { | |||
419 | case T_TILING: | 440 | case T_TILING: |
420 | case T_URGENT: | 441 | case T_URGENT: |
421 | case T_INVALID: | 442 | case T_INVALID: |
443 | *autofail = false; | ||
422 | break; | 444 | break; |
423 | } | 445 | } |
424 | if (value) { | 446 | if (value) { |
@@ -439,7 +461,12 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { | |||
439 | 461 | ||
440 | char *effective_value = NULL; | 462 | char *effective_value = NULL; |
441 | if (value && strcmp(value, "__focused__") == 0) { | 463 | if (value && strcmp(value, "__focused__") == 0) { |
442 | effective_value = get_focused_prop(token); | 464 | bool autofail = false; |
465 | effective_value = get_focused_prop(token, &autofail); | ||
466 | if (!effective_value && autofail) { | ||
467 | criteria->autofail = true; | ||
468 | return true; | ||
469 | } | ||
443 | } else if (value) { | 470 | } else if (value) { |
444 | effective_value = strdup(value); | 471 | effective_value = strdup(value); |
445 | } | 472 | } |