From 19c273a2adde5e6248566b7bd13b5cee80f84b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sun, 27 Dec 2015 22:11:51 -0500 Subject: [PATCH] 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 --- include/con.h | 6 ++++ include/tree.h | 6 ---- src/commands.c | 14 +++------ src/con.c | 30 +++++++++++++++++++ src/tree.c | 28 ----------------- .../261-match-con_id-con_mark-combinations.t | 4 +++ 6 files changed, 44 insertions(+), 44 deletions(-) diff --git a/include/con.h b/include/con.h index 655fde7f..db5fcfbf 100644 --- a/include/con.h +++ b/include/con.h @@ -30,6 +30,12 @@ Con *con_new(Con *parent, i3Window *window); */ 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) * diff --git a/include/tree.h b/include/tree.h index 4a640446..c64c173d 100644 --- a/include/tree.h +++ b/include/tree.h @@ -56,12 +56,6 @@ bool level_down(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 * (horizontal/vertical). diff --git a/src/commands.c b/src/commands.c index eb1834e7..579b5e0e 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1258,7 +1258,6 @@ void cmd_split(I3_CMD, const char *direction) { void cmd_kill(I3_CMD, const char *kill_mode_str) { if (kill_mode_str == NULL) kill_mode_str = "window"; - owindow *current; DLOG("kill_mode=%s\n", kill_mode_str); @@ -1273,16 +1272,11 @@ void cmd_kill(I3_CMD, const char *kill_mode_str) { return; } - HANDLE_INVALID_MATCH; + HANDLE_EMPTY_MATCH; - /* check if the match is empty, not if the result is empty */ - if (match_is_empty(current_match)) - tree_close_con(kill_mode); - else { - TAILQ_FOREACH(current, &owindows, owindows) { - DLOG("matching: %p / %s\n", current->con, current->con->name); - tree_close_internal(current->con, kill_mode, false, false); - } + owindow *current; + TAILQ_FOREACH(current, &owindows, owindows) { + con_close(current->con, kill_mode); } cmd_output->needs_tree_render = true; diff --git a/src/con.c b/src/con.c index f0353f97..591419e4 100644 --- a/src/con.c +++ b/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) * diff --git a/src/tree.c b/src/tree.c index e296a981..5642c5c7 100644 --- a/src/tree.c +++ b/src/tree.c @@ -362,34 +362,6 @@ bool tree_close_internal(Con *con, kill_window_t kill_window, bool dont_kill_par 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 * container which contains the old one and the future ones. diff --git a/testcases/t/261-match-con_id-con_mark-combinations.t b/testcases/t/261-match-con_id-con_mark-combinations.t index b255558e..61ff1ff0 100644 --- a/testcases/t/261-match-con_id-con_mark-combinations.t +++ b/testcases/t/261-match-con_id-con_mark-combinations.t @@ -27,9 +27,11 @@ $ws = fresh_workspace; open_window(wm_class => 'matchme'); cmd '[con_id=__focused__ class=doesnotmatch] kill'; +sync_with_i3; is(@{get_ws($ws)->{nodes}}, 1, 'window was not killed'); cmd '[con_id=__focused__ class=matchme] kill'; +sync_with_i3; is(@{get_ws($ws)->{nodes}}, 0, 'window was killed'); ############################################################################### @@ -41,9 +43,11 @@ open_window(wm_class => 'matchme'); cmd 'mark marked'; cmd '[con_mark=marked class=doesnotmatch] kill'; +sync_with_i3; is(@{get_ws($ws)->{nodes}}, 1, 'window was not killed'); cmd '[con_mark=marked class=matchme] kill'; +sync_with_i3; is(@{get_ws($ws)->{nodes}}, 0, 'window was killed'); ###############################################################################