]> git.sur5r.net Git - i3/i3/commitdiff
Implement options to change the default mode of containers
authorMichael Stapelberg <michael@stapelberg.de>
Sun, 27 Sep 2009 21:08:27 +0000 (23:08 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Sun, 27 Sep 2009 21:08:27 +0000 (23:08 +0200)
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.

include/config.h
src/cfgparse.l
src/cfgparse.y
src/layout.c
src/mainx.c
src/table.c
src/util.c
src/workspace.c

index 6bb53209bdf9268bab19421acc56237d2b9e244f..f11a7b5b249384ce92e807199cb4a688ac764279 100644 (file)
@@ -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;
index 9ef12a86200dc9e723b436fc49a8e9bed9bd18ad..45ea6333b32b6c0fd4261b1426b5ddf094581b09 100644 (file)
@@ -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; }
index f41a69b0d1a11c1aee229b77485015213691437b..d706b4001b6157f2822fa3bd62ebabad87709065 100644 (file)
@@ -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
         {
index 7ae3672cc68de64e6a71cc99c1f3a524becf4d82..fa18bbc107ad14796ec289ad1095f4dc8096ffce 100644 (file)
@@ -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]));
 
index 5ed63f17e20439cb38cc837601373caf533998a2..4f235eca8cef4e40a9f304bf570f9725aa116f70 100644 (file)
@@ -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);
 
index 6612a5e3e93898222b9acd126bcb698c18a22ff6..4c5653aa5b9caef257a0c4459d42c77fe89a2cb0 100644 (file)
@@ -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;
 }
 
 /*
index 94a5e336b4dc31489efbc5080e499bd383c89fe1..7990b56e3f460420969fb8570e787815b600d31d 100644 (file)
@@ -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];
index de6308751ad40070065027f1e7ba5988d9c450fe..94759cebc3c5ad0fd314f2e5a1b6c0a867baaa32 100644 (file)
@@ -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");
         }