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 <stdbool.h>
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
#include "i3.h"
|
||||||
|
|
||||||
typedef struct Config Config;
|
typedef struct Config Config;
|
||||||
extern Config config;
|
extern Config config;
|
||||||
|
@ -71,6 +72,10 @@ struct Config {
|
||||||
|
|
||||||
const char *ipc_socket_path;
|
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
|
/** The modifier which needs to be pressed in combination with your mouse
|
||||||
* buttons to do things with floating windows (move, resize) */
|
* buttons to do things with floating windows (move, resize) */
|
||||||
uint32_t floating_modifier;
|
uint32_t floating_modifier;
|
||||||
|
|
|
@ -37,6 +37,13 @@ assign { BEGIN(ASSIGN_COND); return TOKASSIGN; }
|
||||||
set[^\n]* { return TOKCOMMENT; }
|
set[^\n]* { return TOKCOMMENT; }
|
||||||
ipc-socket { BEGIN(BIND_AWS_COND); return TOKIPCSOCKET; }
|
ipc-socket { BEGIN(BIND_AWS_COND); return TOKIPCSOCKET; }
|
||||||
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; }
|
exec { BEGIN(BIND_AWS_COND); return TOKEXEC; }
|
||||||
client.focused { BEGIN(COLOR_COND); yylval.color = &config.client.focused; return TOKCOLOR; }
|
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; }
|
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 TOKCOLOR
|
||||||
%token TOKARROW
|
%token TOKARROW
|
||||||
%token TOKMODE
|
%token TOKMODE
|
||||||
|
%token TOKNEWCONTAINER
|
||||||
|
%token TOKCONTAINERMODE
|
||||||
|
%token TOKSTACKLIMIT
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
@ -201,6 +204,7 @@ line:
|
||||||
bindline
|
bindline
|
||||||
| mode
|
| mode
|
||||||
| floating_modifier
|
| floating_modifier
|
||||||
|
| new_container
|
||||||
| workspace
|
| workspace
|
||||||
| assign
|
| assign
|
||||||
| ipcsocket
|
| 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:
|
workspace:
|
||||||
TOKWORKSPACE WHITESPACE NUMBER WHITESPACE TOKSCREEN WHITESPACE screen workspace_name
|
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) {
|
void render_layout(xcb_connection_t *conn) {
|
||||||
i3Screen *screen;
|
i3Screen *screen;
|
||||||
|
|
||||||
|
if (virtual_screens == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
TAILQ_FOREACH(screen, virtual_screens, screens)
|
TAILQ_FOREACH(screen, virtual_screens, screens)
|
||||||
render_workspace(conn, screen, &(workspaces[screen->current_workspace]));
|
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);
|
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 */
|
/* 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);
|
#define REQUEST_ATOM(name) atom_cookies[name] = xcb_intern_atom(conn, 0, strlen(#name), #name);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "i3.h"
|
#include "i3.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
int current_workspace = 0;
|
int current_workspace = 0;
|
||||||
int num_workspaces = 1;
|
int num_workspaces = 1;
|
||||||
|
@ -45,8 +46,6 @@ void init_table() {
|
||||||
workspaces[0].screen = NULL;
|
workspaces[0].screen = NULL;
|
||||||
workspaces[0].num = 0;
|
workspaces[0].num = 0;
|
||||||
TAILQ_INIT(&(workspaces[0].floating_clients));
|
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) {
|
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->col = col;
|
||||||
new->row = row;
|
new->row = row;
|
||||||
new->workspace = workspace;
|
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)
|
if (container->mode == MODE_STACK || container->mode == MODE_TABBED)
|
||||||
goto after_stackwin;
|
goto after_stackwin;
|
||||||
|
|
||||||
/* When entering stacking mode, we need to open a window on which we can draw the
|
/* When entering stacking mode, we need to open a window on
|
||||||
title bars of the clients, it has height 1 because we don’t bother here with
|
* which we can draw the title bars of the clients, it has
|
||||||
calculating the correct height - it will be adjusted when rendering anyways. */
|
* height 1 because we don’t bother here with calculating the
|
||||||
Rect rect = {container->x, container->y, container->width, 1};
|
* 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 mask = 0;
|
||||||
uint32_t values[2];
|
uint32_t values[2];
|
||||||
|
|
|
@ -66,16 +66,14 @@ Workspace *workspace_get(int number) {
|
||||||
LOG("We need to initialize that one\n");
|
LOG("We need to initialize that one\n");
|
||||||
num_workspaces = number+1;
|
num_workspaces = number+1;
|
||||||
workspaces = realloc(workspaces, num_workspaces * sizeof(Workspace));
|
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));
|
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);
|
c_ws = workspace_get((int)c_ws);
|
||||||
|
|
||||||
for (int c = 0; c < old_num_workspaces; c++)
|
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");
|
LOG("done\n");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue