layout toggle: take any combination of layouts as arguments (#2649)

With this PR the 'layout toggle' command can be passed any
combination of valid layout keywords as arguments. They will
be activated one after another each time you issue the command,
advancing from left to right always selecting the layout after
the currently active layout or the leftmost layout if the active
layout is not in the argument list.

This PR also incorporates the feature request from #2476.
This commit is contained in:
s3rb31
2017-01-19 20:49:56 +01:00
parent 3410cb256d
commit 37658bd6d7
5 changed files with 143 additions and 20 deletions

View File

@ -1719,28 +1719,64 @@ void con_toggle_layout(Con *con, const char *toggle_mode) {
parent = con->parent;
DLOG("con_toggle_layout(%p, %s), parent = %p\n", con, toggle_mode, parent);
if (strcmp(toggle_mode, "split") == 0) {
/* Toggle between splits. When the current layout is not a split
* layout, we just switch back to last_split_layout. Otherwise, we
* change to the opposite split layout. */
if (parent->layout != L_SPLITH && parent->layout != L_SPLITV)
con_set_layout(con, parent->last_split_layout);
else {
if (parent->layout == L_SPLITH)
con_set_layout(con, L_SPLITV);
else
con_set_layout(con, L_SPLITH);
const char delim[] = " ";
if (strcasecmp(toggle_mode, "split") == 0 || strstr(toggle_mode, delim)) {
/* L_DEFAULT is used as a placeholder value to distinguish if
* the first layout has already been saved. (it can never be L_DEFAULT) */
layout_t new_layout = L_DEFAULT;
bool current_layout_found = false;
char *tm_dup = sstrdup(toggle_mode);
char *cur_tok = strtok(tm_dup, delim);
for (layout_t layout; cur_tok != NULL; cur_tok = strtok(NULL, delim)) {
if (strcasecmp(cur_tok, "split") == 0) {
/* Toggle between splits. When the current layout is not a split
* layout, we just switch back to last_split_layout. Otherwise, we
* change to the opposite split layout. */
if (parent->layout != L_SPLITH && parent->layout != L_SPLITV) {
layout = parent->last_split_layout;
} else {
layout = (parent->layout == L_SPLITH) ? L_SPLITV : L_SPLITH;
}
} else {
bool success = layout_from_name(cur_tok, &layout);
if (!success || layout == L_DEFAULT) {
ELOG("The token '%s' was not recognized and has been skipped.\n", cur_tok);
continue;
}
}
/* If none of the specified layouts match the current,
* fall back to the first layout in the list */
if (new_layout == L_DEFAULT) {
new_layout = layout;
}
/* We found the active layout in the last iteration, so
* now let's activate the current layout (next in list) */
if (current_layout_found) {
new_layout = layout;
free(tm_dup);
break;
}
if (parent->layout == layout) {
current_layout_found = true;
}
}
} else {
con_set_layout(con, new_layout);
} else if (strcasecmp(toggle_mode, "all") == 0 || strcasecmp(toggle_mode, "default") == 0) {
if (parent->layout == L_STACKED)
con_set_layout(con, L_TABBED);
else if (parent->layout == L_TABBED) {
if (strcmp(toggle_mode, "all") == 0)
if (strcasecmp(toggle_mode, "all") == 0)
con_set_layout(con, L_SPLITH);
else
con_set_layout(con, parent->last_split_layout);
} else if (parent->layout == L_SPLITH || parent->layout == L_SPLITV) {
if (strcmp(toggle_mode, "all") == 0) {
if (strcasecmp(toggle_mode, "all") == 0) {
/* When toggling through all modes, we toggle between
* splith/splitv, whereas normally we just directly jump to
* stacked. */