Introduce "--add" for marking windows.
In order to keep compatibility to before allowing multiple marks on a window, we introduce a flag "--add" that must be set to put more than one mark on a window. The default, which is also available as "--replace", keeps the old behavior of overwriting a mark when setting a new one. fixes #2014
This commit is contained in:
parent
9bb2f038ab
commit
7a77c5f0bb
|
@ -2115,17 +2115,21 @@ for this purpose: It lets you input a command and sends the command to i3. It
|
||||||
can also prefix this command and display a custom prompt for the input dialog.
|
can also prefix this command and display a custom prompt for the input dialog.
|
||||||
|
|
||||||
The additional +--toggle+ option will remove the mark if the window already has
|
The additional +--toggle+ option will remove the mark if the window already has
|
||||||
this mark, add it if the window has none or replace the current mark if it has
|
this mark or add it otherwise. Note that you may need to use this in
|
||||||
another mark.
|
combination with +--add+ (see below) as any other marks will otherwise be
|
||||||
|
removed.
|
||||||
|
|
||||||
|
By default, a window can only have one mark. You can use the +--add+ flag to
|
||||||
|
put more than one mark on a window.
|
||||||
|
|
||||||
Refer to <<show_marks>> if you don't want marks to be shown in the window decoration.
|
Refer to <<show_marks>> if you don't want marks to be shown in the window decoration.
|
||||||
|
|
||||||
*Syntax*:
|
*Syntax*:
|
||||||
------------------------------
|
----------------------------------------------
|
||||||
mark [--toggle] <identifier>
|
mark [--add|--replace] [--toggle] <identifier>
|
||||||
[con_mark="identifier"] focus
|
[con_mark="identifier"] focus
|
||||||
unmark <identifier>
|
unmark <identifier>
|
||||||
------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
*Example (in a terminal)*:
|
*Example (in a terminal)*:
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
|
@ -115,10 +115,10 @@ void cmd_workspace_back_and_forth(I3_CMD);
|
||||||
void cmd_workspace_name(I3_CMD, const char *name);
|
void cmd_workspace_name(I3_CMD, const char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of 'mark [--toggle] <mark>'
|
* Implementation of 'mark [--add|--replace] [--toggle] <mark>'
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cmd_mark(I3_CMD, const char *mark, const char *toggle);
|
void cmd_mark(I3_CMD, const char *mark, const char *mode, const char *toggle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of 'unmark [mark]'
|
* Implementation of 'unmark [mark]'
|
||||||
|
|
|
@ -158,13 +158,13 @@ bool con_has_mark(Con *con, const char *mark);
|
||||||
* Otherwise, the mark is assigned to the container.
|
* Otherwise, the mark is assigned to the container.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void con_mark_toggle(Con *con, const char *mark);
|
void con_mark_toggle(Con *con, const char *mark, mark_mode_t mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns a mark to the container.
|
* Assigns a mark to the container.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void con_mark(Con *con, const char *mark);
|
void con_mark(Con *con, const char *mark, mark_mode_t mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If mark is NULL, this removes all existing marks.
|
* If mark is NULL, this removes all existing marks.
|
||||||
|
|
|
@ -75,6 +75,9 @@ typedef enum { ADJ_NONE = 0,
|
||||||
ADJ_UPPER_SCREEN_EDGE = (1 << 2),
|
ADJ_UPPER_SCREEN_EDGE = (1 << 2),
|
||||||
ADJ_LOWER_SCREEN_EDGE = (1 << 4) } adjacent_t;
|
ADJ_LOWER_SCREEN_EDGE = (1 << 4) } adjacent_t;
|
||||||
|
|
||||||
|
typedef enum { MM_REPLACE,
|
||||||
|
MM_ADD } mark_mode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container layouts. See Con::layout.
|
* Container layouts. See Con::layout.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -199,12 +199,14 @@ state FLOATING:
|
||||||
floating = 'enable', 'disable', 'toggle'
|
floating = 'enable', 'disable', 'toggle'
|
||||||
-> call cmd_floating($floating)
|
-> call cmd_floating($floating)
|
||||||
|
|
||||||
# mark [--toggle] <mark>
|
# mark [--add|--replace] [--toggle] <mark>
|
||||||
state MARK:
|
state MARK:
|
||||||
|
mode = '--add', '--replace'
|
||||||
|
->
|
||||||
toggle = '--toggle'
|
toggle = '--toggle'
|
||||||
->
|
->
|
||||||
mark = string
|
mark = string
|
||||||
-> call cmd_mark($mark, $toggle)
|
-> call cmd_mark($mark, $mode, $toggle)
|
||||||
|
|
||||||
# unmark [mark]
|
# unmark [mark]
|
||||||
state UNMARK:
|
state UNMARK:
|
||||||
|
|
|
@ -1003,10 +1003,10 @@ void cmd_workspace_name(I3_CMD, const char *name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implementation of 'mark [--toggle] <mark>'
|
* Implementation of 'mark [--add|--replace] [--toggle] <mark>'
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cmd_mark(I3_CMD, const char *mark, const char *toggle) {
|
void cmd_mark(I3_CMD, const char *mark, const char *mode, const char *toggle) {
|
||||||
HANDLE_EMPTY_MATCH;
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
owindow *current = TAILQ_FIRST(&owindows);
|
owindow *current = TAILQ_FIRST(&owindows);
|
||||||
|
@ -1022,10 +1022,12 @@ void cmd_mark(I3_CMD, const char *mark, const char *toggle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
|
|
||||||
|
mark_mode_t mark_mode = (mode == NULL || strcmp(mode, "--replace") == 0) ? MM_REPLACE : MM_ADD;
|
||||||
if (toggle != NULL) {
|
if (toggle != NULL) {
|
||||||
con_mark_toggle(current->con, mark);
|
con_mark_toggle(current->con, mark, mark_mode);
|
||||||
} else {
|
} else {
|
||||||
con_mark(current->con, mark);
|
con_mark(current->con, mark, mark_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
|
|
14
src/con.c
14
src/con.c
|
@ -540,14 +540,14 @@ bool con_has_mark(Con *con, const char *mark) {
|
||||||
* Otherwise, the mark is assigned to the container.
|
* Otherwise, the mark is assigned to the container.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void con_mark_toggle(Con *con, const char *mark) {
|
void con_mark_toggle(Con *con, const char *mark, mark_mode_t mode) {
|
||||||
assert(con != NULL);
|
assert(con != NULL);
|
||||||
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(mark);
|
||||||
} else {
|
} else {
|
||||||
con_mark(con, mark);
|
con_mark(con, mark, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,11 +555,19 @@ void con_mark_toggle(Con *con, const char *mark) {
|
||||||
* Assigns a mark to the container.
|
* Assigns a mark to the container.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void con_mark(Con *con, const char *mark) {
|
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(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mark_t *new = scalloc(1, sizeof(mark_t));
|
mark_t *new = scalloc(1, sizeof(mark_t));
|
||||||
new->name = sstrdup(mark);
|
new->name = sstrdup(mark);
|
||||||
|
|
|
@ -246,7 +246,7 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
|
||||||
char *mark;
|
char *mark;
|
||||||
sasprintf(&mark, "%.*s", (int)len, val);
|
sasprintf(&mark, "%.*s", (int)len, val);
|
||||||
|
|
||||||
con_mark(json_node, mark);
|
con_mark(json_node, mark, MM_ADD);
|
||||||
} else {
|
} else {
|
||||||
if (strcasecmp(last_key, "name") == 0) {
|
if (strcasecmp(last_key, "name") == 0) {
|
||||||
json_node->name = scalloc(len + 1, 1);
|
json_node->name = scalloc(len + 1, 1);
|
||||||
|
@ -354,7 +354,7 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
sasprintf(&buf, "%.*s", (int)len, val);
|
sasprintf(&buf, "%.*s", (int)len, val);
|
||||||
|
|
||||||
con_mark(json_node, buf);
|
con_mark(json_node, buf, MM_REPLACE);
|
||||||
} else if (strcasecmp(last_key, "floating") == 0) {
|
} else if (strcasecmp(last_key, "floating") == 0) {
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
sasprintf(&buf, "%.*s", (int)len, val);
|
sasprintf(&buf, "%.*s", (int)len, val);
|
||||||
|
|
|
@ -118,7 +118,17 @@ cmd 'mark --toggle important';
|
||||||
is_deeply(get_mark_for_window_on_workspace($tmp, $con), [ 'important' ], 'container now has the mark');
|
is_deeply(get_mark_for_window_on_workspace($tmp, $con), [ 'important' ], 'container now has the mark');
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
# 7: mark a con, toggle the mark on another con,
|
# 7: mark a con, toggle a different mark, check it is marked
|
||||||
|
# with the new mark
|
||||||
|
##############################################################
|
||||||
|
|
||||||
|
$con = open_window;
|
||||||
|
cmd 'mark boring';
|
||||||
|
cmd 'mark --replace --toggle important';
|
||||||
|
is_deeply(get_mark_for_window_on_workspace($tmp, $con), [ 'important' ], 'container has the most recent mark');
|
||||||
|
|
||||||
|
##############################################################
|
||||||
|
# 8: mark a con, toggle the mark on another con,
|
||||||
# check only the latter has the mark
|
# check only the latter has the mark
|
||||||
##############################################################
|
##############################################################
|
||||||
|
|
||||||
|
@ -133,7 +143,7 @@ is_deeply(get_mark_for_window_on_workspace($tmp, $first), [ 'important' ], 'left
|
||||||
ok(!get_mark_for_window_on_workspace($tmp, $second), 'second containr no longer has the mark');
|
ok(!get_mark_for_window_on_workspace($tmp, $second), 'second containr no longer has the mark');
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
# 8: try to mark two cons with the same mark and check that
|
# 9: try to mark two cons with the same mark and check that
|
||||||
# it fails
|
# it fails
|
||||||
##############################################################
|
##############################################################
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ sub get_mark_for_window_on_workspace {
|
||||||
|
|
||||||
$ws = fresh_workspace;
|
$ws = fresh_workspace;
|
||||||
$con = open_window;
|
$con = open_window;
|
||||||
cmd 'mark A';
|
cmd 'mark --add A';
|
||||||
cmd 'mark B';
|
cmd 'mark --add B';
|
||||||
|
|
||||||
is_deeply(sort(get_marks()), [ 'A', 'B' ], 'both marks exist');
|
is_deeply(sort(get_marks()), [ 'A', 'B' ], 'both marks exist');
|
||||||
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B' ], 'both marks are on the same window');
|
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B' ], 'both marks are on the same window');
|
||||||
|
@ -54,9 +54,9 @@ $ws = fresh_workspace;
|
||||||
$con = open_window;
|
$con = open_window;
|
||||||
cmd 'mark A';
|
cmd 'mark A';
|
||||||
|
|
||||||
cmd 'mark --toggle B';
|
cmd 'mark --add --toggle B';
|
||||||
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B' ], 'both marks are on the same window');
|
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B' ], 'both marks are on the same window');
|
||||||
cmd 'mark --toggle B';
|
cmd 'mark --add --toggle B';
|
||||||
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A' ], 'only mark B has been removed');
|
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A' ], 'only mark B has been removed');
|
||||||
|
|
||||||
cmd 'unmark';
|
cmd 'unmark';
|
||||||
|
@ -67,9 +67,9 @@ cmd 'unmark';
|
||||||
|
|
||||||
$ws = fresh_workspace;
|
$ws = fresh_workspace;
|
||||||
$con = open_window;
|
$con = open_window;
|
||||||
cmd 'mark A';
|
cmd 'mark --add A';
|
||||||
cmd 'mark B';
|
cmd 'mark --add B';
|
||||||
cmd 'mark C';
|
cmd 'mark --add C';
|
||||||
|
|
||||||
cmd 'unmark B';
|
cmd 'unmark B';
|
||||||
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'C' ], 'only mark B has been removed');
|
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'C' ], 'only mark B has been removed');
|
||||||
|
@ -82,11 +82,11 @@ cmd 'unmark';
|
||||||
|
|
||||||
$ws = fresh_workspace;
|
$ws = fresh_workspace;
|
||||||
$con = open_window;
|
$con = open_window;
|
||||||
cmd 'mark A';
|
cmd 'mark --add A';
|
||||||
cmd 'mark B';
|
cmd 'mark --add B';
|
||||||
open_window;
|
open_window;
|
||||||
|
|
||||||
cmd '[con_mark=B] mark C';
|
cmd '[con_mark=B] mark --add C';
|
||||||
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B', 'C' ], 'matching on a mark works with multiple marks');
|
is_deeply(get_mark_for_window_on_workspace($ws, $con), [ 'A', 'B', 'C' ], 'matching on a mark works with multiple marks');
|
||||||
|
|
||||||
cmd 'unmark';
|
cmd 'unmark';
|
||||||
|
|
Loading…
Reference in New Issue