Make table dynamic
This commit is contained in:
parent
b77bed65b3
commit
aaa697494c
6
Makefile
6
Makefile
|
@ -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
11
data.h
|
@ -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
112
mainx.c
|
@ -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 what’s necessary */
|
/* Go through the whole table and render what’s 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) {
|
||||||
/* Let’s see if we can perform up/down focus in the current container */
|
/* Let’s 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;
|
||||||
|
|
|
@ -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. I’ve 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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue