diff --git a/i3.config b/i3.config index 71511a50..b4c584fa 100644 --- a/i3.config +++ b/i3.config @@ -19,7 +19,13 @@ bindsym Mod1+Return exec /usr/bin/urxvt # Start dmenu (Mod1+p) bindsym Mod1+p exec /usr/bin/dmenu_run +# Default orientation +new_container_orientation horizontal + +# Horizontal orientation bindsym Mod1+h split h + +# Vertical orientation bindsym Mod1+v split v # Fullscreen (Mod1+f) diff --git a/include/config.h b/include/config.h index 32212e3d..f639df36 100644 --- a/include/config.h +++ b/include/config.h @@ -95,6 +95,9 @@ struct Config { int container_stack_limit; int container_stack_limit_value; + /** Default orientation for new containers */ + int default_orientation; + /** By default, focus follows mouse. If the user explicitly wants to * turn this off (and instead rely only on the keyboard for changing * focus), we allow him to do this with this relatively special option. diff --git a/src/cfgparse.l b/src/cfgparse.l index b8b1d73d..4776527b 100644 --- a/src/cfgparse.l +++ b/src/cfgparse.l @@ -92,6 +92,10 @@ set[^\n]* { return TOKCOMMENT; } ipc-socket { BEGIN(BIND_AWS_COND); return TOKIPCSOCKET; } ipc_socket { BEGIN(BIND_AWS_COND); return TOKIPCSOCKET; } restart_state { BEGIN(BIND_AWS_COND); return TOKRESTARTSTATE; } +new_container_orientation { return TOK_ORIENTATION; } +horizontal { return TOK_HORIZ; } +vertical { return TOK_VERT; } +auto { return TOK_AUTO; } new_container { return TOKNEWCONTAINER; } new_window { return TOKNEWWINDOW; } normal { return TOK_NORMAL; } diff --git a/src/cfgparse.y b/src/cfgparse.y index 5ee6dfd4..50058680 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -224,6 +224,10 @@ void parse_file(const char *f) { %token TOKCOLOR %token TOKARROW "→" %token TOKMODE "mode" +%token TOK_ORIENTATION "new_container_orientation" +%token TOK_HORIZ "horizontal" +%token TOK_VERT "vertical" +%token TOK_AUTO "auto" %token TOKNEWCONTAINER "new_container" %token TOKNEWWINDOW "new_window" %token TOK_NORMAL "normal" @@ -249,6 +253,7 @@ line: bindline | mode | floating_modifier + | orientation | new_container | new_window | focus_follows_mouse @@ -373,6 +378,20 @@ floating_modifier: } ; +orientation: + TOK_ORIENTATION WHITESPACE direction + { + DLOG("New containers should start with split direction %d\n", $3); + config.default_orientation = $3; + } + ; + +direction: + TOK_HORIZ { $$ = HORIZ; } + | TOK_VERT { $$ = VERT; } + | TOK_AUTO { $$ = NO_ORIENTATION; } + ; + new_container: TOKNEWCONTAINER WHITESPACE TOKCONTAINERMODE { diff --git a/src/con.c b/src/con.c index 04db250b..e1359069 100644 --- a/src/con.c +++ b/src/con.c @@ -794,7 +794,11 @@ void con_set_layout(Con *con, int 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. */ - new->orientation = HORIZ; + if (config.default_orientation == NO_ORIENTATION) { + new->orientation = (con->rect.height > con->rect.width) ? VERT : HORIZ; + } else { + new->orientation = config.default_orientation; + } Con *old_focused = TAILQ_FIRST(&(con->focus_head)); if (old_focused == TAILQ_END(&(con->focus_head))) diff --git a/src/config.c b/src/config.c index 80071d21..8f8790eb 100644 --- a/src/config.c +++ b/src/config.c @@ -331,6 +331,8 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, INIT_COLOR(config.bar.urgent, "#2f343a", "#900000", "#ffffff"); config.default_border = BS_NORMAL; + /* Set default_orientation to NO_ORIENTATION for auto orientation. */ + config.default_orientation = NO_ORIENTATION; parse_configuration(override_configpath); diff --git a/src/randr.c b/src/randr.c index acac36ca..14b9085d 100644 --- a/src/randr.c +++ b/src/randr.c @@ -361,7 +361,17 @@ void output_init_con(Output *output) { free(name); ws->fullscreen_mode = CF_OUTPUT; - ws->orientation = HORIZ; + + /* 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; + } + /* TODO: Set focus in main.c */ con_focus(ws); @@ -384,6 +394,30 @@ static void output_change_mode(xcb_connection_t *conn, Output *output) { DLOG("Output mode changed, updating rect\n"); assert(output->con != NULL); output->con->rect = output->rect; + + Con *current,*workspace,*child; + + /* Point current to the container of the workspaces */ + current = output->con->nodes_head.tqh_first->nodes.tqe_next; + + /* If default_orientation is NO_ORIENTATION, we change the orientation of + * the workspaces and their childs depending on output resolution. This is + * only done for workspaces with maximum one child. */ + if (config.default_orientation == NO_ORIENTATION) { + TAILQ_FOREACH(workspace, &(current->nodes_head), nodes) { + + /* Check if this workspace has <= 1 childs. */ + child = workspace->nodes_head.tqh_first; + if (child != NULL) + if (child->nodes.tqe_next == NULL) { + workspace->orientation = (output->rect.height > output->rect.width) ? VERT : HORIZ; + DLOG("Setting workspace [%d,%s]'s orientation to %d.\n", workspace->num, workspace->name, workspace->orientation); + child->orientation = workspace->orientation; + DLOG("Setting child [%d,%s]'s orientation to %d.\n", child->num, child->name, child->orientation); + } + } + } + #if 0 Rect bar_rect = {output->rect.x, output->rect.y + output->rect.height - (font->height + 6), diff --git a/src/workspace.c b/src/workspace.c index 77b5ceb2..4e93b92e 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -59,7 +59,18 @@ Con *workspace_get(const char *num, bool *created) { workspace->num = -1; else workspace->num = parsed_num; LOG("num = %d\n", workspace->num); - workspace->orientation = HORIZ; + + /* 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; + } + con_attach(workspace, content, false); ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}");