#include <stdbool.h>
#include "queue.h"
+#include "i3.h"
typedef struct Config Config;
extern Config 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;
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; }
%token TOKCOLOR
%token TOKARROW
%token TOKMODE
+%token TOKNEWCONTAINER
+%token TOKCONTAINERMODE
+%token TOKSTACKLIMIT
%%
bindline
| mode
| floating_modifier
+ | new_container
| workspace
| assign
| ipcsocket
}
;
+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
{
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]));
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);
#include "util.h"
#include "i3.h"
#include "layout.h"
+#include "config.h"
int current_workspace = 0;
int num_workspaces = 1;
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) {
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;
}
/*
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];
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++)
}
}
+ /* 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");
}