Merge pull request #4826 from AntGarSil/agd/ignore-tray-applets

feat (tray): Ignore Tray items by service name and when dbus properties load
This commit is contained in:
Alexis Rouillard
2026-07-03 23:42:51 +02:00
committed by GitHub
4 changed files with 102 additions and 7 deletions
+5 -1
View File
@@ -14,11 +14,14 @@ namespace waybar::modules::SNI {
class Host {
public:
Host(const std::size_t id, const Json::Value&, const Bar&,
Host(const std::size_t id, const Json::Value&, const Bar&, const std::vector<std::string>&,
const std::function<void(std::unique_ptr<Item>&)>&,
const std::function<void(std::unique_ptr<Item>&)>&, const std::function<void()>&);
~Host();
void checkIgnoreList(const std::vector<std::string>& ignore_list,
const std::function<void(std::unique_ptr<Item>&)>& on_remove);
private:
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
void nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring,
@@ -47,6 +50,7 @@ class Host {
unsigned retry_count_ = 0;
const Json::Value& config_;
const Bar& bar_;
const std::vector<std::string> ignore_list_;
const std::function<void(std::unique_ptr<Item>&)> on_add_;
const std::function<void(std::unique_ptr<Item>&)> on_remove_;
const std::function<void()> on_update_;
+3
View File
@@ -19,11 +19,14 @@ class Tray : public AModule {
private:
void onAdd(std::unique_ptr<Item>& item);
void onRemove(std::unique_ptr<Item>& item);
void checkIgnoreList(std::unique_ptr<Item>* item);
std::vector<std::string> parseIgnoreList(const Json::Value& config);
void queueUpdate();
static inline std::size_t nb_hosts_ = 0;
Gtk::Box box_;
SNI::Watcher::singleton watcher_;
std::vector<std::string> ignore_list_;
SNI::Host host_;
};
+57 -5
View File
@@ -10,6 +10,7 @@ static const unsigned RETRY_DELAY_MS = 200;
static const unsigned MAX_RETRIES = 10;
Host::Host(const std::size_t id, const Json::Value& config, const Bar& bar,
const std::vector<std::string>& ignore_list,
const std::function<void(std::unique_ptr<Item>&)>& on_add,
const std::function<void(std::unique_ptr<Item>&)>& on_remove,
const std::function<void()>& on_update)
@@ -20,6 +21,7 @@ Host::Host(const std::size_t id, const Json::Value& config, const Bar& bar,
sigc::mem_fun(*this, &Host::busAcquired))),
config_(config),
bar_(bar),
ignore_list_(ignore_list),
on_add_(on_add),
on_remove_(on_remove),
on_update_(on_update) {}
@@ -39,6 +41,42 @@ Host::~Host() {
g_clear_object(&watcher_);
}
void Host::checkIgnoreList(const std::vector<std::string>& ignore_list,
const std::function<void(std::unique_ptr<Item>&)>& on_remove) {
spdlog::debug("Host::checkIgnoreList - checking {} items against {} patterns", items_.size(),
ignore_list.size());
for (auto it = items_.begin(); it != items_.end();) {
auto& item = *it;
spdlog::debug(" Checking item: bus_name='{}', category='{}', icon_name='{}', title='{}'",
item->bus_name, item->category, item->icon_name, item->title);
bool should_remove = false;
for (const auto& ignored : ignore_list) {
if (item->bus_name.find(ignored) != std::string::npos ||
item->category.find(ignored) != std::string::npos ||
item->icon_name.find(ignored) != std::string::npos ||
item->id.find(ignored) != std::string::npos ||
item->title.find(ignored) != std::string::npos) {
spdlog::info(
"Host: Ignoring item bus_name='{}', category='{}', icon_name='{}', title='{}' - "
"matched pattern '{}'",
item->bus_name, item->category, item->icon_name, item->title, ignored);
on_remove(item);
should_remove = true;
break;
}
}
if (should_remove) {
it = items_.erase(it);
} else {
++it;
}
}
}
void Host::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
watcher_id_ = Gio::DBus::watch_name(conn, "org.kde.StatusNotifierWatcher",
sigc::mem_fun(*this, &Host::nameAppeared),
@@ -82,7 +120,8 @@ void Host::proxyReady(GObject* src, GAsyncResult* res, gpointer data) {
spdlog::error("Host: {}", error->message);
g_clear_object(&host->cancellable_);
if (host->retry_count_ >= MAX_RETRIES) {
spdlog::warn("Host: giving up on watcher proxy creation after {} retries", host->retry_count_);
spdlog::warn("Host: giving up on watcher proxy creation after {} retries",
host->retry_count_);
return;
}
host->retry_count_ += 1;
@@ -127,7 +166,9 @@ void Host::registerHost(GObject* src, GAsyncResult* res, gpointer data) {
g_signal_connect(host->watcher_, "item-unregistered", G_CALLBACK(&Host::itemUnregistered), data);
auto items = sn_watcher_dup_registered_items(host->watcher_);
if (items != nullptr) {
spdlog::info("Host: Found {} pre-registered SNI items", g_strv_length(items));
for (uint32_t i = 0; items[i] != nullptr; i += 1) {
spdlog::info("Host: Processing pre-registered item: {}", items[i]);
host->addRegisteredItem(items[i]);
}
}
@@ -136,7 +177,10 @@ void Host::registerHost(GObject* src, GAsyncResult* res, gpointer data) {
void Host::itemRegistered(SnWatcher* watcher, const gchar* service, gpointer data) {
auto host = static_cast<SNI::Host*>(data);
spdlog::info("Host::itemRegistered called with service: {}", service);
host->addRegisteredItem(service);
// host->checkIgnoreList(host->ignore_list_, std::bind(&Host::itemUnregistered, host,
// std::placeholders::_1, std::placeholders::_2, data));
}
void Host::itemUnregistered(SnWatcher* watcher, const gchar* service, gpointer data) {
@@ -197,17 +241,25 @@ std::tuple<std::string, std::string> Host::getBusNameAndObjectPath(const std::st
}
void Host::addRegisteredItem(const std::string& service) {
// Check service string directly before parsing
for (const auto& ignored : ignore_list_) {
if (service.find(ignored) != std::string::npos) {
spdlog::info("Host: Ignoring service '{}' - matched pattern '{}'", service, ignored);
return;
}
}
std::string bus_name, object_path;
std::tie(bus_name, object_path) = getBusNameAndObjectPath(service);
spdlog::debug("SNI item registered: bus_name={}, object_path={}, full_service={}", bus_name,
object_path, service);
auto it = std::find_if(items_.begin(), items_.end(), [&bus_name, &object_path](const auto& item) {
return bus_name == item->bus_name && object_path == item->object_path;
});
if (it == items_.end()) {
spdlog::debug("Adding SNI item: {}", bus_name);
items_.emplace_back(std::make_unique<Item>(
bus_name, object_path, config_, bar_,
[this](Item& item) { itemReady(item); },
[this](Item& item) { itemInvalidated(item); },
on_update_));
bus_name, object_path, config_, bar_, [this](Item& item) { itemReady(item); },
[this](Item& item) { itemInvalidated(item); }, on_update_));
}
}
+37 -1
View File
@@ -8,11 +8,29 @@
namespace waybar::modules::SNI {
std::vector<std::string> Tray::parseIgnoreList(const Json::Value& config) {
std::vector<std::string> ignore_list;
if (config["ignore-list"].isArray()) {
spdlog::info("Tray: Found ignore-list with {} items", config["ignore-list"].size());
for (const auto& item : config["ignore-list"]) {
if (item.isString()) {
ignore_list.push_back(item.asString());
spdlog::info("Tray: Adding to ignore list: {}", item.asString());
}
}
} else {
spdlog::info("Tray: No ignore-list configured");
}
return ignore_list;
}
Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config)
: AModule(config, "tray", id),
box_(bar.orientation, 0),
watcher_(SNI::Watcher::getInstance()),
host_(nb_hosts_, config, bar, std::bind(&Tray::onAdd, this, std::placeholders::_1),
ignore_list_(parseIgnoreList(config)),
host_(nb_hosts_, config, bar, ignore_list_,
std::bind(&Tray::onAdd, this, std::placeholders::_1),
std::bind(&Tray::onRemove, this, std::placeholders::_1),
std::bind(&Tray::queueUpdate, this)) {
box_.set_name("tray");
@@ -31,14 +49,26 @@ Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config)
dp.emit();
}
void Tray::checkIgnoreList(std::unique_ptr<Item>* item_ptr) {
// Delegate to Host's checkIgnoreList method
host_.checkIgnoreList(ignore_list_, std::bind(&Tray::onRemove, this, std::placeholders::_1));
}
void Tray::queueUpdate() { dp.emit(); }
void Tray::onAdd(std::unique_ptr<Item>& item) {
spdlog::info("Tray::onAdd - item bus_name='{}', category='{}', icon_name='{}', title='{}'",
item->bus_name, item->category, item->icon_name, item->title);
if (config_["reverse-direction"].isBool() && config_["reverse-direction"].asBool()) {
box_.pack_end(item->event_box);
} else {
box_.pack_start(item->event_box);
}
spdlog::debug("Tray::onAdd deferred check - checking ignore list");
host_.checkIgnoreList(ignore_list_, std::bind(&Tray::onRemove, this, std::placeholders::_1));
item->event_box.signal_show().connect([this] { dp.emit(); });
item->event_box.signal_hide().connect([this] { dp.emit(); });
dp.emit();
@@ -50,6 +80,12 @@ void Tray::onRemove(std::unique_ptr<Item>& item) {
}
auto Tray::update() -> void {
// Check if any items should be ignored now that properties have loaded
if (!ignore_list_.empty()) {
spdlog::debug("Tray::update() - checking ignore list");
host_.checkIgnoreList(ignore_list_, std::bind(&Tray::onRemove, this, std::placeholders::_1));
}
std::vector<Gtk::Widget*> children = box_.get_children();
event_box_.set_visible(std::any_of(children.begin(), children.end(),
[](Gtk::Widget* child) { return child->get_visible(); }));