summaryrefslogtreecommitdiffstats
path: root/swaybar/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'swaybar/render.c')
-rw-r--r--swaybar/render.c190
1 files changed, 105 insertions, 85 deletions
diff --git a/swaybar/render.c b/swaybar/render.c
index 4ebf922e..55f680ed 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -1,5 +1,6 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 2#include <assert.h>
3#include <linux/input-event-codes.h>
3#include <limits.h> 4#include <limits.h>
4#include <stdlib.h> 5#include <stdlib.h>
5#include <stdint.h> 6#include <stdint.h>
@@ -14,6 +15,9 @@
14#include "swaybar/ipc.h" 15#include "swaybar/ipc.h"
15#include "swaybar/render.h" 16#include "swaybar/render.h"
16#include "swaybar/status_line.h" 17#include "swaybar/status_line.h"
18#if HAVE_TRAY
19#include "swaybar/tray/tray.h"
20#endif
17#include "wlr-layer-shell-unstable-v1-client-protocol.h" 21#include "wlr-layer-shell-unstable-v1-client-protocol.h"
18 22
19static const int WS_HORIZONTAL_PADDING = 5; 23static const int WS_HORIZONTAL_PADDING = 5;
@@ -32,7 +36,8 @@ static uint32_t render_status_line_error(cairo_t *cairo,
32 cairo_set_source_u32(cairo, 0xFF0000FF); 36 cairo_set_source_u32(cairo, 0xFF0000FF);
33 37
34 int margin = 3 * output->scale; 38 int margin = 3 * output->scale;
35 int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; 39 double ws_vertical_padding =
40 output->bar->config->status_padding * output->scale;
36 41
37 char *font = output->bar->config->font; 42 char *font = output->bar->config->font;
38 int text_width, text_height; 43 int text_width, text_height;
@@ -41,7 +46,8 @@ static uint32_t render_status_line_error(cairo_t *cairo,
41 46
42 uint32_t ideal_height = text_height + ws_vertical_padding * 2; 47 uint32_t ideal_height = text_height + ws_vertical_padding * 2;
43 uint32_t ideal_surface_height = ideal_height / output->scale; 48 uint32_t ideal_surface_height = ideal_height / output->scale;
44 if (output->height < ideal_surface_height) { 49 if (!output->bar->config->height &&
50 output->height < ideal_surface_height) {
45 return ideal_surface_height; 51 return ideal_surface_height;
46 } 52 }
47 *x -= text_width + margin; 53 *x -= text_width + margin;
@@ -68,12 +74,13 @@ static uint32_t render_status_line_text(cairo_t *cairo,
68 get_text_size(cairo, config->font, &text_width, &text_height, NULL, 74 get_text_size(cairo, config->font, &text_width, &text_height, NULL,
69 output->scale, config->pango_markup, "%s", text); 75 output->scale, config->pango_markup, "%s", text);
70 76
71 int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; 77 double ws_vertical_padding = config->status_padding * output->scale;
72 int margin = 3 * output->scale; 78 int margin = 3 * output->scale;
73 79
74 uint32_t ideal_height = text_height + ws_vertical_padding * 2; 80 uint32_t ideal_height = text_height + ws_vertical_padding * 2;
75 uint32_t ideal_surface_height = ideal_height / output->scale; 81 uint32_t ideal_surface_height = ideal_height / output->scale;
76 if (output->height < ideal_surface_height) { 82 if (!output->bar->config->height &&
83 output->height < ideal_surface_height) {
77 return ideal_surface_height; 84 return ideal_surface_height;
78 } 85 }
79 86
@@ -87,13 +94,24 @@ static uint32_t render_status_line_text(cairo_t *cairo,
87 return output->height; 94 return output->height;
88} 95}
89 96
90static void render_sharp_line(cairo_t *cairo, uint32_t color, 97static void render_sharp_rectangle(cairo_t *cairo, uint32_t color,
91 double x, double y, double width, double height) { 98 double x, double y, double width, double height) {
99 cairo_save(cairo);
92 cairo_set_source_u32(cairo, color); 100 cairo_set_source_u32(cairo, color);
101 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE);
102 cairo_rectangle(cairo, x, y, width, height);
103 cairo_fill(cairo);
104 cairo_restore(cairo);
105}
106
107static void render_sharp_line(cairo_t *cairo, uint32_t color,
108 double x, double y, double width, double height) {
93 if (width > 1 && height > 1) { 109 if (width > 1 && height > 1) {
94 cairo_rectangle(cairo, x, y, width, height); 110 render_sharp_rectangle(cairo, color, x, y, width, height);
95 cairo_fill(cairo);
96 } else { 111 } else {
112 cairo_save(cairo);
113 cairo_set_source_u32(cairo, color);
114 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE);
97 if (width == 1) { 115 if (width == 1) {
98 x += 0.5; 116 x += 0.5;
99 height += y; 117 height += y;
@@ -108,14 +126,17 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color,
108 cairo_set_line_width(cairo, 1.0); 126 cairo_set_line_width(cairo, 1.0);
109 cairo_line_to(cairo, width, height); 127 cairo_line_to(cairo, width, height);
110 cairo_stroke(cairo); 128 cairo_stroke(cairo);
129 cairo_restore(cairo);
111 } 130 }
112} 131}
113 132
114static enum hotspot_event_handling block_hotspot_callback(struct swaybar_output *output, 133static enum hotspot_event_handling block_hotspot_callback(
115 int x, int y, enum x11_button button, void *data) { 134 struct swaybar_output *output, struct swaybar_hotspot *hotspot,
135 int x, int y, uint32_t button, void *data) {
116 struct i3bar_block *block = data; 136 struct i3bar_block *block = data;
117 struct status_line *status = output->bar->status; 137 struct status_line *status = output->bar->status;
118 return i3bar_block_send_click(status, block, x, y, button); 138 return i3bar_block_send_click(status, block, x, y, x - hotspot->x,
139 y - hotspot->y, hotspot->width, hotspot->height, button);
119} 140}
120 141
121static void i3bar_block_unref_callback(void *data) { 142static void i3bar_block_unref_callback(void *data) {
@@ -136,7 +157,7 @@ static uint32_t render_status_block(cairo_t *cairo,
136 output->scale, block->markup, "%s", block->full_text); 157 output->scale, block->markup, "%s", block->full_text);
137 158
138 int margin = 3 * output->scale; 159 int margin = 3 * output->scale;
139 int ws_vertical_padding = WS_VERTICAL_PADDING * 2; 160 double ws_vertical_padding = config->status_padding * output->scale;
140 161
141 int width = text_width; 162 int width = text_width;
142 if (width < block->min_width) { 163 if (width < block->min_width) {
@@ -146,37 +167,40 @@ static uint32_t render_status_block(cairo_t *cairo,
146 double block_width = width; 167 double block_width = width;
147 uint32_t ideal_height = text_height + ws_vertical_padding * 2; 168 uint32_t ideal_height = text_height + ws_vertical_padding * 2;
148 uint32_t ideal_surface_height = ideal_height / output->scale; 169 uint32_t ideal_surface_height = ideal_height / output->scale;
149 if (output->height < ideal_surface_height) { 170 if (!output->bar->config->height &&
171 output->height < ideal_surface_height) {
150 return ideal_surface_height; 172 return ideal_surface_height;
151 } 173 }
152 174
153 *x -= width; 175 *x -= width;
154 if (block->border && block->border_left > 0) { 176 if ((block->border || block->urgent) && block->border_left > 0) {
155 *x -= (block->border_left + margin); 177 *x -= (block->border_left * output->scale + margin);
156 block_width += block->border_left + margin; 178 block_width += block->border_left * output->scale + margin;
157 } 179 }
158 if (block->border && block->border_right > 0) { 180 if ((block->border || block->urgent) && block->border_right > 0) {
159 *x -= (block->border_right + margin); 181 *x -= (block->border_right * output->scale + margin);
160 block_width += block->border_right + margin; 182 block_width += block->border_right * output->scale + margin;
161 } 183 }
162 184
163 int sep_width, sep_height; 185 int sep_width, sep_height;
186 int sep_block_width = block->separator_block_width;
164 if (!edge) { 187 if (!edge) {
165 if (config->sep_symbol) { 188 if (config->sep_symbol) {
166 get_text_size(cairo, config->font, &sep_width, &sep_height, NULL, 189 get_text_size(cairo, config->font, &sep_width, &sep_height, NULL,
167 output->scale, false, "%s", config->sep_symbol); 190 output->scale, false, "%s", config->sep_symbol);
168 uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; 191 uint32_t _ideal_height = sep_height + ws_vertical_padding * 2;
169 uint32_t _ideal_surface_height = _ideal_height / output->scale; 192 uint32_t _ideal_surface_height = _ideal_height / output->scale;
170 if (output->height < _ideal_surface_height) { 193 if (!output->bar->config->height &&
194 output->height < _ideal_surface_height) {
171 return _ideal_surface_height; 195 return _ideal_surface_height;
172 } 196 }
173 if (sep_width > block->separator_block_width) { 197 if (sep_width > sep_block_width) {
174 block->separator_block_width = sep_width + margin * 2; 198 sep_block_width = sep_width + margin * 2;
175 } 199 }
176 } 200 }
177 *x -= block->separator_block_width; 201 *x -= sep_block_width;
178 } else { 202 } else if (config->status_edge_padding) {
179 *x -= margin; 203 *x -= config->status_edge_padding * output->scale;
180 } 204 }
181 205
182 uint32_t height = output->height * output->scale; 206 uint32_t height = output->height * output->scale;
@@ -193,53 +217,55 @@ static uint32_t render_status_block(cairo_t *cairo,
193 wl_list_insert(&output->hotspots, &hotspot->link); 217 wl_list_insert(&output->hotspots, &hotspot->link);
194 } 218 }
195 219
196 double pos = *x; 220 double x_pos = *x;
197 if (block->background) { 221 double y_pos = ws_vertical_padding;
198 cairo_set_source_u32(cairo, block->background); 222 double render_height = height - ws_vertical_padding * 2;
199 cairo_rectangle(cairo, pos - 0.5 * output->scale, 223
200 output->scale, width, height); 224 uint32_t bg_color = block->urgent
201 cairo_fill(cairo); 225 ? config->colors.urgent_workspace.background : block->background;
226 if (bg_color) {
227 render_sharp_rectangle(cairo, bg_color, x_pos, y_pos,
228 block_width, render_height);
202 } 229 }
203 230
204 if (block->border && block->border_top > 0) { 231 uint32_t border_color = block->urgent
205 render_sharp_line(cairo, block->border, 232 ? config->colors.urgent_workspace.border : block->border;
206 pos - 0.5 * output->scale, output->scale, 233 if (border_color && block->border_top > 0) {
207 block_width, block->border_top); 234 render_sharp_line(cairo, border_color, x_pos, y_pos,
235 block_width, block->border_top * output->scale);
208 } 236 }
209 if (block->border && block->border_bottom > 0) { 237 if (border_color && block->border_bottom > 0) {
210 render_sharp_line(cairo, block->border, 238 render_sharp_line(cairo, border_color, x_pos,
211 pos - 0.5 * output->scale, 239 y_pos + render_height - block->border_bottom * output->scale,
212 height - output->scale - block->border_bottom, 240 block_width, block->border_bottom * output->scale);
213 block_width, block->border_bottom);
214 } 241 }
215 if (block->border != 0 && block->border_left > 0) { 242 if (border_color && block->border_left > 0) {
216 render_sharp_line(cairo, block->border, 243 render_sharp_line(cairo, border_color, x_pos, y_pos,
217 pos - 0.5 * output->scale, output->scale, 244 block->border_left * output->scale, render_height);
218 block->border_left, height); 245 x_pos += block->border_left * output->scale + margin;
219 pos += block->border_left + margin;
220 } 246 }
221 247
222 double offset = 0; 248 double offset = 0;
223 if (strncmp(block->align, "left", 5) == 0) { 249 if (strncmp(block->align, "left", 5) == 0) {
224 offset = pos; 250 offset = x_pos;
225 } else if (strncmp(block->align, "right", 5) == 0) { 251 } else if (strncmp(block->align, "right", 5) == 0) {
226 offset = pos + width - text_width; 252 offset = x_pos + width - text_width;
227 } else if (strncmp(block->align, "center", 6) == 0) { 253 } else if (strncmp(block->align, "center", 6) == 0) {
228 offset = pos + (width - text_width) / 2; 254 offset = x_pos + (width - text_width) / 2;
229 } 255 }
230 cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); 256 cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0);
231 uint32_t color = block->color ? *block->color : config->colors.statusline; 257 uint32_t color = block->color ? *block->color : config->colors.statusline;
258 color = block->urgent ? config->colors.urgent_workspace.text : color;
232 cairo_set_source_u32(cairo, color); 259 cairo_set_source_u32(cairo, color);
233 pango_printf(cairo, config->font, output->scale, 260 pango_printf(cairo, config->font, output->scale,
234 block->markup, "%s", block->full_text); 261 block->markup, "%s", block->full_text);
235 pos += width; 262 x_pos += width;
236 263
237 if (block->border && block->border_right > 0) { 264 if (block->border && block->border_right > 0) {
238 pos += margin; 265 x_pos += margin;
239 render_sharp_line(cairo, block->border, 266 render_sharp_line(cairo, border_color, x_pos, y_pos,
240 pos - 0.5 * output->scale, output->scale, 267 block->border_right * output->scale, render_height);
241 block->border_right, height); 268 x_pos += block->border_right * output->scale;
242 pos += block->border_right;
243 } 269 }
244 270
245 if (!edge && block->separator) { 271 if (!edge && block->separator) {
@@ -249,16 +275,14 @@ static uint32_t render_status_block(cairo_t *cairo,
249 cairo_set_source_u32(cairo, config->colors.separator); 275 cairo_set_source_u32(cairo, config->colors.separator);
250 } 276 }
251 if (config->sep_symbol) { 277 if (config->sep_symbol) {
252 offset = pos + (block->separator_block_width - sep_width) / 2; 278 offset = x_pos + (sep_block_width - sep_width) / 2;
253 cairo_move_to(cairo, offset, height / 2.0 - sep_height / 2.0); 279 cairo_move_to(cairo, offset, height / 2.0 - sep_height / 2.0);
254 pango_printf(cairo, config->font, output->scale, false, 280 pango_printf(cairo, config->font, output->scale, false,
255 "%s", config->sep_symbol); 281 "%s", config->sep_symbol);
256 } else { 282 } else {
257 cairo_set_line_width(cairo, 1); 283 cairo_set_line_width(cairo, 1);
258 cairo_move_to(cairo, 284 cairo_move_to(cairo, x_pos + sep_block_width / 2, margin);
259 pos + block->separator_block_width / 2, margin); 285 cairo_line_to(cairo, x_pos + sep_block_width / 2, height - margin);
260 cairo_line_to(cairo,
261 pos + block->separator_block_width / 2, height - margin);
262 cairo_stroke(cairo); 286 cairo_stroke(cairo);
263 } 287 }
264 } 288 }
@@ -268,7 +292,7 @@ static uint32_t render_status_block(cairo_t *cairo,
268static uint32_t render_status_line_i3bar(cairo_t *cairo, 292static uint32_t render_status_line_i3bar(cairo_t *cairo,
269 struct swaybar_output *output, double *x) { 293 struct swaybar_output *output, double *x) {
270 uint32_t max_height = 0; 294 uint32_t max_height = 0;
271 bool edge = true; 295 bool edge = *x == output->width * output->scale;
272 struct i3bar_block *block; 296 struct i3bar_block *block;
273 wl_list_for_each(block, &output->bar->status->blocks, link) { 297 wl_list_for_each(block, &output->bar->status->blocks, link) {
274 uint32_t h = render_status_block(cairo, output, block, x, edge); 298 uint32_t h = render_status_block(cairo, output, block, x, edge);
@@ -314,7 +338,8 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo,
314 uint32_t ideal_height = text_height + ws_vertical_padding * 2 338 uint32_t ideal_height = text_height + ws_vertical_padding * 2
315 + border_width * 2; 339 + border_width * 2;
316 uint32_t ideal_surface_height = ideal_height / output->scale; 340 uint32_t ideal_surface_height = ideal_height / output->scale;
317 if (output->height < ideal_surface_height) { 341 if (!output->bar->config->height &&
342 output->height < ideal_surface_height) {
318 return ideal_surface_height; 343 return ideal_surface_height;
319 } 344 }
320 uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; 345 uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2;
@@ -342,22 +367,10 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo,
342 return output->height; 367 return output->height;
343} 368}
344 369
345static const char *strip_workspace_number(const char *ws_name) { 370static enum hotspot_event_handling workspace_hotspot_callback(
346 size_t len = strlen(ws_name); 371 struct swaybar_output *output, struct swaybar_hotspot *hotspot,
347 for (size_t i = 0; i < len; ++i) { 372 int x, int y, uint32_t button, void *data) {
348 if (ws_name[i] < '0' || ws_name[i] > '9') { 373 if (button != BTN_LEFT) {
349 if (':' == ws_name[i] && i < len - 1 && i > 0) {
350 return ws_name + i + 1;
351 }
352 return ws_name;
353 }
354 }
355 return ws_name;
356}
357
358static enum hotspot_event_handling workspace_hotspot_callback(struct swaybar_output *output,
359 int x, int y, enum x11_button button, void *data) {
360 if (button != LEFT) {
361 return HOTSPOT_PROCESS; 374 return HOTSPOT_PROCESS;
362 } 375 }
363 ipc_send_workspace_command(output->bar, (const char *)data); 376 ipc_send_workspace_command(output->bar, (const char *)data);
@@ -368,11 +381,6 @@ static uint32_t render_workspace_button(cairo_t *cairo,
368 struct swaybar_output *output, 381 struct swaybar_output *output,
369 struct swaybar_workspace *ws, double *x) { 382 struct swaybar_workspace *ws, double *x) {
370 struct swaybar_config *config = output->bar->config; 383 struct swaybar_config *config = output->bar->config;
371 const char *name = ws->name;
372 if (config->strip_workspace_numbers) {
373 name = strip_workspace_number(ws->name);
374 }
375
376 struct box_colors box_colors; 384 struct box_colors box_colors;
377 if (ws->urgent) { 385 if (ws->urgent) {
378 box_colors = config->colors.urgent_workspace; 386 box_colors = config->colors.urgent_workspace;
@@ -388,7 +396,7 @@ static uint32_t render_workspace_button(cairo_t *cairo,
388 396
389 int text_width, text_height; 397 int text_width, text_height;
390 get_text_size(cairo, config->font, &text_width, &text_height, NULL, 398 get_text_size(cairo, config->font, &text_width, &text_height, NULL,
391 output->scale, config->pango_markup, "%s", name); 399 output->scale, config->pango_markup, "%s", ws->label);
392 400
393 int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; 401 int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale;
394 int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; 402 int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale;
@@ -397,7 +405,8 @@ static uint32_t render_workspace_button(cairo_t *cairo,
397 uint32_t ideal_height = ws_vertical_padding * 2 + text_height 405 uint32_t ideal_height = ws_vertical_padding * 2 + text_height
398 + border_width * 2; 406 + border_width * 2;
399 uint32_t ideal_surface_height = ideal_height / output->scale; 407 uint32_t ideal_surface_height = ideal_height / output->scale;
400 if (output->height < ideal_surface_height) { 408 if (!output->bar->config->height &&
409 output->height < ideal_surface_height) {
401 return ideal_surface_height; 410 return ideal_surface_height;
402 } 411 }
403 412
@@ -421,7 +430,7 @@ static uint32_t render_workspace_button(cairo_t *cairo,
421 cairo_set_source_u32(cairo, box_colors.text); 430 cairo_set_source_u32(cairo, box_colors.text);
422 cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); 431 cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y));
423 pango_printf(cairo, config->font, output->scale, config->pango_markup, 432 pango_printf(cairo, config->font, output->scale, config->pango_markup,
424 "%s", name); 433 "%s", ws->label);
425 434
426 struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); 435 struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
427 hotspot->x = *x; 436 hotspot->x = *x;
@@ -459,6 +468,12 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) {
459 * utilize the available space. 468 * utilize the available space.
460 */ 469 */
461 double x = output->width * output->scale; 470 double x = output->width * output->scale;
471#if HAVE_TRAY
472 if (bar->tray) {
473 uint32_t h = render_tray(cairo, output, &x);
474 max_height = h > max_height ? h : max_height;
475 }
476#endif
462 if (bar->status) { 477 if (bar->status) {
463 uint32_t h = render_status_line(cairo, output, &x); 478 uint32_t h = render_status_line(cairo, output, &x);
464 max_height = h > max_height ? h : max_height; 479 max_height = h > max_height ? h : max_height;
@@ -518,12 +533,17 @@ void render_frame(struct swaybar_output *output) {
518 cairo_restore(cairo); 533 cairo_restore(cairo);
519 uint32_t height = render_to_cairo(cairo, output); 534 uint32_t height = render_to_cairo(cairo, output);
520 int config_height = output->bar->config->height; 535 int config_height = output->bar->config->height;
521 if (config_height >= 0 && height < (uint32_t)config_height) { 536 if (config_height > 0) {
522 height = config_height; 537 height = config_height;
523 } 538 }
524 if (height != output->height || output->width == 0) { 539 if (height != output->height || output->width == 0) {
525 // Reconfigure surface 540 // Reconfigure surface
526 zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height); 541 zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height);
542 zwlr_layer_surface_v1_set_margin(output->layer_surface,
543 output->bar->config->gaps.top,
544 output->bar->config->gaps.right,
545 output->bar->config->gaps.bottom,
546 output->bar->config->gaps.left);
527 if (strcmp(output->bar->config->mode, "dock") == 0) { 547 if (strcmp(output->bar->config->mode, "dock") == 0) {
528 zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); 548 zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height);
529 } 549 }