aboutsummaryrefslogtreecommitdiffstats
path: root/swaybar/render.c
diff options
context:
space:
mode:
authorLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-01-23 20:55:01 +0100
committerLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-01-24 14:22:19 +0100
commita6349a2444571624c792ca222dff57c7f1711c71 (patch)
tree486e5df9eff701f75ce05d80a3e16c397ad596dc /swaybar/render.c
parentswaybar: Separate config (diff)
downloadsway-a6349a2444571624c792ca222dff57c7f1711c71.tar.gz
sway-a6349a2444571624c792ca222dff57c7f1711c71.tar.zst
sway-a6349a2444571624c792ca222dff57c7f1711c71.zip
swaybar: feactor render, statusline
Diffstat (limited to 'swaybar/render.c')
-rw-r--r--swaybar/render.c311
1 files changed, 311 insertions, 0 deletions
diff --git a/swaybar/render.c b/swaybar/render.c
new file mode 100644
index 00000000..1e1554c5
--- /dev/null
+++ b/swaybar/render.c
@@ -0,0 +1,311 @@
1#include <stdlib.h>
2#include <stdint.h>
3#include <string.h>
4
5#include "client/pango.h"
6#include "client/window.h"
7#include "config.h"
8#include "status_line.h"
9#include "render.h"
10
11static void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
12 cairo_set_source_rgba(cairo,
13 ((color & 0xFF000000) >> 24) / 256.0,
14 ((color & 0xFF0000) >> 16) / 256.0,
15 ((color & 0xFF00) >> 8) / 256.0,
16 (color & 0xFF) / 256.0);
17}
18
19/**
20 * Renders a sharp line of any width and height.
21 *
22 * The line is drawn from (x,y) to (x+width,y+height) where width/height is 0
23 * if the line has a width/height of one pixel, respectively.
24 */
25static void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y, double width, double height) {
26 cairo_set_source_u32(cairo, color);
27
28 if (width > 1 && height > 1) {
29 cairo_rectangle(cairo, x, y, width, height);
30 cairo_fill(cairo);
31 } else {
32 if (width == 1) {
33 x += 0.5;
34 height += y;
35 width = x;
36 }
37
38 if (height == 1) {
39 y += 0.5;
40 width += x;
41 height = y;
42 }
43
44 cairo_move_to(cairo, x, y);
45 cairo_set_line_width(cairo, 1.0);
46 cairo_line_to(cairo, width, height);
47 cairo_stroke(cairo);
48 }
49}
50
51static void render_block(struct window *window, struct swaybar_config *config, struct status_block *block, double *x, bool edge) {
52 int width, height, sep_width;
53 get_text_size(window, &width, &height, "%s", block->full_text);
54
55 int textwidth = width;
56 double block_width = width;
57
58 if (width < block->min_width) {
59 width = block->min_width;
60 }
61
62 *x -= width;
63
64 if (block->border != 0 && block->border_left > 0) {
65 *x -= (block->border_left + config->margin);
66 block_width += block->border_left + config->margin;
67 }
68
69 if (block->border != 0 && block->border_right > 0) {
70 *x -= (block->border_right + config->margin);
71 block_width += block->border_right + config->margin;
72 }
73
74 // Add separator
75 if (!edge) {
76 if (config->sep_symbol) {
77 get_text_size(window, &sep_width, &height, "%s", config->sep_symbol);
78 if (sep_width > block->separator_block_width) {
79 block->separator_block_width = sep_width + config->margin * 2;
80 }
81 }
82
83 *x -= block->separator_block_width;
84 } else {
85 *x -= config->margin;
86 }
87
88 double pos = *x;
89
90 // render background
91 if (block->background != 0x0) {
92 cairo_set_source_u32(window->cairo, block->background);
93 cairo_rectangle(window->cairo, pos - 0.5, 1, block_width, window->height - 2);
94 cairo_fill(window->cairo);
95 }
96
97 // render top border
98 if (block->border != 0 && block->border_top > 0) {
99 render_sharp_line(window->cairo, block->border,
100 pos - 0.5,
101 1,
102 block_width,
103 block->border_top);
104 }
105
106 // render bottom border
107 if (block->border != 0 && block->border_bottom > 0) {
108 render_sharp_line(window->cairo, block->border,
109 pos - 0.5,
110 window->height - 1 - block->border_bottom,
111 block_width,
112 block->border_bottom);
113 }
114
115 // render left border
116 if (block->border != 0 && block->border_left > 0) {
117 render_sharp_line(window->cairo, block->border,
118 pos - 0.5,
119 1,
120 block->border_left,
121 window->height - 2);
122
123 pos += block->border_left + config->margin;
124 }
125
126 // render text
127 double offset = 0;
128
129 if (strncmp(block->align, "left", 5) == 0) {
130 offset = pos;
131 } else if (strncmp(block->align, "right", 5) == 0) {
132 offset = pos + width - textwidth;
133 } else if (strncmp(block->align, "center", 6) == 0) {
134 offset = pos + (width - textwidth) / 2;
135 }
136
137 cairo_move_to(window->cairo, offset, config->margin);
138 cairo_set_source_u32(window->cairo, block->color);
139 pango_printf(window, "%s", block->full_text);
140
141 pos += width;
142
143 // render right border
144 if (block->border != 0 && block->border_right > 0) {
145 pos += config->margin;
146
147 render_sharp_line(window->cairo, block->border,
148 pos - 0.5,
149 1,
150 block->border_right,
151 window->height - 2);
152
153 pos += block->border_right;
154 }
155
156 // render separator
157 if (!edge && block->separator) {
158 cairo_set_source_u32(window->cairo, config->colors.separator);
159 if (config->sep_symbol) {
160 offset = pos + (block->separator_block_width - sep_width) / 2;
161 cairo_move_to(window->cairo, offset, config->margin);
162 pango_printf(window, "%s", config->sep_symbol);
163 } else {
164 cairo_set_line_width(window->cairo, 1);
165 cairo_move_to(window->cairo, pos + block->separator_block_width/2,
166 config->margin);
167 cairo_line_to(window->cairo, pos + block->separator_block_width/2,
168 window->height - config->margin);
169 cairo_stroke(window->cairo);
170 }
171 }
172
173}
174
175static char *handle_workspace_number(bool strip_num, const char *ws_name) {
176 bool strip = false;
177 int i;
178
179 if (strip_num) {
180 int len = strlen(ws_name);
181 for (i = 0; i < len; ++i) {
182 if (!('0' <= ws_name[i] && ws_name[i] <= '9')) {
183 if (':' == ws_name[i] && i < len-1 && i > 0) {
184 strip = true;
185 ++i;
186 }
187 break;
188 }
189 }
190 }
191
192 if (strip) {
193 return strdup(ws_name + i);
194 }
195
196 return strdup(ws_name);
197}
198
199static void render_workspace_button(struct window *window, struct swaybar_config *config, struct workspace *ws, double *x) {
200 // strip workspace numbers if required
201 char *name = handle_workspace_number(config->strip_workspace_numbers, ws->name);
202
203 int width, height;
204 get_text_size(window, &width, &height, "%s", name);
205 struct box_colors box_colors;
206 if (ws->urgent) {
207 box_colors = config->colors.urgent_workspace;
208 } else if (ws->focused) {
209 box_colors = config->colors.focused_workspace;
210 } else if (ws->visible) {
211 box_colors = config->colors.active_workspace;
212 } else {
213 box_colors = config->colors.inactive_workspace;
214 }
215
216 // background
217 cairo_set_source_u32(window->cairo, box_colors.background);
218 cairo_rectangle(window->cairo, *x, 1.5, width + config->ws_horizontal_padding * 2 - 1,
219 height + config->ws_vertical_padding * 2);
220 cairo_fill(window->cairo);
221
222 // border
223 cairo_set_source_u32(window->cairo, box_colors.border);
224 cairo_rectangle(window->cairo, *x, 1.5, width + config->ws_horizontal_padding * 2 - 1,
225 height + config->ws_vertical_padding * 2);
226 cairo_stroke(window->cairo);
227
228 // text
229 cairo_set_source_u32(window->cairo, box_colors.text);
230 cairo_move_to(window->cairo, (int)*x + config->ws_horizontal_padding, config->margin);
231 pango_printf(window, "%s", name);
232
233 *x += width + config->ws_horizontal_padding * 2 + config->ws_spacing;
234
235 free(name);
236}
237
238static void render_binding_mode_indicator(struct window *window, struct swaybar_config *config, double pos) {
239 int width, height;
240 get_text_size(window, &width, &height, "%s", config->mode);
241
242 // background
243 cairo_set_source_u32(window->cairo, config->colors.binding_mode.background);
244 cairo_rectangle(window->cairo, pos, 1.5, width + config->ws_horizontal_padding * 2 - 1,
245 height + config->ws_vertical_padding * 2);
246 cairo_fill(window->cairo);
247
248 // border
249 cairo_set_source_u32(window->cairo, config->colors.binding_mode.border);
250 cairo_rectangle(window->cairo, pos, 1.5, width + config->ws_horizontal_padding * 2 - 1,
251 height + config->ws_vertical_padding * 2);
252 cairo_stroke(window->cairo);
253
254 // text
255 cairo_set_source_u32(window->cairo, config->colors.binding_mode.text);
256 cairo_move_to(window->cairo, (int)pos + config->ws_horizontal_padding, config->margin);
257 pango_printf(window, "%s", config->mode);
258}
259
260void render(struct output *output, struct swaybar_config *config, struct status_line *line) {
261 int i;
262
263 struct window *window = output->window;
264 cairo_t *cairo = window->cairo;
265
266 // Clear
267 cairo_save(cairo);
268 cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
269 cairo_paint(cairo);
270 cairo_restore(cairo);
271
272 // Background
273 cairo_set_source_u32(cairo, config->colors.background);
274 cairo_paint(cairo);
275
276 // Command output
277 cairo_set_source_u32(cairo, config->colors.statusline);
278 int width, height;
279
280 if (line->protocol == TEXT) {
281 get_text_size(window, &width, &height, "%s", line->text_line);
282 cairo_move_to(cairo, window->width - config->margin - width, config->margin);
283 pango_printf(window, "%s", line);
284 } else if (line->protocol == I3BAR && line->block_line) {
285 double pos = window->width - 0.5;
286 bool edge = true;
287 for (i = line->block_line->length - 1; i >= 0; --i) {
288 struct status_block *block = line->block_line->items[i];
289 if (block->full_text && block->full_text[0]) {
290 render_block(window, config, block, &pos, edge);
291 edge = false;
292 }
293 }
294 }
295
296 cairo_set_line_width(cairo, 1.0);
297 double x = 0.5;
298
299 // Workspaces
300 if (config->workspace_buttons) {
301 for (i = 0; i < output->workspaces->length; ++i) {
302 struct workspace *ws = output->workspaces->items[i];
303 render_workspace_button(window, config, ws, &x);
304 }
305 }
306
307 // binding mode indicator
308 if (config->mode && config->binding_mode_indicator) {
309 render_binding_mode_indicator(window, config, x);
310 }
311}