2018-08-29 20:36:39 +02:00
|
|
|
#include "modules/sni/snh.hpp"
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
2018-09-04 23:50:08 +02:00
|
|
|
using namespace waybar::modules::SNI;
|
|
|
|
|
2018-10-26 14:53:39 +02:00
|
|
|
Host::Host(Glib::Dispatcher* dp, const Json::Value &config)
|
|
|
|
: dp_(dp), config_(config)
|
2018-08-29 20:36:39 +02:00
|
|
|
{
|
|
|
|
GBusNameOwnerFlags flags = static_cast<GBusNameOwnerFlags>(
|
|
|
|
G_BUS_NAME_OWNER_FLAGS_NONE);
|
|
|
|
bus_name_ = "org.kde.StatusNotifierHost-" + std::to_string(getpid());
|
|
|
|
object_path_ = "/StatusNotifierHost";
|
|
|
|
bus_name_id_ = g_bus_own_name(G_BUS_TYPE_SESSION,
|
|
|
|
bus_name_.c_str(), flags,
|
|
|
|
&Host::busAcquired, nullptr, nullptr, this, nullptr);
|
|
|
|
}
|
|
|
|
|
2018-09-04 23:50:08 +02:00
|
|
|
void Host::busAcquired(GDBusConnection* connection,
|
2018-08-29 20:36:39 +02:00
|
|
|
const gchar* name, gpointer data)
|
|
|
|
{
|
|
|
|
auto host = static_cast<SNI::Host *>(data);
|
|
|
|
host->watcher_id_ = g_bus_watch_name(
|
|
|
|
G_BUS_TYPE_SESSION,
|
|
|
|
"org.kde.StatusNotifierWatcher",
|
|
|
|
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
|
|
&Host::nameAppeared, &Host::nameVanished, data, nullptr);
|
|
|
|
}
|
|
|
|
|
2018-09-04 23:50:08 +02:00
|
|
|
void Host::nameAppeared(GDBusConnection* connection,
|
2018-08-29 20:36:39 +02:00
|
|
|
const gchar* name, const gchar* name_owner, gpointer data)
|
|
|
|
{
|
|
|
|
auto host = static_cast<SNI::Host *>(data);
|
|
|
|
if (host->cancellable_ != nullptr) {
|
2018-10-25 13:49:30 +02:00
|
|
|
// TODO
|
2018-10-29 21:52:53 +01:00
|
|
|
return;
|
2018-08-29 20:36:39 +02:00
|
|
|
}
|
|
|
|
host->cancellable_ = g_cancellable_new();
|
2018-10-26 10:05:54 +02:00
|
|
|
sn_watcher_proxy_new(
|
2018-08-29 20:36:39 +02:00
|
|
|
connection,
|
|
|
|
G_DBUS_PROXY_FLAGS_NONE,
|
|
|
|
"org.kde.StatusNotifierWatcher",
|
|
|
|
"/StatusNotifierWatcher",
|
|
|
|
host->cancellable_, &Host::proxyReady, data);
|
|
|
|
}
|
|
|
|
|
2018-09-04 23:50:08 +02:00
|
|
|
void Host::nameVanished(GDBusConnection* connection,
|
2018-08-29 20:36:39 +02:00
|
|
|
const gchar* name, gpointer data)
|
|
|
|
{
|
|
|
|
auto host = static_cast<SNI::Host *>(data);
|
|
|
|
g_cancellable_cancel(host->cancellable_);
|
|
|
|
g_clear_object(&host->cancellable_);
|
|
|
|
g_clear_object(&host->watcher_);
|
|
|
|
host->items.clear();
|
|
|
|
}
|
|
|
|
|
2018-09-04 23:50:08 +02:00
|
|
|
void Host::proxyReady(GObject* src, GAsyncResult* res,
|
2018-08-29 20:36:39 +02:00
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
GError* error = nullptr;
|
2018-10-26 10:05:54 +02:00
|
|
|
SnWatcher* watcher = sn_watcher_proxy_new_finish(res, &error);
|
2018-08-29 20:36:39 +02:00
|
|
|
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
|
|
std::cerr << error->message << std::endl;
|
|
|
|
g_error_free(error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto host = static_cast<SNI::Host *>(data);
|
|
|
|
host->watcher_ = watcher;
|
|
|
|
if (error != nullptr) {
|
|
|
|
std::cerr << error->message << std::endl;
|
|
|
|
g_error_free(error);
|
|
|
|
return;
|
|
|
|
}
|
2018-10-26 10:05:54 +02:00
|
|
|
sn_watcher_call_register_host(
|
2018-08-29 20:36:39 +02:00
|
|
|
host->watcher_, host->object_path_.c_str(), host->cancellable_,
|
|
|
|
&Host::registerHost, data);
|
|
|
|
}
|
|
|
|
|
2018-09-04 23:50:08 +02:00
|
|
|
void Host::registerHost(GObject* src, GAsyncResult* res,
|
2018-08-29 20:36:39 +02:00
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
GError* error = nullptr;
|
2018-10-26 10:05:54 +02:00
|
|
|
sn_watcher_call_register_host_finish(SN_WATCHER(src), res, &error);
|
2018-08-29 20:36:39 +02:00
|
|
|
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
|
|
std::cerr << error->message << std::endl;
|
|
|
|
g_error_free(error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto host = static_cast<SNI::Host *>(data);
|
|
|
|
if (error != nullptr) {
|
|
|
|
std::cerr << error->message << std::endl;
|
|
|
|
g_error_free(error);
|
|
|
|
return;
|
|
|
|
}
|
2018-10-26 10:05:54 +02:00
|
|
|
g_signal_connect(host->watcher_, "item-registered",
|
2018-08-29 20:36:39 +02:00
|
|
|
G_CALLBACK(&Host::itemRegistered), data);
|
2018-10-26 10:05:54 +02:00
|
|
|
g_signal_connect(host->watcher_, "item-unregistered",
|
2018-08-29 20:36:39 +02:00
|
|
|
G_CALLBACK(&Host::itemUnregistered), data);
|
2018-10-26 10:05:54 +02:00
|
|
|
auto items = sn_watcher_dup_registered_items(host->watcher_);
|
2018-08-29 20:36:39 +02:00
|
|
|
if (items) {
|
|
|
|
for (uint32_t i = 0; items[i] != nullptr; i += 1) {
|
|
|
|
host->addRegisteredItem(items[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_strfreev(items);
|
|
|
|
}
|
|
|
|
|
2018-09-04 23:50:08 +02:00
|
|
|
void Host::itemRegistered(
|
2018-10-26 10:05:54 +02:00
|
|
|
SnWatcher* watcher, const gchar* service, gpointer data)
|
2018-08-29 20:36:39 +02:00
|
|
|
{
|
|
|
|
auto host = static_cast<SNI::Host *>(data);
|
|
|
|
host->addRegisteredItem(service);
|
|
|
|
}
|
|
|
|
|
2018-09-04 23:50:08 +02:00
|
|
|
void Host::itemUnregistered(
|
2018-10-26 10:05:54 +02:00
|
|
|
SnWatcher* watcher, const gchar* service, gpointer data)
|
2018-08-29 20:36:39 +02:00
|
|
|
{
|
2018-09-04 23:50:08 +02:00
|
|
|
auto host = static_cast<SNI::Host *>(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);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
host->dp_->emit();
|
2018-08-29 20:36:39 +02:00
|
|
|
}
|
|
|
|
|
2018-09-04 23:50:08 +02:00
|
|
|
std::tuple<std::string, std::string> Host::getBusNameAndObjectPath(
|
|
|
|
const gchar* service)
|
2018-08-29 20:36:39 +02:00
|
|
|
{
|
2018-09-04 23:50:08 +02:00
|
|
|
std::string bus_name;
|
|
|
|
std::string object_path;
|
|
|
|
gchar* tmp = g_strstr_len(service, -1, "/");
|
2018-08-29 20:36:39 +02:00
|
|
|
if (tmp != nullptr) {
|
|
|
|
gchar** str = g_strsplit(service, "/", 2);
|
2018-09-04 23:50:08 +02:00
|
|
|
bus_name = str[0];
|
|
|
|
object_path = tmp;
|
2018-08-29 20:36:39 +02:00
|
|
|
g_strfreev(str);
|
|
|
|
} else {
|
2018-09-04 23:50:08 +02:00
|
|
|
bus_name = service;
|
|
|
|
object_path = "/StatusNotifierItem";
|
2018-08-29 20:36:39 +02:00
|
|
|
}
|
2018-09-04 23:50:08 +02:00
|
|
|
return { bus_name, object_path };
|
2018-08-29 20:36:39 +02:00
|
|
|
}
|
|
|
|
|
2018-09-04 23:50:08 +02:00
|
|
|
void Host::addRegisteredItem(const gchar* service)
|
2018-08-29 20:36:39 +02:00
|
|
|
{
|
2018-09-04 23:50:08 +02:00
|
|
|
auto [bus_name, object_path] = getBusNameAndObjectPath(service);
|
2018-10-26 14:53:39 +02:00
|
|
|
items.emplace_back(bus_name, object_path, dp_, config_);
|
2018-10-04 18:03:01 +02:00
|
|
|
}
|