Implement Workspaces
This commit is contained in:
parent
2bdcb322a3
commit
d46ac1ebc5
18
data.h
18
data.h
|
@ -14,6 +14,7 @@ typedef struct Font i3Font;
|
||||||
typedef struct Container Container;
|
typedef struct Container Container;
|
||||||
typedef struct Client Client;
|
typedef struct Client Client;
|
||||||
typedef struct Binding Binding;
|
typedef struct Binding Binding;
|
||||||
|
typedef struct Workspace Workspace;
|
||||||
|
|
||||||
/* Helper types */
|
/* Helper types */
|
||||||
typedef enum { D_LEFT, D_RIGHT, D_UP, D_DOWN } direction_t;
|
typedef enum { D_LEFT, D_RIGHT, D_UP, D_DOWN } direction_t;
|
||||||
|
@ -30,9 +31,24 @@ enum {
|
||||||
BIND_MODE_SWITCH = (1 << 8)
|
BIND_MODE_SWITCH = (1 << 8)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct table_dimensions_t {
|
struct Workspace {
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int num;
|
||||||
|
|
||||||
|
/* table dimensions */
|
||||||
|
int cols;
|
||||||
|
int rows;
|
||||||
|
|
||||||
|
/* These are stored here just while this workspace is _not_ shown (see show_workspace()) */
|
||||||
|
int current_row;
|
||||||
|
int current_col;
|
||||||
|
|
||||||
|
/* This is a two-dimensional dynamic array of Container-pointers. I’ve always wanted
|
||||||
|
* to be a three-star programmer :) */
|
||||||
|
Container ***table;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
113
mainx.c
113
mainx.c
|
@ -25,7 +25,7 @@
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
|
||||||
#define TERMINAL "/usr/bin/urxvt"
|
#define TERMINAL "/usr/pkg/bin/urxvt"
|
||||||
|
|
||||||
Display *xkbdpy;
|
Display *xkbdpy;
|
||||||
|
|
||||||
|
@ -482,27 +482,24 @@ void render_layout(xcb_connection_t *conn) {
|
||||||
int width = root_screen->width_in_pixels;
|
int width = root_screen->width_in_pixels;
|
||||||
int height = root_screen->height_in_pixels;
|
int height = root_screen->height_in_pixels;
|
||||||
|
|
||||||
int num_cols = table_dims.x, num_rows = table_dims.y;
|
printf("got %d rows and %d cols\n", c_ws->rows, c_ws->cols);
|
||||||
|
|
||||||
printf("got %d rows and %d cols\n", num_rows, num_cols);
|
|
||||||
printf("each of them therefore is %d px width and %d px height\n",
|
printf("each of them therefore is %d px width and %d px height\n",
|
||||||
width / num_cols, height / num_rows);
|
width / c_ws->cols, height / c_ws->rows);
|
||||||
|
|
||||||
/* Go through the whole table and render what’s necessary */
|
/* Go through the whole table and render what’s necessary */
|
||||||
for (cols = 0; cols < table_dims.x; cols++)
|
for (cols = 0; cols < c_ws->cols; cols++)
|
||||||
for (rows = 0; rows < table_dims.y; rows++)
|
for (rows = 0; rows < c_ws->rows; rows++) {
|
||||||
if (table[cols][rows] != NULL) {
|
Container *con = CUR_TABLE[cols][rows];
|
||||||
Container *con = table[cols][rows];
|
|
||||||
printf("container has %d colspan, %d rowspan\n",
|
printf("container has %d colspan, %d rowspan\n",
|
||||||
con->colspan, con->rowspan);
|
con->colspan, con->rowspan);
|
||||||
/* Update position of the container */
|
/* Update position of the container */
|
||||||
con->row = rows;
|
con->row = rows;
|
||||||
con->col = cols;
|
con->col = cols;
|
||||||
con->width = (width / num_cols) * con->colspan;
|
con->width = (width / c_ws->cols) * con->colspan;
|
||||||
con->height = (height / num_rows) * con->rowspan;
|
con->height = (height / c_ws->rows) * con->rowspan;
|
||||||
|
|
||||||
/* Render it */
|
/* Render it */
|
||||||
render_container(conn, table[cols][rows]);
|
render_container(conn, CUR_TABLE[cols][rows]);
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
|
@ -714,13 +711,13 @@ static void move_current_window(xcb_connection_t *connection, direction_t direct
|
||||||
if (current_col == 0)
|
if (current_col == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new = table[--current_col][current_row];
|
new = CUR_TABLE[--current_col][current_row];
|
||||||
break;
|
break;
|
||||||
case D_RIGHT:
|
case D_RIGHT:
|
||||||
if (current_col == (table_dims.x-1))
|
if (current_col == (c_ws->cols-1))
|
||||||
expand_table_cols();
|
expand_table_cols(c_ws);
|
||||||
|
|
||||||
new = table[++current_col][current_row];
|
new = CUR_TABLE[++current_col][current_row];
|
||||||
break;
|
break;
|
||||||
case D_UP:
|
case D_UP:
|
||||||
/* TODO: if we’re at the up-most position, move the rest of the table down */
|
/* TODO: if we’re at the up-most position, move the rest of the table down */
|
||||||
|
@ -728,16 +725,16 @@ static void move_current_window(xcb_connection_t *connection, direction_t direct
|
||||||
current_row == 0)
|
current_row == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new = table[current_col][--current_row];
|
new = CUR_TABLE[current_col][--current_row];
|
||||||
break;
|
break;
|
||||||
case D_DOWN:
|
case D_DOWN:
|
||||||
if (move_current_window_in_container(connection, current_client, D_DOWN))
|
if (move_current_window_in_container(connection, current_client, D_DOWN))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (current_row == (table_dims.y-1))
|
if (current_row == (c_ws->rows-1))
|
||||||
expand_table_rows();
|
expand_table_rows(c_ws);
|
||||||
|
|
||||||
new = table[current_col][++current_row];
|
new = CUR_TABLE[current_col][++current_row];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,7 +774,7 @@ static void snap_current_container(xcb_connection_t *connection, direction_t dir
|
||||||
case D_RIGHT:
|
case D_RIGHT:
|
||||||
/* Check if the cell is used */
|
/* Check if the cell is used */
|
||||||
if (!cell_exists(container->col + 1, container->row) ||
|
if (!cell_exists(container->col + 1, container->row) ||
|
||||||
table[container->col+1][container->row]->currently_focused != NULL) {
|
CUR_TABLE[container->col+1][container->row]->currently_focused != NULL) {
|
||||||
printf("cannot snap to right - the cell is already used\n");
|
printf("cannot snap to right - the cell is already used\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -786,10 +783,10 @@ static void snap_current_container(xcb_connection_t *connection, direction_t dir
|
||||||
* If so, reduce their rowspan. */
|
* If so, reduce their rowspan. */
|
||||||
for (i = container->row-1; i >= 0; i--) {
|
for (i = container->row-1; i >= 0; i--) {
|
||||||
printf("we got cell %d, %d with rowspan %d\n",
|
printf("we got cell %d, %d with rowspan %d\n",
|
||||||
container->col+1, i, table[container->col+1][i]->rowspan);
|
container->col+1, i, CUR_TABLE[container->col+1][i]->rowspan);
|
||||||
while ((table[container->col+1][i]->rowspan-1) >= (container->row - i))
|
while ((CUR_TABLE[container->col+1][i]->rowspan-1) >= (container->row - i))
|
||||||
table[container->col+1][i]->rowspan--;
|
CUR_TABLE[container->col+1][i]->rowspan--;
|
||||||
printf("new rowspan = %d\n", table[container->col+1][i]->rowspan);
|
printf("new rowspan = %d\n", CUR_TABLE[container->col+1][i]->rowspan);
|
||||||
}
|
}
|
||||||
|
|
||||||
container->colspan++;
|
container->colspan++;
|
||||||
|
@ -801,17 +798,17 @@ static void snap_current_container(xcb_connection_t *connection, direction_t dir
|
||||||
case D_DOWN:
|
case D_DOWN:
|
||||||
printf("snapping down\n");
|
printf("snapping down\n");
|
||||||
if (!cell_exists(container->col, container->row+1) ||
|
if (!cell_exists(container->col, container->row+1) ||
|
||||||
table[container->col][container->row+1]->currently_focused != NULL) {
|
CUR_TABLE[container->col][container->row+1]->currently_focused != NULL) {
|
||||||
printf("cannot snap down - the cell is already used\n");
|
printf("cannot snap down - the cell is already used\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = container->col-1; i >= 0; i--) {
|
for (i = container->col-1; i >= 0; i--) {
|
||||||
printf("we got cell %d, %d with colspan %d\n",
|
printf("we got cell %d, %d with colspan %d\n",
|
||||||
i, container->row+1, table[i][container->row+1]->colspan);
|
i, container->row+1, CUR_TABLE[i][container->row+1]->colspan);
|
||||||
while ((table[i][container->row+1]->colspan-1) >= (container->col - i))
|
while ((CUR_TABLE[i][container->row+1]->colspan-1) >= (container->col - i))
|
||||||
table[i][container->row+1]->colspan--;
|
CUR_TABLE[i][container->row+1]->colspan--;
|
||||||
printf("new colspan = %d\n", table[i][container->row+1]->colspan);
|
printf("new colspan = %d\n", CUR_TABLE[i][container->row+1]->colspan);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,6 +889,41 @@ static int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_rel
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void show_workspace(xcb_connection_t *conn, int workspace) {
|
||||||
|
int cols, rows;
|
||||||
|
Client *client;
|
||||||
|
printf("show_workspace(%d)\n", workspace);
|
||||||
|
|
||||||
|
/* Store current_row/current_col */
|
||||||
|
c_ws->current_row = current_row;
|
||||||
|
c_ws->current_col = current_col;
|
||||||
|
xcb_grab_server(conn);
|
||||||
|
|
||||||
|
/* Unmap all clients */
|
||||||
|
for (cols = 0; cols < c_ws->cols; cols++)
|
||||||
|
for (rows = 0; rows < c_ws->rows; rows++) {
|
||||||
|
CIRCLEQ_FOREACH(client, &(c_ws->table[cols][rows]->clients), clients)
|
||||||
|
xcb_unmap_window(conn, client->frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
c_ws = &workspaces[workspace-1];
|
||||||
|
current_row = c_ws->current_row;
|
||||||
|
current_col = c_ws->current_col;
|
||||||
|
printf("new current row = %d, current col = %d\n", current_row, current_col);
|
||||||
|
|
||||||
|
|
||||||
|
/* Map all clients on the new workspace */
|
||||||
|
for (cols = 0; cols < c_ws->cols; cols++)
|
||||||
|
for (rows = 0; rows < c_ws->rows; rows++) {
|
||||||
|
CIRCLEQ_FOREACH(client, &(c_ws->table[cols][rows]->clients), clients)
|
||||||
|
xcb_map_window(conn, client->frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_ungrab_server(conn);
|
||||||
|
|
||||||
|
render_layout(conn);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parses a command, see file CMDMODE for more information
|
* Parses a command, see file CMDMODE for more information
|
||||||
*
|
*
|
||||||
|
@ -931,9 +963,14 @@ static void parse_command(xcb_connection_t *conn, const char *command) {
|
||||||
rest++;
|
rest++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*rest == '\0') {
|
||||||
|
/* No rest? This was a tag number, not a times specification */
|
||||||
|
show_workspace(conn, times);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now perform action to <where> */
|
/* Now perform action to <where> */
|
||||||
while (*rest != '\0') {
|
while (*rest != '\0') {
|
||||||
/* TODO: tags */
|
|
||||||
if (*rest == 'h')
|
if (*rest == 'h')
|
||||||
direction = D_LEFT;
|
direction = D_LEFT;
|
||||||
else if (*rest == 'j')
|
else if (*rest == 'j')
|
||||||
|
@ -955,7 +992,6 @@ static void parse_command(xcb_connection_t *conn, const char *command) {
|
||||||
snap_current_container(conn, direction);
|
snap_current_container(conn, direction);
|
||||||
|
|
||||||
rest++;
|
rest++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("--- done ---\n");
|
printf("--- done ---\n");
|
||||||
|
@ -1197,14 +1233,14 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *c, xcb_unmap_notify_
|
||||||
int rows, cols;
|
int rows, cols;
|
||||||
Client *con_client;
|
Client *con_client;
|
||||||
/* TODO: clear this up */
|
/* TODO: clear this up */
|
||||||
for (cols = 0; cols < table_dims.x; cols++)
|
for (cols = 0; cols < c_ws->cols; cols++)
|
||||||
for (rows = 0; rows < table_dims.y; rows++)
|
for (rows = 0; rows < c_ws->rows; rows++)
|
||||||
CIRCLEQ_FOREACH(con_client, &(table[cols][rows]->clients), clients)
|
CIRCLEQ_FOREACH(con_client, &(CUR_TABLE[cols][rows]->clients), clients)
|
||||||
if (con_client == client) {
|
if (con_client == client) {
|
||||||
printf("removing from container\n");
|
printf("removing from container\n");
|
||||||
if (client->container->currently_focused == client)
|
if (client->container->currently_focused == client)
|
||||||
client->container->currently_focused = NULL;
|
client->container->currently_focused = NULL;
|
||||||
CIRCLEQ_REMOVE(&(table[cols][rows]->clients), con_client, clients);
|
CIRCLEQ_REMOVE(&(CUR_TABLE[cols][rows]->clients), con_client, clients);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1384,7 +1420,7 @@ int main(int argc, char *argv[], char *env[]) {
|
||||||
/* 38 = 'a' */
|
/* 38 = 'a' */
|
||||||
BIND(38, BIND_MODE_SWITCH, "foo");
|
BIND(38, BIND_MODE_SWITCH, "foo");
|
||||||
|
|
||||||
BIND(30, 0, "exec /usr/bin/urxvt");
|
BIND(30, 0, "exec /usr/pkg/bin/urxvt");
|
||||||
|
|
||||||
BIND(44, BIND_MOD_1, "h");
|
BIND(44, BIND_MOD_1, "h");
|
||||||
BIND(45, BIND_MOD_1, "j");
|
BIND(45, BIND_MOD_1, "j");
|
||||||
|
@ -1401,6 +1437,9 @@ int main(int argc, char *argv[], char *env[]) {
|
||||||
BIND(46, BIND_MOD_1 | BIND_SHIFT, "mk");
|
BIND(46, BIND_MOD_1 | BIND_SHIFT, "mk");
|
||||||
BIND(47, BIND_MOD_1 | BIND_SHIFT, "ml");
|
BIND(47, BIND_MOD_1 | BIND_SHIFT, "ml");
|
||||||
|
|
||||||
|
BIND(10, BIND_MOD_1 , "1");
|
||||||
|
BIND(11, BIND_MOD_1 , "2");
|
||||||
|
|
||||||
Binding *bind;
|
Binding *bind;
|
||||||
TAILQ_FOREACH(bind, &bindings, bindings) {
|
TAILQ_FOREACH(bind, &bindings, bindings) {
|
||||||
printf("Grabbing %d\n", bind->keycode);
|
printf("Grabbing %d\n", bind->keycode);
|
||||||
|
|
46
table.c
46
table.c
|
@ -14,19 +14,24 @@
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
|
|
||||||
/* This is a two-dimensional dynamic array of Container-pointers. I’ve always wanted
|
int current_workspace = 0;
|
||||||
* to be a three-star programmer :) */
|
Workspace workspaces[10];
|
||||||
Container ***table = NULL;
|
/* Convenience pointer to the current workspace */
|
||||||
|
Workspace *c_ws = &workspaces[0];
|
||||||
struct table_dimensions_t table_dims = {0, 0};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize table
|
* Initialize table
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void init_table() {
|
void init_table() {
|
||||||
expand_table_cols();
|
int i;
|
||||||
expand_table_rows();
|
printf("sizof(workspaces) = %d\n", sizeof(workspaces));
|
||||||
|
memset(workspaces, 0, sizeof(workspaces));
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
expand_table_cols(&(workspaces[i]));
|
||||||
|
expand_table_rows(&(workspaces[i]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void new_container(Container **container) {
|
static void new_container(Container **container) {
|
||||||
|
@ -41,14 +46,14 @@ static void new_container(Container **container) {
|
||||||
* Add one row to the table
|
* Add one row to the table
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void expand_table_rows() {
|
void expand_table_rows(Workspace *workspace) {
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
table_dims.y++;
|
workspace->rows++;
|
||||||
|
|
||||||
for (c = 0; c < table_dims.x; c++) {
|
for (c = 0; c < workspace->cols; c++) {
|
||||||
table[c] = realloc(table[c], sizeof(Container*) * table_dims.y);
|
workspace->table[c] = realloc(workspace->table[c], sizeof(Container*) * workspace->rows);
|
||||||
new_container(&(table[c][table_dims.y-1]));
|
new_container(&(workspace->table[c][workspace->rows-1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,14 +61,15 @@ void expand_table_rows() {
|
||||||
* Add one column to the table
|
* Add one column to the table
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void expand_table_cols() {
|
void expand_table_cols(Workspace *workspace) {
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
table_dims.x++;
|
workspace->cols++;
|
||||||
table = realloc(table, sizeof(Container**) * table_dims.x);
|
|
||||||
table[table_dims.x-1] = calloc(sizeof(Container*) * table_dims.y, 1);
|
workspace->table = realloc(workspace->table, sizeof(Container**) * workspace->cols);
|
||||||
for (c = 0; c < table_dims.y; c++)
|
workspace->table[workspace->cols-1] = calloc(sizeof(Container*) * workspace->rows, 1);
|
||||||
new_container(&(table[table_dims.x-1][c]));
|
for (c = 0; c < workspace->rows; c++)
|
||||||
|
new_container(&(workspace->table[workspace->cols-1][c]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -71,6 +77,6 @@ void expand_table_cols() {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool cell_exists(int col, int row) {
|
bool cell_exists(int col, int row) {
|
||||||
return (col >= 0 && col < table_dims.x) &&
|
return (col >= 0 && col < c_ws->rows) &&
|
||||||
(row >= 0 && row < table_dims.y);
|
(row >= 0 && row < c_ws->cols);
|
||||||
}
|
}
|
||||||
|
|
11
table.h
11
table.h
|
@ -4,14 +4,15 @@
|
||||||
#ifndef _TABLE_H
|
#ifndef _TABLE_H
|
||||||
#define _TABLE_H
|
#define _TABLE_H
|
||||||
|
|
||||||
#define CUR_CELL (table[current_col][current_row])
|
#define CUR_TABLE (c_ws->table)
|
||||||
|
#define CUR_CELL (CUR_TABLE[current_col][current_row])
|
||||||
|
|
||||||
extern Container ***table;
|
extern Workspace *c_ws;
|
||||||
extern struct table_dimensions_t table_dims;
|
extern Workspace workspaces[10];
|
||||||
|
|
||||||
void init_table();
|
void init_table();
|
||||||
void expand_table_rows();
|
void expand_table_rows(Workspace *workspace);
|
||||||
void expand_table_cols();
|
void expand_table_cols(Workspace *workspace);
|
||||||
bool cell_exists(int col, int row);
|
bool cell_exists(int col, int row);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue