]> git.sur5r.net Git - i3/i3/commitdiff
Implement moving containers, implement moving windows to the top if top-most, change...
authorMichael Stapelberg <michael+x200@stapelberg.de>
Wed, 11 Mar 2009 17:56:31 +0000 (18:56 +0100)
committerMichael Stapelberg <michael+x200@stapelberg.de>
Wed, 11 Mar 2009 17:56:31 +0000 (18:56 +0100)
i3.config
include/table.h
src/commands.c
src/table.c

index 61e20c8be393a715e5a1498b6e7d8865907e8eef..0d7488a6730bf09d8a7b7be61d424101dd3a103d 100644 (file)
--- a/i3.config
+++ b/i3.config
@@ -1,4 +1,9 @@
+# This configuration uses Mod1 and Mod3. Make sure they are mapped properly using xev(1)
+# and xmodmap(1). Usually, Mod1 is Alt (Alt_L) and Mod3 is Windows (Super_L)
+
 terminal /usr/bin/urxvt
+
+# ISO 10646 = Unicode
 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
 
 # Fullscreen (Mod1+f)
@@ -17,16 +22,16 @@ bind Mod1+46 k
 bind Mod1+47 l
 
 # Focus Container (Mod1+j/k/l/;)
-bind Mod1+Control+44 wch
-bind Mod1+Control+45 wcj
-bind Mod1+Control+46 wck
-bind Mod1+Control+47 wcl
+bind Mod3+44 wch
+bind Mod3+45 wcj
+bind Mod3+46 wck
+bind Mod3+47 wcl
 
 # Snap (Mod1+Control+j/k/l/;)
-bind Mod1+Shift+Control+44 sh
-bind Mod1+Shift+Control+45 sj
-bind Mod1+Shift+Control+46 sk
-bind Mod1+Shift+Control+47 sl
+bind Mod1+Control+44 sh
+bind Mod1+Control+45 sj
+bind Mod1+Control+46 sk
+bind Mod1+Control+47 sl
 
 # Move (Mod1+Shift+j/k/l/;)
 bind Mod1+Shift+44 mh
@@ -34,6 +39,12 @@ bind Mod1+Shift+45 mj
 bind Mod1+Shift+46 mk
 bind Mod1+Shift+47 ml
 
+# Move Container (Mod3+Shift+j/k/l/;)
+bind Mod3+Shift+44 wcmh
+bind Mod3+Shift+45 wcmj
+bind Mod3+Shift+46 wcmk
+bind Mod3+Shift+47 wcml
+
 # Workspaces (Mod1+1/2/…)
 bind Mod1+10 1
 bind Mod1+11 2
index 0e4cdfe9b917479280c65fb9f3af243494e61998..5db1cda440465a64b14390fc01d39d47c1b5f260 100644 (file)
@@ -27,6 +27,7 @@ extern int current_row;
 
 void init_table();
 void expand_table_rows(Workspace *workspace);
+void expand_table_rows_at_head(Workspace *workspace);
 void expand_table_cols(Workspace *workspace);
 void expand_table_cols_at_head(Workspace *workspace);
 bool cell_exists(int col, int row);
index 22d067a4d2930ba4f2596678c14a5edbc296ef9a..4e9f304aedaf9a0c430e8444faeff84c6bcf2b60 100644 (file)
@@ -153,13 +153,13 @@ static bool move_current_window_in_container(xcb_connection_t *conn, Client *cli
 }
 
 /*
- * Moves the current window to the given direction, creating a column/row if
- * necessary
+ * Moves the current window or whole container to the given direction, creating a column/row if
+ * necessary.
  *
  */
 static void move_current_window(xcb_connection_t *conn, direction_t direction) {
         LOG("moving window to direction %s\n", (direction == D_UP ? "up" : (direction == D_DOWN ? "down" :
-                                        (direction == D_LEFT ? "left" : "right"))));
+                                            (direction == D_LEFT ? "left" : "right"))));
         /* Get current window */
         Container *container = CUR_CELL,
                   *new = NULL;
