diff options
author | Ian Fan <ianfan0@gmail.com> | 2018-12-07 12:37:33 +0000 |
---|---|---|
committer | Ian Fan <ianfan0@gmail.com> | 2018-12-31 20:40:18 +0000 |
commit | fa2c5282c1d09eced82a9c15a4ee26e7b00a37c4 (patch) | |
tree | ec9e36055d21478466d663e2dc1796658ab273ca /swaybar/tray/item.c | |
parent | swaybar: implement tray config (diff) | |
download | sway-fa2c5282c1d09eced82a9c15a4ee26e7b00a37c4.tar.gz sway-fa2c5282c1d09eced82a9c15a4ee26e7b00a37c4.tar.zst sway-fa2c5282c1d09eced82a9c15a4ee26e7b00a37c4.zip |
swaybar: implement tray rendering
Diffstat (limited to 'swaybar/tray/item.c')
-rw-r--r-- | swaybar/tray/item.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c index 561a3425..019e8ed0 100644 --- a/swaybar/tray/item.c +++ b/swaybar/tray/item.c | |||
@@ -1,14 +1,27 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <cairo.h> | ||
3 | #include <stdbool.h> | ||
2 | #include <stdlib.h> | 4 | #include <stdlib.h> |
3 | #include <string.h> | 5 | #include <string.h> |
6 | #include "swaybar/bar.h" | ||
7 | #include "swaybar/config.h" | ||
4 | #include "swaybar/tray/host.h" | 8 | #include "swaybar/tray/host.h" |
9 | #include "swaybar/tray/icon.h" | ||
5 | #include "swaybar/tray/item.h" | 10 | #include "swaybar/tray/item.h" |
6 | #include "swaybar/tray/tray.h" | 11 | #include "swaybar/tray/tray.h" |
12 | #include "background-image.h" | ||
13 | #include "cairo.h" | ||
7 | #include "list.h" | 14 | #include "list.h" |
8 | #include "log.h" | 15 | #include "log.h" |
9 | 16 | ||
10 | // TODO menu | 17 | // TODO menu |
11 | 18 | ||
19 | static bool sni_ready(struct swaybar_sni *sni) { | ||
20 | return sni->status && (sni->status[0] == 'N' ? | ||
21 | sni->attention_icon_name || sni->attention_icon_pixmap : | ||
22 | sni->icon_name || sni->icon_pixmap); | ||
23 | } | ||
24 | |||
12 | static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni, | 25 | static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni, |
13 | const char *prop, list_t **dest) { | 26 | const char *prop, list_t **dest) { |
14 | int ret = sd_bus_message_enter_container(msg, 'a', "(iiay)"); | 27 | int ret = sd_bus_message_enter_container(msg, 'a', "(iiay)"); |
@@ -234,3 +247,74 @@ void destroy_sni(struct swaybar_sni *sni) { | |||
234 | free(sni->menu); | 247 | free(sni->menu); |
235 | free(sni); | 248 | free(sni); |
236 | } | 249 | } |
250 | |||
251 | uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x, | ||
252 | struct swaybar_sni *sni) { | ||
253 | uint32_t height = output->height * output->scale; | ||
254 | int padding = output->bar->config->tray_padding; | ||
255 | int ideal_size = height - 2*padding; | ||
256 | if ((ideal_size < sni->min_size || ideal_size > sni->max_size) && sni_ready(sni)) { | ||
257 | bool icon_found = false; | ||
258 | char *icon_name = sni->status[0] == 'N' ? | ||
259 | sni->attention_icon_name : sni->icon_name; | ||
260 | if (icon_name) { | ||
261 | char *icon_path = find_icon(sni->tray->themes, sni->tray->basedirs, | ||
262 | icon_name, ideal_size, output->bar->config->icon_theme, | ||
263 | &sni->min_size, &sni->max_size); | ||
264 | if (icon_path) { | ||
265 | cairo_surface_destroy(sni->icon); | ||
266 | sni->icon = load_background_image(icon_path); | ||
267 | free(icon_path); | ||
268 | icon_found = true; | ||
269 | } | ||
270 | } | ||
271 | if (!icon_found) { | ||
272 | list_t *pixmaps = sni->status[0] == 'N' ? | ||
273 | sni->attention_icon_pixmap : sni->icon_pixmap; | ||
274 | if (pixmaps) { | ||
275 | int idx = -1; | ||
276 | unsigned smallest_error = -1; // UINT_MAX | ||
277 | for (int i = 0; i < pixmaps->length; ++i) { | ||
278 | struct swaybar_pixmap *pixmap = pixmaps->items[i]; | ||
279 | unsigned error = (ideal_size - pixmap->size) * | ||
280 | (ideal_size < pixmap->size ? -1 : 1); | ||
281 | if (error < smallest_error) { | ||
282 | smallest_error = error; | ||
283 | idx = i; | ||
284 | } | ||
285 | } | ||
286 | struct swaybar_pixmap *pixmap = pixmaps->items[idx]; | ||
287 | cairo_surface_destroy(sni->icon); | ||
288 | sni->icon = cairo_image_surface_create_for_data(pixmap->pixels, | ||
289 | CAIRO_FORMAT_ARGB32, pixmap->size, pixmap->size, | ||
290 | cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pixmap->size)); | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | |||
295 | if (!sni->icon) { | ||
296 | // TODO fallback | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | cairo_surface_t *icon; | ||
301 | int actual_size = cairo_image_surface_get_height(sni->icon); | ||
302 | int icon_size = actual_size < ideal_size ? | ||
303 | actual_size * (ideal_size / actual_size) : ideal_size; | ||
304 | icon = cairo_image_surface_scale(sni->icon, icon_size, icon_size); | ||
305 | |||
306 | int padded_size = icon_size + 2*padding; | ||
307 | *x -= padded_size; | ||
308 | int y = floor((height - padded_size) / 2.0); | ||
309 | |||
310 | cairo_operator_t op = cairo_get_operator(cairo); | ||
311 | cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); | ||
312 | cairo_set_source_surface(cairo, icon, *x + padding, y + padding); | ||
313 | cairo_rectangle(cairo, *x, y, padded_size, padded_size); | ||
314 | cairo_fill(cairo); | ||
315 | cairo_set_operator(cairo, op); | ||
316 | |||
317 | cairo_surface_destroy(icon); | ||
318 | |||
319 | return output->height; | ||
320 | } | ||