cleanup in auto layouts

- added L_AUTO_FIRST/LAST instead of using explicit layouts.
- when switching between auto layout that don't share the same major axis, invert the
  width/height of their child views to preserve their relative proportions.
This commit is contained in:
wil 2016-12-29 20:26:35 +01:00
parent 2b0e3c212a
commit a0aa8d9780
6 changed files with 70 additions and 18 deletions

View File

@ -44,6 +44,9 @@ enum swayc_layouts {
L_AUTO_TOP, L_AUTO_TOP,
L_AUTO_BOTTOM, L_AUTO_BOTTOM,
L_AUTO_FIRST = L_AUTO_LEFT,
L_AUTO_LAST = L_AUTO_BOTTOM,
// Keep last // Keep last
L_LAYOUTS, L_LAYOUTS,
}; };

View File

@ -76,6 +76,6 @@ void swayc_log(log_importance_t verbosity, swayc_t *cont, const char* format, ..
enum swayc_layouts default_layout(swayc_t *output); enum swayc_layouts default_layout(swayc_t *output);
inline bool is_auto_layout(enum swayc_layouts layout) { inline bool is_auto_layout(enum swayc_layouts layout) {
return (layout >= L_AUTO_LEFT) && (layout <= L_AUTO_BOTTOM); return (layout >= L_AUTO_FIRST) && (layout <= L_AUTO_LAST);
} }
#endif #endif

View File

@ -56,24 +56,12 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
swayc_change_layout(parent, L_HORIZ); swayc_change_layout(parent, L_HORIZ);
} }
} else if (strcasecmp(argv[0], "auto_left") == 0) { } else if (strcasecmp(argv[0], "auto_left") == 0) {
if (parent->type != C_CONTAINER && !swayc_is_empty_workspace(parent)){
parent = new_container(parent, L_AUTO_LEFT);
}
swayc_change_layout(parent, L_AUTO_LEFT); swayc_change_layout(parent, L_AUTO_LEFT);
} else if (strcasecmp(argv[0], "auto_right") == 0) { } else if (strcasecmp(argv[0], "auto_right") == 0) {
if (parent->type != C_CONTAINER && !swayc_is_empty_workspace(parent)){
parent = new_container(parent, L_AUTO_RIGHT);
}
swayc_change_layout(parent, L_AUTO_RIGHT); swayc_change_layout(parent, L_AUTO_RIGHT);
} else if (strcasecmp(argv[0], "auto_top") == 0) { } else if (strcasecmp(argv[0], "auto_top") == 0) {
if (parent->type != C_CONTAINER && !swayc_is_empty_workspace(parent)){
parent = new_container(parent, L_AUTO_TOP);
}
swayc_change_layout(parent, L_AUTO_TOP); swayc_change_layout(parent, L_AUTO_TOP);
} else if (strcasecmp(argv[0], "auto_bot") == 0) { } else if (strcasecmp(argv[0], "auto_bot") == 0) {
if (parent->type != C_CONTAINER && !swayc_is_empty_workspace(parent)){
parent = new_container(parent, L_AUTO_BOTTOM);
}
swayc_change_layout(parent, L_AUTO_BOTTOM); swayc_change_layout(parent, L_AUTO_BOTTOM);
} else if (strcasecmp(argv[0], "incnmaster") == 0) { } else if (strcasecmp(argv[0], "incnmaster") == 0) {
if ((error = checkarg(argc, "layout incnmaster", if ((error = checkarg(argc, "layout incnmaster",
@ -105,6 +93,42 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
((int)container->parent->nb_slave_groups + inc >= 1)) { ((int)container->parent->nb_slave_groups + inc >= 1)) {
container->parent->nb_slave_groups += inc; container->parent->nb_slave_groups += inc;
} }
} else if (strcasecmp(argv[0], "auto") == 0) {
if ((error = checkarg(argc, "auto", EXPECTED_EQUAL_TO, 2))) {
return error;
}
swayc_t *container = get_focused_view(swayc_active_workspace());
swayc_t *parent = container->parent;
enum swayc_layouts layout;
if (strcasecmp(argv[1], "next") == 0) {
if (is_auto_layout(parent->layout) && parent->layout < L_AUTO_LAST) {
layout = parent->layout + 1;
} else {
layout = L_AUTO_FIRST;
}
} else if (strcasecmp(argv[1], "prev") == 0) {
if (is_auto_layout(parent->layout) && parent->layout > L_AUTO_FIRST) {
layout = parent->layout - 1;
} else {
layout = L_AUTO_FIRST;
}
} else {
return cmd_results_new(CMD_FAILURE, "layout auto",
"Must be one of <prev|next>.");
}
swayc_change_layout(parent, layout);
} else if (strcasecmp(argv[0], "promote") == 0) {
// swap first child in auto layout with currently focused child
swayc_t *container = get_focused_view(swayc_active_workspace());
swayc_t *parent = container->parent;
if (is_auto_layout(parent->layout)) {
int focused_idx = index_child(container);
swayc_t *first = parent->children->items[0];
if (focused_idx > 0) {
list_swap(parent->children, 0, focused_idx);
swap_geometry(first, container);
}
}
} }
} }

View File

@ -13,8 +13,16 @@ struct cmd_results *cmd_workspace_layout(int argc, char **argv) {
config->default_layout = L_STACKED; config->default_layout = L_STACKED;
} else if (strcasecmp(argv[0], "tabbed") == 0) { } else if (strcasecmp(argv[0], "tabbed") == 0) {
config->default_layout = L_TABBED; config->default_layout = L_TABBED;
} else if (strcasecmp(argv[0], "auto_left") == 0) {
config->default_layout = L_AUTO_LEFT;
} else if (strcasecmp(argv[0], "auto_right") == 0) {
config->default_layout = L_AUTO_RIGHT;
} else if (strcasecmp(argv[0], "auto_top") == 0) {
config->default_layout = L_AUTO_TOP;
} else if (strcasecmp(argv[0], "auto_bottom") == 0) {
config->default_layout = L_AUTO_BOTTOM;
} else { } else {
return cmd_results_new(CMD_INVALID, "workspace_layout", "Expected 'workspace_layout <default|stacking|tabbed>'"); return cmd_results_new(CMD_INVALID, "workspace_layout", "Expected 'workspace_layout <default|stacking|tabbed|auto_left|auto_right|auto_top|auto_bottom>'");
} }
return cmd_results_new(CMD_SUCCESS, NULL, NULL); return cmd_results_new(CMD_SUCCESS, NULL, NULL);
} }