@@ -184,10 +184,9 @@ static void move_current_window(xcb_connection_t *conn, direction_t direction) {
                         /* If we’re at the left-most position, move the rest of the table right */
                         if (current_col == 0) {
                                 expand_table_cols_at_head(c_ws);
-                                new = CUR_TABLE[current_col][current_row];
+                                new = CUR_CELL;
                         } else
                                 new = CUR_TABLE[--current_col][current_row];
-
                         break;
                 case D_RIGHT:
                         if (current_col == (c_ws->cols-1))
@@ -196,12 +195,15 @@ static void move_current_window(xcb_connection_t *conn, direction_t direction) {
                         new = CUR_TABLE[++current_col][current_row];
                         break;
                 case D_UP:
-                        /* TODO: if we’re at the up-most position, move the rest of the table down */
-                        if (move_current_window_in_container(conn, current_client, D_UP) ||
-                                current_row == 0)
+                        if (move_current_window_in_container(conn, current_client, D_UP))
                                 return;
 
-                        new = CUR_TABLE[current_col][--current_row];
+                        /* if we’re at the up-most position, move the rest of the table down */
+                        if (current_row == 0) {
+                                expand_table_rows_at_head(c_ws);
+                                new = CUR_CELL;
+                        } else
+                                new = CUR_TABLE[current_col][--current_row];
                         break;
                 case D_DOWN:
                         if (move_current_window_in_container(conn, current_client, D_DOWN))
@@ -236,6 +238,76 @@ static void move_current_window(xcb_connection_t *conn, direction_t direction) {
         set_focus(conn, current_client);
 }
 
+static void move_current_container(xcb_connection_t *conn, direction_t direction) {
+        LOG("moving container to direction %s\n", (direction == D_UP ? "up" : (direction == D_DOWN ? "down" :
+                                            (direction == D_LEFT ? "left" : "right"))));
+        /* Get current window */
+        Container *container = CUR_CELL,
+                  *new = NULL;
+
+        Container **old = &CUR_CELL;
+
+        /* There has to be a container, see focus_window() */
+        assert(container != NULL);
+
+        switch (direction) {
+                case D_LEFT:
+                        /* If we’re at the left-most position, move the rest of the table right */
+                        if (current_col == 0) {
+                                expand_table_cols_at_head(c_ws);
+                                new = CUR_CELL;
+                                old = &CUR_TABLE[current_col+1][current_row];
+                        } else
+                                new = CUR_TABLE[--current_col][current_row];
+                        break;
+                case D_RIGHT:
+                        if (current_col == (c_ws->cols-1))
+                                expand_table_cols(c_ws);
+
+                        new = CUR_TABLE[++current_col][current_row];
+                        break;
+                case D_UP:
+                        /* if we’re at the up-most position, move the rest of the table down */
+                        if (current_row == 0) {
+                                expand_table_rows_at_head(c_ws);
+                                new = CUR_CELL;
+                                old = &CUR_TABLE[current_col][current_row+1];
+                        } else
+                                new = CUR_TABLE[current_col][--current_row];
+                        break;
+                case D_DOWN:
+                        if (current_row == (c_ws->rows-1))
+                                expand_table_rows(c_ws);
+
+                        new = CUR_TABLE[current_col][++current_row];
+                        break;
+        }
+
+        LOG("old = %d,%d and new = %d,%d\n", container->col, container->row, new->col, new->row);
+
+        /* Swap the containers */
+        int col = new->col;
+        int row = new->row;
+
+        *old = new;
+        new->col = container->col;
+        new->row = container->row;
+
+        CUR_CELL = container;
+        container->col = col;
+        container->row = row;
+
+        Workspace *workspace = container->workspace;
+
+        /* delete all empty columns/rows */
+        cleanup_table(conn, workspace);
+
+        /* Fix colspan/rowspan if it’d overlap */
+        fix_colrowspan(conn, workspace);
+
+        render_layout(conn);
+}
+
 /*
  * "Snaps" the current container (not possible for windows, because it works at table base)
  * to the given direction, that is, adjusts cellspan/rowspan
@@ -572,11 +644,13 @@ void parse_command(xcb_connection_t *conn, const char *command) {
                         return;
                 }
 
-                if (action == ACTION_FOCUS) {
+                if (action == ACTION_FOCUS)
                         focus_thing(conn, direction, (with == WITH_WINDOW ? THING_WINDOW : THING_CONTAINER));
+                else if (action == ACTION_MOVE) {
+                        if (with == WITH_WINDOW)
+                                move_current_window(conn, direction);
+                        else move_current_container(conn, direction);
                 }
-                else if (action == ACTION_MOVE)
-                        move_current_window(conn, direction);
                 else if (action == ACTION_SNAP)
                         snap_current_container(conn, direction);
 
index 917639723fd0af0d92d2feb7dafc4d28cc9e4607..62bdba78cd26d7e946a16a4ab87eca50c5bcfd4e 100644 (file)
@@ -72,6 +72,27 @@ void expand_table_rows(Workspace *workspace) {
         }
 }
 
+/*
+ * Adds one row at the head of the table
+ *
+ */
+void expand_table_rows_at_head(Workspace *workspace) {
+        workspace->rows++;
+
+        for (int cols = 0; cols < workspace->cols; cols++)
+                workspace->table[cols] = realloc(workspace->table[cols], sizeof(Container*) * workspace->rows);
+
+        /* Move the other rows */
+        for (int cols = 0; cols < workspace->cols; cols++)
+                for (int rows = workspace->rows - 1; rows > 0; rows--) {
+                        LOG("Moving row %d to %d\n", rows-1, rows);
+                        workspace->table[cols][rows] = workspace->table[cols][rows-1];
+                        workspace->table[cols][rows]->row = rows;
+                }
+        for (int cols = 0; cols < workspace->cols; cols++)
+                new_container(workspace, &(workspace->table[cols][0]), cols, 0);
+}
+
 /*
  * Add one column to the table
  *