Merge remote-tracking branch 'origin/master' into agd/ignore-tray-applets
# Conflicts: # include/modules/sni/tray.hpp # src/modules/sni/host.cpp # src/modules/sni/tray.cpp
This commit is contained in:
+93
-22
@@ -6,10 +6,14 @@
|
||||
|
||||
namespace waybar::modules::SNI {
|
||||
|
||||
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(std::unique_ptr<Item>&)>& on_remove,
|
||||
const std::function<void()>& on_update)
|
||||
: bus_name_("org.kde.StatusNotifierHost-" + std::to_string(getpid()) + "-" +
|
||||
std::to_string(id)),
|
||||
object_path_("/StatusNotifierHost/" + std::to_string(id)),
|
||||
@@ -19,9 +23,11 @@ Host::Host(const std::size_t id, const Json::Value& config, const Bar& bar,
|
||||
bar_(bar),
|
||||
ignore_list_(ignore_list),
|
||||
on_add_(on_add),
|
||||
on_remove_(on_remove) {}
|
||||
on_remove_(on_remove),
|
||||
on_update_(on_update) {}
|
||||
|
||||
Host::~Host() {
|
||||
retry_connection_.disconnect();
|
||||
if (bus_name_id_ > 0) {
|
||||
Gio::DBus::unown_name(bus_name_id_);
|
||||
bus_name_id_ = 0;
|
||||
@@ -37,29 +43,32 @@ Host::~Host() {
|
||||
|
||||
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(); ) {
|
||||
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='{}'",
|
||||
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);
|
||||
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 {
|
||||
@@ -86,15 +95,17 @@ void Host::nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>& conn, const G
|
||||
}
|
||||
|
||||
void Host::nameVanished(const Glib::RefPtr<Gio::DBus::Connection>& conn, const Glib::ustring name) {
|
||||
retry_connection_.disconnect();
|
||||
retry_count_ = 0;
|
||||
g_cancellable_cancel(cancellable_);
|
||||
g_clear_object(&cancellable_);
|
||||
g_clear_object(&watcher_);
|
||||
items_.clear();
|
||||
clearItems();
|
||||
}
|
||||
|
||||
void Host::proxyReady(GObject* src, GAsyncResult* res, gpointer data) {
|
||||
GError* error = nullptr;
|
||||
waybar::util::ScopeGuard error_deleter([error]() {
|
||||
waybar::util::ScopeGuard error_deleter([&error]() {
|
||||
if (error != nullptr) {
|
||||
g_error_free(error);
|
||||
}
|
||||
@@ -105,18 +116,38 @@ void Host::proxyReady(GObject* src, GAsyncResult* res, gpointer data) {
|
||||
return;
|
||||
}
|
||||
auto host = static_cast<SNI::Host*>(data);
|
||||
host->watcher_ = watcher;
|
||||
if (error != nullptr) {
|
||||
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_);
|
||||
return;
|
||||
}
|
||||
host->retry_count_ += 1;
|
||||
// Store the timeout connection so it is disconnected in ~Host, avoiding a
|
||||
// use-after-free if the Host is destroyed before the retry fires.
|
||||
host->retry_connection_ = Glib::signal_timeout().connect(
|
||||
[host]() {
|
||||
if (host->watcher_ != nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto conn = Gio::DBus::Connection::get_sync(Gio::DBus::BusType::BUS_TYPE_SESSION);
|
||||
host->nameAppeared(conn, "org.kde.StatusNotifierWatcher", "");
|
||||
return false;
|
||||
},
|
||||
RETRY_DELAY_MS);
|
||||
return;
|
||||
}
|
||||
host->retry_count_ = 0;
|
||||
host->watcher_ = watcher;
|
||||
sn_watcher_call_register_host(host->watcher_, host->object_path_.c_str(), host->cancellable_,
|
||||
&Host::registerHost, data);
|
||||
}
|
||||
|
||||
void Host::registerHost(GObject* src, GAsyncResult* res, gpointer data) {
|
||||
GError* error = nullptr;
|
||||
waybar::util::ScopeGuard error_deleter([error]() {
|
||||
waybar::util::ScopeGuard error_deleter([&error]() {
|
||||
if (error != nullptr) {
|
||||
g_error_free(error);
|
||||
}
|
||||
@@ -148,7 +179,8 @@ void Host::itemRegistered(SnWatcher* watcher, const gchar* service, gpointer dat
|
||||
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));
|
||||
// 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) {
|
||||
@@ -156,13 +188,50 @@ void Host::itemUnregistered(SnWatcher* watcher, const gchar* service, gpointer d
|
||||
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->on_remove_(*it);
|
||||
host->items_.erase(it);
|
||||
host->removeItem(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Host::itemReady(Item& item) {
|
||||
auto it = std::find_if(items_.begin(), items_.end(),
|
||||
[&item](const auto& candidate) { return candidate.get() == &item; });
|
||||
if (it != items_.end() && (*it)->isReady()) {
|
||||
on_add_(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void Host::itemInvalidated(Item& item) {
|
||||
auto it = std::find_if(items_.begin(), items_.end(),
|
||||
[&item](const auto& candidate) { return candidate.get() == &item; });
|
||||
if (it != items_.end()) {
|
||||
removeItem(it);
|
||||
}
|
||||
}
|
||||
|
||||
void Host::removeItem(std::vector<std::unique_ptr<Item>>::iterator it) {
|
||||
if ((*it)->isReady()) {
|
||||
on_remove_(*it);
|
||||
}
|
||||
items_.erase(it);
|
||||
}
|
||||
|
||||
void Host::clearItems() {
|
||||
bool removed_ready_item = false;
|
||||
for (auto& item : items_) {
|
||||
if (item->isReady()) {
|
||||
on_remove_(item);
|
||||
removed_ready_item = true;
|
||||
}
|
||||
}
|
||||
bool had_items = !items_.empty();
|
||||
items_.clear();
|
||||
if (had_items && !removed_ready_item) {
|
||||
on_update_();
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<std::string, std::string> Host::getBusNameAndObjectPath(const std::string service) {
|
||||
auto it = service.find('/');
|
||||
if (it != std::string::npos) {
|
||||
@@ -171,7 +240,7 @@ std::tuple<std::string, std::string> Host::getBusNameAndObjectPath(const std::st
|
||||
return {service, "/StatusNotifierItem"};
|
||||
}
|
||||
|
||||
void Host::addRegisteredItem(std::string service) {
|
||||
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) {
|
||||
@@ -181,14 +250,16 @@ void Host::addRegisteredItem(std::string service) {
|
||||
}
|
||||
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);
|
||||
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(new Item(bus_name, object_path, config_, bar_));
|
||||
on_add_(items_.back());
|
||||
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_));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user