From be406d036dfa584d06f736a152ba3d74d6ce6301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Mon, 29 Jun 2015 23:58:48 +0200 Subject: [PATCH] Implement new criterion 'workspace'. If the match expression is a plain number (e.g., '99'), the number of a workspace will be compared strictly. Otherwise, the match expression is taken as a regular expression and compared against the workspace's name. This allows all of the following: for_window [workspace=5] ... for_window [workspace="5:foo"] ... for_window [workspace="foo"] ... fixes #1769 --- docs/userguide | 6 ++++-- include/data.h | 1 + parser-specs/commands.spec | 1 + parser-specs/config.spec | 1 + src/commands.c | 5 +++++ src/config_directives.c | 5 +++++ src/match.c | 15 +++++++++++++++ testcases/t/165-for_window.t | 23 +++++++++++++++++++++++ 8 files changed, 55 insertions(+), 2 deletions(-) diff --git a/docs/userguide b/docs/userguide index 64f614f5..65d82d97 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1597,14 +1597,16 @@ urgent:: Compares the urgent state of the window. Can be "latest" or "oldest". Matches the latest or oldest urgent window, respectively. (The following aliases are also available: newest, last, recent, first) +workspace:: + Compares the workspace name of the workspace the window belongs to. con_mark:: Compares the mark set for this container, see <>. con_id:: Compares the i3-internal container ID, which you can get via the IPC interface. Handy for scripting. -The criteria +class+, +instance+, +role+, +title+ and +mark+ are actually -regular expressions (PCRE). See +pcresyntax(3)+ or +perldoc perlre+ for +The criteria +class+, +instance+, +role+, +title+, +workspace+ and +mark+ are +actually regular expressions (PCRE). See +pcresyntax(3)+ or +perldoc perlre+ for information on how to use them. [[exec]] diff --git a/include/data.h b/include/data.h index e08cdd4c..66000e45 100644 --- a/include/data.h +++ b/include/data.h @@ -417,6 +417,7 @@ struct Match { struct regex *instance; struct regex *mark; struct regex *window_role; + struct regex *workspace; xcb_atom_t window_type; enum { U_DONTCHECK = -1, diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec index c756dd8b..94dc630a 100644 --- a/parser-specs/commands.spec +++ b/parser-specs/commands.spec @@ -51,6 +51,7 @@ state CRITERIA: ctype = 'con_mark' -> CRITERION ctype = 'title' -> CRITERION ctype = 'urgent' -> CRITERION + ctype = 'workspace' -> CRITERION ']' -> call cmd_criteria_match_windows(); INITIAL state CRITERION: diff --git a/parser-specs/config.spec b/parser-specs/config.spec index 932be5fc..3767acf8 100644 --- a/parser-specs/config.spec +++ b/parser-specs/config.spec @@ -170,6 +170,7 @@ state CRITERIA: ctype = 'con_mark' -> CRITERION ctype = 'title' -> CRITERION ctype = 'urgent' -> CRITERION + ctype = 'workspace' -> CRITERION ']' -> call cfg_criteria_pop_state() diff --git a/src/commands.c b/src/commands.c index 71b48182..53921e86 100644 --- a/src/commands.c +++ b/src/commands.c @@ -411,6 +411,11 @@ void cmd_criteria_add(I3_CMD, char *ctype, char *cvalue) { return; } + if (strcmp(ctype, "workspace") == 0) { + current_match->workspace = regex_new(cvalue); + return; + } + ELOG("Unknown criterion: %s\n", ctype); } diff --git a/src/config_directives.c b/src/config_directives.c index 0e477b70..91f408d5 100644 --- a/src/config_directives.c +++ b/src/config_directives.c @@ -137,6 +137,11 @@ CFGFUN(criteria_add, const char *ctype, const char *cvalue) { return; } + if (strcmp(ctype, "workspace") == 0) { + current_match->workspace = regex_new(cvalue); + return; + } + ELOG("Unknown criterion: %s\n", ctype); } diff --git a/src/match.c b/src/match.c index f1bc8430..03a9cbee 100644 --- a/src/match.c +++ b/src/match.c @@ -48,6 +48,7 @@ bool match_is_empty(Match *match) { match->class == NULL && match->instance == NULL && match->window_role == NULL && + match->workspace == NULL && match->urgent == U_DONTCHECK && match->id == XCB_NONE && match->window_type == UINT32_MAX && @@ -78,6 +79,7 @@ void match_copy(Match *dest, Match *src) { DUPLICATE_REGEX(class); DUPLICATE_REGEX(instance); DUPLICATE_REGEX(window_role); + DUPLICATE_REGEX(workspace); } /* @@ -172,6 +174,19 @@ bool match_matches_window(Match *match, i3Window *window) { LOG("urgent matches oldest\n"); } + if (match->workspace != NULL) { + Con *con = con_by_window_id(window->id); + assert(con != NULL); + Con *ws = con_get_workspace(con); + assert(ws != NULL); + + if (regex_matches(match->workspace, ws->name)) { + LOG("workspace matches (%s)\n", ws->name); + } else { + return false; + } + } + if (match->dock != M_DONTCHECK) { if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) || (window->dock == W_DOCK_BOTTOM && match->dock == M_DOCK_BOTTOM) || diff --git a/testcases/t/165-for_window.t b/testcases/t/165-for_window.t index b684d41f..985a7bfd 100644 --- a/testcases/t/165-for_window.t +++ b/testcases/t/165-for_window.t @@ -17,6 +17,8 @@ use i3test i3_autostart => 0; use X11::XCB qw(PROP_MODE_REPLACE); +my (@nodes); + ############################################################## # 1: test the following directive: # for_window [class="borderless"] border none @@ -435,6 +437,27 @@ EOT } +############################################################## +# 12: check that the criterion 'workspace' works +############################################################## + +$config = <<"EOT"; +# i3 config file (v4) +font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 +for_window [workspace="trigger"] floating enable, mark triggered +EOT + +$pid = launch_with_config($config); + +cmd 'workspace trigger'; +$window = open_window; + +@nodes = @{get_ws('trigger')->{floating_nodes}}; +cmp_ok(@nodes, '==', 1, 'one floating container on this workspace'); +is($nodes[0]->{nodes}[0]->{mark}, 'triggered', "mark set for workspace criterion"); + +exit_gracefully($pid); + ############################################################## done_testing;