6 #include <xcb/xcb_event.h>
15 #define p_clear(p, count) ((void)memset((p), 0, sizeof(*(p)) * (count)))
17 bool locate_window(xcb_window_t win, window_location_t *loc)
20 desktop_t *d = desk_head;
26 n = first_extrema(d->root);
28 if (n->client->window == win) {
41 void draw_triple_border(node_t *n, uint32_t main_border_color_pxl)
49 xcb_window_t win = n->client->window;
50 xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, win), NULL);
55 uint16_t width = geom->width;
56 uint16_t height = geom->height;
57 uint8_t depth = geom->depth;
61 uint16_t full_width = width + 2 * border_width;
62 uint16_t full_height = height + 2 * border_width;
64 xcb_rectangle_t inner_rectangles[] =
66 { width, 0, 2 * border_width, height + 2 * border_width },
67 { 0, height, width + 2 * border_width, 2 * border_width }
70 xcb_rectangle_t main_rectangles[] =
72 { width + inner_border_width, 0, 2 * (main_border_width + outer_border_width), height + 2 * border_width },
73 { 0, height + inner_border_width, width + 2 * border_width, 2 * (main_border_width + outer_border_width) }
76 xcb_rectangle_t outer_rectangles[] =
78 { width + inner_border_width + main_border_width, 0, 2 * outer_border_width, height + 2 * border_width },
79 { 0, height + inner_border_width + main_border_width, width + 2 * border_width, 2 * outer_border_width }
82 xcb_rectangle_t *presel_rectangles;
84 xcb_pixmap_t pix = xcb_generate_id(dpy);
85 xcb_create_pixmap(dpy, depth, pix, win, full_width, full_height);
87 xcb_gcontext_t gc = xcb_generate_id(dpy);
88 xcb_create_gc(dpy, gc, pix, 0, NULL);
91 if (inner_border_width > 0) {
92 xcb_change_gc(dpy, gc, XCB_GC_FOREGROUND, &inner_border_color_pxl);
93 xcb_poly_fill_rectangle(dpy, pix, gc, LENGTH(inner_rectangles), inner_rectangles);
97 if (main_border_width > 0) {
98 xcb_change_gc(dpy, gc, XCB_GC_FOREGROUND, &main_border_color_pxl);
99 xcb_poly_fill_rectangle(dpy, pix, gc, LENGTH(main_rectangles), main_rectangles);
103 if (outer_border_width > 0) {
104 xcb_change_gc(dpy, gc, XCB_GC_FOREGROUND, &outer_border_color_pxl);
105 xcb_poly_fill_rectangle(dpy, pix, gc, LENGTH(outer_rectangles), outer_rectangles);
108 if (split_mode == MODE_MANUAL && main_border_color_pxl == active_border_color_pxl) {
109 uint16_t fence = (int16_t) (n->split_ratio * ((split_dir == DIR_UP || split_dir == DIR_DOWN) ? height : width));
110 presel_rectangles = malloc(2 * sizeof(xcb_rectangle_t));
113 presel_rectangles[0] = (xcb_rectangle_t) {width, 0, 2 * border_width, fence};
114 presel_rectangles[1] = (xcb_rectangle_t) {0, height + border_width, full_width, border_width};
117 presel_rectangles[0] = (xcb_rectangle_t) {width, fence + 1, 2 * border_width, height + border_width - (fence + 1)};
118 presel_rectangles[1] = (xcb_rectangle_t) {0, height, full_width, border_width};
121 presel_rectangles[0] = (xcb_rectangle_t) {0, height, fence, 2 * border_width};
122 presel_rectangles[1] = (xcb_rectangle_t) {width + border_width, 0, border_width, full_height};
125 presel_rectangles[0] = (xcb_rectangle_t) {fence + 1, height, width + border_width - (fence + 1), 2 * border_width};
126 presel_rectangles[1] = (xcb_rectangle_t) {width, 0, border_width, full_height};
129 xcb_change_gc(dpy, gc, XCB_GC_FOREGROUND, &presel_border_color_pxl);
130 xcb_poly_fill_rectangle(dpy, pix, gc, 2, presel_rectangles);
131 free(presel_rectangles);
134 /* apply border pixmap */
135 xcb_change_window_attributes(dpy, win, XCB_CW_BORDER_PIXMAP, &pix);
137 xcb_free_gc(dpy, gc);
138 xcb_free_pixmap(dpy, pix);
141 void close_window(desktop_t *d, node_t *n)
143 if (n == NULL || n->client->locked)
146 PUTS("close window\n");
148 xcb_atom_t WM_DELETE_WINDOW;
149 xcb_window_t win = n->client->window;
150 xcb_client_message_event_t e;
152 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(dpy, xcb_intern_atom(dpy, 0, strlen("WM_DELETE_WINDOW"), "WM_DELETE_WINDOW"), NULL);
154 WM_DELETE_WINDOW = reply->atom;
157 PUTS("could not acquire WM_DELETE_WINDOW atom\n");
161 e.response_type = XCB_CLIENT_MESSAGE;
165 e.type = ewmh->WM_PROTOCOLS;
166 e.data.data32[0] = WM_DELETE_WINDOW;
167 e.data.data32[1] = XCB_CURRENT_TIME;
169 xcb_send_event(dpy, false, win, XCB_EVENT_MASK_NO_EVENT, (char *) &e);
173 void toggle_fullscreen(client_t *c)
176 c->fullscreen = false;
177 xcb_atom_t values[] = {XCB_NONE};
178 xcb_ewmh_set_wm_state(ewmh, c->window, LENGTH(values), values);
179 xcb_rectangle_t rect = c->rectangle;
180 window_border_width(c->window, border_width);
181 window_move_resize(c->window, rect.x, rect.y, rect.width, rect.height);
183 c->fullscreen = true;
184 xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, c->window), NULL);
186 c->rectangle = (xcb_rectangle_t) {geom->x, geom->y, geom->width, geom->height};
189 xcb_atom_t values[] = {ewmh->_NET_WM_STATE_FULLSCREEN};
190 xcb_ewmh_set_wm_state(ewmh, c->window, LENGTH(values), values);
191 window_raise(c->window);
192 window_border_width(c->window, 0);
193 window_move_resize(c->window, 0, 0, screen_width, screen_height);
197 void list_windows(char *rsp)
201 desktop_t *d = desk_head;
204 node_t *n = first_extrema(d->root);
206 sprintf(line, "0x%X\n", n->client->window);
214 void window_border_width(xcb_window_t win, uint32_t bw)
216 uint32_t values[] = {bw};
217 xcb_configure_window(dpy, win, XCB_CONFIG_WINDOW_BORDER_WIDTH, values);
220 void window_move_resize(xcb_window_t win, int16_t x, int16_t y, uint16_t w, uint16_t h)
222 uint32_t values[] = {x, y, w, h};
223 xcb_configure_window(dpy, win, XCB_CONFIG_WINDOW_X_Y_WIDTH_HEIGHT, values);
226 void window_raise(xcb_window_t win)
228 uint32_t values[] = {XCB_STACK_MODE_ABOVE};
229 xcb_configure_window(dpy, win, XCB_CONFIG_WINDOW_STACK_MODE, values);