]> git.sur5r.net Git - i3/i3/blobdiff - mainx.c
Cleanups, first strike. Move stuff to separate files, eliminate warnings
[i3/i3] / mainx.c
diff --git a/mainx.c b/mainx.c
index 421aab5d342f78567a2629868e636c9fad93844c..359e3f7430099834846e93ef82b0ab931ac49e71 100644 (file)
--- a/mainx.c
+++ b/mainx.c
 #include <X11/XKBlib.h>
 #include <X11/extensions/XKB.h>
 
-#include "xcb_wm.h"
-#include "xcb_aux.h"
-#include "xcb_event.h"
-#include "xcb_property.h"
-#include "xcb_keysyms.h"
-#include "xcb_icccm.h"
-#include "xinerama.h"
+#include <xcb/xcb_wm.h>
+#include <xcb/xcb_aux.h>
+#include <xcb/xcb_event.h>
+#include <xcb/xcb_property.h>
+#include <xcb/xcb_keysyms.h>
+#include <xcb/xcb_icccm.h>
+#include <xcb/xinerama.h>
 #include "data.h"
 
 #include "queue.h"
 #include "table.h"
 #include "font.h"
+#include "layout.h"
+#include "debug.h"
+#include "handlers.h"
+#include "util.h"
 
 #define TERMINAL "/usr/pkg/bin/urxvt"
 
@@ -40,7 +44,7 @@ static const int RIGHT = 5;
 
 /* This is the filtered environment which will be passed to opened applications.
  * It contains DISPLAY (naturally) and locales stuff (LC_*, LANG) */
-static char **environment;
+char **environment;
 
 /* hm, xcb_wm wants us to implement this. */
 table_t *byChild = 0;
@@ -50,209 +54,6 @@ xcb_window_t root_win;
 char *pattern = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso8859-1";
 int num_screens = 0;
 
