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