2018-08-29 18:36:39 +00:00
|
|
|
#include "modules/sni/snw.hpp"
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
2018-09-04 21:50:08 +00:00
|
|
|
using namespace waybar::modules::SNI;
|
|
|
|
|
|
|
|
Watcher::Watcher()
|
2018-08-29 18:36:39 +00:00
|
|
|
{
|
|
|
|
GBusNameOwnerFlags flags = static_cast<GBusNameOwnerFlags>(
|
|
|
|
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
|
|
|
|
| G_BUS_NAME_OWNER_FLAGS_REPLACE);
|
|
|
|
bus_name_id_ = g_bus_own_name(G_BUS_TYPE_SESSION,
|
|
|
|
"org.kde.StatusNotifierWatcher", flags,
|
|
|
|
&Watcher::busAcquired, nullptr, nullptr, this, nullptr);
|
2018-10-26 08:05:54 +00:00
|
|
|
watcher_ = sn_watcher_skeleton_new();
|
2018-10-26 08:56:45 +00:00
|
|
|
sn_watcher_set_protocol_version(watcher_, 1);
|
2018-08-29 18:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-04 21:50:08 +00:00
|
|
|
Watcher::~Watcher()
|
2018-08-29 18:36:39 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-09-04 21:50:08 +00:00
|
|
|
void Watcher::busAcquired(GDBusConnection* connection, const gchar* name,
|
|
|
|
gpointer data)
|
2018-08-29 18:36:39 +00:00
|
|
|
{
|
|
|
|
GError* error = nullptr;
|
|
|
|
auto host = static_cast<SNI::Watcher*>(data);
|
|
|
|
g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(host->watcher_),
|
|
|
|
connection, "/StatusNotifierWatcher", &error);
|
|
|
|
if (error != nullptr) {
|
|
|
|
std::cerr << error->message << std::endl;
|
|
|
|
g_error_free(error);
|
|
|
|
return;
|
|
|
|
}
|
2018-10-26 08:39:25 +00:00
|
|
|
g_signal_connect_swapped(host->watcher_, "handle-register-item",
|
2018-08-29 18:36:39 +00:00
|
|
|
G_CALLBACK(&Watcher::handleRegisterItem), data);
|
2018-10-26 08:39:25 +00:00
|
|
|
g_signal_connect_swapped(host->watcher_, "handle-register-host",
|
2018-08-29 18:36:39 +00:00
|
|
|
G_CALLBACK(&Watcher::handleRegisterHost), data);
|
|
|
|
}
|
|
|
|
|
2018-09-04 21:50:08 +00:00
|
|
|
gboolean Watcher::handleRegisterHost(Watcher* obj,
|
|
|
|
GDBusMethodInvocation* invocation, const gchar* service)
|
2018-08-29 18:36:39 +00:00
|
|
|
{
|
|
|
|
const gchar* bus_name = service;
|
|
|
|
const gchar* object_path = "/StatusNotifierHost";
|
|
|
|
|
|
|
|
if (*service == '/') {
|
|
|
|
bus_name = g_dbus_method_invocation_get_sender(invocation);
|
|
|
|
object_path = service;
|
|
|
|
}
|
|
|
|
if (g_dbus_is_name(bus_name) == FALSE) {
|
|
|
|
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_INVALID_ARGS, "D-Bus bus name '%s' is not valid", bus_name);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
auto watch = gfWatchFind(obj->hosts_, bus_name, object_path);
|
|
|
|
if (watch != nullptr) {
|
|
|
|
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_INVALID_ARGS, "Status Notifier Host with bus name '%s' and object path '%s' is already registered",
|
|
|
|
bus_name, object_path);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2018-09-04 21:50:08 +00:00
|
|
|
watch = gfWatchNew(GF_WATCH_TYPE_HOST, service, bus_name, object_path, obj);
|
2018-08-29 18:36:39 +00:00
|
|
|
obj->hosts_ = g_slist_prepend(obj->hosts_, watch);
|
2018-10-26 08:27:15 +00:00
|
|
|
if (!sn_watcher_get_is_host_registered(obj->watcher_)) {
|
|
|
|
sn_watcher_set_is_host_registered(obj->watcher_, TRUE);
|
2018-10-26 08:05:54 +00:00
|
|
|
sn_watcher_emit_host_registered(obj->watcher_);
|
2018-08-29 18:36:39 +00:00
|
|
|
}
|
2018-10-26 08:05:54 +00:00
|
|
|
sn_watcher_complete_register_host(obj->watcher_, invocation);
|
2018-08-29 18:36:39 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-09-04 21:50:08 +00:00
|
|
|
gboolean Watcher::handleRegisterItem(Watcher* obj,
|
|
|
|
GDBusMethodInvocation* invocation, const gchar* service)
|
2018-08-29 18:36:39 +00:00
|
|
|
{
|
|
|
|
const gchar* bus_name = service;
|
|
|
|
const gchar* object_path = "/StatusNotifierItem";
|
|
|
|
|
|
|
|
if (*service == '/') {
|
|
|
|
bus_name = g_dbus_method_invocation_get_sender(invocation);
|
|
|
|
object_path = service;
|
|
|
|
}
|
|
|
|
if (g_dbus_is_name(bus_name) == FALSE) {
|
|
|
|
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_INVALID_ARGS, "D-Bus bus name '%s' is not valid", bus_name);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
auto watch = gfWatchFind(obj->items_, bus_name, object_path);
|
|
|
|
if (watch != nullptr) {
|
|
|
|
g_warning("Status Notifier Item with bus name '%s' and object path '%s' is already registered",
|
|
|
|
bus_name, object_path);
|
2018-10-26 08:05:54 +00:00
|
|
|
sn_watcher_complete_register_item(obj->watcher_, invocation);
|
2018-08-29 18:36:39 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2018-09-04 21:50:08 +00:00
|
|
|
watch = gfWatchNew(GF_WATCH_TYPE_ITEM, service, bus_name, object_path, obj);
|
2018-08-29 18:36:39 +00:00
|
|
|
obj->items_ = g_slist_prepend(obj->items_, watch);
|
|
|
|
obj->updateRegisteredItems(obj->watcher_);
|
|
|
|
gchar* tmp = g_strdup_printf("%s%s", bus_name, object_path);
|
2018-10-26 08:05:54 +00:00
|
|
|
sn_watcher_emit_item_registered(obj->watcher_, tmp);
|
2018-08-29 18:36:39 +00:00
|
|
|
g_free(tmp);
|
2018-10-26 08:05:54 +00:00
|
|
|
sn_watcher_complete_register_item(obj->watcher_, invocation);
|
2018-08-29 18:36:39 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-09-04 21:50:08 +00:00
|
|
|
Watcher::GfWatch* Watcher::gfWatchFind(GSList* list, const gchar* bus_name,
|
|
|
|
const gchar* object_path)
|
2018-08-29 18:36:39 +00:00
|
|
|
{
|
|
|
|
for (GSList* l = list; l != nullptr; l = g_slist_next (l)) {
|
|
|
|
GfWatch* watch = static_cast<GfWatch*>(l->data);
|
|
|
|
if (g_strcmp0 (watch->bus_name, bus_name) == 0
|
|
|
|
&& g_strcmp0 (watch->object_path, object_path) == 0) {
|
|
|
|
return watch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-09-04 21:50:08 +00:00
|
|
|
Watcher::GfWatch* Watcher::gfWatchNew(GfWatchType type, const gchar* service,
|
|
|
|
const gchar* bus_name, const gchar* object_path, Watcher* watcher)
|
2018-08-29 18:36:39 +00:00
|
|
|
{
|
|
|
|
GfWatch* watch = g_new0(GfWatch, 1);
|
|
|
|
watch->type = type;
|
2018-09-04 21:50:08 +00:00
|
|
|
watch->watcher = watcher;
|
2018-08-29 18:36:39 +00:00
|
|
|
watch->service = g_strdup(service);
|
|
|
|
watch->bus_name = g_strdup(bus_name);
|
|
|
|
watch->object_path = g_strdup(object_path);
|
|
|
|
watch->watch_id = g_bus_watch_name(G_BUS_TYPE_SESSION, bus_name,
|
|
|
|
G_BUS_NAME_WATCHER_FLAGS_NONE, nullptr, &Watcher::nameVanished, watch,
|
|
|
|
nullptr);
|
|
|
|
return watch;
|
|
|
|
}
|
|
|
|
|
2018-09-04 21:50:08 +00:00
|
|
|
void Watcher::nameVanished(GDBusConnection* connection, const char* name,
|
|
|
|
gpointer data)
|
2018-08-29 18:36:39 +00:00
|
|
|
{
|
2018-09-04 21:50:08 +00:00
|
|
|
auto watch = static_cast<GfWatch *>(data);
|
|
|
|
if (watch->type == GF_WATCH_TYPE_HOST) {
|
|
|
|
watch->watcher->hosts_ = g_slist_remove(watch->watcher->hosts_, watch);
|
|
|
|
if (watch->watcher->hosts_ == nullptr) {
|
2018-10-26 08:05:54 +00:00
|
|
|
sn_watcher_set_is_host_registered(watch->watcher->watcher_, FALSE);
|
|
|
|
sn_watcher_emit_host_registered(watch->watcher->watcher_);
|
2018-09-04 21:50:08 +00:00
|
|
|
}
|
|
|
|
} 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);
|
2018-10-26 08:05:54 +00:00
|
|
|
sn_watcher_emit_item_unregistered(watch->watcher->watcher_, tmp);
|
2018-09-04 21:50:08 +00:00
|
|
|
g_free(tmp);
|
|
|
|
}
|
2018-08-29 18:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-10-26 08:05:54 +00:00
|
|
|
void Watcher::updateRegisteredItems(SnWatcher* obj)
|
2018-08-29 18:36:39 +00:00
|
|
|
{
|
|
|
|
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<GfWatch*>(l->data);
|
2018-09-04 21:50:08 +00:00
|
|
|
gchar* item = g_strdup_printf("%s%s", watch->bus_name, watch->object_path);
|
|
|
|
g_variant_builder_add(&builder, "s", item);
|
|
|
|
g_free(item);
|
2018-08-29 18:36:39 +00:00
|
|
|
}
|
|
|
|
GVariant* variant = g_variant_builder_end(&builder);
|
2018-09-04 21:50:08 +00:00
|
|
|
const gchar** items = g_variant_get_strv(variant, nullptr);
|
2018-10-26 08:05:54 +00:00
|
|
|
sn_watcher_set_registered_items(obj, items);
|
2018-08-29 18:36:39 +00:00
|
|
|
g_variant_unref(variant);
|
|
|
|
g_free(items);
|
|
|
|
}
|