]> git.lizzy.rs Git - bspwm.git/blob - utils.c
cba173dccbc933b6467a8692abff6e1b8b8ebe9d
[bspwm.git] / utils.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <xcb/xcb.h>
6 #include <xcb/xcb_event.h>
7 #include "helpers.h"
8 #include "types.h"
9 #include "tree.h"
10 #include "bspwm.h"
11 #include "settings.h"
12 #include "utils.h"
13
14 void die(const char *errstr, ...) {
15     va_list ap;
16     va_start(ap, errstr);
17     vfprintf(stderr, errstr, ap);
18     va_end(ap);
19     exit(EXIT_FAILURE);
20 }
21
22 window_location_t locate_window(xcb_window_t w)
23 {
24     node_t *n;
25     desktop_t *d = desk_head;
26     window_location_t l = {NULL, NULL};
27
28     if (d == NULL)
29         return l;
30
31     while (d != NULL) {
32         n = first_extrema(d->root);
33         while (n != NULL) {
34             if (n->client->window == w) {
35                 l.desktop = d;
36                 l.node = n;
37                 return l;
38             }
39             n = next_leaf(n);
40         }
41         d = d->next;
42     }
43
44     return l;
45 }
46
47 bool is_managed(xcb_window_t w)
48 {
49     window_location_t l = locate_window(w);
50     return (l.desktop != NULL && l.node != NULL);
51 }
52
53 uint32_t color_pixel(char *hex)
54 {
55     char strgroups[3][3]  = {{hex[1], hex[2], '\0'}, {hex[3], hex[4], '\0'}, {hex[5], hex[6], '\0'}};
56     uint16_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)), (strtol(strgroups[1], NULL, 16)), (strtol(strgroups[2], NULL, 16))};
57     return (rgb16[0] << 16) + (rgb16[1] << 8) + rgb16[2];
58 }
59
60 uint32_t get_color(char *col)
61 {
62     xcb_colormap_t map = screen->default_colormap;
63     xcb_alloc_color_reply_t *rpl;
64     xcb_alloc_named_color_reply_t *rpln;
65     uint32_t rgb, pxl;
66     uint16_t r, g, b;
67
68     if (col[0] == '#') {
69         rgb = color_pixel(col);
70         r = rgb >> 16;
71         g = rgb >> 8 & 0xFF;
72         b = rgb & 0xFF;
73         rpl = xcb_alloc_color_reply(dpy, xcb_alloc_color(dpy, map, r * 257, g * 257, b * 257), NULL);
74         if (rpl != NULL) {
75             pxl = rpl->pixel;
76             free(rpl);
77         }
78     } else {
79         rpln = xcb_alloc_named_color_reply(dpy, xcb_alloc_named_color(dpy, map, strlen(col), col), NULL);
80         if (rpln != NULL) {
81             pxl = rpln->pixel;
82             free(rpln);
83         }
84     }
85
86     /* if (!rpl) */
87     /*     die("error: cannot allocate color '%s'\n", col); */
88
89     return pxl;
90 }
91
92 void draw_triple_border(node_t *n, uint32_t main_border_color_pxl)
93 {
94     if (border_width < 1)
95         return;
96
97     xcb_window_t win = n->client->window;
98     xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, win), NULL);
99
100     uint16_t width = geom->width;
101     uint16_t height = geom->height;
102
103     uint8_t depth = geom->depth;
104
105     uint16_t full_width = width + 2 * border_width;
106     uint16_t full_height = height + 2 * border_width;
107
108     uint16_t split_pos;
109
110     xcb_rectangle_t inner_rectangles[] =
111     {
112         { width, 0, 2 * border_width, height + 2 * border_width },
113         { 0, height, width + 2 * border_width, 2 * border_width }
114     };
115
116     xcb_rectangle_t main_rectangles[] =
117     {
118         { width + inner_border_width, 0, 2 * (main_border_width + outer_border_width), height + 2 * border_width },
119         { 0, height + inner_border_width, width + 2 * border_width, 2 * (main_border_width + outer_border_width) }
120     };
121
122     xcb_rectangle_t outer_rectangles[] =
123     {
124         { width + inner_border_width + main_border_width, 0, 2 * outer_border_width, height + 2 * border_width },
125         { 0, height + inner_border_width + main_border_width, width + 2 * border_width, 2 * outer_border_width }
126     };
127
128     xcb_rectangle_t *presel_rectangles;
129
130     xcb_pixmap_t pix = xcb_generate_id(dpy);
131     xcb_create_pixmap(dpy, depth, pix, win, full_width, full_height);
132
133     xcb_gcontext_t gc = xcb_generate_id(dpy);
134     xcb_create_gc(dpy, gc, pix, 0, NULL);
135
136     /* inner border */
137     if (inner_border_width > 0) {
138         xcb_change_gc(dpy, gc, XCB_GC_FOREGROUND, &inner_border_color_pxl);
139         xcb_poly_fill_rectangle(dpy, pix, gc, LENGTH(inner_rectangles), inner_rectangles);
140     }
141
142     /* main border */
143     if (main_border_width > 0) {
144         xcb_change_gc(dpy, gc, XCB_GC_FOREGROUND, &main_border_color_pxl);
145         xcb_poly_fill_rectangle(dpy, pix, gc, LENGTH(main_rectangles), main_rectangles);
146     }
147
148     /* outer border */
149     if (outer_border_width > 0) {
150         xcb_change_gc(dpy, gc, XCB_GC_FOREGROUND, &outer_border_color_pxl);
151         xcb_poly_fill_rectangle(dpy, pix, gc, LENGTH(outer_rectangles), outer_rectangles);
152     }
153
154     if (split_mode == MODE_MANUAL) {
155         split_pos = (int16_t) n->split_ratio * ((split_dir == DIR_UP || split_dir == DIR_DOWN) ? height : width);
156         printf("%i\n", split_pos);
157         presel_rectangles = malloc(2 * sizeof(xcb_rectangle_t));
158         switch (split_dir) {
159             case DIR_UP:
160                 presel_rectangles[0] = (xcb_rectangle_t) {width, 0, 2 * border_width, split_pos};
161                 presel_rectangles[1] = (xcb_rectangle_t) {0, height + border_width, full_width, border_width};
162                 break;
163             case DIR_DOWN:
164                 presel_rectangles[0] = (xcb_rectangle_t) {width, split_pos + 1, 2 * border_width, height + border_width - (split_pos + 1)};
165                 presel_rectangles[1] = (xcb_rectangle_t) {0, height + border_width, full_width, border_width};
166                 break;
167             case DIR_LEFT:
168                 presel_rectangles[0] = (xcb_rectangle_t) {0, height, split_pos, 2 * border_width};
169                 presel_rectangles[1] = (xcb_rectangle_t) {width + border_width, 0, border_width, full_height};
170                 break;
171             case DIR_RIGHT:
172                 presel_rectangles[0] = (xcb_rectangle_t) {split_pos + 1, height, width + border_width - (split_pos + 1), 2 * border_width};
173                 presel_rectangles[1] = (xcb_rectangle_t) {width, 0, border_width, full_height};
174                 break;
175         }
176         xcb_change_gc(dpy, gc, XCB_GC_FOREGROUND, &presel_border_color_pxl);
177         xcb_poly_fill_rectangle(dpy, pix, gc, LENGTH(presel_rectangles), presel_rectangles);
178         free(presel_rectangles);
179     }
180
181
182     /* apply border pixmap */
183     xcb_change_window_attributes(dpy, win, XCB_CW_BORDER_PIXMAP, &pix);
184
185     free(geom);
186     xcb_free_gc(dpy, gc);
187     xcb_free_pixmap(dpy, pix);
188 }
189
190 void toggle_fullscreen(node_t *n)
191 {
192     n = n;
193 }