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
This commit is contained in:
Ingo Bürk 2015-06-29 23:58:48 +02:00
parent 8df7e4ecb9
commit be406d036d
8 changed files with 55 additions and 2 deletions

View File

@ -1597,14 +1597,16 @@ urgent::
Compares the urgent state of the window. Can be "latest" or "oldest". Compares the urgent state of the window. Can be "latest" or "oldest".
Matches the latest or oldest urgent window, respectively. Matches the latest or oldest urgent window, respectively.
(The following aliases are also available: newest, last, recent, first) (The following aliases are also available: newest, last, recent, first)
workspace::
Compares the workspace name of the workspace the window belongs to.
con_mark:: con_mark::
Compares the mark set for this container, see <<vim_like_marks>>. Compares the mark set for this container, see <<vim_like_marks>>.
con_id:: con_id::
Compares the i3-internal container ID, which you can get via the IPC Compares the i3-internal container ID, which you can get via the IPC
interface. Handy for scripting. interface. Handy for scripting.
The criteria +class+, +instance+, +role+, +title+ and +mark+ are actually The criteria +class+, +instance+, +role+, +title+, +workspace+ and +mark+ are
regular expressions (PCRE). See +pcresyntax(3)+ or +perldoc perlre+ for actually regular expressions (PCRE). See +pcresyntax(3)+ or +perldoc perlre+ for
information on how to use them. information on how to use them.
[[exec]] [[exec]]

View File

@ -417,6 +417,7 @@ struct Match {
struct regex *instance; struct regex *instance;
struct regex *mark; struct regex *mark;
struct regex *window_role; struct regex *window_role;
struct regex *workspace;
xcb_atom_t window_type; xcb_atom_t window_type;
enum { enum {
U_DONTCHECK = -1, U_DONTCHECK = -1,

View File

@ -51,6 +51,7 @@ state CRITERIA:
ctype = 'con_mark' -> CRITERION ctype = 'con_mark' -> CRITERION
ctype = 'title' -> CRITERION ctype = 'title' -> CRITERION
ctype = 'urgent' -> CRITERION ctype = 'urgent' -> CRITERION
ctype = 'workspace' -> CRITERION
']' -> call cmd_criteria_match_windows(); INITIAL ']' -> call cmd_criteria_match_windows(); INITIAL
state CRITERION: state CRITERION:

View File

@ -170,6 +170,7 @@ state CRITERIA:
ctype = 'con_mark' -> CRITERION ctype = 'con_mark' -> CRITERION
ctype = 'title' -> CRITERION ctype = 'title' -> CRITERION
ctype = 'urgent' -> CRITERION ctype = 'urgent' -> CRITERION
ctype = 'workspace' -> CRITERION
']' ']'
-> call cfg_criteria_pop_state() -> call cfg_criteria_pop_state()

View File

@ -411,6 +411,11 @@ void cmd_criteria_add(I3_CMD, char *ctype, char *cvalue) {
return; return;
} }
if (strcmp(ctype, "workspace") == 0) {
current_match->workspace = regex_new(cvalue);
return;
}
ELOG("Unknown criterion: %s\n", ctype); ELOG("Unknown criterion: %s\n", ctype);
} }

View File

@ -137,6 +137,11 @@ CFGFUN(criteria_add, const char *ctype, const char *cvalue) {
return; return;
} }
if (strcmp(ctype, "workspace") == 0) {
current_match->workspace = regex_new(cvalue);
return;
}
ELOG("Unknown criterion: %s\n", ctype); ELOG("Unknown criterion: %s\n", ctype);
} }

View File

@ -48,6 +48,7 @@ bool match_is_empty(Match *match) {
match->class == NULL && match->class == NULL &&
match->instance == NULL && match->instance == NULL &&
match->window_role == NULL && match->window_role == NULL &&
match->workspace == NULL &&
match->urgent == U_DONTCHECK && match->urgent == U_DONTCHECK &&
match->id == XCB_NONE && match->id == XCB_NONE &&
match->window_type == UINT32_MAX && match->window_type == UINT32_MAX &&
@ -78,6 +79,7 @@ void match_copy(Match *dest, Match *src) {
DUPLICATE_REGEX(class); DUPLICATE_REGEX(class);
DUPLICATE_REGEX(instance); DUPLICATE_REGEX(instance);
DUPLICATE_REGEX(window_role); DUPLICATE_REGEX(window_role);
DUPLICATE_REGEX(workspace);
} }
/* /*
@ -172,6 +174,19 @@ bool match_matches_window(Match *match, i3Window *window) {
LOG("urgent matches oldest\n"); 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 (match->dock != M_DONTCHECK) {
if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) || if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) ||
(window->dock == W_DOCK_BOTTOM && match->dock == M_DOCK_BOTTOM) || (window->dock == W_DOCK_BOTTOM && match->dock == M_DOCK_BOTTOM) ||

View File

@ -17,6 +17,8 @@
use i3test i3_autostart => 0; use i3test i3_autostart => 0;
use X11::XCB qw(PROP_MODE_REPLACE); use X11::XCB qw(PROP_MODE_REPLACE);
my (@nodes);
############################################################## ##############################################################
# 1: test the following directive: # 1: test the following directive:
# for_window [class="borderless"] border none # 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; done_testing;