-
-int current_col = 0;
-int current_row = 0;
-
-
-int globalc = 0;
-
-
-static const char *labelError[] = {
-    "Success",
-    "BadRequest",
-    "BadValue",
-    "BadWindow",
-    "BadPixmap",
-    "BadAtom",
-    "BadCursor",
-    "BadFont",
-    "BadMatch",
-    "BadDrawable",
-    "BadAccess",
-    "BadAlloc",
-    "BadColor",
-    "BadGC",
-    "BadIDChoice",
-    "BadName",
-    "BadLength",
-    "BadImplementation",
-};
-
-static const char *labelRequest[] = {
-    "no request",
-    "CreateWindow",
-    "ChangeWindowAttributes",
-    "GetWindowAttributes",
-    "DestroyWindow",
-    "DestroySubwindows",
-    "ChangeSaveSet",
-    "ReparentWindow",
-    "MapWindow",
-    "MapSubwindows",
-    "UnmapWindow",
-    "UnmapSubwindows",
-    "ConfigureWindow",
-    "CirculateWindow",
-    "GetGeometry",
-    "QueryTree",
-    "InternAtom",
-    "GetAtomName",
-    "ChangeProperty",
-    "DeleteProperty",
-    "GetProperty",
-    "ListProperties",
-    "SetSelectionOwner",
-    "GetSelectionOwner",
-    "ConvertSelection",
-    "SendEvent",
-    "GrabPointer",
-    "UngrabPointer",
-    "GrabButton",
-    "UngrabButton",
-    "ChangeActivePointerGrab",
-    "GrabKeyboard",
-    "UngrabKeyboard",
-    "GrabKey",
-    "UngrabKey",
-    "AllowEvents",
-    "GrabServer",
-    "UngrabServer",
-    "QueryPointer",
-    "GetMotionEvents",
-    "TranslateCoords",
-    "WarpPointer",
-    "SetInputFocus",
-    "GetInputFocus",
-    "QueryKeymap",
-    "OpenFont",
-    "CloseFont",
-    "QueryFont",
-    "QueryTextExtents",
-    "ListFonts",
-    "ListFontsWithInfo",
-    "SetFontPath",
-    "GetFontPath",
-    "CreatePixmap",
-    "FreePixmap",
-    "CreateGC",
-    "ChangeGC",
-    "CopyGC",
-    "SetDashes",
-    "SetClipRectangles",
-    "FreeGC",
-    "ClearArea",
-    "CopyArea",
-    "CopyPlane",
-    "PolyPoint",
-    "PolyLine",
-    "PolySegment",
-    "PolyRectangle",
-    "PolyArc",
-    "FillPoly",
-    "PolyFillRectangle",
-    "PolyFillArc",
-    "PutImage",
-    "GetImage",
-    "PolyText",
-    "PolyText",
-    "ImageText",
-    "ImageText",
-    "CreateColormap",
-    "FreeColormap",
-    "CopyColormapAndFree",
-    "InstallColormap",
-    "UninstallColormap",
-    "ListInstalledColormaps",
-    "AllocColor",
-    "AllocNamedColor",
-    "AllocColorCells",
-    "AllocColorPlanes",
-    "FreeColors",
-    "StoreColors",
-    "StoreNamedColor",
-    "QueryColors",
-    "LookupColor",
-    "CreateCursor",
-    "CreateGlyphCursor",
-    "FreeCursor",
-    "RecolorCursor",
-    "QueryBestSize",
-    "QueryExtension",
-    "ListExtensions",
-    "ChangeKeyboardMapping",
-    "GetKeyboardMapping",
-    "ChangeKeyboardControl",
-    "GetKeyboardControl",
-    "Bell",
-    "ChangePointerControl",
-    "GetPointerControl",
-    "SetScreenSaver",
-    "GetScreenSaver",
-    "ChangeHosts",
-    "ListHosts",
-    "SetAccessControl",
-    "SetCloseDownMode",
-    "KillClient",
-    "RotateProperties",
-    "ForceScreenSaver",
-    "SetPointerMapping",
-    "GetPointerMapping",
-    "SetModifierMapping",
-    "GetModifierMapping",
-    "major 120",
-    "major 121",
-    "major 122",
-    "major 123",
-    "major 124",
-    "major 125",
-    "major 126",
-    "NoOperation",
-};
-
-static const char *labelEvent[] = {
-    "error",
-    "reply",
-    "KeyPress",
-    "KeyRelease",
-    "ButtonPress",
-    "ButtonRelease",
-    "MotionNotify",
-    "EnterNotify",
-    "LeaveNotify",
-    "FocusIn",
-    "FocusOut",
-    "KeymapNotify",
-    "Expose",
-    "GraphicsExpose",
-    "NoExpose",
-    "VisibilityNotify",
-    "CreateNotify",
-    "DestroyNotify",
-    "UnmapNotify",
-    "MapNotify",
-    "MapRequest",
-    "ReparentNotify",
-    "ConfigureNotify",
-    "ConfigureRequest",
-    "GravityNotify",
-    "ResizeRequest",
-    "CirculateNotify",
-    "CirculateRequest",
-    "PropertyNotify",
-    "SelectionClear",
-    "SelectionRequest",
-    "SelectionNotify",
-    "ColormapNotify",
-    "ClientMessage",
-    "MappingNotify",
-};
-
-static const char *labelSendEvent[] = {
-    "",
-    " (from SendEvent)",
-};
-
 /*
  *
  * TODO: what exactly does this, what happens if we leave stuff out?
@@ -308,211 +109,6 @@ void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *c, xcb_win
        free(geom);
 }
 
-
-/*
- * Returns the colorpixel to use for the given hex color (think of HTML).
- *
- * The hex_color has to start with #, for example #FF00FF.
- *
- * NOTE that get_colorpixel() does _NOT_ check the given color code for validity.
- * This has to be done by the caller.
- *
- */
-uint32_t get_colorpixel(xcb_connection_t *conn, xcb_window_t window, char *hex) {
-       #define RGB_8_TO_16(i) (65535 * ((i) & 0xFF) / 255)
-        char strgroups[3][3] = {{hex[1], hex[2], '\0'},
-                                {hex[3], hex[4], '\0'},
-                                {hex[5], hex[6], '\0'}};
-       int rgb16[3] = {RGB_8_TO_16(strtol(strgroups[0], NULL, 16)),
-                       RGB_8_TO_16(strtol(strgroups[1], NULL, 16)),
-                       RGB_8_TO_16(strtol(strgroups[2], NULL, 16))};
-
-       xcb_screen_t *root_screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
-
-       xcb_colormap_t colormapId = xcb_generate_id(conn);
-       xcb_create_colormap(conn, XCB_COLORMAP_ALLOC_NONE, colormapId, window, root_screen->root_visual);
-       xcb_alloc_color_reply_t *reply = xcb_alloc_color_reply(conn,
-                       xcb_alloc_color(conn, colormapId, rgb16[0], rgb16[1], rgb16[2]), NULL);
-
-       if (!reply) {
-               printf("color fail\n");
-               exit(1);
-       }
-
-       uint32_t pixel = reply->pixel;
-       free(reply);
-       xcb_free_colormap(conn, colormapId);
-       return pixel;
-}
-
-/*
- * (Re-)draws window decorations for a given Client
- *
- */
-void decorate_window(xcb_connection_t *conn, Client *client) {
-       uint32_t mask = 0;
-       uint32_t values[3];
-       i3Font *font = load_font(conn, pattern);
-       uint32_t background_color,
-                text_color,
-                border_color;
-
-       if (client->container->currently_focused == client) {
-               background_color = get_colorpixel(conn, client->frame, "#285577");
-               text_color = get_colorpixel(conn, client->frame, "#ffffff");
-               border_color = get_colorpixel(conn, client->frame, "#4c7899");
-       } else {
-               background_color = get_colorpixel(conn, client->frame, "#222222");
-               text_color = get_colorpixel(conn, client->frame, "#888888");
-               border_color = get_colorpixel(conn, client->frame, "#333333");
-       }
-
-       /* Our plan is the following:
-          - Draw a rect around the whole client in background_color
-          - Draw two lines in a lighter color
-          - Draw the window’s title
-
-          Note that xcb_image_text apparently adds 1xp border around the font? Can anyone confirm this?
-        */
-
-       /* Draw a green rectangle around the window */
-       mask = XCB_GC_FOREGROUND;
-       values[0] = background_color;
-       xcb_change_gc(conn, client->titlegc, mask, values);
-
-       xcb_rectangle_t rect = {0, 0, client->width, client->height};
-       xcb_poly_fill_rectangle(conn, client->frame, client->titlegc, 1, &rect);
-
-       /* Draw the lines */
-       /* TODO: this needs to be more beautiful somewhen. maybe stdarg + change_gc(gc, ...) ? */
-#define DRAW_LINE(colorpixel, x, y, to_x, to_y) { \
-               uint32_t draw_values[1]; \
-               draw_values[0] = colorpixel; \
-               xcb_change_gc(conn, client->titlegc, XCB_GC_FOREGROUND, draw_values); \
-               xcb_point_t points[] = {{x, y}, {to_x, to_y}}; \
-               xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, client->frame, client->titlegc, 2, points); \
-       }
-
-       DRAW_LINE(border_color, 2, 0, client->width, 0);
-       DRAW_LINE(border_color, 2, font->height + 3, 2 + client->width, font->height + 3);
-
-       /* Draw the font */
-       mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
-
-       values[0] = text_color;
-       values[1] = background_color;
-       values[2] = font->id;
-
-       xcb_change_gc(conn, client->titlegc, mask, values);
-
-       /* TODO: utf8? */
-       char *label;
-       asprintf(&label, "(%08x) %.*s", client->frame, client->name_len, client->name);
-        xcb_void_cookie_t text_cookie = xcb_image_text_8_checked(conn, strlen(label), client->frame,
-                                       client->titlegc, 3 /* X */, font->height /* Y = baseline of font */, label);
-       free(label);
-}
-
-void render_container(xcb_connection_t *connection, Container *container) {
-       Client *client;
-       uint32_t values[4];
-       uint32_t mask = XCB_CONFIG_WINDOW_X |
-                       XCB_CONFIG_WINDOW_Y |
-                       XCB_CONFIG_WINDOW_WIDTH |
-                       XCB_CONFIG_WINDOW_HEIGHT;
-       i3Font *font = load_font(connection, pattern);
-
-       if (container->mode == MODE_DEFAULT) {
-               int num_clients = 0;
-               CIRCLEQ_FOREACH(client, &(container->clients), clients)
-                       num_clients++;
-               printf("got %d clients in this default container.\n", num_clients);
-
-               int current_client = 0;
-               CIRCLEQ_FOREACH(client, &(container->clients), clients) {
-                       /* TODO: rewrite this block so that the need to puke vanishes :) */
-                       /* TODO: at the moment, every column/row is 200px. This
-                        * needs to be changed to "percentage of the screen" by
-                        * default and adjustable by the user if necessary.
-                        */
-                       values[0] = container->x + (container->col * container->width); /* x */
-                       values[1] = container->y + (container->row * container->height +
-                               (container->height / num_clients) * current_client); /* y */
-
-                       if (client->x != values[0] || client->y != values[1]) {
-                               printf("frame needs to be pushed to %dx%d\n",
-                                               values[0], values[1]);
-                               client->x = values[0];
-                               client->y = values[1];
-                               xcb_configure_window(connection, client->frame,
-                                               XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
-                       }
-                       /* TODO: vertical default layout */
-                       values[0] = container->width; /* width */
-                       values[1] = container->height / num_clients; /* height */
-
-                       if (client->width != values[0] || client->height != values[1]) {
-                               client->width = values[0];
-                               client->height = values[1];
-                               xcb_configure_window(connection, client->frame,
-                                               XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
-                       }
-
-                       /* TODO: hmm, only do this for new wins */
-                       /* The coordinates of the child are relative to its frame, we
-                        * add a border of 2 pixel to each value */
-                       values[0] = 2;
-                       values[1] = font->height + 2 + 2;
-                       values[2] = client->width - (values[0] + 2);
-                       values[3] = client->height - (values[1] + 2);
-                       printf("child itself will be at %dx%d with size %dx%d\n",
-                                       values[0], values[1], values[2], values[3]);
-
-                       xcb_configure_window(connection, client->child, mask, values);
-
-                       decorate_window(connection, client);
-                       current_client++;
-               }
-       } else {
-               /* TODO: Implement stacking */
-       }
-}
-
-void render_layout(xcb_connection_t *conn) {
-       int cols, rows;
-       int screen;
-       for (screen = 0; screen < num_screens; screen++) {
-               printf("Rendering screen %d\n", screen);
-               /* TODO: get the workspace which is active on the screen */
-               int width = workspaces[screen].width;
-               int height = workspaces[screen].height;
-
-               printf("got %d rows and %d cols\n", c_ws->rows, c_ws->cols);
-               printf("each of them therefore is %d px width and %d px height\n",
-                               width / c_ws->cols, height / c_ws->rows);
-
-               /* Go through the whole table and render what’s necessary */
-               for (cols = 0; cols < c_ws->cols; cols++)
-                       for (rows = 0; rows < c_ws->rows; rows++) {
-                               Container *con = CUR_TABLE[cols][rows];
-                               printf("container has %d colspan, %d rowspan\n",
-                                               con->colspan, con->rowspan);
-                               /* Update position of the container */
-                               con->row = rows;
-                               con->col = cols;
-                               con->x = workspaces[screen].x;
-                               con->y = workspaces[screen].y;
-                               con->width = (width / c_ws->cols) * con->colspan;
-                               con->height = (height / c_ws->rows) * con->rowspan;
-
-                               /* Render it */
-                               render_container(conn, CUR_TABLE[cols][rows]);
-                       }
-       }
-
-       xcb_flush(conn);
-}
-
 /*
  * Let’s own this window…
  *
@@ -609,701 +205,6 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
        render_layout(conn);
 }
 
-static bool focus_window_in_container(xcb_connection_t *connection, Container *container,
-               direction_t direction) {
-       /* If this container is empty, we’re done */
-       if (container->currently_focused == NULL)
-               return false;
-
-       Client *candidad;
-       if (direction == D_UP)
-               candidad = CIRCLEQ_PREV(container->currently_focused, clients);
-       else if (direction == D_DOWN)
-               candidad = CIRCLEQ_NEXT(container->currently_focused, clients);
-
-       /* If we don’t have anything to select, we’re done */
-       if (candidad == CIRCLEQ_END(&(container->clients)))
-               return false;
-
-       /* Set focus if we could successfully move */
-       container->currently_focused = candidad;
-       xcb_set_input_focus(connection, XCB_INPUT_FOCUS_NONE, candidad->child, XCB_CURRENT_TIME);
-       render_layout(connection);
-
-       return true;
-}
-
-static void focus_window(xcb_connection_t *connection, direction_t direction) {
-       printf("focusing direction %d\n", 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 = CUR_CELL;
-
-               /* There always is a container. If not, current_col or current_row is wrong */
-               assert(container != NULL);
-
-               if (focus_window_in_container(connection, container, direction))
-                       return;
-       } else if (direction == D_LEFT || direction == D_RIGHT) {
-               if (direction == D_RIGHT && cell_exists(current_col+1, current_row))
-                       current_col++;
-               else if (direction == D_LEFT && cell_exists(current_col-1, current_row))
-                       current_col--;
-               else {
-                       printf("nah, not possible\n");
-                       return;
-               }
-               if (CUR_CELL->currently_focused != NULL) {
-                       xcb_set_input_focus(connection, XCB_INPUT_FOCUS_NONE,
-                                       CUR_CELL->currently_focused->child, XCB_CURRENT_TIME);
-                       render_layout(connection);
-               }
-
-       } else {
-               printf("direction unhandled\n");
-       }
-}
-
-/*
- * Tries to move the window inside its current container.
- *
- * Returns true if the window could be moved, false otherwise.
- *
- */
-static bool move_current_window_in_container(xcb_connection_t *connection, Client *client,
-               direction_t direction) {
-       Client *other = (direction == D_UP ? CIRCLEQ_PREV(client, clients) :
-                                               CIRCLEQ_NEXT(client, clients));
-
-       if (other == CIRCLEQ_END(&(client->container->clients)))
-               return false;
-
-       printf("i can do that\n");
-       /* We can move the client inside its current container */
-       CIRCLEQ_REMOVE(&(client->container->clients), client, clients);
-       if (direction == D_UP)
-               CIRCLEQ_INSERT_BEFORE(&(client->container->clients), other, client, clients);
-       else CIRCLEQ_INSERT_AFTER(&(client->container->clients), other, client, clients);
-       render_layout(connection);
-       return true;
-}
-
-/*
- * Moves the current window to the given direction, creating a column/row if
- * necessary
- *
- */
-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 = CUR_CELL,
-                 *new;
-
-       /* There has to be a container, see focus_window() */
-       assert(container != NULL);
-
-       /* If there is no window, we’re done */
-       if (container->currently_focused == NULL)
-               return;
-
-       /* 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 *current_client = container->currently_focused;
-       Client *to_focus = CIRCLEQ_NEXT(current_client, clients);
-       if (to_focus == CIRCLEQ_END(&(container->clients)))
-               to_focus = NULL;
-
-       switch (direction) {
-               case D_LEFT:
-                       if (current_col == 0)
-                               return;
-
-                       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:
-                       /* TODO: if we’re at the up-most position, move the rest of the table down */
-                       if (move_current_window_in_container(connection, current_client, D_UP) ||
-                               current_row == 0)
-                               return;
-
-                       new = CUR_TABLE[current_col][--current_row];
-                       break;
-               case D_DOWN:
-                       if (move_current_window_in_container(connection, current_client, D_DOWN))
-                               return;
-
-                       if (current_row == (c_ws->rows-1))
-                               expand_table_rows(c_ws);
-
-                       new = CUR_TABLE[current_col][++current_row];
-                       break;
-       }
-
-       /* 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;
-
-       /* TODO: delete all empty columns/rows */
-
-       render_layout(connection);
-}
-
-/*
- * "Snaps" the current container (not possible for windows, because it works at table base)
- * to the given direction, that is, adjusts cellspan/rowspan
- *
- */
-static void snap_current_container(xcb_connection_t *connection, direction_t direction) {
-       printf("snapping container to direction %d\n", direction);
-
-       Container *container = CUR_CELL;
-       int i;
-
-       assert(container != NULL);
-
-       switch (direction) {
-               case D_LEFT:
-                       /* Snap to the left is actually a move to the left and then a snap right */
-                       move_current_window(connection, D_LEFT);
-                       snap_current_container(connection, D_RIGHT);
-                       return;
-               case D_RIGHT:
-                       /* Check if the cell is used */
-                       if (!cell_exists(container->col + 1, container->row) ||
-                               CUR_TABLE[container->col+1][container->row]->currently_focused != NULL) {
-                               printf("cannot snap to right - the cell is already used\n");
-                               return;
-                       }
-
-                       /* Check if there are other cells with rowspan, which are in our way.
-                        * If so, reduce their rowspan. */
-                       for (i = container->row-1; i >= 0; i--) {
-                               printf("we got cell %d, %d with rowspan %d\n",
-                                               container->col+1, i, CUR_TABLE[container->col+1][i]->rowspan);
-                               while ((CUR_TABLE[container->col+1][i]->rowspan-1) >= (container->row - i))
-                                       CUR_TABLE[container->col+1][i]->rowspan--;
-                               printf("new rowspan = %d\n", CUR_TABLE[container->col+1][i]->rowspan);
-                       }
-
-                       container->colspan++;
-                       break;
-               case D_UP:
-                       move_current_window(connection, D_UP);
-                       snap_current_container(connection, D_DOWN);
-                       return;
-               case D_DOWN:
-                       printf("snapping down\n");
-                       if (!cell_exists(container->col, container->row+1) ||
-                               CUR_TABLE[container->col][container->row+1]->currently_focused != NULL) {
-                               printf("cannot snap down - the cell is already used\n");
-                               return;
-                       }
-
-                       for (i = container->col-1; i >= 0; i--) {
-                               printf("we got cell %d, %d with colspan %d\n",
-                                               i, container->row+1, CUR_TABLE[i][container->row+1]->colspan);
-                               while ((CUR_TABLE[i][container->row+1]->colspan-1) >= (container->col - i))
-                                       CUR_TABLE[i][container->row+1]->colspan--;
-                               printf("new colspan = %d\n", CUR_TABLE[i][container->row+1]->colspan);
-
-                       }
-
-                       container->rowspan++;
-                       break;
-       }
-
-       render_layout(connection);
-}
-
-int format_event(xcb_generic_event_t *e)
-{           
-    uint8_t sendEvent;
-    uint16_t seqnum;
-
-    sendEvent = (e->response_type & 0x80) ? 1 : 0;
-    e->response_type &= ~0x80;
-    seqnum = *((uint16_t *) e + 1);
-
-    switch(e->response_type) 
-    {   
-    case 0:
-        printf("Error %s on seqnum %d (%s).\n",
-            labelError[*((uint8_t *) e + 1)],
-            seqnum,
-            labelRequest[*((uint8_t *) e + 10)]);
-        break;
-    default:
-        printf("Event %s following seqnum %d%s.\n",
-            labelEvent[e->response_type],
-            seqnum,
-            labelSendEvent[sendEvent]);
-        break;  
-    case XCB_KEYMAP_NOTIFY:
-        printf("Event %s%s.\n",
-            labelEvent[e->response_type],
-            labelSendEvent[sendEvent]);
-        break;
-    }
-
-    fflush(stdout);
-    return 1;
-}
-
-
-static int handleEvent(void *ignored, xcb_connection_t *c, xcb_generic_event_t *e)
-{
-        return format_event(e);
-}
-
-/*
- * Starts the given application with the given args.
- *
- */
-static void start_application(const char *path, const char *args) {
-       pid_t pid;
-       if ((pid = vfork()) == 0) {
-               /* This is the child */
-               char *argv[2];
-               /* TODO: For now, we ignore args. Later on, they should be parsed
-                  correctly (like in the shell?) */
-               argv[0] = strdup(path);
-               argv[1] = NULL;
-               execve(path, argv, environment);
-               /* not reached */
-       }
-}
-
-/*
- * Due to bindings like Mode_switch + <a>, we need to bind some keys in XCB_GRAB_MODE_SYNC.
- * Therefore, we just replay all key presses.
- *
- */
-static int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_release_event_t *event) {
-       printf("got key release, just passing\n");
-       xcb_allow_events(conn, ReplayKeyboard, event->time);
-       xcb_flush(conn);
-       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;
-
-       /* TODO: does grabbing the server actually bring us any (speed)advantages? */
-       //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);
-               }
-
-       /* Restore focus on the new workspace */
-       if (CUR_CELL->currently_focused != NULL)
-               xcb_set_input_focus(conn, XCB_INPUT_FOCUS_NONE, CUR_CELL->currently_focused->child, XCB_CURRENT_TIME);
-       else xcb_set_input_focus(conn, XCB_INPUT_FOCUS_NONE, root_win, XCB_CURRENT_TIME);
-
-       //xcb_ungrab_server(conn);
-
-       render_layout(conn);
-}
-
-/*
- * Parses a command, see file CMDMODE for more information
- *
- */
-static void parse_command(xcb_connection_t *conn, const char *command) {
-       printf("--- parsing command \"%s\" ---\n", command);
-       /* Hmm, just to be sure */
-       if (command[0] == '\0')
-               return;
-
-       /* Is it an <exec>? */
-       if (strncmp(command, "exec ", strlen("exec ")) == 0) {
-               printf("starting \"%s\"\n", command + strlen("exec "));
-               start_application(command+strlen("exec "), NULL);
-               return;
-       }
-
-       /* Is it a <with>? */
-       if (command[0] == 'w') {
-               /* TODO: implement */
-               printf("not yet implemented.\n");
-               return;
-       }
-
-       /* It's a normal <cmd> */
-       int times;
-       char *rest = NULL;
-       enum { ACTION_FOCUS, ACTION_MOVE, ACTION_SNAP } action = ACTION_FOCUS;
-       direction_t direction;
-       times = strtol(command, &rest, 10);
-       if (rest == NULL) {
-               printf("Invalid command: Consists only of a movement\n");
-               return;
-       }
-       if (*rest == 'm' || *rest == 's') {
-               action = (*rest == 'm' ? ACTION_MOVE : ACTION_SNAP);
-               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> */
-       while (*rest != '\0') {
-               if (*rest == 'h')
-                       direction = D_LEFT;
-               else if (*rest == 'j')
-                       direction = D_DOWN;
-               else if (*rest == 'k')
-                       direction = D_UP;
-               else if (*rest == 'l')
-                       direction = D_RIGHT;
-               else {
-                       printf("unknown direction: %c\n", *rest);
-                       return;
-               }
-
-               if (action == ACTION_FOCUS)
-                       focus_window(conn, direction);
-               else if (action == ACTION_MOVE)
-                       move_current_window(conn, direction);
-               else if (action == ACTION_SNAP)
-                       snap_current_container(conn, direction);
-
-               rest++;
-       }
-
-       printf("--- done ---\n");
-}
-
-/*
- * There was a key press. We lookup the key symbol and see if there are any bindings
- * on that. This allows to do things like binding special characters (think of ä) to
- * functions to get one more modifier while not losing AltGr :-)
- * TODO: this description needs to be more understandable
- *
- */
-static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_t *event) {
-       printf("Keypress %d\n", event->detail);
-
-       /* We need to get the keysym group (There are group 1 to group 4, each holding
-          two keysyms (without shift and with shift) using Xkb because X fails to
-          provide them reliably (it works in Xephyr, it does not in real X) */
-       XkbStateRec state;
-       if (XkbGetState(xkbdpy, XkbUseCoreKbd, &state) == Success && (state.group+1) == 2)
-               event->state |= 0x2;
-
-       printf("state %d\n", event->state);
-
-       /* Find the binding */
-       /* TODO: event->state durch eine bitmask filtern und dann direkt vergleichen */
-       Binding *bind, *best_match = TAILQ_END(&bindings);
-       TAILQ_FOREACH(bind, &bindings, bindings) {
-               if (bind->keycode == event->detail &&
-                       (bind->mods & event->state) == bind->mods) {
-                       if (best_match == TAILQ_END(&bindings) ||
-                               bind->mods > best_match->mods)
-                               best_match = bind;
-               }
-       }
-
-       /* No match? Then it was an actively grabbed key, that is with Mode_switch, and
-          the user did not press Mode_switch, so just pass it… */
-       if (best_match == TAILQ_END(&bindings)) {
-               xcb_allow_events(conn, ReplayKeyboard, event->time);
-               xcb_flush(conn);
-               return 1;
-       }
-
-       if (event->state & 0x2) {
-               printf("that's mode_switch\n");
-               parse_command(conn, best_match->command);
-               printf("ok, hiding this event.\n");
-               xcb_allow_events(conn, SyncKeyboard, event->time);
-               xcb_flush(conn);
-               return 1;
-       }
-
-       parse_command(conn, best_match->command);
-       return 1;
-}
-
-static void set_focus(xcb_connection_t *conn, Client *client) {
-       /* Update container */
-       Client *old_client = client->container->currently_focused;
-       client->container->currently_focused = client;
-
-       current_col = client->container->col;
-       current_row = client->container->row;
-
-       /* Set focus to the entered window, and flush xcb buffer immediately */
-       xcb_set_input_focus(conn, XCB_INPUT_FOCUS_NONE, client->child, XCB_CURRENT_TIME);
-       /* Update last/current client’s titlebar */
-       if (old_client != NULL)
-               decorate_window(conn, old_client);
-       decorate_window(conn, client);
-       xcb_flush(conn);
-}
-
-/*
- * When the user moves the mouse pointer onto a window, this callback gets called.
- *
- */
-static int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_event_t *event) {
-       printf("enter_notify\n");
-
-       /* This was either a focus for a client’s parent (= titlebar)… */
-       Client *client = table_get(byParent, event->event);
-       /* …or the client itself */
-       if (client == NULL)
-               client = table_get(byChild, event->event);
-
-       /* If not, then this event is not interesting. This should not happen */
-       if (client == NULL) {
-               printf("DEBUG: Uninteresting enter_notify-event?\n");
-               return 1;
-       }
-
-       set_focus(conn, client);
-
-       return 1;
-}
-
-static int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_event_t *event) {
-       printf("button press!\n");
-       /* This was either a focus for a client’s parent (= titlebar)… */
-       Client *client = table_get(byChild, event->event);
-       if (client == NULL)
-               client = table_get(byParent, event->event);
-       if (client == NULL)
-               return 1;
-
-       xcb_window_t root = xcb_setup_roots_iterator(xcb_get_setup(conn)).data->root;
-       xcb_screen_t *root_screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
-
-       /* Set focus in any case */
-       set_focus(conn, client);
-
-       /* Let’s see if this was on the borders (= resize). If not, we’re done */
-       i3Font *font = load_font(conn, pattern);
-       printf("press button on x=%d, y=%d\n", event->event_x, event->event_y);
-       if (event->event_y <= (font->height + 2))
-               return 1;
-
-       printf("that was resize\n");
-
-       /* Open a new window, the resizebar. Grab the pointer and move the window around
-          as the user moves the pointer. */
-
-
-       /* TODO: the whole logic is missing. this is just a proof of concept */
-       xcb_window_t grabwin = xcb_generate_id(conn);
-
-       uint32_t mask = 0;
-       uint32_t values[3];
-
-       xcb_create_window(conn,
-                       0,
-                       grabwin,
-                       root,
-                       0, /* x */
-                       0, /* y */
-                       root_screen->width_in_pixels, /* width */
-                       root_screen->height_in_pixels, /* height */
-                       /* border_width */ 0,
-                       XCB_WINDOW_CLASS_INPUT_ONLY,
-                       root_screen->root_visual,
-                       0,
-                       values);
-
-       /* Map the window on the screen (= make it visible) */
-       xcb_map_window(conn, grabwin);
-
-       xcb_window_t helpwin = xcb_generate_id(conn);
-
-       mask = XCB_CW_BACK_PIXEL;
-       values[0] = root_screen->white_pixel;
-       xcb_create_window(conn, root_screen->root_depth, helpwin, root,
-                       event->root_x,
-                       0,
-                       5,
-                       root_screen->height_in_pixels,
-                       /* bordor */ 0,
-                       XCB_WINDOW_CLASS_INPUT_OUTPUT,
-                       root_screen->root_visual,
-                       mask,
-                       values);
-
-       xcb_map_window(conn, helpwin);
-       xcb_circulate_window(conn, XCB_CIRCULATE_RAISE_LOWEST, helpwin);
-
-       xcb_grab_pointer(conn, false, root, XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION,
-                       XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, grabwin, XCB_NONE, XCB_CURRENT_TIME);
-
-       xcb_flush(conn);
-
-       xcb_generic_event_t *inside_event;
-       /* I’ve always wanted to have my own eventhandler… */
-       while ((inside_event = xcb_wait_for_event(conn))) {
-               /* Same as get_event_handler in xcb */
-               int nr = inside_event->response_type;
-               if (nr == 0) {
-                       handleEvent(NULL, conn, inside_event);
-                       continue;
-               }
-               assert(nr < 256);
-               nr &= XCB_EVENT_RESPONSE_TYPE_MASK;
-               assert(nr >= 2);
-
-               /* Check if we need to escape this loop… */
-               if (nr == XCB_BUTTON_RELEASE)
-                       break;
-
-               switch (nr) {
-                       case XCB_MOTION_NOTIFY:
-                               values[0] = ((xcb_motion_notify_event_t*)inside_event)->root_x;
-                               xcb_configure_window(conn, helpwin, XCB_CONFIG_WINDOW_X, values);
-                               xcb_flush(conn);
-                               break;
-                       case XCB_EXPOSE:
-                               /* Use original handler */
-                               xcb_event_handle(&evenths, inside_event);
-                               break;
-                       default:
-                               printf("Ignoring event of type %d\n", nr);
-                               break;
-               }
-               printf("---\n");
-               free(inside_event);
-       }
-
-       xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
-       xcb_destroy_window(conn, helpwin);
-       xcb_destroy_window(conn, grabwin);
-       xcb_flush(conn);
-
-       return 1;
-}
-
-int handle_map_notify_event(void *prophs, xcb_connection_t *c, xcb_map_notify_event_t *e)
-{
-       window_attributes_t wa = { TAG_VALUE };
-       wa.u.override_redirect = e->override_redirect;
-       printf("MapNotify for 0x%08x.\n", e->window);
-       manage_window(prophs, c, e->window, wa);
-       return 1;
-}
-
-/*
- * Our window decorations were unmapped. That means, the window will be killed now,
- * so we better clean up before.
- *
- */
-int handle_unmap_notify_event(void *data, xcb_connection_t *c, xcb_unmap_notify_event_t *e) {
-       Client *client = table_remove(byChild, e->event);
-       xcb_window_t root;
-       printf("UnmapNotify for 0x%08x (received from 0x%08x): ", e->window, e->event);
-       if(!client)
-       {
-               printf("not a managed window. Ignoring.\n");
-               return 0;
-       }
-
-       int rows, cols;
-       Client *con_client;
-       /* TODO: clear this up */
-       for (cols = 0; cols < c_ws->cols; cols++)
-               for (rows = 0; rows < c_ws->rows; rows++)
-                       CIRCLEQ_FOREACH(con_client, &(CUR_TABLE[cols][rows]->clients), clients)
-                               if (con_client == client) {
-                                       printf("removing from container\n");
-                                       if (client->container->currently_focused == client)
-                                               client->container->currently_focused = NULL;
-                                       CIRCLEQ_REMOVE(&(CUR_TABLE[cols][rows]->clients), con_client, clients);
-                                       break;
-                               }
-
-
-
-       root = xcb_setup_roots_iterator(xcb_get_setup(c)).data->root;
-       printf("child of 0x%08x.\n", client->frame);
-       xcb_reparent_window(c, client->child, root, 0, 0);
-       xcb_destroy_window(c, client->frame);
-       xcb_flush(c);
-       table_remove(byParent, client->frame);
-       free(client);
-
-       render_layout(c);
-
-       return 1;
-}
-
-/*
- * Called when a window changes its title
- *
- */
-static int handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state,
-                               xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
-       printf("window's name changed.\n");
-       Client *client = table_get(byChild, window);
-       if (client == NULL)
-               return 1;
-
-       client->name_len = xcb_get_property_value_length(prop);
-       client->name = malloc(client->name_len);
-       strncpy(client->name, xcb_get_property_value(prop), client->name_len);
-       printf("rename to \"%.*s\".\n", client->name_len, client->name);
-
-       decorate_window(conn, client);
-       xcb_flush(conn);
-
-       return 1;
-}
-
-
-static int handleExposeEvent(void *data, xcb_connection_t *c, xcb_expose_event_t *e) {
-printf("exposeevent\n");
-       Client *client = table_get(byParent, e->window);
-       if(!client || e->count != 0)
-               return 1;
-       decorate_window(c, client);
-       return 1;
-}
 void manage_existing_windows(xcb_connection_t *c, xcb_property_handlers_t *prophs, xcb_window_t root) {
        xcb_query_tree_cookie_t wintree;
        xcb_query_tree_reply_t *rep;
@@ -1429,14 +330,14 @@ int main(int argc, char *argv[], char *env[]) {
 
        xcb_event_handlers_init(c, &evenths);
        for(i = 2; i < 128; ++i)
-               xcb_event_set_handler(&evenths, i, handleEvent, 0);
+               xcb_event_set_handler(&evenths, i, handle_event, 0);
 
        for(i = 0; i < 256; ++i)
-               xcb_event_set_error_handler(&evenths, i, (xcb_generic_error_handler_t) handleEvent, 0);
+               xcb_event_set_error_handler(&evenths, i, (xcb_generic_error_handler_t)handle_event, 0);
 
        /* Expose = an Application should redraw itself. That is, we have to redraw our
         * contents (= top/bottom bar, titlebars for each window) */
-       xcb_event_set_expose_handler(&evenths, handleExposeEvent, 0);
+       xcb_event_set_expose_handler(&evenths, handle_expose_event, 0);
 
        /* Key presses/releases are pretty obvious, I think */
        xcb_event_set_key_press_handler(&evenths, handle_key_press, 0);