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