diff --git a/i3.config b/i3.config index 61e20c8b..0d7488a6 100644 --- 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 diff --git a/include/table.h b/include/table.h index 0e4cdfe9..5db1cda4 100644 --- a/include/table.h +++ b/include/table.h @@ -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); diff --git a/src/commands.c b/src/commands.c index 22d067a4..4e9f304a 100644 --- a/src/commands.c +++ b/src/commands.c @@ -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); diff --git a/src/table.c b/src/table.c index 91763972..62bdba78 100644 --- a/src/table.c +++ b/src/table.c @@ -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 *