summaryrefslogtreecommitdiffstats
path: root/swaybar/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'swaybar/render.c')
-rw-r--r--swaybar/render.c238
1 files changed, 218 insertions, 20 deletions
diff --git a/swaybar/render.c b/swaybar/render.c
index c2358724..6f3b0788 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -18,10 +18,33 @@ static const int ws_horizontal_padding = 5;
18static const double ws_vertical_padding = 1.5; 18static const double ws_vertical_padding = 1.5;
19static const double border_width = 1; 19static const double border_width = 1;
20 20
21static uint32_t render_status_line_error(cairo_t *cairo,
22 struct swaybar_config *config, const char *error,
23 double *x, uint32_t width, uint32_t height) {
24 if (!error) {
25 return 0;
26 }
27 cairo_set_source_u32(cairo, 0xFF0000FF);
28 static const int margin = 3;
29 int text_width, text_height;
30 get_text_size(cairo, config->font,
31 &text_width, &text_height, 1, false, "%s", error);
32 uint32_t ideal_height = text_height + ws_vertical_padding * 2;
33 if (height < ideal_height) {
34 return ideal_height;
35 }
36 *x -= text_width + margin;
37 double text_y = height / 2.0 - text_height / 2.0;
38 cairo_move_to(cairo, *x, (int)floor(text_y));
39 pango_printf(cairo, config->font, 1, false, "%s", error);
40 *x -= margin;
41 return ideal_height;
42}
43
21static uint32_t render_status_line_text(cairo_t *cairo, 44static uint32_t render_status_line_text(cairo_t *cairo,
22 struct swaybar_config *config, struct status_line *status, 45 struct swaybar_config *config, const char *text,
23 bool focused, uint32_t width, uint32_t height) { 46 bool focused, double *x, uint32_t width, uint32_t height) {
24 if (!status->text) { 47 if (!text) {
25 return 0; 48 return 0;
26 } 49 }
27 cairo_set_source_u32(cairo, focused ? 50 cairo_set_source_u32(cairo, focused ?
@@ -29,38 +52,211 @@ static uint32_t render_status_line_text(cairo_t *cairo,
29 static const int margin = 3; 52 static const int margin = 3;
30 int text_width, text_height; 53 int text_width, text_height;
31 get_text_size(cairo, config->font, &text_width, &text_height, 54 get_text_size(cairo, config->font, &text_width, &text_height,
32 1, config->pango_markup, "%s", status->text); 55 1, config->pango_markup, "%s", text);
33 uint32_t ideal_height = text_height + ws_vertical_padding * 2; 56 uint32_t ideal_height = text_height + ws_vertical_padding * 2;
34 if (height < ideal_height) { 57 if (height < ideal_height) {
35 return ideal_height; 58 return ideal_height;
36 } 59 }
60 *x -= text_width + margin;
37 double text_y = height / 2.0 - text_height / 2.0; 61 double text_y = height / 2.0 - text_height / 2.0;
38 cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y)); 62 cairo_move_to(cairo, *x, (int)floor(text_y));
39 pango_printf(cairo, config->font, 1, config->pango_markup, 63 pango_printf(cairo, config->font, 1, config->pango_markup, "%s", text);
40 "%s", status->text); 64 *x -= margin;
65 return ideal_height;
66}
67
68static void render_sharp_line(cairo_t *cairo, uint32_t color,
69 double x, double y, double width, double height) {
70 cairo_set_source_u32(cairo, color);
71 if (width > 1 && height > 1) {
72 cairo_rectangle(cairo, x, y, width, height);
73 cairo_fill(cairo);
74 } else {
75 if (width == 1) {
76 x += 0.5;
77 height += y;
78 width = x;
79 }
80 if (height == 1) {
81 y += 0.5;
82 width += x;
83 height = y;
84 }
85 cairo_move_to(cairo, x, y);
86 cairo_set_line_width(cairo, 1.0);
87 cairo_line_to(cairo, width, height);
88 cairo_stroke(cairo);
89 }
90}
91
92static void block_hotspot_callback(struct swaybar_output *output,
93 int x, int y, uint32_t button, void *data) {
94 struct i3bar_block *block = data;
95 struct status_line *status = output->bar->status;
96 i3bar_block_send_click(status, block, x, y, button);
97}
98
99static uint32_t render_status_block(cairo_t *cairo,
100 struct swaybar_config *config, struct swaybar_output *output,
101 struct i3bar_block *block, double *x,
102 uint32_t height, bool focused, bool edge) {
103 static const int margin = 3;
104 if (!block->full_text || !*block->full_text) {
105 return 0;
106 }
107
108 int text_width, text_height;
109 get_text_size(cairo, config->font, &text_width, &text_height,
110 1, block->markup, "%s", block->full_text);
111 int width = text_width;
112 if (width < block->min_width) {
113 width = block->min_width;
114 }
115 double block_width = width;
116 uint32_t ideal_height = text_height + ws_vertical_padding * 2;
117 if (height < ideal_height) {
118 return ideal_height;
119 }
120
121 *x -= width;
122 if (block->border && block->border_left > 0) {
123 *x -= (block->border_left + margin);
124 block_width += block->border_left + margin;
125 }
126 if (block->border && block->border_right > 0) {
127 *x -= (block->border_right + margin);
128 block_width += block->border_right + margin;
129 }
130
131 int sep_width;
132 if (!edge) {
133 if (config->sep_symbol) {
134 int _height;
135 get_text_size(cairo, config->font, &sep_width, &_height,
136 1, false, "%s", config->sep_symbol);
137 uint32_t _ideal_height = _height + ws_vertical_padding * 2;
138 if (height < _ideal_height) {
139 return _height;
140 }
141 if (sep_width > block->separator_block_width) {
142 block->separator_block_width = sep_width + margin * 2;
143 }
144 }
145 *x -= block->separator_block_width;
146 } else {
147 *x -= margin;
148 }
149
150 struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
151 hotspot->x = *x;
152 hotspot->y = 0;
153 hotspot->width = width;
154 hotspot->height = height;
155 hotspot->callback = block_hotspot_callback;
156 hotspot->destroy = NULL;
157 hotspot->data = block;
158 wl_list_insert(&output->hotspots, &hotspot->link);
159
160 double pos = *x;
161 if (block->background) {
162 cairo_set_source_u32(cairo, block->background);
163 cairo_rectangle(cairo, pos - 0.5, 1, block_width, height);
164 cairo_fill(cairo);
165 }
166
167 if (block->border && block->border_top > 0) {
168 render_sharp_line(cairo, block->border,
169 pos - 0.5, 1, block_width, block->border_top);
170 }
171 if (block->border && block->border_bottom > 0) {
172 render_sharp_line(cairo, block->border,
173 pos - 0.5, height - 1 - block->border_bottom,
174 block_width, block->border_bottom);
175 }
176 if (block->border != 0 && block->border_left > 0) {
177 render_sharp_line(cairo, block->border,
178 pos - 0.5, 1, block->border_left, height);
179 pos += block->border_left + margin;
180 }
181
182 double offset = 0;
183 if (strncmp(block->align, "left", 5) == 0) {
184 offset = pos;
185 } else if (strncmp(block->align, "right", 5) == 0) {
186 offset = pos + width - text_width;
187 } else if (strncmp(block->align, "center", 6) == 0) {
188 offset = pos + (width - text_width) / 2;
189 }
190 cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0);
191 uint32_t color = block->color ? *block->color : config->colors.statusline;
192 cairo_set_source_u32(cairo, color);
193 pango_printf(cairo, config->font, 1, block->markup, "%s", block->full_text);
194 pos += width;
195
196 if (block->border && block->border_right > 0) {
197 pos += margin;
198 render_sharp_line(cairo, block->border,
199 pos - 0.5, 1, block->border_right, height);
200 pos += block->border_right;
201 }
202
203 if (!edge && block->separator) {
204 if (focused) {
205 cairo_set_source_u32(cairo, config->colors.focused_separator);
206 } else {
207 cairo_set_source_u32(cairo, config->colors.separator);
208 }
209 if (config->sep_symbol) {
210 offset = pos + (block->separator_block_width - sep_width) / 2;
211 cairo_move_to(cairo, offset, margin);
212 pango_printf(cairo, config->font, 1, false,
213 "%s", config->sep_symbol);
214 } else {
215 cairo_set_line_width(cairo, 1);
216 cairo_move_to(cairo,
217 pos + block->separator_block_width / 2, margin);
218 cairo_line_to(cairo,
219 pos + block->separator_block_width / 2, height - margin);
220 cairo_stroke(cairo);
221 }
222 }
41 return ideal_height; 223 return ideal_height;
42} 224}
43 225
44static uint32_t render_status_line_i3bar(cairo_t *cairo, 226static uint32_t render_status_line_i3bar(cairo_t *cairo,
45 struct swaybar_config *config, struct status_line *status, 227 struct swaybar_config *config, struct swaybar_output *output,
46 bool focused, uint32_t width, uint32_t height) { 228 struct status_line *status, bool focused,
47 // TODO 229 double *x, uint32_t width, uint32_t height) {
48 return 0; 230 uint32_t max_height = 0;
231 bool edge = true;
232 struct i3bar_block *block;
233 wl_list_for_each(block, &status->blocks, link) {
234 uint32_t h = render_status_block(cairo, config, output,
235 block, x, height, focused, edge);
236 max_height = h > max_height ? h : max_height;
237 edge = false;
238 }
239 return max_height;
49} 240}
50 241
51static uint32_t render_status_line(cairo_t *cairo, 242static uint32_t render_status_line(cairo_t *cairo,
52 struct swaybar_config *config, struct status_line *status, 243 struct swaybar_config *config, struct swaybar_output *output,
53 bool focused, uint32_t width, uint32_t height) { 244 struct status_line *status, bool focused,
245 double *x, uint32_t width, uint32_t height) {
54 switch (status->protocol) { 246 switch (status->protocol) {
247 case PROTOCOL_ERROR:
248 return render_status_line_error(cairo,
249 config, status->text, x, width, height);
55 case PROTOCOL_TEXT: 250 case PROTOCOL_TEXT:
56 return render_status_line_text(cairo, 251 return render_status_line_text(cairo,
57 config, status, focused, width, height); 252 config, status->text, focused, x, width, height);
58 case PROTOCOL_I3BAR: 253 case PROTOCOL_I3BAR:
59 return render_status_line_i3bar(cairo, 254 return render_status_line_i3bar(cairo, config, output, status,
60 config, status, focused, width, height); 255 focused, x, width, height);
61 default: 256 case PROTOCOL_UNDEF:
62 return 0; 257 return 0;
63 } 258 }
259 return 0;
64} 260}
65 261
66static uint32_t render_binding_mode_indicator(cairo_t *cairo, 262static uint32_t render_binding_mode_indicator(cairo_t *cairo,
@@ -166,8 +362,8 @@ static uint32_t render_workspace_button(cairo_t *cairo,
166 struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); 362 struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
167 hotspot->x = *x; 363 hotspot->x = *x;
168 hotspot->y = 0; 364 hotspot->y = 0;
169 hotspot->height = height;
170 hotspot->width = width; 365 hotspot->width = width;
366 hotspot->height = height;
171 hotspot->callback = workspace_hotspot_callback; 367 hotspot->callback = workspace_hotspot_callback;
172 hotspot->destroy = free; 368 hotspot->destroy = free;
173 hotspot->data = strdup(name); 369 hotspot->data = strdup(name);
@@ -180,6 +376,7 @@ static uint32_t render_workspace_button(cairo_t *cairo,
180static uint32_t render_to_cairo(cairo_t *cairo, 376static uint32_t render_to_cairo(cairo_t *cairo,
181 struct swaybar *bar, struct swaybar_output *output) { 377 struct swaybar *bar, struct swaybar_output *output) {
182 struct swaybar_config *config = bar->config; 378 struct swaybar_config *config = bar->config;
379 wlr_log(L_DEBUG, "output %p", output);
183 380
184 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); 381 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
185 if (output->focused) { 382 if (output->focused) {
@@ -211,9 +408,10 @@ static uint32_t render_to_cairo(cairo_t *cairo,
211 cairo, config, config->mode, x, output->height); 408 cairo, config, config->mode, x, output->height);
212 max_height = h > max_height ? h : max_height; 409 max_height = h > max_height ? h : max_height;
213 } 410 }
411 x = output->width;
214 if (bar->status) { 412 if (bar->status) {
215 uint32_t h = render_status_line(cairo, config, bar->status, 413 uint32_t h = render_status_line(cairo, config, output, bar->status,
216 output->focused, output->width, output->height); 414 output->focused, &x, output->width, output->height);
217 max_height = h > max_height ? h : max_height; 415 max_height = h > max_height ? h : max_height;
218 } 416 }
219 417