From dc799adf458e331ab4fe362a4c4bc1f8234615be Mon Sep 17 00:00:00 2001 From: Alexis Date: Sun, 9 Sep 2018 20:46:26 +0200 Subject: [PATCH] feat(Tray): icon pixmap --- include/modules/sni/sni.hpp | 2 ++ src/modules/sni/sni.cpp | 52 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/include/modules/sni/sni.hpp b/include/modules/sni/sni.hpp index 9b04404b..2aa0a017 100644 --- a/include/modules/sni/sni.hpp +++ b/include/modules/sni/sni.hpp @@ -23,6 +23,7 @@ class Item { std::string title; int32_t window_id; std::string icon_name; + Glib::RefPtr icon_pixmap; std::string overlay_icon_name; std::string attention_icon_name; std::string attention_movie_name; @@ -34,6 +35,7 @@ class Item { static void getAll(GObject* obj, GAsyncResult* res, gpointer data); void updateImage(); + Glib::RefPtr extractPixBuf(GVariant* variant); Glib::RefPtr getIconByName(std::string name, int size); Glib::Dispatcher* dp_; GCancellable* cancellable_ = nullptr; diff --git a/src/modules/sni/sni.cpp b/src/modules/sni/sni.cpp index ae5ca4ff..d7d5000c 100644 --- a/src/modules/sni/sni.cpp +++ b/src/modules/sni/sni.cpp @@ -74,6 +74,7 @@ void waybar::modules::SNI::Item::getAll(GObject* obj, GAsyncResult* res, } else if (g_strcmp0(key, "IconName") == 0) { item->icon_name = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "IconPixmap") == 0) { + item->icon_pixmap = item->extractPixBuf(value); // TODO: icon pixmap } else if (g_strcmp0(key, "OverlayIconName") == 0) { item->overlay_icon_name = g_variant_dup_string(value, nullptr); @@ -114,6 +115,55 @@ void waybar::modules::SNI::Item::getAll(GObject* obj, GAsyncResult* res, // TODO: handle change } +Glib::RefPtr waybar::modules::SNI::Item::extractPixBuf( + GVariant* variant) +{ + GVariantIter* it; + g_variant_get(variant, "a(iiay)", &it); + if (it == nullptr) { + return Glib::RefPtr{}; + } + GVariant* val; + gint lwidth = 0; + gint lheight = 0; + gint width; + gint height; + guchar* array = nullptr; + while (g_variant_iter_loop(it, "(ii@ay)", &width, &height, &val)) { + if (width > 0 && height > 0 && val != nullptr + && width * height > lwidth * lheight) { + auto size = g_variant_get_size(val); + /* Sanity check */ + if (size == 4U * width * height) { + /* Find the largest image */ + gconstpointer data = g_variant_get_data(val); + if (data != nullptr) { + if (array != nullptr) { + g_free(array); + } + array = static_cast(g_memdup(data, size)); + lwidth = width; + lheight = height; + } + } + } + } + g_variant_iter_free(it); + if (array != nullptr) { + /* argb to rgba */ + for (uint32_t i = 0; i < 4U * lwidth * lheight; i += 4) { + guchar alpha = array[i]; + array[i] = array[i + 1]; + array[i + 1] = array[i + 2]; + array[i + 2] = array[i + 3]; + array[i + 3] = alpha; + } + return Gdk::Pixbuf::create_from_data(array, Gdk::Colorspace::COLORSPACE_RGB, + true, 8, lwidth, lheight, 4 * lwidth); + } + return Glib::RefPtr{}; +} + void waybar::modules::SNI::Item::updateImage() { if (!icon_name.empty()) { @@ -131,6 +181,8 @@ void waybar::modules::SNI::Item::updateImage() pixbuf = getIconByName("image-missing", icon_size); } image->set(pixbuf); + } else if (icon_pixmap) { + image->set(icon_pixmap); } else { image->set_from_icon_name("image-missing", Gtk::ICON_SIZE_MENU); image->set_pixel_size(icon_size);