diff --git a/include/modules/sni/snh.hpp b/include/modules/sni/snh.hpp index 585f2888..e56950e1 100644 --- a/include/modules/sni/snh.hpp +++ b/include/modules/sni/snh.hpp @@ -1,6 +1,8 @@ #pragma once #include + +#include #include #include "modules/sni/sni.hpp" @@ -8,8 +10,7 @@ namespace waybar::modules::SNI { class Host { public: - Host(Glib::Dispatcher&); - ~Host(); + Host(Glib::Dispatcher*); std::vector items; private: static void busAcquired(GDBusConnection*, const gchar*, gpointer); @@ -23,14 +24,14 @@ class Host { static void itemUnregistered(SnOrgKdeStatusNotifierWatcher*, const gchar*, gpointer); - void getBusNameAndObjectPath(const gchar*, gchar**, gchar**); + std::tuple getBusNameAndObjectPath(const gchar*); void addRegisteredItem(const gchar* service); uint32_t bus_name_id_; uint32_t watcher_id_; std::string bus_name_; std::string object_path_; - Glib::Dispatcher& dp_; + Glib::Dispatcher* dp_; GCancellable* cancellable_ = nullptr; SnOrgKdeStatusNotifierWatcher* watcher_ = nullptr; }; diff --git a/include/modules/sni/sni.hpp b/include/modules/sni/sni.hpp index 60aee86a..5cf95138 100644 --- a/include/modules/sni/sni.hpp +++ b/include/modules/sni/sni.hpp @@ -1,42 +1,51 @@ #pragma once -#include #include +#include namespace waybar::modules::SNI { class Item { - public: - Item(std::string, std::string, Glib::Dispatcher&); - ~Item(); - int icon_size; - int effective_icon_size; - Gtk::Widget* widget = nullptr; - Gtk::Image* image = nullptr; - std::string category; - std::string id; - std::string status; +public: + Item(std::string, std::string, Glib::Dispatcher *); - std::string title; - int32_t window_id; - std::string icon_name; - std::string overlay_icon_name; - std::string attention_icon_name; - std::string attention_movie_name; - std::string icon_theme_path; - std::string menu; - bool item_is_menu; - private: - static void proxyReady(GObject* obj, GAsyncResult* res, gpointer data); - static void getAll(GObject* obj, GAsyncResult* res, gpointer data); + std::string bus_name; + std::string object_path; + Gtk::EventBox event_box; - void updateImage(); - Glib::RefPtr getIconByName(std::string name, int size); - std::string bus_name_; - std::string object_path_; - Glib::Dispatcher& dp_; - GCancellable* cancellable_ = nullptr; - SnOrgKdeStatusNotifierItem* proxy_ = nullptr; + int icon_size; + int effective_icon_size; + Gtk::Image *image; + Gtk::Menu *gtk_menu = nullptr; + std::string category; + std::string id; + std::string status; + + 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; + std::string icon_theme_path; + std::string menu; + bool item_is_menu; + +private: + static void proxyReady(GObject *obj, GAsyncResult *res, gpointer data); + static void getAll(GObject *obj, GAsyncResult *res, gpointer data); + static void handleActivate(GObject *, GAsyncResult *, gpointer); + static void handleSecondaryActivate(GObject *, GAsyncResult *, gpointer); + + void updateImage(); + Glib::RefPtr extractPixBuf(GVariant *variant); + Glib::RefPtr getIconByName(std::string name, int size); + bool handleClick(GdkEventButton *const & /*ev*/); + + Glib::Dispatcher *dp_; + GCancellable *cancellable_ = nullptr; + SnOrgKdeStatusNotifierItem *proxy_ = nullptr; }; -} +} // namespace waybar::modules::SNI diff --git a/include/modules/sni/snw.hpp b/include/modules/sni/snw.hpp index f8965e38..d67ef7ea 100644 --- a/include/modules/sni/snw.hpp +++ b/include/modules/sni/snw.hpp @@ -1,47 +1,46 @@ #pragma once -#include #include +#include namespace waybar::modules::SNI { -typedef enum { - GF_WATCH_TYPE_HOST, - GF_WATCH_TYPE_ITEM -} GfWatchType; - -typedef struct { - GfWatchType type; - gchar* service; - gchar* bus_name; - gchar* object_path; - guint watch_id; -} GfWatch; - class Watcher { - public: - Watcher(); - ~Watcher(); - private: - static void busAcquired(GDBusConnection*, const gchar*, gpointer); - static gboolean handleRegisterHost(Watcher*, - GDBusMethodInvocation*, const gchar*); - static gboolean handleRegisterItem(Watcher*, - GDBusMethodInvocation*, const gchar*); - static GfWatch* gfWatchFind(GSList* list, const gchar* bus_name, - const gchar* object_path); - static GfWatch* gfWatchNew(GfWatchType type, - const gchar* service, const gchar* bus_name, const gchar* object_path); - static void nameVanished(GDBusConnection* connection, const char* name, - gpointer data); +public: + Watcher(); + ~Watcher(); - void updateRegisteredItems(SnOrgKdeStatusNotifierWatcher* obj); +private: + typedef enum { GF_WATCH_TYPE_HOST, GF_WATCH_TYPE_ITEM } GfWatchType; - uint32_t bus_name_id_; - uint32_t watcher_id_; - GSList* hosts_ = nullptr; - GSList* items_ = nullptr; - SnOrgKdeStatusNotifierWatcher *watcher_ = nullptr; + typedef struct { + GfWatchType type; + Watcher *watcher; + gchar *service; + gchar *bus_name; + gchar *object_path; + guint watch_id; + } GfWatch; + + static void busAcquired(GDBusConnection *, const gchar *, gpointer); + static gboolean handleRegisterHost(Watcher *, GDBusMethodInvocation *, + const gchar *); + static gboolean handleRegisterItem(Watcher *, GDBusMethodInvocation *, + const gchar *); + static GfWatch *gfWatchFind(GSList *list, const gchar *bus_name, + const gchar *object_path); + static GfWatch *gfWatchNew(GfWatchType, const gchar *, const gchar *, + const gchar *, Watcher *); + static void nameVanished(GDBusConnection *connection, const char *name, + gpointer data); + + void updateRegisteredItems(SnOrgKdeStatusNotifierWatcher *obj); + + uint32_t bus_name_id_; + uint32_t watcher_id_; + GSList *hosts_ = nullptr; + GSList *items_ = nullptr; + SnOrgKdeStatusNotifierWatcher *watcher_ = nullptr; }; -} +} // namespace waybar::modules::SNI diff --git a/protocol/meson.build b/protocol/meson.build index 17fe3264..01cb771b 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -54,14 +54,10 @@ client_protos_headers += gdbus_header.process('./dbus-status-notifier-watcher.xm client_protos_src += gdbus_code.process('./dbus-status-notifier-item.xml') client_protos_headers += gdbus_header.process('./dbus-status-notifier-item.xml') -client_protos_src += gdbus_code.process('./dbus-menu.xml') -client_protos_headers += gdbus_header.process('./dbus-menu.xml') - lib_client_protos = static_library( 'client_protos', client_protos_src + client_protos_headers, - dependencies: [wayland_client, gtkmm], - include_directories: include_directories('..'), + dependencies: [wayland_client, gtkmm] ) # for the include directory client_protos = declare_dependency( diff --git a/resources/style.css b/resources/style.css index a3538d48..d15c8947 100644 --- a/resources/style.css +++ b/resources/style.css @@ -5,7 +5,7 @@ font-size: 13px; } -window { +window#waybar { background: rgba(43, 48, 59, 0.5); border-bottom: 3px solid rgba(100, 114, 125, 0.5); color: white; @@ -93,4 +93,4 @@ window { #tray { background-color: #2980b9; -} \ No newline at end of file +} diff --git a/src/bar.cpp b/src/bar.cpp index 750816ca..406a86d6 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -21,6 +21,7 @@ waybar::Bar::Bar(const Client& client, zxdg_output_v1_add_listener(xdg_output_, &xdgOutputListener, this); window.set_title("waybar"); window.set_decorated(false); + window.set_name("waybar"); setupConfig(); setupCss(); setupWidgets(); @@ -198,14 +199,14 @@ auto waybar::Bar::setupWidgets() -> void getModules(factory, "modules-left"); getModules(factory, "modules-center"); getModules(factory, "modules-right"); - for (auto& module : modules_left_) { + for (auto const& module : modules_left_) { left.pack_start(*module, false, true, 0); } - for (auto& module : modules_center_) { + for (auto const& module : modules_center_) { center.pack_start(*module, true, true, 0); } std::reverse(modules_right_.begin(), modules_right_.end()); - for (auto& module : modules_right_) { + for (auto const& module : modules_right_) { right.pack_end(*module, false, false, 0); } } diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 78470e77..002b8ed5 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -4,7 +4,7 @@ waybar::modules::Battery::Battery(const Json::Value& config) : ALabel(config, "{capacity}%") { try { - for (auto &node : fs::directory_iterator(data_dir_)) { + for (auto const& node : fs::directory_iterator(data_dir_)) { if (fs::is_directory(node) && fs::exists(node / "capacity") && fs::exists(node / "status") && fs::exists(node / "uevent")) { batteries_.push_back(node); @@ -20,7 +20,7 @@ waybar::modules::Battery::Battery(const Json::Value& config) if (fd_ == -1) { throw std::runtime_error("Unable to listen batteries."); } - for (auto &bat : batteries_) { + for (auto const& bat : batteries_) { inotify_add_watch(fd_, (bat / "uevent").c_str(), IN_ACCESS); } label_.set_name("battery"); @@ -51,7 +51,7 @@ auto waybar::modules::Battery::update() -> void try { uint16_t total = 0; std::string status; - for (auto &bat : batteries_) { + for (auto const& bat : batteries_) { uint16_t capacity; std::string _status; std::ifstream(bat / "capacity") >> capacity; diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index 4d41fd56..3e59a675 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -118,7 +118,7 @@ const std::string waybar::modules::Pulseaudio::getPortIcon() const "hifi", "phone", }; - for (auto port : ports) { + for (auto const& port : ports) { if (port_name_.find(port) != std::string::npos) { return port; } diff --git a/src/modules/sni/snh.cpp b/src/modules/sni/snh.cpp index 8bef40f1..74abf2e0 100644 --- a/src/modules/sni/snh.cpp +++ b/src/modules/sni/snh.cpp @@ -2,7 +2,9 @@ #include -waybar::modules::SNI::Host::Host(Glib::Dispatcher& dp) +using namespace waybar::modules::SNI; + +Host::Host(Glib::Dispatcher* dp) : dp_(dp) { GBusNameOwnerFlags flags = static_cast( @@ -14,11 +16,7 @@ waybar::modules::SNI::Host::Host(Glib::Dispatcher& dp) &Host::busAcquired, nullptr, nullptr, this, nullptr); } -waybar::modules::SNI::Host::~Host() -{ -} - -void waybar::modules::SNI::Host::busAcquired(GDBusConnection* connection, +void Host::busAcquired(GDBusConnection* connection, const gchar* name, gpointer data) { auto host = static_cast(data); @@ -29,7 +27,7 @@ void waybar::modules::SNI::Host::busAcquired(GDBusConnection* connection, &Host::nameAppeared, &Host::nameVanished, data, nullptr); } -void waybar::modules::SNI::Host::nameAppeared(GDBusConnection* connection, +void Host::nameAppeared(GDBusConnection* connection, const gchar* name, const gchar* name_owner, gpointer data) { auto host = static_cast(data); @@ -45,7 +43,7 @@ void waybar::modules::SNI::Host::nameAppeared(GDBusConnection* connection, host->cancellable_, &Host::proxyReady, data); } -void waybar::modules::SNI::Host::nameVanished(GDBusConnection* connection, +void Host::nameVanished(GDBusConnection* connection, const gchar* name, gpointer data) { auto host = static_cast(data); @@ -55,7 +53,7 @@ void waybar::modules::SNI::Host::nameVanished(GDBusConnection* connection, host->items.clear(); } -void waybar::modules::SNI::Host::proxyReady(GObject* src, GAsyncResult* res, +void Host::proxyReady(GObject* src, GAsyncResult* res, gpointer data) { GError* error = nullptr; @@ -78,7 +76,7 @@ void waybar::modules::SNI::Host::proxyReady(GObject* src, GAsyncResult* res, &Host::registerHost, data); } -void waybar::modules::SNI::Host::registerHost(GObject* src, GAsyncResult* res, +void Host::registerHost(GObject* src, GAsyncResult* res, gpointer data) { GError* error = nullptr; @@ -109,7 +107,7 @@ void waybar::modules::SNI::Host::registerHost(GObject* src, GAsyncResult* res, g_strfreev(items); } -void waybar::modules::SNI::Host::itemRegistered( +void Host::itemRegistered( SnOrgKdeStatusNotifierWatcher* watcher, const gchar* service, gpointer data) { std::cout << "Item registered" << std::endl; @@ -117,32 +115,41 @@ void waybar::modules::SNI::Host::itemRegistered( host->addRegisteredItem(service); } -void waybar::modules::SNI::Host::itemUnregistered( +void Host::itemUnregistered( SnOrgKdeStatusNotifierWatcher* watcher, const gchar* service, gpointer data) { - std::cout << "Item Unregistered" << std::endl; + auto host = static_cast(data); + auto [bus_name, object_path] = host->getBusNameAndObjectPath(service); + for (auto it = host->items.begin(); it != host->items.end(); ++it) { + if (it->bus_name == bus_name && it->object_path == object_path) { + host->items.erase(it); + std::cout << "Item Unregistered" << std::endl; + break; + } + } + host->dp_->emit(); } -void waybar::modules::SNI::Host::getBusNameAndObjectPath(const gchar* service, - gchar** bus_name, gchar** object_path) +std::tuple Host::getBusNameAndObjectPath( + const gchar* service) { - gchar* tmp = g_strstr_len (service, -1, "/"); + std::string bus_name; + std::string object_path; + gchar* tmp = g_strstr_len(service, -1, "/"); if (tmp != nullptr) { gchar** str = g_strsplit(service, "/", 2); - *bus_name = g_strdup(str[0]); - *object_path = g_strdup(tmp); + bus_name = str[0]; + object_path = tmp; g_strfreev(str); } else { - *bus_name = g_strdup(service); - *object_path = g_strdup("/StatusNotifierItem"); + bus_name = service; + object_path = "/StatusNotifierItem"; } + return { bus_name, object_path }; } -void waybar::modules::SNI::Host::addRegisteredItem(const gchar* service) +void Host::addRegisteredItem(const gchar* service) { - gchar* bus_name = nullptr; - gchar* object_path = nullptr; - - getBusNameAndObjectPath(service, &bus_name, &object_path); + auto [bus_name, object_path] = getBusNameAndObjectPath(service); items.emplace_back(bus_name, object_path, dp_); } diff --git a/src/modules/sni/sni.cpp b/src/modules/sni/sni.cpp index 60dd51b8..6f5837b0 100644 --- a/src/modules/sni/sni.cpp +++ b/src/modules/sni/sni.cpp @@ -1,22 +1,22 @@ #include "modules/sni/sni.hpp" +#include #include -#include - -waybar::modules::SNI::Item::Item(std::string bus_name, std::string object_path, - Glib::Dispatcher &dp) - : icon_size(16), effective_icon_size(0), - image(Gtk::manage(new Gtk::Image())), bus_name_(bus_name), - object_path_(object_path), dp_(dp) { +waybar::modules::SNI::Item::Item(std::string bn, std::string op, + Glib::Dispatcher *dp) + : bus_name(bn), object_path(op), event_box(), icon_size(16), + effective_icon_size(0), image(Gtk::manage(new Gtk::Image())), dp_(dp) { + event_box.add(*image); + event_box.add_events(Gdk::BUTTON_PRESS_MASK); + event_box.signal_button_press_event().connect( + sigc::mem_fun(*this, &Item::handleClick)); cancellable_ = g_cancellable_new(); sn_org_kde_status_notifier_item_proxy_new_for_bus( - G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, bus_name_.c_str(), - object_path_.c_str(), cancellable_, &Item::proxyReady, this); + G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, bus_name.c_str(), + object_path.c_str(), cancellable_, &Item::proxyReady, this); } -waybar::modules::SNI::Item::~Item() {} - void waybar::modules::SNI::Item::proxyReady(GObject *obj, GAsyncResult *res, gpointer data) { GError *error = nullptr; @@ -34,20 +34,15 @@ void waybar::modules::SNI::Item::proxyReady(GObject *obj, GAsyncResult *res, return; } auto conn = g_dbus_proxy_get_connection(G_DBUS_PROXY(proxy)); - g_dbus_connection_call(conn, item->bus_name_.c_str(), - item->object_path_.c_str(), + + g_dbus_connection_call(conn, item->bus_name.c_str(), + item->object_path.c_str(), "org.freedesktop.DBus.Properties", "GetAll", g_variant_new("(s)", "org.kde.StatusNotifierItem"), G_VARIANT_TYPE("(a{sv})"), G_DBUS_CALL_FLAGS_NONE, -1, item->cancellable_, &Item::getAll, data); } -static auto nonull(const char *c) { - if (c != nullptr) - return c; - return ""; -} - void waybar::modules::SNI::Item::getAll(GObject *obj, GAsyncResult *res, gpointer data) { GError *error = nullptr; @@ -69,35 +64,35 @@ void waybar::modules::SNI::Item::getAll(GObject *obj, GAsyncResult *res, GVariant *value; while (g_variant_iter_next(it, "{sv}", &key, &value)) { if (g_strcmp0(key, "Category") == 0) { - item->category = nonull(g_variant_dup_string(value, nullptr)); + item->category = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "Id") == 0) { - item->id = nonull(g_variant_dup_string(value, nullptr)); + item->id = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "Title") == 0) { - item->title = nonull(g_variant_dup_string(value, nullptr)); + item->title = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "Status") == 0) { - item->status = nonull(g_variant_dup_string(value, nullptr)); + item->status = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "WindowId") == 0) { item->window_id = g_variant_get_int32(value); } else if (g_strcmp0(key, "IconName") == 0) { - item->icon_name = nonull(g_variant_dup_string(value, nullptr)); + item->icon_name = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "IconPixmap") == 0) { - // TODO: icon pixmap + item->icon_pixmap = item->extractPixBuf(value); } else if (g_strcmp0(key, "OverlayIconName") == 0) { - item->overlay_icon_name = nonull(g_variant_dup_string(value, nullptr)); + item->overlay_icon_name = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "OverlayIconPixmap") == 0) { // TODO: overlay_icon_pixmap } else if (g_strcmp0(key, "AttentionIconName") == 0) { - item->attention_icon_name = nonull(g_variant_dup_string(value, nullptr)); + item->attention_icon_name = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "AttentionIconPixmap") == 0) { // TODO: attention_icon_pixmap } else if (g_strcmp0(key, "AttentionMovieName") == 0) { - item->attention_movie_name = nonull(g_variant_dup_string(value, nullptr)); + item->attention_movie_name = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "ToolTip") == 0) { // TODO: tooltip } else if (g_strcmp0(key, "IconThemePath") == 0) { - item->icon_theme_path = nonull(g_variant_dup_string(value, nullptr)); + item->icon_theme_path = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "Menu") == 0) { - item->menu = nonull(g_variant_dup_string(value, nullptr)); + item->menu = g_variant_dup_string(value, nullptr); } else if (g_strcmp0(key, "ItemIsMenu") == 0) { item->item_is_menu = g_variant_get_boolean(value); } @@ -107,8 +102,8 @@ void waybar::modules::SNI::Item::getAll(GObject *obj, GAsyncResult *res, g_variant_iter_free(it); g_variant_unref(properties); if (item->id.empty() || item->category.empty() || item->status.empty()) { - std::cerr << "Invalid Status Notifier Item: " + item->bus_name_ + "," + - item->object_path_ + std::cerr << "Invalid Status Notifier Item: " + item->bus_name + "," + + item->object_path << std::endl; return; } @@ -118,10 +113,58 @@ void waybar::modules::SNI::Item::getAll(GObject *obj, GAsyncResult *res, item->icon_theme_path.c_str()); } item->updateImage(); - item->dp_.emit(); + item->dp_->emit(); // 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()) { auto pixbuf = getIconByName(icon_name, icon_size); @@ -144,34 +187,16 @@ 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); } - auto *evt_box = Gtk::manage(new Gtk::EventBox()); - evt_box->add(*image); - widget = evt_box; if (!menu.empty()) { - auto *dbmenu = dbusmenu_gtkmenu_new(bus_name_.data(), menu.data()); - Gtk::Menu *dmenu = Glib::wrap(GTK_MENU(dbmenu), false); - if (dbmenu && dmenu) { - widget->signal_button_press_event().connect( - [this, dmenu](GdkEventButton *btn) { - if (!dmenu->get_parent()) { - dmenu->reparent(*image); - } - if (!dmenu->get_attach_widget()) { - dmenu->attach_to_widget(*widget); - } - dmenu->popup(btn->button, btn->time); - return true; - }); - } - } else { - widget->signal_button_press_event().connect([this](GdkEventButton *btn) { - std::cout << this->menu << std::endl; - return true; - }); + auto *dbmenu = dbusmenu_gtkmenu_new(bus_name.data(), menu.data()); + if (dbmenu) + gtk_menu = Glib::wrap(GTK_MENU(dbmenu), false); } } @@ -181,7 +206,8 @@ waybar::modules::SNI::Item::getIconByName(std::string name, int request_size) { Glib::RefPtr icon_theme = Gtk::IconTheme::get_default(); icon_theme->rescan_if_needed(); auto sizes = icon_theme->get_icon_sizes(name.c_str()); - for (auto size : sizes) { + + for (auto const &size : sizes) { // -1 == scalable if (size == request_size || size == -1) { icon_size = request_size; @@ -196,3 +222,38 @@ waybar::modules::SNI::Item::getIconByName(std::string name, int request_size) { return icon_theme->load_icon(name.c_str(), icon_size, Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE); } + +void waybar::modules::SNI::Item::handleActivate(GObject *src, GAsyncResult *res, + gpointer data) { + auto item = static_cast(data); + sn_org_kde_status_notifier_item_call_activate_finish(item->proxy_, res, + nullptr); +} + +void waybar::modules::SNI::Item::handleSecondaryActivate(GObject *src, + GAsyncResult *res, + gpointer data) { + auto item = static_cast(data); + sn_org_kde_status_notifier_item_call_secondary_activate_finish(item->proxy_, + res, nullptr); +} + +bool waybar::modules::SNI::Item::handleClick(GdkEventButton *const &ev) { + if (ev->type == GDK_BUTTON_PRESS) { + if (gtk_menu) { + if (!gtk_menu->get_attach_widget()) { + gtk_menu->attach_to_widget(event_box); + } + gtk_menu->popup(ev->button, ev->time); + } else { + sn_org_kde_status_notifier_item_call_activate( + proxy_, ev->x, ev->y, nullptr, &Item::handleActivate, this); + } + } else if (ev->type == GDK_2BUTTON_PRESS) { + sn_org_kde_status_notifier_item_call_secondary_activate( + proxy_, ev->x, ev->y, nullptr, &Item::handleSecondaryActivate, this); + } else { + return false; + } + return true; +} diff --git a/src/modules/sni/snw.cpp b/src/modules/sni/snw.cpp index 3ec33ae0..6db5d710 100644 --- a/src/modules/sni/snw.cpp +++ b/src/modules/sni/snw.cpp @@ -2,7 +2,10 @@ #include -waybar::modules::SNI::Watcher::Watcher() + +using namespace waybar::modules::SNI; + +Watcher::Watcher() { GBusNameOwnerFlags flags = static_cast( G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT @@ -13,12 +16,12 @@ waybar::modules::SNI::Watcher::Watcher() watcher_ = sn_org_kde_status_notifier_watcher_skeleton_new(); } -waybar::modules::SNI::Watcher::~Watcher() +Watcher::~Watcher() { } -void waybar::modules::SNI::Watcher::busAcquired(GDBusConnection* connection, - const gchar* name, gpointer data) +void Watcher::busAcquired(GDBusConnection* connection, const gchar* name, + gpointer data) { GError* error = nullptr; auto host = static_cast(data); @@ -41,9 +44,9 @@ void waybar::modules::SNI::Watcher::busAcquired(GDBusConnection* connection, std::cout << "Bus aquired" << std::endl; } -gboolean waybar::modules::SNI::Watcher::handleRegisterHost( - Watcher* obj, GDBusMethodInvocation* invocation, - const gchar* service) + +gboolean Watcher::handleRegisterHost(Watcher* obj, + GDBusMethodInvocation* invocation, const gchar* service) { const gchar* bus_name = service; const gchar* object_path = "/StatusNotifierHost"; @@ -64,7 +67,7 @@ gboolean waybar::modules::SNI::Watcher::handleRegisterHost( bus_name, object_path); return TRUE; } - watch = gfWatchNew(GF_WATCH_TYPE_HOST, service, bus_name, object_path); + watch = gfWatchNew(GF_WATCH_TYPE_HOST, service, bus_name, object_path, obj); obj->hosts_ = g_slist_prepend(obj->hosts_, watch); sn_org_kde_status_notifier_watcher_set_is_status_notifier_host_registered( obj->watcher_, TRUE); @@ -78,9 +81,8 @@ gboolean waybar::modules::SNI::Watcher::handleRegisterHost( return TRUE; } -gboolean waybar::modules::SNI::Watcher::handleRegisterItem( - Watcher* obj, GDBusMethodInvocation* invocation, - const gchar* service) +gboolean Watcher::handleRegisterItem(Watcher* obj, + GDBusMethodInvocation* invocation, const gchar* service) { const gchar* bus_name = service; const gchar* object_path = "/StatusNotifierItem"; @@ -102,7 +104,7 @@ gboolean waybar::modules::SNI::Watcher::handleRegisterItem( obj->watcher_, invocation); return TRUE; } - watch = gfWatchNew(GF_WATCH_TYPE_ITEM, service, bus_name, object_path); + watch = gfWatchNew(GF_WATCH_TYPE_ITEM, service, bus_name, object_path, obj); obj->items_ = g_slist_prepend(obj->items_, watch); obj->updateRegisteredItems(obj->watcher_); gchar* tmp = g_strdup_printf("%s%s", bus_name, object_path); @@ -114,8 +116,8 @@ gboolean waybar::modules::SNI::Watcher::handleRegisterItem( return TRUE; } -waybar::modules::SNI::GfWatch* waybar::modules::SNI::Watcher::gfWatchFind( - GSList* list, const gchar* bus_name, const gchar* object_path) +Watcher::GfWatch* Watcher::gfWatchFind(GSList* list, const gchar* bus_name, + const gchar* object_path) { for (GSList* l = list; l != nullptr; l = g_slist_next (l)) { GfWatch* watch = static_cast(l->data); @@ -127,12 +129,12 @@ waybar::modules::SNI::GfWatch* waybar::modules::SNI::Watcher::gfWatchFind( return nullptr; } -waybar::modules::SNI::GfWatch* waybar::modules::SNI::Watcher::gfWatchNew( - GfWatchType type, const gchar* service, const gchar* bus_name, - const gchar* object_path) +Watcher::GfWatch* Watcher::gfWatchNew(GfWatchType type, const gchar* service, + const gchar* bus_name, const gchar* object_path, Watcher* watcher) { GfWatch* watch = g_new0(GfWatch, 1); watch->type = type; + watch->watcher = watcher; watch->service = g_strdup(service); watch->bus_name = g_strdup(bus_name); watch->object_path = g_strdup(object_path); @@ -142,26 +144,40 @@ waybar::modules::SNI::GfWatch* waybar::modules::SNI::Watcher::gfWatchNew( return watch; } -void waybar::modules::SNI::Watcher::nameVanished(GDBusConnection* connection, - const char* name, gpointer data) +void Watcher::nameVanished(GDBusConnection* connection, const char* name, + gpointer data) { - //TODO - std::cout << "name vanished" << std::endl; + auto watch = static_cast(data); + if (watch->type == GF_WATCH_TYPE_HOST) { + watch->watcher->hosts_ = g_slist_remove(watch->watcher->hosts_, watch); + if (watch->watcher->hosts_ == nullptr) { + sn_org_kde_status_notifier_watcher_set_is_status_notifier_host_registered( + watch->watcher->watcher_, FALSE); + sn_org_kde_status_notifier_watcher_emit_status_notifier_host_registered( + watch->watcher->watcher_); + } + } else if (watch->type == GF_WATCH_TYPE_ITEM) { + watch->watcher->items_ = g_slist_remove(watch->watcher->items_, watch); + watch->watcher->updateRegisteredItems(watch->watcher->watcher_); + gchar* tmp = g_strdup_printf("%s%s", watch->bus_name, watch->object_path); + sn_org_kde_status_notifier_watcher_emit_status_notifier_item_unregistered( + watch->watcher->watcher_, tmp); + g_free(tmp); + } } -void waybar::modules::SNI::Watcher::updateRegisteredItems( - SnOrgKdeStatusNotifierWatcher* obj) +void Watcher::updateRegisteredItems(SnOrgKdeStatusNotifierWatcher* obj) { GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE("as")); for (GSList* l = items_; l != nullptr; l = g_slist_next(l)) { GfWatch* watch = static_cast(l->data); - gchar* item = g_strdup_printf ("%s%s", watch->bus_name, watch->object_path); - g_variant_builder_add (&builder, "s", item); - g_free (item); + gchar* item = g_strdup_printf("%s%s", watch->bus_name, watch->object_path); + g_variant_builder_add(&builder, "s", item); + g_free(item); } GVariant* variant = g_variant_builder_end(&builder); - const gchar** items = g_variant_get_strv (variant, nullptr); + const gchar** items = g_variant_get_strv(variant, nullptr); sn_org_kde_status_notifier_watcher_set_registered_status_notifier_items( obj, items); g_variant_unref(variant); diff --git a/src/modules/sni/tray.cpp b/src/modules/sni/tray.cpp index e0414179..92d2b189 100644 --- a/src/modules/sni/tray.cpp +++ b/src/modules/sni/tray.cpp @@ -3,14 +3,12 @@ #include waybar::modules::SNI::Tray::Tray(const Json::Value &config) - : config_(config), watcher_(), host_(dp) {} + : config_(config), watcher_(), host_(&dp) {} auto waybar::modules::SNI::Tray::update() -> void { - for (auto item : host_.items) { - if (item.widget) { - item.widget->set_tooltip_text(item.title); - box_.pack_start(*item.widget); - } + for (auto &item : host_.items) { + item.event_box.set_tooltip_text(item.title); + box_.pack_start(item.event_box); } if (box_.get_children().size() > 0) { box_.set_name("tray"); diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp index a2f4469b..8faf7491 100644 --- a/src/modules/sway/window.cpp +++ b/src/modules/sway/window.cpp @@ -44,7 +44,7 @@ auto waybar::modules::sway::Window::update() -> void std::tuple waybar::modules::sway::Window::getFocusedNode( Json::Value nodes) { - for (auto &node : nodes) { + for (auto const& node : nodes) { if (node["focused"].asBool() && node["type"] == "con") { return { node["id"].asInt(), node["name"].asString() }; } diff --git a/src/modules/sway/workspaces.cpp b/src/modules/sway/workspaces.cpp index 3e74801b..878f783c 100644 --- a/src/modules/sway/workspaces.cpp +++ b/src/modules/sway/workspaces.cpp @@ -49,7 +49,7 @@ auto waybar::modules::sway::Workspaces::update() -> void ++it; } } - for (auto node : workspaces_) { + for (auto const& node : workspaces_) { if (!config_["all-outputs"].asBool() && bar_.output_name != node["output"].asString()) { continue;