From 843ad38b3c427adb0bf319e9613d9813c8d9246c Mon Sep 17 00:00:00 2001 From: Calvin Lee Date: Wed, 7 Jun 2017 16:45:28 -0700 Subject: Implement Tray Icons This commit implements the StatusNotifierItem protocol, and enables swaybar to show tray icons. It also uses `xembedsniproxy` in order to communicate with xembed applications. The tray is completely optional, and can be disabled on compile time with the `enable-tray` option. Or on runtime with the bar config option `tray_output none`. Overview of changes: In swaybar very little is changed outside the tray subfolder except that all events are now polled in `event_loop.c`, this creates no functional difference. Six bar configuration options were added, these are detailed in sway-bar(5) The tray subfolder is where all protocol implementation takes place and is organised as follows: tray/sni_watcher.c: This file contains the StatusNotifierWatcher. It keeps track of items and hosts and reports when they come or go. tray/tray.c This file contains the StatusNotifierHost. It keeps track of sway's version of the items and represents the tray itself. tray/sni.c This file contains the StatusNotifierItem struct and all communication with individual items. tray/icon.c This file implements the icon theme protocol. It allows for finding icons by name, rather than by pixmap. tray/dbus.c This file allows for asynchronous DBus communication. See #986 #343 --- swaybar/render.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 3 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index 2eae997f..0b2ac438 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -8,6 +8,10 @@ #include "swaybar/config.h" #include "swaybar/status_line.h" #include "swaybar/render.h" +#ifdef ENABLE_TRAY +#include "swaybar/tray/tray.h" +#include "swaybar/tray/sni.h" +#endif #include "log.h" @@ -297,6 +301,72 @@ void render(struct output *output, struct config *config, struct status_line *li } cairo_paint(cairo); +#ifdef ENABLE_TRAY + // Tray icons + uint32_t tray_padding = config->tray_padding; + unsigned int tray_width = window->width * window->scale; + const int item_size = (window->height * window->scale) - (2 * tray_padding); + + if (item_size < 0) { + // Can't render items if the padding is too large + goto no_tray; + } + + if (config->tray_output && strcmp(config->tray_output, output->name) != 0) { + goto no_tray; + } + + for (int i = 0; i < tray->items->length; ++i) { + struct StatusNotifierItem *item = + tray->items->items[i]; + if (!item->image) { + continue; + } + + struct sni_icon_ref *render_item = NULL; + int j; + for (j = i; j < output->items->length; ++j) { + struct sni_icon_ref *ref = + output->items->items[j]; + if (ref->ref == item) { + render_item = ref; + break; + } else { + sni_icon_ref_free(ref); + list_del(output->items, j); + } + } + + if (!render_item) { + render_item = sni_icon_ref_create(item, item_size); + list_add(output->items, render_item); + } else if (item->dirty) { + // item needs re-render + sni_icon_ref_free(render_item); + output->items->items[j] = render_item = + sni_icon_ref_create(item, item_size); + } + + tray_width -= tray_padding; + tray_width -= item_size; + + cairo_set_source_surface(cairo, render_item->icon, tray_width, tray_padding); + cairo_rectangle(cairo, tray_width, tray_padding, item_size, item_size); + cairo_fill(cairo); + + item->dirty = false; + } + + + if (tray_width != window->width * window->scale) { + tray_width -= tray_padding; + } + +no_tray: +#else + const int tray_width = window->width * window->scale; +#endif + // Command output if (is_focused) { cairo_set_source_u32(cairo, config->colors.focused_statusline); @@ -309,12 +379,11 @@ void render(struct output *output, struct config *config, struct status_line *li if (line->protocol == TEXT) { get_text_size(window->cairo, window->font, &width, &height, window->scale, config->pango_markup, "%s", line->text_line); - cairo_move_to(cairo, (window->width * window->scale) - - margin - width, margin); + cairo_move_to(cairo, tray_width - margin - width, margin); pango_printf(window->cairo, window->font, window->scale, config->pango_markup, "%s", line->text_line); } else if (line->protocol == I3BAR && line->block_line) { - double pos = (window->width * window->scale) - 0.5; + double pos = tray_width - 0.5; bool edge = true; for (i = line->block_line->length - 1; i >= 0; --i) { struct status_block *block = line->block_line->items[i]; -- cgit v1.2.3 From 790887ce762fb51d18e966de22bd2ab5b6a593c7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 7 Jun 2017 22:45:33 -0400 Subject: Fix cairo blending on tray icons --- swaybar/render.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index 0b2ac438..d02ecbbb 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -350,9 +350,12 @@ void render(struct output *output, struct config *config, struct status_line *li tray_width -= tray_padding; tray_width -= item_size; + cairo_operator_t op = cairo_get_operator(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); cairo_set_source_surface(cairo, render_item->icon, tray_width, tray_padding); cairo_rectangle(cairo, tray_width, tray_padding, item_size, item_size); cairo_fill(cairo); + cairo_set_operator(cairo, op); item->dirty = false; } -- cgit v1.2.3 From 1451ee8fd13dd35227d11e393c80871c70ad90f0 Mon Sep 17 00:00:00 2001 From: Calvin Lee Date: Wed, 7 Jun 2017 21:32:48 -0700 Subject: Reorganize Tray Code Remove tray code from bar.c and render.c --- swaybar/render.c | 67 ++------------------------------------------------------ 1 file changed, 2 insertions(+), 65 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index d02ecbbb..6ec47e79 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -302,72 +302,9 @@ void render(struct output *output, struct config *config, struct status_line *li cairo_paint(cairo); #ifdef ENABLE_TRAY - // Tray icons - uint32_t tray_padding = config->tray_padding; - unsigned int tray_width = window->width * window->scale; - const int item_size = (window->height * window->scale) - (2 * tray_padding); - - if (item_size < 0) { - // Can't render items if the padding is too large - goto no_tray; - } - - if (config->tray_output && strcmp(config->tray_output, output->name) != 0) { - goto no_tray; - } - - for (int i = 0; i < tray->items->length; ++i) { - struct StatusNotifierItem *item = - tray->items->items[i]; - if (!item->image) { - continue; - } - - struct sni_icon_ref *render_item = NULL; - int j; - for (j = i; j < output->items->length; ++j) { - struct sni_icon_ref *ref = - output->items->items[j]; - if (ref->ref == item) { - render_item = ref; - break; - } else { - sni_icon_ref_free(ref); - list_del(output->items, j); - } - } - - if (!render_item) { - render_item = sni_icon_ref_create(item, item_size); - list_add(output->items, render_item); - } else if (item->dirty) { - // item needs re-render - sni_icon_ref_free(render_item); - output->items->items[j] = render_item = - sni_icon_ref_create(item, item_size); - } - - tray_width -= tray_padding; - tray_width -= item_size; - - cairo_operator_t op = cairo_get_operator(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); - cairo_set_source_surface(cairo, render_item->icon, tray_width, tray_padding); - cairo_rectangle(cairo, tray_width, tray_padding, item_size, item_size); - cairo_fill(cairo); - cairo_set_operator(cairo, op); - - item->dirty = false; - } - - - if (tray_width != window->width * window->scale) { - tray_width -= tray_padding; - } - -no_tray: + uint32_t tray_width = tray_render(output, config); #else - const int tray_width = window->width * window->scale; + const uint32_t tray_width = window->width * window->scale; #endif // Command output -- cgit v1.2.3