Make table dynamic

This commit is contained in:
Michael Stapelberg 2009-02-08 04:04:35 +01:00
parent b77bed65b3
commit aaa697494c
6 changed files with 168 additions and 70 deletions

View File

@ -1,2 +1,6 @@
all: all:
gcc -Wall -gdwarf-2 -g3 -I/usr/include/xcb -o mainx mainx.c -lxcb-wm gcc -Wall -gdwarf-2 -g3 -I/usr/include/xcb -c mainx.c
gcc -Wall -gdwarf-2 -g3 -I/usr/include/xcb -c table.c
gcc -Wall -gdwarf-2 -g3 -I/usr/include/xcb -c test_table.c
gcc -Wall -gdwarf-2 -g3 -I/usr/include/xcb -o mainx mainx.o table.o -lxcb-wm
gcc -Wall -gdwarf-2 -g3 -I/usr/include/xcb -o tt test_table.o table.o

11
data.h
View File

@ -1,3 +1,7 @@
#include <xcb/xcb.h>
#ifndef _DATA_H
#define _DATA_H
/* /*
* This file defines all data structures used by i3 * This file defines all data structures used by i3
* *
@ -10,7 +14,12 @@ typedef struct Font Font;
typedef struct Container Container; typedef struct Container Container;
typedef struct Client Client; typedef struct Client Client;
/* 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;
struct table_dimensions_t {
int x;
int y;
};
/* /*
* Defines a position in the table * Defines a position in the table
@ -72,3 +81,5 @@ struct Container {
enum { MODE_DEFAULT = 0, MODE_STACK = 1 } mode; enum { MODE_DEFAULT = 0, MODE_STACK = 1 } mode;
CIRCLEQ_HEAD(client_head, Client) clients; CIRCLEQ_HEAD(client_head, Client) clients;
}; };
#endif

112
mainx.c
View File

@ -18,6 +18,7 @@
#include "data.h" #include "data.h"
#include "queue.h" #include "queue.h"
#include "table.h"
Font myfont; Font myfont;
@ -31,8 +32,7 @@ table_t *byChild = 0;
table_t *byParent = 0; table_t *byParent = 0;
xcb_window_t root_win; xcb_window_t root_win;
/* _the_ table. Stores all clients. */
Container *table[10][10];
int current_col = 0; int current_col = 0;
int current_row = 0; int current_row = 0;
@ -401,26 +401,15 @@ 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 = 0, num_rows = 0; int num_cols = table_dims.x, num_rows = table_dims.y;
bool row_has_content;
for (rows = 0; rows < 10; rows++) {
row_has_content = false;
for (cols = 0; cols < 10; cols++)
if (table[cols][rows] != NULL) {
num_cols++;
row_has_content = true;
}
if (row_has_content)
num_rows++;
}
printf("got %d rows and %d cols\n", num_rows, num_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 / num_cols, height / num_rows);
/* Go through the whole table and render whats necessary */ /* Go through the whole table and render whats necessary */
for (rows = 0; rows < 10; rows++) for (cols = 0; cols < table_dims.x; cols++)
for (cols = 0; cols < 10; cols++) for (rows = 0; rows < table_dims.y; rows++)
if (table[cols][rows] != NULL) { if (table[cols][rows] != NULL) {
/* Update position of the container */ /* Update position of the container */
table[cols][rows]->row = rows; table[cols][rows]->row = rows;
@ -454,11 +443,11 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
xcb_screen_t *root_screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; xcb_screen_t *root_screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
/* Insert into the currently active container */ /* Insert into the currently active container */
CIRCLEQ_INSERT_TAIL(&(table[current_col][current_row]->clients), new, clients); CIRCLEQ_INSERT_TAIL(&(CUR_CELL->clients), new, clients);
printf("currently_focused = %p\n", new); printf("currently_focused = %p\n", new);
table[current_col][current_row]->currently_focused = new; CUR_CELL->currently_focused = new;
new->container = table[current_col][current_row]; new->container = CUR_CELL;
new->window = xcb_generate_id(conn); new->window = xcb_generate_id(conn);
new->child = child; new->child = child;
@ -554,7 +543,7 @@ static void focus_window(xcb_connection_t *connection, direction_t direction) {
/* TODO: for horizontal default layout, this has to be expanded to LEFT/RIGHT */ /* TODO: for horizontal default layout, this has to be expanded to LEFT/RIGHT */
if (direction == D_UP || direction == D_DOWN) { if (direction == D_UP || direction == D_DOWN) {
/* Lets see if we can perform up/down focus in the current container */ /* Lets see if we can perform up/down focus in the current container */
Container *container = table[current_col][current_row]; Container *container = CUR_CELL;
/* There always is a container. If not, current_col or current_row is wrong */ /* There always is a container. If not, current_col or current_row is wrong */
assert(container != NULL); assert(container != NULL);
@ -562,20 +551,17 @@ static void focus_window(xcb_connection_t *connection, direction_t direction) {
if (focus_window_in_container(connection, container, direction)) if (focus_window_in_container(connection, container, direction))
return; return;
} else if (direction == D_LEFT || direction == D_RIGHT) { } else if (direction == D_LEFT || direction == D_RIGHT) {
if (direction == D_RIGHT && table[current_col+1][current_row] != NULL) if (direction == D_RIGHT && cell_exists(current_col+1, current_row))
current_col++; current_col++;
else if (direction == D_LEFT && current_col > 0 && table[current_col-1][current_row] != NULL) else if (direction == D_LEFT && cell_exists(current_col-1, current_row))
current_col--; current_col--;
else { else {
printf("nah, not possible\n"); printf("nah, not possible\n");
return; return;
} }
if (table[current_col][current_row]->currently_focused != NULL) { if (CUR_CELL->currently_focused != NULL) {
printf("updating focus\n"); xcb_set_input_focus(connection, XCB_INPUT_FOCUS_NONE,
printf("entry = %p\n", table[current_col][current_row]->currently_focused); CUR_CELL->currently_focused->child, XCB_CURRENT_TIME);
printf("child = %p\n", table[current_col][current_row]->currently_focused->child);
xcb_set_input_focus(connection, XCB_INPUT_FOCUS_NONE, table[current_col][current_row]->currently_focused->child, XCB_CURRENT_TIME);
xcb_flush(connection); xcb_flush(connection);
} }
@ -587,7 +573,7 @@ static void focus_window(xcb_connection_t *connection, direction_t direction) {
static void move_current_window(xcb_connection_t *connection, direction_t direction) { static void move_current_window(xcb_connection_t *connection, direction_t direction) {
printf("moving window to direction %d\n", direction); printf("moving window to direction %d\n", direction);
/* Get current window */ /* Get current window */
Container *container = table[current_col][current_row]; Container *container = CUR_CELL;
/* There has to be a container, see focus_window() */ /* There has to be a container, see focus_window() */
assert(container != NULL); assert(container != NULL);
@ -600,28 +586,27 @@ static void move_current_window(xcb_connection_t *connection, direction_t direct
if (direction == D_RIGHT) { if (direction == D_RIGHT) {
printf("ok, moving right\n"); printf("ok, moving right\n");
if (table[current_col+1][current_row] == NULL) { expand_table_cols();
Container *new;
/* Create a new container */
new = table[current_col+1][current_row] = calloc(sizeof(Container), 1);
CIRCLEQ_INIT(&(new->clients));
/* As soon as the client is moved away, the next client in the old
* container needs to get focus, if any. Therefore, we save it here. */
Client *to_focus = CIRCLEQ_NEXT(current_client, clients);
if (to_focus == CIRCLEQ_END(&(container->clients)))
to_focus = NULL;
/* Remove it from the old container and put it into the new one */ Container *new = table[current_col+1][current_row];
CIRCLEQ_REMOVE(&(container->clients), current_client, clients);
CIRCLEQ_INSERT_TAIL(&(new->clients), current_client, clients);
/* Update data structures */ /* As soon as the client is moved away, the next client in the old
current_client->container = new; * container needs to get focus, if any. Therefore, we save it here. */
container->currently_focused = to_focus; Client *to_focus = CIRCLEQ_NEXT(current_client, clients);
new->currently_focused = current_client; if (to_focus == CIRCLEQ_END(&(container->clients)))
to_focus = NULL;
/* Remove it from the old container and put it into the new one */
CIRCLEQ_REMOVE(&(container->clients), current_client, clients);
CIRCLEQ_INSERT_TAIL(&(new->clients), current_client, clients);
/* Update data structures */
current_client->container = new;
container->currently_focused = to_focus;
new->currently_focused = current_client;
current_col++;
current_col++;
}
printf("done\n"); printf("done\n");
} }
@ -785,18 +770,16 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *c, xcb_unmap_notify_
return 0; return 0;
} }
/* TODO: make a list of containers to run through */
int rows, cols; int rows, cols;
Client *con_client; Client *con_client;
for (rows = 0; rows < 10; rows++) for (cols = 0; cols < table_dims.x; cols++)
for (cols = 0; cols < 10; cols++) for (rows = 0; rows < table_dims.y; rows++)
if (table[cols][rows] != NULL) CIRCLEQ_FOREACH(con_client, &(table[cols][rows]->clients), clients)
CIRCLEQ_FOREACH(con_client, &(table[cols][rows]->clients), clients) if (con_client == client) {
if (con_client == client) { printf("removing from container\n");
printf("removing from container\n"); CIRCLEQ_REMOVE(&(table[cols][rows]->clients), con_client, clients);
CIRCLEQ_REMOVE(&(table[cols][rows]->clients), con_client, clients); break;
break; }
}
@ -855,18 +838,9 @@ void manage_existing_windows(xcb_connection_t *c, xcb_property_handlers_t *proph
} }
int main() { int main() {
int i, j; int i;
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
table[i][j] = NULL;
/* init_table();
* By default, the table is one row and one column big. It contains
* one container in default mode in it.
*
*/
table[0][0] = calloc(sizeof(Container), 1);
CIRCLEQ_INIT(&(table[0][0]->clients));
xcb_connection_t *c; xcb_connection_t *c;
xcb_event_handlers_t evenths; xcb_event_handlers_t evenths;

62
table.c Normal file
View File

@ -0,0 +1,62 @@
/*
* This file provides functions for easier accessing of _the_ table
*
*/
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdbool.h>
#include <assert.h>
#include "data.h"
#include "table.h"
/* This is a two-dimensional dynamic array of Container-pointers. Ive always wanted
* to be a three-star programmer :) */
Container ***table = NULL;
struct table_dimensions_t table_dims = {0, 0};
void init_table() {
expand_table_cols();
expand_table_rows();
}
void expand_table_rows() {
int c;
Container *new;
table_dims.y++;
for (c = 0; c < table_dims.x; c++) {
table[c] = realloc(table[c], sizeof(Container*) * table_dims.y);
new = table[c][table_dims.y-1] = calloc(sizeof(Container), 1);
CIRCLEQ_INIT(&(new->clients));
}
}
void expand_table_cols() {
int c;
Container *new;
table_dims.x++;
table = realloc(table, sizeof(Container**) * table_dims.x);
table[table_dims.x-1] = calloc(sizeof(Container*) * table_dims.y, 1);
for (c = 0; c < table_dims.y; c++) {
new = table[table_dims.x-1][c] = calloc(sizeof(Container), 1);
CIRCLEQ_INIT(&(new->clients));
}
}
/*
* Performs simple bounds checking for the given column/row
*
*/
bool cell_exists(int col, int row) {
return (col >= 0 && col < table_dims.x) &&
(row >= 0 && row < table_dims.y);
}

17
table.h Normal file
View File

@ -0,0 +1,17 @@
#include <stdbool.h>
#include "data.h"
#ifndef _TABLE_H
#define _TABLE_H
#define CUR_CELL (table[current_col][current_row])
extern Container ***table;
extern struct table_dimensions_t table_dims;
void init_table();
void expand_table_rows();
void expand_table_cols();
bool cell_exists(int col, int row);
#endif

30
test_table.c Normal file
View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include "table.h"
void print_table() {
int r, c;
printf("printing table...\n");
for (c = 0; c < table_dims.x; c++)
for (r = 0; r < table_dims.y; r++)
printf("table[%d][%d] = %p\n", c, r, table[c][r]);
printf("done\n");
}
int main() {
printf("table.c tests\n");
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
init_table();
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
print_table();
printf("expand_table_cols()\n");
expand_table_cols();
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
print_table();
printf("expand_table_rows()\n");
expand_table_rows();
printf("table_dimensions = %d, %d\n", table_dims.x, table_dims.y);
print_table();
}