Introduce splith/splitv layouts, remove orientation

With this commit, the "default" layout is replaced by the splith and
splitv layouts. splith is equivalent to default with orientation
horizontal and splitv is equivalent to default with orientation
vertical.

The "split h" and "split v" commands continue to work as before, they
split the current container and you will end up in a split container
with layout splith (after "split h") or splitv (after "split v").

To change a splith container into a splitv container, use either "layout
splitv" or "layout toggle split". The latter command is used in the
default config as mod+l (previously "layout default"). In case you have
"layout default" in your config file, it is recommended to just replace
it by "layout toggle split", which will work as "layout default" did
before when pressing it once, but toggle between horizontal/vertical
when pressing it repeatedly.

The rationale behind this commit is that it’s cleaner to have all
parameters that influence how windows are rendered in the layout itself
rather than having a special parameter in combination with only one
layout. This enables us to change existing split containers in all cases
without breaking existing features (see ticket #464). Also, users should
feel more confident about whether they are actually splitting or just
changing an existing split container now.

As a nice side-effect, this commit brings back the "layout toggle"
feature we once had in i3 version 3 (see the userguide).

AFAIK, it is safe to use in-place restart to upgrade into versions
after this commit (switching to an older version will break your layout,
though).

Fixes #464
This commit is contained in:
Michael Stapelberg
2012-08-04 03:04:00 +02:00
parent 077e021e26
commit de94f6da1a
22 changed files with 458 additions and 156 deletions

View File

@ -14,6 +14,25 @@
* back-and-forth switching. */
static char *previous_workspace_name = NULL;
/*
* Sets ws->layout to splith/splitv if default_orientation was specified in the
* configfile. Otherwise, it uses splith/splitv depending on whether the output
* is higher than wide.
*
*/
static void _workspace_apply_default_orientation(Con *ws) {
/* If default_orientation is set to NO_ORIENTATION we determine
* orientation depending on output resolution. */
if (config.default_orientation == NO_ORIENTATION) {
Con *output = con_get_output(ws);
ws->layout = (output->rect.height > output->rect.width) ? L_SPLITV : L_SPLITH;
DLOG("Auto orientation. Workspace size set to (%d,%d), setting layout to %d.\n",
output->rect.width, output->rect.height, ws->layout);
} else {
ws->layout = (config.default_orientation == HORIZ) ? L_SPLITH : L_SPLITV;
}
}
/*
* Returns a pointer to the workspace with the given number (starting at 0),
* creating the workspace if necessary (by allocating the necessary amount of
@ -64,16 +83,8 @@ Con *workspace_get(const char *num, bool *created) {
else workspace->num = parsed_num;
LOG("num = %d\n", workspace->num);
/* If default_orientation is set to NO_ORIENTATION we
* determine workspace orientation from workspace size.
* Otherwise we just set the orientation to default_orientation. */
if (config.default_orientation == NO_ORIENTATION) {
workspace->orientation = (output->rect.height > output->rect.width) ? VERT : HORIZ;
DLOG("Auto orientation. Output resolution set to (%d,%d), setting orientation to %d.\n",
workspace->rect.width, workspace->rect.height, workspace->orientation);
} else {
workspace->orientation = config.default_orientation;
}
workspace->parent = content;
_workspace_apply_default_orientation(workspace);
con_attach(workspace, content, false);
@ -198,19 +209,12 @@ Con *create_workspace_on_output(Output *output, Con *content) {
ws->fullscreen_mode = CF_OUTPUT;
/* If default_orientation is set to NO_ORIENTATION we determine
* orientation depending on output resolution. */
if (config.default_orientation == NO_ORIENTATION) {
ws->orientation = (output->rect.height > output->rect.width) ? VERT : HORIZ;
DLOG("Auto orientation. Workspace size set to (%d,%d), setting orientation to %d.\n",
output->rect.width, output->rect.height, ws->orientation);
} else {
ws->orientation = config.default_orientation;
}
_workspace_apply_default_orientation(ws);
return ws;
}
/*
* Returns true if the workspace is currently visible. Especially important for
* multi-monitor environments, as they can have multiple currenlty active
@ -686,8 +690,7 @@ void workspace_update_urgent_flag(Con *ws) {
/*
* 'Forces' workspace orientation by moving all cons into a new split-con with
* the same orientation as the workspace and then changing the workspace
* orientation.
* the same layout as the workspace and then changing the workspace layout.
*
*/
void ws_force_orientation(Con *ws, orientation_t orientation) {
@ -695,9 +698,8 @@ void ws_force_orientation(Con *ws, orientation_t orientation) {
Con *split = con_new(NULL, NULL);
split->parent = ws;
/* 2: copy layout and orientation from workspace */
/* 2: copy layout from workspace */
split->layout = ws->layout;
split->orientation = ws->orientation;
Con *old_focused = TAILQ_FIRST(&(ws->focus_head));
@ -709,8 +711,8 @@ void ws_force_orientation(Con *ws, orientation_t orientation) {
con_attach(child, split, true);
}
/* 4: switch workspace orientation */
ws->orientation = orientation;
/* 4: switch workspace layout */
ws->layout = (orientation == HORIZ) ? L_SPLITH : L_SPLITV;
/* 5: attach the new split container to the workspace */
DLOG("Attaching new split to ws\n");
@ -745,19 +747,11 @@ Con *workspace_attach_to(Con *ws) {
/* 1: create a new split container */
Con *new = con_new(NULL, NULL);
new->parent = ws;
new->split = true;
/* 2: set the requested layout on the split con */
new->layout = config.default_layout;
/* 3: While the layout is irrelevant in stacked/tabbed mode, it needs
* to be set. Otherwise, this con will not be interpreted as a split
* container. */
if (config.default_orientation == NO_ORIENTATION) {
new->orientation = (ws->rect.height > ws->rect.width) ? VERT : HORIZ;
} else {
new->orientation = config.default_orientation;
}
/* 4: attach the new split container to the workspace */
DLOG("Attaching new split %p to workspace %p\n", new, ws);
con_attach(new, ws, false);