From 9537ada5ad8ec1f43a3dbdf69d92cc6b0dd0ac0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Tue, 20 Oct 2015 08:14:42 +0200 Subject: [PATCH] Make 'unmark' aware of matched windows. This patch allows using 'unmark' on matched windows. The old behavior of applying it to all windows if no criteria were specified is kept. relates to #2014 --- docs/userguide | 18 ++++++++++----- include/con.h | 8 ++++--- src/commands.c | 9 +++++++- src/con.c | 59 +++++++++++++++++++++++++++----------------------- 4 files changed, 58 insertions(+), 36 deletions(-) diff --git a/docs/userguide b/docs/userguide index e07e544d..21caae6e 100644 --- a/docs/userguide +++ b/docs/userguide @@ -2132,11 +2132,19 @@ unmark ---------------------------------------------- *Example (in a terminal)*: ------------------------------- -$ i3-msg mark irssi -$ i3-msg '[con_mark="irssi"] focus' -$ i3-msg unmark irssi ------------------------------- +--------------------------------------------------------- +# marks the focused container +mark irssi + +# focus the container with the mark "irssi" +'[con_mark="irssi"] focus' + +# remove the mark "irssi" from whichever container has it +unmark irssi + +# remove all marks on all firefox windows +[class="(?i)firefox"] unmark +--------------------------------------------------------- /////////////////////////////////////////////////////////////////// TODO: make i3-input replace %s diff --git a/include/con.h b/include/con.h index b448b8c2..1c8e341b 100644 --- a/include/con.h +++ b/include/con.h @@ -166,12 +166,14 @@ void con_mark_toggle(Con *con, const char *mark, mark_mode_t mode); */ void con_mark(Con *con, const char *mark, mark_mode_t mode); -/** - * If mark is NULL, this removes all existing marks. +/* + * Removes marks from containers. + * If con is NULL, all containers are considered. + * If name is NULL, this removes all existing marks. * Otherwise, it will only remove the given mark (if it is present). * */ -void con_unmark(const char *mark); +void con_unmark(Con *con, const char *name); /** * Returns the first container below 'con' which wants to swallow this window diff --git a/src/commands.c b/src/commands.c index a9b98c53..f1cc969b 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1040,7 +1040,14 @@ void cmd_mark(I3_CMD, const char *mark, const char *mode, const char *toggle) { * */ void cmd_unmark(I3_CMD, const char *mark) { - con_unmark(mark); + if (match_is_empty(current_match)) { + con_unmark(NULL, mark); + } else { + owindow *current; + TAILQ_FOREACH(current, &owindows, owindows) { + con_unmark(current->con, mark); + } + } cmd_output->needs_tree_render = true; // XXX: default reply for now, make this a better reply diff --git a/src/con.c b/src/con.c index 9238acad..cebe0a7e 100644 --- a/src/con.c +++ b/src/con.c @@ -545,7 +545,7 @@ void con_mark_toggle(Con *con, const char *mark, mark_mode_t mode) { DLOG("Toggling mark \"%s\" on con = %p.\n", mark, con); if (con_has_mark(con, mark)) { - con_unmark(mark); + con_unmark(con, mark); } else { con_mark(con, mark, mode); } @@ -559,13 +559,13 @@ void con_mark(Con *con, const char *mark, mark_mode_t mode) { assert(con != NULL); DLOG("Setting mark \"%s\" on con = %p.\n", mark, con); - con_unmark(mark); + con_unmark(NULL, mark); if (mode == MM_REPLACE) { DLOG("Removing all existing marks on con = %p.\n", con); mark_t *current; TAILQ_FOREACH(current, &(con->marks_head), marks) { - con_unmark(current->name); + con_unmark(con, current->name); } } @@ -577,47 +577,52 @@ void con_mark(Con *con, const char *mark, mark_mode_t mode) { } /* - * If mark is NULL, this removes all existing marks. + * Removes marks from containers. + * If con is NULL, all containers are considered. + * If name is NULL, this removes all existing marks. * Otherwise, it will only remove the given mark (if it is present). * */ -void con_unmark(const char *mark) { - Con *con; - if (mark == NULL) { +void con_unmark(Con *con, const char *name) { + Con *current; + if (name == NULL) { DLOG("Unmarking all containers.\n"); - TAILQ_FOREACH(con, &all_cons, all_cons) { - if (TAILQ_EMPTY(&(con->marks_head))) + TAILQ_FOREACH(current, &all_cons, all_cons) { + if (con != NULL && current != con) continue; - mark_t *current; - while (!TAILQ_EMPTY(&(con->marks_head))) { - current = TAILQ_FIRST(&(con->marks_head)); - FREE(current->name); - TAILQ_REMOVE(&(con->marks_head), current, marks); - FREE(current); + if (TAILQ_EMPTY(&(current->marks_head))) + continue; + + mark_t *mark; + while (!TAILQ_EMPTY(&(current->marks_head))) { + mark = TAILQ_FIRST(&(current->marks_head)); + FREE(mark->name); + TAILQ_REMOVE(&(current->marks_head), mark, marks); + FREE(mark); } - con->mark_changed = true; + current->mark_changed = true; } } else { - DLOG("Removing mark \"%s\".\n", mark); - con = con_by_mark(mark); - if (con == NULL) { + DLOG("Removing mark \"%s\".\n", name); + current = (con == NULL) ? con_by_mark(name) : con; + if (current == NULL) { DLOG("No container found with this mark, so there is nothing to do.\n"); return; } - DLOG("Found mark on con = %p. Removing it now.\n", con); - con->mark_changed = true; + DLOG("Found mark on con = %p. Removing it now.\n", current); + current->mark_changed = true; - mark_t *current; - TAILQ_FOREACH(current, &(con->marks_head), marks) { - if (strcmp(current->name, mark) != 0) + mark_t *mark; + TAILQ_FOREACH(mark, &(current->marks_head), marks) { + if (strcmp(mark->name, name) != 0) continue; - FREE(current->name); - TAILQ_REMOVE(&(con->marks_head), current, marks); - FREE(current); + FREE(mark->name); + TAILQ_REMOVE(&(current->marks_head), mark, marks); + FREE(mark); break; } }