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
This commit is contained in:
Ingo Bürk 2015-10-20 08:14:42 +02:00
parent 7a77c5f0bb
commit 9537ada5ad
4 changed files with 58 additions and 36 deletions

View File

@ -2132,11 +2132,19 @@ unmark <identifier>
---------------------------------------------- ----------------------------------------------
*Example (in a terminal)*: *Example (in a terminal)*:
------------------------------ ---------------------------------------------------------
$ i3-msg mark irssi # marks the focused container
$ i3-msg '[con_mark="irssi"] focus' mark irssi
$ i3-msg unmark 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 TODO: make i3-input replace %s

View File

@ -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); 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). * 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 * Returns the first container below 'con' which wants to swallow this window

View File

@ -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) { 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; cmd_output->needs_tree_render = true;
// XXX: default reply for now, make this a better reply // XXX: default reply for now, make this a better reply

View File

@ -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); DLOG("Toggling mark \"%s\" on con = %p.\n", mark, con);
if (con_has_mark(con, mark)) { if (con_has_mark(con, mark)) {
con_unmark(mark); con_unmark(con, mark);
} else { } else {
con_mark(con, mark, mode); con_mark(con, mark, mode);
} }
@ -559,13 +559,13 @@ void con_mark(Con *con, const char *mark, mark_mode_t mode) {
assert(con != NULL); assert(con != NULL);
DLOG("Setting mark \"%s\" on con = %p.\n", mark, con); DLOG("Setting mark \"%s\" on con = %p.\n", mark, con);
con_unmark(mark); con_unmark(NULL, mark);
if (mode == MM_REPLACE) { if (mode == MM_REPLACE) {
DLOG("Removing all existing marks on con = %p.\n", con); DLOG("Removing all existing marks on con = %p.\n", con);
mark_t *current; mark_t *current;
TAILQ_FOREACH(current, &(con->marks_head), marks) { 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). * 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) {
Con *con; Con *current;
if (mark == NULL) { if (name == NULL) {
DLOG("Unmarking all containers.\n"); DLOG("Unmarking all containers.\n");
TAILQ_FOREACH(con, &all_cons, all_cons) { TAILQ_FOREACH(current, &all_cons, all_cons) {
if (TAILQ_EMPTY(&(con->marks_head))) if (con != NULL && current != con)
continue; continue;
mark_t *current; if (TAILQ_EMPTY(&(current->marks_head)))
while (!TAILQ_EMPTY(&(con->marks_head))) { continue;
current = TAILQ_FIRST(&(con->marks_head));
FREE(current->name); mark_t *mark;
TAILQ_REMOVE(&(con->marks_head), current, marks); while (!TAILQ_EMPTY(&(current->marks_head))) {
FREE(current); 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 { } else {
DLOG("Removing mark \"%s\".\n", mark); DLOG("Removing mark \"%s\".\n", name);
con = con_by_mark(mark); current = (con == NULL) ? con_by_mark(name) : con;
if (con == NULL) { if (current == NULL) {
DLOG("No container found with this mark, so there is nothing to do.\n"); DLOG("No container found with this mark, so there is nothing to do.\n");
return; return;
} }
DLOG("Found mark on con = %p. Removing it now.\n", con); DLOG("Found mark on con = %p. Removing it now.\n", current);
con->mark_changed = true; current->mark_changed = true;
mark_t *current; mark_t *mark;
TAILQ_FOREACH(current, &(con->marks_head), marks) { TAILQ_FOREACH(mark, &(current->marks_head), marks) {
if (strcmp(current->name, mark) != 0) if (strcmp(mark->name, name) != 0)
continue; continue;
FREE(current->name); FREE(mark->name);
TAILQ_REMOVE(&(con->marks_head), current, marks); TAILQ_REMOVE(&(current->marks_head), mark, marks);
FREE(current); FREE(mark);
break; break;
} }
} }