diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-03-31 14:39:18 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-04-02 11:09:23 -0400 |
commit | 333dbcbe72b6af95573e374b66ad6ab63f274299 (patch) | |
tree | b73facc5f8399ca6328898749941d5ae195dec8d /swaybar/render.c | |
parent | Demarcate i3bar JSON into individual updates (diff) | |
download | sway-333dbcbe72b6af95573e374b66ad6ab63f274299.tar.gz sway-333dbcbe72b6af95573e374b66ad6ab63f274299.tar.zst sway-333dbcbe72b6af95573e374b66ad6ab63f274299.zip |
Render i3bar blocks
Diffstat (limited to 'swaybar/render.c')
-rw-r--r-- | swaybar/render.c | 209 |
1 files changed, 194 insertions, 15 deletions
diff --git a/swaybar/render.c b/swaybar/render.c index c2358724..3ad6d5d7 100644 --- a/swaybar/render.c +++ b/swaybar/render.c | |||
@@ -18,10 +18,33 @@ static const int ws_horizontal_padding = 5; | |||
18 | static const double ws_vertical_padding = 1.5; | 18 | static const double ws_vertical_padding = 1.5; |
19 | static const double border_width = 1; | 19 | static const double border_width = 1; |
20 | 20 | ||
21 | static 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 | |||
21 | static uint32_t render_status_line_text(cairo_t *cairo, | 44 | static 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,193 @@ 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 | |||
68 | static 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 | |||
92 | static uint32_t render_status_block(cairo_t *cairo, | ||
93 | struct swaybar_config *config, struct i3bar_block *block, | ||
94 | double *x, uint32_t height, bool focused, bool edge) { | ||
95 | static const int margin = 3; | ||
96 | if (!block->full_text || !*block->full_text) { | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | int text_width, text_height; | ||
101 | get_text_size(cairo, config->font, &text_width, &text_height, | ||
102 | 1, block->markup, "%s", block->full_text); | ||
103 | int width = text_width; | ||
104 | if (width < block->min_width) { | ||
105 | width = block->min_width; | ||
106 | } | ||
107 | double block_width = width; | ||
108 | uint32_t ideal_height = text_height + ws_vertical_padding * 2; | ||
109 | if (height < ideal_height) { | ||
110 | return ideal_height; | ||
111 | } | ||
112 | |||
113 | *x -= width; | ||
114 | if (block->border && block->border_left > 0) { | ||
115 | *x -= (block->border_left + margin); | ||
116 | block_width += block->border_left + margin; | ||
117 | } | ||
118 | if (block->border && block->border_right > 0) { | ||
119 | *x -= (block->border_right + margin); | ||
120 | block_width += block->border_right + margin; | ||
121 | } | ||
122 | |||
123 | int sep_width; | ||
124 | if (!edge) { | ||
125 | if (config->sep_symbol) { | ||
126 | int _height; | ||
127 | get_text_size(cairo, config->font, &sep_width, &_height, | ||
128 | 1, false, "%s", config->sep_symbol); | ||
129 | uint32_t _ideal_height = _height + ws_vertical_padding * 2; | ||
130 | if (height < _ideal_height) { | ||
131 | return _height; | ||
132 | } | ||
133 | if (sep_width > block->separator_block_width) { | ||
134 | block->separator_block_width = sep_width + margin * 2; | ||
135 | } | ||
136 | } | ||
137 | *x -= block->separator_block_width; | ||
138 | } else { | ||
139 | *x -= margin; | ||
140 | } | ||
141 | |||
142 | // TODO: Create hotspot here | ||
143 | |||
144 | double pos = *x; | ||
145 | if (block->background) { | ||
146 | cairo_set_source_u32(cairo, block->background); | ||
147 | cairo_rectangle(cairo, pos - 0.5, 1, block_width, height); | ||
148 | cairo_fill(cairo); | ||
149 | } | ||
150 | |||
151 | if (block->border && block->border_top > 0) { | ||
152 | render_sharp_line(cairo, block->border, | ||
153 | pos - 0.5, 1, block_width, block->border_top); | ||
154 | } | ||
155 | if (block->border && block->border_bottom > 0) { | ||
156 | render_sharp_line(cairo, block->border, | ||
157 | pos - 0.5, height - 1 - block->border_bottom, | ||
158 | block_width, block->border_bottom); | ||
159 | } | ||
160 | if (block->border != 0 && block->border_left > 0) { | ||
161 | render_sharp_line(cairo, block->border, | ||
162 | pos - 0.5, 1, block->border_left, height); | ||
163 | pos += block->border_left + margin; | ||
164 | } | ||
165 | |||
166 | double offset = 0; | ||
167 | if (strncmp(block->align, "left", 5) == 0) { | ||
168 | offset = pos; | ||
169 | } else if (strncmp(block->align, "right", 5) == 0) { | ||
170 | offset = pos + width - text_width; | ||
171 | } else if (strncmp(block->align, "center", 6) == 0) { | ||
172 | offset = pos + (width - text_width) / 2; | ||
173 | } | ||
174 | cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); | ||
175 | uint32_t color = block->color ? *block->color : config->colors.statusline; | ||
176 | cairo_set_source_u32(cairo, color); | ||
177 | pango_printf(cairo, config->font, 1, block->markup, "%s", block->full_text); | ||
178 | pos += width; | ||
179 | |||
180 | if (block->border && block->border_right > 0) { | ||
181 | pos += margin; | ||
182 | render_sharp_line(cairo, block->border, | ||
183 | pos - 0.5, 1, block->border_right, height); | ||
184 | pos += block->border_right; | ||
185 | } | ||
186 | |||
187 | if (!edge && block->separator) { | ||
188 | if (focused) { | ||
189 | cairo_set_source_u32(cairo, config->colors.focused_separator); | ||
190 | } else { | ||
191 | cairo_set_source_u32(cairo, config->colors.separator); | ||
192 | } | ||
193 | if (config->sep_symbol) { | ||
194 | offset = pos + (block->separator_block_width - sep_width) / 2; | ||
195 | cairo_move_to(cairo, offset, margin); | ||
196 | pango_printf(cairo, config->font, 1, false, | ||
197 | "%s", config->sep_symbol); | ||
198 | } else { | ||
199 | cairo_set_line_width(cairo, 1); | ||
200 | cairo_move_to(cairo, | ||
201 | pos + block->separator_block_width / 2, margin); | ||
202 | cairo_line_to(cairo, | ||
203 | pos + block->separator_block_width / 2, height - margin); | ||
204 | cairo_stroke(cairo); | ||
205 | } | ||
206 | } | ||
41 | return ideal_height; | 207 | return ideal_height; |
42 | } | 208 | } |
43 | 209 | ||
44 | static uint32_t render_status_line_i3bar(cairo_t *cairo, | 210 | static uint32_t render_status_line_i3bar(cairo_t *cairo, |
45 | struct swaybar_config *config, struct status_line *status, | 211 | struct swaybar_config *config, struct status_line *status, |
46 | bool focused, uint32_t width, uint32_t height) { | 212 | bool focused, double *x, uint32_t width, uint32_t height) { |
47 | // TODO | 213 | struct i3bar_block *block; |
48 | return 0; | 214 | uint32_t max_height = 0; |
215 | bool edge = true; | ||
216 | wl_list_for_each_reverse(block, &status->blocks, link) { | ||
217 | uint32_t h = render_status_block(cairo, config, | ||
218 | block, x, height, focused, edge); | ||
219 | max_height = h > max_height ? h : max_height; | ||
220 | edge = false; | ||
221 | } | ||
222 | return max_height; | ||
49 | } | 223 | } |
50 | 224 | ||
51 | static uint32_t render_status_line(cairo_t *cairo, | 225 | static uint32_t render_status_line(cairo_t *cairo, |
52 | struct swaybar_config *config, struct status_line *status, | 226 | struct swaybar_config *config, struct status_line *status, |
53 | bool focused, uint32_t width, uint32_t height) { | 227 | bool focused, double *x, uint32_t width, uint32_t height) { |
54 | switch (status->protocol) { | 228 | switch (status->protocol) { |
229 | case PROTOCOL_ERROR: | ||
230 | return render_status_line_error(cairo, | ||
231 | config, status->text, x, width, height); | ||
55 | case PROTOCOL_TEXT: | 232 | case PROTOCOL_TEXT: |
56 | return render_status_line_text(cairo, | 233 | return render_status_line_text(cairo, |
57 | config, status, focused, width, height); | 234 | config, status->text, focused, x, width, height); |
58 | case PROTOCOL_I3BAR: | 235 | case PROTOCOL_I3BAR: |
59 | return render_status_line_i3bar(cairo, | 236 | return render_status_line_i3bar(cairo, |
60 | config, status, focused, width, height); | 237 | config, status, focused, x, width, height); |
61 | default: | 238 | case PROTOCOL_UNDEF: |
62 | return 0; | 239 | return 0; |
63 | } | 240 | } |
241 | return 0; | ||
64 | } | 242 | } |
65 | 243 | ||
66 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, | 244 | static uint32_t render_binding_mode_indicator(cairo_t *cairo, |
@@ -211,9 +389,10 @@ static uint32_t render_to_cairo(cairo_t *cairo, | |||
211 | cairo, config, config->mode, x, output->height); | 389 | cairo, config, config->mode, x, output->height); |
212 | max_height = h > max_height ? h : max_height; | 390 | max_height = h > max_height ? h : max_height; |
213 | } | 391 | } |
392 | x = output->width; | ||
214 | if (bar->status) { | 393 | if (bar->status) { |
215 | uint32_t h = render_status_line(cairo, config, bar->status, | 394 | uint32_t h = render_status_line(cairo, config, bar->status, |
216 | output->focused, output->width, output->height); | 395 | output->focused, &x, output->width, output->height); |
217 | max_height = h > max_height ? h : max_height; | 396 | max_height = h > max_height ? h : max_height; |
218 | } | 397 | } |
219 | 398 | ||