Implement options to change the default mode of containers
The following new directives have been implemented for the configuration file: new_container <default|stacking|tabbed> new_container stack-limit <cols|rows> <value> Note that they require using the new lexer/parser, which you can do by passing -l to i3 when starting.
This commit is contained in:
parent
fa868ed61c
commit
e101940c5e
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include "queue.h"
|
||||
#include "i3.h"
|
||||
|
||||
typedef struct Config Config;
|
||||
extern Config config;
|
||||
|
@ -71,6 +72,10 @@ struct Config {
|
|||
|
||||
const char *ipc_socket_path;
|
||||
|
||||
int container_mode;
|
||||
int container_stack_limit;
|
||||
int container_stack_limit_value;
|
||||
|
||||
/** The modifier which needs to be pressed in combination with your mouse
|
||||
* buttons to do things with floating windows (move, resize) */
|
||||
uint32_t floating_modifier;
|
||||
|
|
|
@ -37,6 +37,13 @@ assign { BEGIN(ASSIGN_COND); return TOKASSIGN; }
|
|||
set[^\n]* { return TOKCOMMENT; }
|
||||
ipc-socket { BEGIN(BIND_AWS_COND); return TOKIPCSOCKET; }
|
||||
ipc_socket { BEGIN(BIND_AWS_COND); return TOKIPCSOCKET; }
|
||||
new_container { return TOKNEWCONTAINER; }
|
||||
default { yylval.number = MODE_DEFAULT; return TOKCONTAINERMODE; }
|
||||
stacking { yylval.number = MODE_STACK; return TOKCONTAINERMODE; }
|
||||
tabbed { yylval.number = MODE_TABBED; return TOKCONTAINERMODE; }
|
||||
stack-limit { return TOKSTACKLIMIT; }
|
||||
cols { yylval.number = STACK_LIMIT_COLS; return TOKSTACKLIMIT; }
|
||||
rows { yylval.number = STACK_LIMIT_ROWS; return TOKSTACKLIMIT; }
|
||||
exec { BEGIN(BIND_AWS_COND); return TOKEXEC; }
|
||||
client.focused { BEGIN(COLOR_COND); yylval.color = &config.client.focused; return TOKCOLOR; }
|
||||
client.focused_inactive { BEGIN(COLOR_COND); yylval.color = &config.client.focused_inactive; return TOKCOLOR; }
|
||||
|
|
|
@ -189,6 +189,9 @@ void parse_file(const char *f) {
|
|||
%token TOKCOLOR
|
||||
%token TOKARROW
|
||||
%token TOKMODE
|
||||
%token TOKNEWCONTAINER
|
||||
%token TOKCONTAINERMODE
|
||||
%token TOKSTACKLIMIT
|
||||
|
||||
%%
|
||||
|
||||
|
@ -201,6 +204,7 @@ line:
|
|||
bindline
|
||||
| mode
|
||||
| floating_modifier
|
||||
| new_container
|
||||
| workspace
|
||||
| assign
|
||||
| ipcsocket
|
||||
|
@ -309,6 +313,45 @@ floating_modifier:
|
|||
}
|
||||
;
|
||||
|
||||
new_container:
|
||||
TOKNEWCONTAINER WHITESPACE TOKCONTAINERMODE
|
||||
{
|
||||
LOG("new containers will be in mode %d\n", $<number>3);
|
||||
config.container_mode = $<number>3;
|
||||
|
||||
/* We also need to change the layout of the already existing
|
||||
* workspaces here. Workspaces may exist at this point because
|
||||
* of the other directives which are modifying workspaces
|
||||
* (setting the preferred screen or name). While the workspace
|
||||
* objects are already created, they have never been used.
|
||||
* Thus, the user very likely awaits the default container mode
|
||||
* to trigger in this case, regardless of where it is inside
|
||||
* his configuration file. */
|
||||
for (int c = 0; c < num_workspaces; c++) {
|
||||
if (workspaces[c].table == NULL)
|
||||
continue;
|
||||
switch_layout_mode(global_conn,
|
||||
workspaces[c].table[0][0],
|
||||
config.container_mode);
|
||||
}
|
||||
}
|
||||
| TOKNEWCONTAINER WHITESPACE TOKSTACKLIMIT WHITESPACE TOKSTACKLIMIT WHITESPACE NUMBER
|
||||
{
|
||||
LOG("stack-limit %d with val %d\n", $<number>5, $<number>7);
|
||||
config.container_stack_limit = $<number>5;
|
||||
config.container_stack_limit_value = $<number>7;
|
||||
|
||||
/* See the comment above */
|
||||
for (int c = 0; c < num_workspaces; c++) {
|
||||
if (workspaces[c].table == NULL)
|
||||
continue;
|
||||
Container *con = workspaces[c].table[0][0];
|
||||
con->stack_limit = config.container_stack_limit;
|
||||
con->stack_limit_value = config.container_stack_limit_value;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
workspace:
|
||||
TOKWORKSPACE WHITESPACE NUMBER WHITESPACE TOKSCREEN WHITESPACE screen workspace_name
|
||||
{
|
||||
|
|
|
@ -732,6 +732,9 @@ void render_workspace(xcb_connection_t *conn, i3Screen *screen, Workspace *r_ws)
|
|||
void render_layout(xcb_connection_t *conn) {
|
||||
i3Screen *screen;
|
||||
|
||||
if (virtual_screens == NULL)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(screen, virtual_screens, screens)
|
||||
render_workspace(conn, screen, &(workspaces[screen->current_workspace]));
|
||||
|
||||
|
|
|
@ -206,6 +206,14 @@ int main(int argc, char *argv[], char *env[]) {
|
|||
|
||||
load_configuration(conn, override_configpath, false);
|
||||
|
||||
/* Create the initial container on the first workspace. This used to
|
||||
* be part of init_table, but since it possibly requires an X
|
||||
* connection and a loaded configuration (default mode for new
|
||||
* containers may be stacking, which requires a new window to be
|
||||
* created), it had to be delayed. */
|
||||
expand_table_cols(&(workspaces[0]));
|
||||
expand_table_rows(&(workspaces[0]));
|
||||
|
||||
/* Place requests for the atoms we need as soon as possible */
|
||||
#define REQUEST_ATOM(name) atom_cookies[name] = xcb_intern_atom(conn, 0, strlen(#name), #name);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "util.h"
|
||||
#include "i3.h"
|
||||
#include "layout.h"
|
||||
#include "config.h"
|
||||
|
||||
int current_workspace = 0;
|
||||
int num_workspaces = 1;
|
||||
|
@ -45,8 +46,6 @@ void init_table() {
|
|||
workspaces[0].screen = NULL;
|
||||
workspaces[0].num = 0;
|
||||
TAILQ_INIT(&(workspaces[0].floating_clients));
|
||||
expand_table_cols(&(workspaces[0]));
|
||||
expand_table_rows(&(workspaces[0]));
|
||||
}
|
||||
|
||||
static void new_container(Workspace *workspace, Container **container, int col, int row) {
|
||||
|
@ -58,6 +57,9 @@ static void new_container(Workspace *workspace, Container **container, int col,
|
|||
new->col = col;
|
||||
new->row = row;
|
||||
new->workspace = workspace;
|
||||
switch_layout_mode(global_conn, new, config.container_mode);
|
||||
new->stack_limit = config.container_stack_limit;
|
||||
new->stack_limit_value = config.container_stack_limit_value;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
11
src/util.c
11
src/util.c
|
@ -352,10 +352,13 @@ void switch_layout_mode(xcb_connection_t *conn, Container *container, int mode)
|
|||
if (container->mode == MODE_STACK || container->mode == MODE_TABBED)
|
||||
goto after_stackwin;
|
||||
|
||||
/* When entering stacking mode, we need to open a window on which we can draw the
|
||||
title bars of the clients, it has height 1 because we don’t bother here with
|
||||
calculating the correct height - it will be adjusted when rendering anyways. */
|
||||
Rect rect = {container->x, container->y, container->width, 1};
|
||||
/* When entering stacking mode, we need to open a window on
|
||||
* which we can draw the title bars of the clients, it has
|
||||
* height 1 because we don’t bother here with calculating the
|
||||
* correct height - it will be adjusted when rendering anyways.
|
||||
* Also, we need to use max(width, 1) because windows cannot
|
||||
* be created with either width == 0 or height == 0. */
|
||||
Rect rect = {container->x, container->y, max(container->width, 1), 1};
|
||||
|
||||
uint32_t mask = 0;
|
||||
uint32_t values[2];
|
||||
|
|
|
@ -66,16 +66,14 @@ Workspace *workspace_get(int number) {
|
|||
LOG("We need to initialize that one\n");
|
||||
num_workspaces = number+1;
|
||||
workspaces = realloc(workspaces, num_workspaces * sizeof(Workspace));
|
||||
for (int c = old_num_workspaces; c < num_workspaces; c++) {
|
||||
/* Zero out the new workspaces so that we have sane default values */
|
||||
for (int c = old_num_workspaces; c < num_workspaces; c++)
|
||||
memset(&workspaces[c], 0, sizeof(Workspace));
|
||||
workspaces[c].screen = NULL;
|
||||
workspaces[c].num = c;
|
||||
TAILQ_INIT(&(workspaces[c].floating_clients));
|
||||
expand_table_cols(&(workspaces[c]));
|
||||
expand_table_rows(&(workspaces[c]));
|
||||
workspace_set_name(&(workspaces[c]), NULL);
|
||||
}
|
||||
|
||||
/* Immediately after the realloc(), we restore the pointers.
|
||||
* They may be used when initializing the new workspaces, for
|
||||
* example when the user configures containers to be stacking
|
||||
* by default, thus requiring re-rendering the layout. */
|
||||
c_ws = workspace_get((int)c_ws);
|
||||
|
||||
for (int c = 0; c < old_num_workspaces; c++)
|
||||
|
@ -94,6 +92,15 @@ Workspace *workspace_get(int number) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Initialize the new workspaces */
|
||||
for (int c = old_num_workspaces; c < num_workspaces; c++) {
|
||||
memset(&workspaces[c], 0, sizeof(Workspace));
|
||||
workspaces[c].num = c;
|
||||
TAILQ_INIT(&(workspaces[c].floating_clients));
|
||||
expand_table_cols(&(workspaces[c]));
|
||||
expand_table_rows(&(workspaces[c]));
|
||||
workspace_set_name(&(workspaces[c]), NULL);
|
||||
}
|
||||
|
||||
LOG("done\n");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue