13 /* All functions handling layout/drawing of window decorations */
16 * (Re-)draws window decorations for a given Client
19 void decorate_window(xcb_connection_t *conn, Client *client) {
22 i3Font *font = load_font(conn, pattern);
23 uint32_t background_color,
27 if (client->container->currently_focused == client) {
28 background_color = get_colorpixel(conn, client->frame, "#285577");
29 text_color = get_colorpixel(conn, client->frame, "#ffffff");
30 border_color = get_colorpixel(conn, client->frame, "#4c7899");
32 background_color = get_colorpixel(conn, client->frame, "#222222");
33 text_color = get_colorpixel(conn, client->frame, "#888888");
34 border_color = get_colorpixel(conn, client->frame, "#333333");
37 /* Our plan is the following:
38 - Draw a rect around the whole client in background_color
39 - Draw two lines in a lighter color
40 - Draw the window’s title
42 Note that xcb_image_text apparently adds 1xp border around the font? Can anyone confirm this?
45 /* Draw a green rectangle around the window */
46 mask = XCB_GC_FOREGROUND;
47 values[0] = background_color;
48 xcb_change_gc(conn, client->titlegc, mask, values);
50 xcb_rectangle_t rect = {0, 0, client->width, client->height};
51 xcb_poly_fill_rectangle(conn, client->frame, client->titlegc, 1, &rect);
54 /* TODO: this needs to be more beautiful somewhen. maybe stdarg + change_gc(gc, ...) ? */
55 #define DRAW_LINE(colorpixel, x, y, to_x, to_y) { \
56 uint32_t draw_values[1]; \
57 draw_values[0] = colorpixel; \
58 xcb_change_gc(conn, client->titlegc, XCB_GC_FOREGROUND, draw_values); \
59 xcb_point_t points[] = {{x, y}, {to_x, to_y}}; \
60 xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, client->frame, client->titlegc, 2, points); \
63 DRAW_LINE(border_color, 2, 0, client->width, 0);
64 DRAW_LINE(border_color, 2, font->height + 3, 2 + client->width, font->height + 3);
67 mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
69 values[0] = text_color;
70 values[1] = background_color;
73 xcb_change_gc(conn, client->titlegc, mask, values);
77 asprintf(&label, "(%08x) %.*s", client->frame, client->name_len, client->name);
78 xcb_void_cookie_t text_cookie = xcb_image_text_8_checked(conn, strlen(label), client->frame,
79 client->titlegc, 3 /* X */, font->height /* Y = baseline of font */, label);
80 check_error(conn, text_cookie, "Could not draw client's title");
84 void render_container(xcb_connection_t *connection, Container *container) {
87 uint32_t mask = XCB_CONFIG_WINDOW_X |
89 XCB_CONFIG_WINDOW_WIDTH |
90 XCB_CONFIG_WINDOW_HEIGHT;
91 i3Font *font = load_font(connection, pattern);
93 if (container->mode == MODE_DEFAULT) {
95 CIRCLEQ_FOREACH(client, &(container->clients), clients)
97 printf("got %d clients in this default container.\n", num_clients);
99 int current_client = 0;
100 CIRCLEQ_FOREACH(client, &(container->clients), clients) {
101 /* TODO: rewrite this block so that the need to puke vanishes :) */
102 /* TODO: at the moment, every column/row is 200px. This
103 * needs to be changed to "percentage of the screen" by
104 * default and adjustable by the user if necessary.
106 values[0] = container->x + (container->col * container->width); /* x */
107 values[1] = container->y + (container->row * container->height +
108 (container->height / num_clients) * current_client); /* y */
110 if (client->x != values[0] || client->y != values[1]) {
111 printf("frame needs to be pushed to %dx%d\n",
112 values[0], values[1]);
113 client->x = values[0];
114 client->y = values[1];
115 xcb_configure_window(connection, client->frame,
116 XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
118 /* TODO: vertical default layout */
119 values[0] = container->width; /* width */
120 values[1] = container->height / num_clients; /* height */
122 if (client->width != values[0] || client->height != values[1]) {
123 client->width = values[0];
124 client->height = values[1];
125 xcb_configure_window(connection, client->frame,
126 XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
129 /* TODO: hmm, only do this for new wins */
130 /* The coordinates of the child are relative to its frame, we
131 * add a border of 2 pixel to each value */
133 values[1] = font->height + 2 + 2;
134 values[2] = client->width - (values[0] + 2);
135 values[3] = client->height - (values[1] + 2);
136 printf("child itself will be at %dx%d with size %dx%d\n",
137 values[0], values[1], values[2], values[3]);
139 xcb_configure_window(connection, client->child, mask, values);
141 decorate_window(connection, client);
145 /* TODO: Implement stacking */
149 void render_layout(xcb_connection_t *conn) {
152 for (screen = 0; screen < num_screens; screen++) {
153 printf("Rendering screen %d\n", screen);
154 /* TODO: get the workspace which is active on the screen */
155 int width = workspaces[screen].width;
156 int height = workspaces[screen].height;
158 printf("got %d rows and %d cols\n", c_ws->rows, c_ws->cols);
159 printf("each of them therefore is %d px width and %d px height\n",
160 width / c_ws->cols, height / c_ws->rows);
162 /* Go through the whole table and render what’s necessary */
163 for (cols = 0; cols < c_ws->cols; cols++)
164 for (rows = 0; rows < c_ws->rows; rows++) {
165 Container *con = CUR_TABLE[cols][rows];
166 printf("container has %d colspan, %d rowspan\n",
167 con->colspan, con->rowspan);
168 /* Update position of the container */
171 con->x = workspaces[screen].x;
172 con->y = workspaces[screen].y;
173 con->width = (width / c_ws->cols) * con->colspan;
174 con->height = (height / c_ws->rows) * con->rowspan;
177 render_container(conn, CUR_TABLE[cols][rows]);