Merge pull request #2649 from s3rb31/next
layout toggle: take any combination of layouts as arguments (continuation of #2476)
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
64
src/con.c
64
src/con.c
@ -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. */
|
||||
|
28
src/util.c
28
src/util.c
@ -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".
|
||||
|
Reference in New Issue
Block a user