]> git.sur5r.net Git - i3/i3/commitdiff
Make table dynamic
authorMichael Stapelberg <michael+git@stapelberg.de>
Sun, 8 Feb 2009 03:04:35 +0000 (04:04 +0100)
committerMichael Stapelberg <michael+git@stapelberg.de>
Sun, 8 Feb 2009 03:04:35 +0000 (04:04 +0100)
Makefile
data.h
mainx.c
table.c [new file with mode: 0644]
table.h [new file with mode: 0644]
test_table.c [new file with mode: 0644]

index 2fdcab5886088e77096b9cc40c11799e5122aa77..cf14312177452ebcb035c4e4750bd37bcf96f712 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,6 @@
 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
diff --git a/data.h b/data.h
index b80718021c65cbfca0331fc23b74d56e52855e0d..a9524c38266cdfd9de1ee93718040bff77e3d3ae 100644 (file)
--- a/data.h
+++ b/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
  *
@@ -10,7 +14,12 @@ typedef struct Font Font;
 typedef struct Container Container;
 typedef struct Client Client;
 
+/* Helper types */
 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
@@ -72,3 +81,5 @@ struct Container {
        enum { MODE_DEFAULT = 0, MODE_STACK = 1 } mode;
        CIRCLEQ_HEAD(client_head, Client) clients;
 };
+
+#endif
diff --git a/mainx.c b/mainx.c
index b095cb0dabccb499e24d76e8c4a7702b19162bbc..8fe6ebf3cd9d4fa4e6aed05e66b90698092b51e0 100644 (file)
--- a/mainx.c
+++ b/mainx.c
@@ -18,6 +18,7 @@
 #include "data.h"
 
 #include "queue.h"
+#include "table.h"
 
 Font myfont;
 
@@ -31,8 +32,7 @@ table_t *byChild = 0;
 table_t *byParent = 0;
 xcb_window_t root_win;
 
-/* _the_ table. Stores all clients. */
-Container *table[10][10];
+
 
 int current_col = 0;
 int current_row = 0;
@@ -401,26 +401,15 @@ void render_layout(xcb_connection_t *conn) {
        int width = root_screen->width_in_pixels;
        int height = root_screen->height_in_pixels;
 
-       int num_cols = 0, num_rows = 0;
-       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++;
-       }
+       int num_cols = table_dims.x, num_rows = table_dims.y;
 
        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",
                        width / num_cols, height / num_rows);
 
        /* Go through the whole table and render what’s necessary */
-       for (rows = 0; rows < 10; rows++)
-               for (cols = 0; cols < 10; cols++)
+       for (cols = 0; cols < table_dims.x; cols++)
+               for (rows = 0; rows < table_dims.y; rows++)
                        if (table[cols][rows] != NULL) {
                                /* Update position of the container */
                                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;
 
        /* 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);
-       table[current_col][current_row]->currently_focused = new;
-       new->container = table[current_col][current_row];
+       CUR_CELL->currently_focused = new;
+       new->container = CUR_CELL;
 
        new->window = xcb_generate_id(conn);
        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 */
        if (direction == D_UP || direction == D_DOWN) {
                /* 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 */
                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))
                        return;
        } 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++;
-               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--;
                else {
                        printf("nah, not possible\n");
                        return;
                }
-               if (table[current_col][current_row]->currently_focused != NULL) {
-                       printf("updating focus\n");
-                       printf("entry = %p\n", table[current_col][current_row]->currently_focused);
-                       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);
+               if (CUR_CELL->currently_focused != NULL) {
+                       xcb_set_input_focus(connection, XCB_INPUT_FOCUS_NONE,
+                                       CUR_CELL->currently_focused->child, XCB_CURRENT_TIME);
                        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) {
        printf("moving window to direction %d\n", direction);
        /* Get current window */
-       Container *container = table[current_col][current_row];
+       Container *container = CUR_CELL;
 
        /* There has to be a container, see focus_window() */
        assert(container != NULL);
@@ -600,28 +586,27 @@ static void move_current_window(xcb_connection_t *connection, direction_t direct
 
        if (direction == D_RIGHT) {
                printf("ok, moving right\n");
-               if (table[current_col+1][current_row] == NULL) {
-                       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 */
-                       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;
+               expand_table_cols();
+
+               Container *new = table[current_col+1][current_row];
+
+               /* 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 */
+               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");
        }
 
@@ -785,18 +770,16 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *c, xcb_unmap_notify_
                return 0;
        }
 
-       /* TODO: make a list of containers to run through */
        int rows, cols;
        Client *con_client;
-       for (rows = 0; rows < 10; rows++)
-               for (cols = 0; cols < 10; cols++)
-                       if (table[cols][rows] != NULL)
-                               CIRCLEQ_FOREACH(con_client, &(table[cols][rows]->clients), clients)
-                                       if (con_client == client) {
-                                               printf("removing from container\n");
-                                               CIRCLEQ_REMOVE(&(table[cols][rows]->clients), con_client, clients);
-                                               break;
-                                       }
+       for (cols = 0; cols < table_dims.x; cols++)
+               for (rows = 0; rows < table_dims.y; rows++)
+                       CIRCLEQ_FOREACH(con_client, &(table[cols][rows]->clients), clients)
+                               if (con_client == client) {
+                                       printf("removing from container\n");
+                                       CIRCLEQ_REMOVE(&(table[cols][rows]->clients), con_client, clients);
+                                       break;
+                               }
 
 
 
@@ -855,18 +838,9 @@ void manage_existing_windows(xcb_connection_t *c, xcb_property_handlers_t *proph
 }
 
 int main() {
-       int i, j;
-       for (i = 0; i < 10; i++)
-               for (j = 0; j < 10; j++)
-                       table[i][j] = NULL;
-
-       /*
-        * 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));
+       int i;
+
+       init_table();
 
        xcb_connection_t *c;
        xcb_event_handlers_t evenths;
diff --git a/table.c b/table.c
new file mode 100644 (file)
index 0000000..a94fc1b
--- /dev/null
+++ b/table.c
@@ -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);
+}
+
diff --git a/table.h b/table.h
new file mode 100644 (file)
index 0000000..40a7883
--- /dev/null
+++ b/table.h
@@ -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
diff --git a/test_table.c b/test_table.c
new file mode 100644 (file)
index 0000000..14e36de
--- /dev/null
@@ -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();
+
+}