Validate matched containers for "kill" command correctly.
We now execute the validations when "kill" is executed even if match criteria are used. This prevents users from killing workspace containers, which instead kills all clients (as before when not using criteria). fixes #1761
This commit is contained in:
parent
0dd71674de
commit
19c273a2ad
|
@ -30,6 +30,12 @@ Con *con_new(Con *parent, i3Window *window);
|
||||||
*/
|
*/
|
||||||
void con_focus(Con *con);
|
void con_focus(Con *con);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the given container.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void con_close(Con *con, kill_window_t kill_window);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true when this node is a leaf node (has no children)
|
* Returns true when this node is a leaf node (has no children)
|
||||||
*
|
*
|
||||||
|
|
|
@ -56,12 +56,6 @@ bool level_down(void);
|
||||||
*/
|
*/
|
||||||
void tree_render(void);
|
void tree_render(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the current container using tree_close_internal().
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void tree_close_con(kill_window_t kill_window);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes focus in the given way (next/previous) and given orientation
|
* Changes focus in the given way (next/previous) and given orientation
|
||||||
* (horizontal/vertical).
|
* (horizontal/vertical).
|
||||||
|
|
|
@ -1258,7 +1258,6 @@ void cmd_split(I3_CMD, const char *direction) {
|
||||||
void cmd_kill(I3_CMD, const char *kill_mode_str) {
|
void cmd_kill(I3_CMD, const char *kill_mode_str) {
|
||||||
if (kill_mode_str == NULL)
|
if (kill_mode_str == NULL)
|
||||||
kill_mode_str = "window";
|
kill_mode_str = "window";
|
||||||
owindow *current;
|
|
||||||
|
|
||||||
DLOG("kill_mode=%s\n", kill_mode_str);
|
DLOG("kill_mode=%s\n", kill_mode_str);
|
||||||
|
|
||||||
|
@ -1273,16 +1272,11 @@ void cmd_kill(I3_CMD, const char *kill_mode_str) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE_INVALID_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
/* check if the match is empty, not if the result is empty */
|
owindow *current;
|
||||||
if (match_is_empty(current_match))
|
|
||||||
tree_close_con(kill_mode);
|
|
||||||
else {
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH(current, &owindows, owindows) {
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
con_close(current->con, kill_mode);
|
||||||
tree_close_internal(current->con, kill_mode, false, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
|
|
30
src/con.c
30
src/con.c
|
@ -220,6 +220,36 @@ void con_focus(Con *con) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Closes the given container.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void con_close(Con *con, kill_window_t kill_window) {
|
||||||
|
assert(con != NULL);
|
||||||
|
DLOG("Closing con = %p.\n", con);
|
||||||
|
|
||||||
|
/* We never close output or root containers. */
|
||||||
|
if (con->type == CT_OUTPUT || con->type == CT_ROOT) {
|
||||||
|
DLOG("con = %p is of type %d, not closing anything.\n", con, con->type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->type == CT_WORKSPACE) {
|
||||||
|
DLOG("con = %p is a workspace, closing all children instead.\n", con);
|
||||||
|
Con *child, *nextchild;
|
||||||
|
for (child = TAILQ_FIRST(&(con->focus_head)); child;) {
|
||||||
|
nextchild = TAILQ_NEXT(child, focused);
|
||||||
|
DLOG("killing child = %p.\n", child);
|
||||||
|
tree_close_internal(child, kill_window, false, false);
|
||||||
|
child = nextchild;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_close_internal(con, kill_window, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true when this node is a leaf node (has no children)
|
* Returns true when this node is a leaf node (has no children)
|
||||||
*
|
*
|
||||||
|
|
28
src/tree.c
28
src/tree.c
|
@ -362,34 +362,6 @@ bool tree_close_internal(Con *con, kill_window_t kill_window, bool dont_kill_par
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Closes the current container using tree_close_internal().
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void tree_close_con(kill_window_t kill_window) {
|
|
||||||
assert(focused != NULL);
|
|
||||||
|
|
||||||
/* There *should* be no possibility to focus outputs / root container */
|
|
||||||
assert(focused->type != CT_OUTPUT);
|
|
||||||
assert(focused->type != CT_ROOT);
|
|
||||||
|
|
||||||
if (focused->type == CT_WORKSPACE) {
|
|
||||||
DLOG("Workspaces cannot be close, closing all children instead\n");
|
|
||||||
Con *child, *nextchild;
|
|
||||||
for (child = TAILQ_FIRST(&(focused->focus_head)); child;) {
|
|
||||||
nextchild = TAILQ_NEXT(child, focused);
|
|
||||||
DLOG("killing child=%p\n", child);
|
|
||||||
tree_close_internal(child, kill_window, false, false);
|
|
||||||
child = nextchild;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Kill con */
|
|
||||||
tree_close_internal(focused, kill_window, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Splits (horizontally or vertically) the given container by creating a new
|
* Splits (horizontally or vertically) the given container by creating a new
|
||||||
* container which contains the old one and the future ones.
|
* container which contains the old one and the future ones.
|
||||||
|
|
|
@ -27,9 +27,11 @@ $ws = fresh_workspace;
|
||||||
open_window(wm_class => 'matchme');
|
open_window(wm_class => 'matchme');
|
||||||
|
|
||||||
cmd '[con_id=__focused__ class=doesnotmatch] kill';
|
cmd '[con_id=__focused__ class=doesnotmatch] kill';
|
||||||
|
sync_with_i3;
|
||||||
is(@{get_ws($ws)->{nodes}}, 1, 'window was not killed');
|
is(@{get_ws($ws)->{nodes}}, 1, 'window was not killed');
|
||||||
|
|
||||||
cmd '[con_id=__focused__ class=matchme] kill';
|
cmd '[con_id=__focused__ class=matchme] kill';
|
||||||
|
sync_with_i3;
|
||||||
is(@{get_ws($ws)->{nodes}}, 0, 'window was killed');
|
is(@{get_ws($ws)->{nodes}}, 0, 'window was killed');
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -41,9 +43,11 @@ open_window(wm_class => 'matchme');
|
||||||
cmd 'mark marked';
|
cmd 'mark marked';
|
||||||
|
|
||||||
cmd '[con_mark=marked class=doesnotmatch] kill';
|
cmd '[con_mark=marked class=doesnotmatch] kill';
|
||||||
|
sync_with_i3;
|
||||||
is(@{get_ws($ws)->{nodes}}, 1, 'window was not killed');
|
is(@{get_ws($ws)->{nodes}}, 1, 'window was not killed');
|
||||||
|
|
||||||
cmd '[con_mark=marked class=matchme] kill';
|
cmd '[con_mark=marked class=matchme] kill';
|
||||||
|
sync_with_i3;
|
||||||
is(@{get_ws($ws)->{nodes}}, 0, 'window was killed');
|
is(@{get_ws($ws)->{nodes}}, 0, 'window was killed');
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
Loading…
Reference in New Issue