Merge pull request #2649 from s3rb31/next

layout toggle: take any combination of layouts as arguments (continuation of #2476)
This commit is contained in:
Ingo Bürk
2017-02-24 00:58:19 +01:00
committed by GitHub
7 changed files with 173 additions and 30 deletions

View File

@ -1489,21 +1489,8 @@ void cmd_move_direction(I3_CMD, const char *direction, long move_px) {
void cmd_layout(I3_CMD, const char *layout_str) {
HANDLE_EMPTY_MATCH;
if (strcmp(layout_str, "stacking") == 0)
layout_str = "stacked";
layout_t layout;
/* default is a special case which will be handled in con_set_layout(). */
if (strcmp(layout_str, "default") == 0)
layout = L_DEFAULT;
else if (strcmp(layout_str, "stacked") == 0)
layout = L_STACKED;
else if (strcmp(layout_str, "tabbed") == 0)
layout = L_TABBED;
else if (strcmp(layout_str, "splitv") == 0)
layout = L_SPLITV;
else if (strcmp(layout_str, "splith") == 0)
layout = L_SPLITH;
else {
if (!layout_from_name(layout_str, &layout)) {
ELOG("Unknown layout \"%s\", this is a mismatch between code and parser spec.\n", layout_str);
return;
}

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. */

View File

@ -66,6 +66,34 @@ __attribute__((pure)) bool name_is_digits(const char *name) {
return true;
}
/*
* Set 'out' to the layout_t value for the given layout. The function
* returns true on success or false if the passed string is not a valid
* layout name.
*
*/
bool layout_from_name(const char *layout_str, layout_t *out) {
if (strcmp(layout_str, "default") == 0) {
*out = L_DEFAULT;
return true;
} else if (strcasecmp(layout_str, "stacked") == 0 ||
strcasecmp(layout_str, "stacking") == 0) {
*out = L_STACKED;
return true;
} else if (strcasecmp(layout_str, "tabbed") == 0) {
*out = L_TABBED;
return true;
} else if (strcasecmp(layout_str, "splitv") == 0) {
*out = L_SPLITV;
return true;
} else if (strcasecmp(layout_str, "splith") == 0) {
*out = L_SPLITH;
return true;
}
return false;
}
/*
* Parses the workspace name as a number. Returns -1 if the workspace should be
* interpreted as a "named workspace".