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