View File

@ -962,11 +962,28 @@ swayc_t *swayc_tabbed_stacked_parent(swayc_t *con) {
} }
swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout) { swayc_t *swayc_change_layout(swayc_t *container, enum swayc_layouts layout) {
// if layout change modifies the auto layout's major axis, swap width and height
// to preserve current ratios.
if (is_auto_layout(layout) && is_auto_layout(container->layout)) {
enum swayc_layouts prev_major = (container->layout == L_AUTO_LEFT ||
container->layout == L_AUTO_RIGHT)
? L_HORIZ : L_VERT;
enum swayc_layouts new_major = (layout == L_AUTO_LEFT || layout == L_AUTO_RIGHT)
? L_HORIZ : L_VERT;
if (new_major != prev_major) {
for (int i = 0; i < container->children->length; ++i) {
swayc_t *child = container->children->items[i];
double h = child->height;
child->height = child->width;
child->width = h;
}
}
}
if (container->type == C_WORKSPACE) { if (container->type == C_WORKSPACE) {
container->workspace_layout = layout; container->workspace_layout = layout;
if (layout == L_HORIZ || layout == L_VERT) { if (layout == L_HORIZ || layout == L_VERT || is_auto_layout(layout)) {
container->layout = layout; container->layout = layout;
} }
} else { } else {
container->layout = layout; container->layout = layout;
} }

View File

@ -371,7 +371,7 @@ The default colors are:
switch to workspace 2, then invoke the "workspace 2" command again, you switch to workspace 2, then invoke the "workspace 2" command again, you
will be returned to workspace 1. Defaults to _no_. will be returned to workspace 1. Defaults to _no_.
**workspace_layout** <default|stacking|tabbed>:: **workspace_layout** <default|stacking|tabbed|auto_left|auto_right|auto_top|auto_bottom>::
Specifies the start layout for new workspaces. Specifies the start layout for new workspaces.
**include** <path>:: **include** <path>::