Merge branch 'master' into fix/tray-hide-when-empty
This commit is contained in:
+52
-10
@@ -8,7 +8,8 @@ namespace waybar::modules::SNI {
|
||||
|
||||
Host::Host(const std::size_t id, const Json::Value& config, const Bar& bar,
|
||||
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)),
|
||||
@@ -17,7 +18,8 @@ Host::Host(const std::size_t id, const Json::Value& config, const Bar& bar,
|
||||
config_(config),
|
||||
bar_(bar),
|
||||
on_add_(on_add),
|
||||
on_remove_(on_remove) {}
|
||||
on_remove_(on_remove),
|
||||
on_update_(on_update) {}
|
||||
|
||||
Host::~Host() {
|
||||
if (bus_name_id_ > 0) {
|
||||
@@ -54,12 +56,12 @@ void Host::nameVanished(const Glib::RefPtr<Gio::DBus::Connection>& conn, const G
|
||||
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);
|
||||
}
|
||||
@@ -81,7 +83,7 @@ void Host::proxyReady(GObject* src, GAsyncResult* res, gpointer 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);
|
||||
}
|
||||
@@ -117,13 +119,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) {
|
||||
@@ -132,15 +171,18 @@ 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) {
|
||||
std::string bus_name, object_path;
|
||||
std::tie(bus_name, object_path) = getBusNameAndObjectPath(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()) {
|
||||
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_));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+142
-48
@@ -5,6 +5,7 @@
|
||||
#include <gtkmm/tooltip.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
@@ -37,13 +38,18 @@ namespace waybar::modules::SNI {
|
||||
static const Glib::ustring SNI_INTERFACE_NAME = sn_item_interface_info()->name;
|
||||
static const unsigned UPDATE_DEBOUNCE_TIME = 10;
|
||||
|
||||
Item::Item(const std::string& bn, const std::string& op, const Json::Value& config, const Bar& bar)
|
||||
Item::Item(const std::string& bn, const std::string& op, const Json::Value& config, const Bar& bar,
|
||||
const std::function<void(Item&)>& on_ready,
|
||||
const std::function<void(Item&)>& on_invalidate, const std::function<void()>& on_updated)
|
||||
: bus_name(bn),
|
||||
object_path(op),
|
||||
icon_size(16),
|
||||
effective_icon_size(0),
|
||||
icon_theme(Gtk::IconTheme::create()),
|
||||
bar_(bar) {
|
||||
bar_(bar),
|
||||
on_ready_(on_ready),
|
||||
on_invalidate_(on_invalidate),
|
||||
on_updated_(on_updated) {
|
||||
if (config["icon-size"].isUInt()) {
|
||||
icon_size = config["icon-size"].asUInt();
|
||||
}
|
||||
@@ -85,6 +91,8 @@ Item::~Item() {
|
||||
}
|
||||
}
|
||||
|
||||
bool Item::isReady() const { return ready_; }
|
||||
|
||||
bool Item::handleMouseEnter(GdkEventCrossing* const& e) {
|
||||
event_box.set_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
|
||||
return false;
|
||||
@@ -112,14 +120,18 @@ void Item::proxyReady(Glib::RefPtr<Gio::AsyncResult>& result) {
|
||||
|
||||
if (this->id.empty() || this->category.empty()) {
|
||||
spdlog::error("Invalid Status Notifier Item: {}, {}", bus_name, object_path);
|
||||
invalidate();
|
||||
return;
|
||||
}
|
||||
this->updateImage();
|
||||
setReady();
|
||||
|
||||
} catch (const Glib::Error& err) {
|
||||
spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path, err.what());
|
||||
invalidate();
|
||||
} catch (const std::exception& err) {
|
||||
spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path, err.what());
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,11 +196,11 @@ void Item::setProperty(const Glib::ustring& name, Glib::VariantBase& value) {
|
||||
} else if (name == "OverlayIconName") {
|
||||
overlay_icon_name = get_variant<std::string>(value);
|
||||
} else if (name == "OverlayIconPixmap") {
|
||||
// TODO: overlay_icon_pixmap
|
||||
overlay_icon_pixmap = extractPixBuf(value.gobj());
|
||||
} else if (name == "AttentionIconName") {
|
||||
attention_icon_name = get_variant<std::string>(value);
|
||||
} else if (name == "AttentionIconPixmap") {
|
||||
// TODO: attention_icon_pixmap
|
||||
attention_icon_pixmap = extractPixBuf(value.gobj());
|
||||
} else if (name == "AttentionMovieName") {
|
||||
attention_movie_name = get_variant<std::string>(value);
|
||||
} else if (name == "ToolTip") {
|
||||
@@ -217,18 +229,35 @@ void Item::setProperty(const Glib::ustring& name, Glib::VariantBase& value) {
|
||||
}
|
||||
|
||||
void Item::setStatus(const Glib::ustring& value) {
|
||||
Glib::ustring lower = value.lowercase();
|
||||
event_box.set_visible(show_passive_ || lower.compare("passive") != 0);
|
||||
status_ = value.lowercase();
|
||||
event_box.set_visible(show_passive_ || status_.compare("passive") != 0);
|
||||
|
||||
auto style = event_box.get_style_context();
|
||||
for (const auto& class_name : style->list_classes()) {
|
||||
style->remove_class(class_name);
|
||||
}
|
||||
if (lower.compare("needsattention") == 0) {
|
||||
auto css_class = status_;
|
||||
if (css_class.compare("needsattention") == 0) {
|
||||
// convert status to dash-case for CSS
|
||||
lower = "needs-attention";
|
||||
css_class = "needs-attention";
|
||||
}
|
||||
style->add_class(lower);
|
||||
style->add_class(css_class);
|
||||
on_updated_();
|
||||
}
|
||||
|
||||
void Item::setReady() {
|
||||
if (ready_) {
|
||||
return;
|
||||
}
|
||||
ready_ = true;
|
||||
on_ready_(*this);
|
||||
}
|
||||
|
||||
void Item::invalidate() {
|
||||
if (ready_) {
|
||||
ready_ = false;
|
||||
}
|
||||
on_invalidate_(*this);
|
||||
}
|
||||
|
||||
void Item::setCustomIcon(const std::string& id) {
|
||||
@@ -287,8 +316,8 @@ void Item::processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& _result) {
|
||||
static const std::map<std::string_view, std::set<std::string_view>> signal2props = {
|
||||
{"NewTitle", {"Title"}},
|
||||
{"NewIcon", {"IconName", "IconPixmap"}},
|
||||
// {"NewAttentionIcon", {"AttentionIconName", "AttentionIconPixmap", "AttentionMovieName"}},
|
||||
// {"NewOverlayIcon", {"OverlayIconName", "OverlayIconPixmap"}},
|
||||
{"NewAttentionIcon", {"AttentionIconName", "AttentionIconPixmap", "AttentionMovieName"}},
|
||||
{"NewOverlayIcon", {"OverlayIconName", "OverlayIconPixmap"}},
|
||||
{"NewIconThemePath", {"IconThemePath"}},
|
||||
{"NewToolTip", {"ToolTip"}},
|
||||
{"NewStatus", {"Status"}},
|
||||
@@ -336,11 +365,20 @@ Glib::RefPtr<Gdk::Pixbuf> Item::extractPixBuf(GVariant* variant) {
|
||||
if (array != nullptr) {
|
||||
g_free(array);
|
||||
}
|
||||
#if GLIB_MAJOR_VERSION >= 2 && GLIB_MINOR_VERSION >= 68
|
||||
array = static_cast<guchar*>(g_memdup2(data, size));
|
||||
#else
|
||||
array = static_cast<guchar*>(g_memdup(data, size));
|
||||
#endif
|
||||
// We must allocate our own array because the data from GVariant is read-only
|
||||
// and we need to modify it to convert ARGB to RGBA.
|
||||
array = static_cast<guchar*>(g_malloc(size));
|
||||
|
||||
// Copy and convert ARGB to RGBA in one pass to avoid g_memdup2 overhead
|
||||
const guchar* src = static_cast<const guchar*>(data);
|
||||
for (gsize i = 0; i < size; i += 4) {
|
||||
guchar alpha = src[i];
|
||||
array[i] = src[i + 1];
|
||||
array[i + 1] = src[i + 2];
|
||||
array[i + 2] = src[i + 3];
|
||||
array[i + 3] = alpha;
|
||||
}
|
||||
|
||||
lwidth = width;
|
||||
lheight = height;
|
||||
}
|
||||
@@ -349,14 +387,6 @@ Glib::RefPtr<Gdk::Pixbuf> Item::extractPixBuf(GVariant* variant) {
|
||||
}
|
||||
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, &pixbuf_data_deleter);
|
||||
}
|
||||
@@ -365,47 +395,36 @@ Glib::RefPtr<Gdk::Pixbuf> Item::extractPixBuf(GVariant* variant) {
|
||||
|
||||
void Item::updateImage() {
|
||||
auto pixbuf = getIconPixbuf();
|
||||
if (!pixbuf) return;
|
||||
auto scaled_icon_size = getScaledIconSize();
|
||||
|
||||
// If the loaded icon is not square, assume that the icon height should match the
|
||||
// requested icon size, but the width is allowed to be different. As such, if the
|
||||
// height of the image does not match the requested icon size, resize the icon such that
|
||||
// the aspect ratio is maintained, but the height matches the requested icon size.
|
||||
if (pixbuf->get_height() != scaled_icon_size) {
|
||||
if (pixbuf->get_height() > 0 && pixbuf->get_height() != scaled_icon_size) {
|
||||
int width = scaled_icon_size * pixbuf->get_width() / pixbuf->get_height();
|
||||
pixbuf = pixbuf->scale_simple(width, scaled_icon_size, Gdk::InterpType::INTERP_BILINEAR);
|
||||
}
|
||||
|
||||
pixbuf = overlayPixbufs(pixbuf, getOverlayIconPixbuf());
|
||||
|
||||
auto surface =
|
||||
Gdk::Cairo::create_surface_from_pixbuf(pixbuf, image.get_scale_factor(), image.get_window());
|
||||
image.set(surface);
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> Item::getIconPixbuf() {
|
||||
if (!icon_name.empty()) {
|
||||
try {
|
||||
std::ifstream temp(icon_name);
|
||||
if (temp.is_open()) {
|
||||
return Gdk::Pixbuf::create_from_file(icon_name);
|
||||
}
|
||||
} catch (Glib::Error& e) {
|
||||
// Ignore because we want to also try different methods of getting an icon.
|
||||
//
|
||||
// But a warning is logged, as the file apparently exists, but there was
|
||||
// a failure in creating a pixbuf out of it.
|
||||
|
||||
spdlog::warn("Item '{}': {}", id, static_cast<std::string>(e.what()));
|
||||
}
|
||||
|
||||
try {
|
||||
// Will throw if it can not find an icon.
|
||||
return getIconByName(icon_name, getScaledIconSize());
|
||||
} catch (Glib::Error& e) {
|
||||
spdlog::trace("Item '{}': {}", id, static_cast<std::string>(e.what()));
|
||||
if (status_ == "needsattention") {
|
||||
if (auto attention_pixbuf = getAttentionIconPixbuf()) {
|
||||
return attention_pixbuf;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the pixmap only if an icon for the given name could not be found.
|
||||
if (auto pixbuf = loadIconFromNameOrFile(icon_name, true)) {
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
if (icon_pixmap) {
|
||||
return icon_pixmap;
|
||||
}
|
||||
@@ -420,9 +439,78 @@ Glib::RefPtr<Gdk::Pixbuf> Item::getIconPixbuf() {
|
||||
return getIconByName("image-missing", getScaledIconSize());
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> Item::getIconByName(const std::string& name, int request_size) {
|
||||
icon_theme->rescan_if_needed();
|
||||
Glib::RefPtr<Gdk::Pixbuf> Item::getAttentionIconPixbuf() {
|
||||
if (auto pixbuf = loadIconFromNameOrFile(attention_icon_name, false)) {
|
||||
return pixbuf;
|
||||
}
|
||||
if (auto pixbuf = loadIconFromNameOrFile(attention_movie_name, false)) {
|
||||
return pixbuf;
|
||||
}
|
||||
return attention_icon_pixmap;
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> Item::getOverlayIconPixbuf() {
|
||||
if (auto pixbuf = loadIconFromNameOrFile(overlay_icon_name, false)) {
|
||||
return pixbuf;
|
||||
}
|
||||
return overlay_icon_pixmap;
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> Item::loadIconFromNameOrFile(const std::string& name, bool log_failure) {
|
||||
if (name.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
try {
|
||||
std::ifstream temp(name);
|
||||
if (temp.is_open()) {
|
||||
return Gdk::Pixbuf::create_from_file(name);
|
||||
}
|
||||
} catch (const Glib::Error& e) {
|
||||
if (log_failure) {
|
||||
spdlog::warn("Item '{}': {}", id, static_cast<std::string>(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return getIconByName(name, getScaledIconSize());
|
||||
} catch (const Glib::Error& e) {
|
||||
if (log_failure) {
|
||||
spdlog::trace("Item '{}': {}", id, static_cast<std::string>(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> Item::overlayPixbufs(const Glib::RefPtr<Gdk::Pixbuf>& base,
|
||||
const Glib::RefPtr<Gdk::Pixbuf>& overlay) {
|
||||
if (!base || !overlay) {
|
||||
return base;
|
||||
}
|
||||
|
||||
auto composed = base->copy();
|
||||
if (!composed) {
|
||||
return base;
|
||||
}
|
||||
|
||||
int overlay_target_size =
|
||||
std::max(1, std::min(composed->get_width(), composed->get_height()) / 2);
|
||||
auto scaled_overlay = overlay->scale_simple(overlay_target_size, overlay_target_size,
|
||||
Gdk::InterpType::INTERP_BILINEAR);
|
||||
if (!scaled_overlay) {
|
||||
return composed;
|
||||
}
|
||||
|
||||
int dest_x = std::max(0, composed->get_width() - scaled_overlay->get_width());
|
||||
int dest_y = std::max(0, composed->get_height() - scaled_overlay->get_height());
|
||||
scaled_overlay->composite(composed, dest_x, dest_y, scaled_overlay->get_width(),
|
||||
scaled_overlay->get_height(), dest_x, dest_y, 1.0, 1.0,
|
||||
Gdk::InterpType::INTERP_BILINEAR, 255);
|
||||
return composed;
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> Item::getIconByName(const std::string& name, int request_size) {
|
||||
if (!icon_theme_path.empty()) {
|
||||
auto icon_info = icon_theme->lookup_icon(name.c_str(), request_size,
|
||||
Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
|
||||
@@ -464,6 +552,9 @@ void Item::makeMenu() {
|
||||
}
|
||||
|
||||
bool Item::handleClick(GdkEventButton* const& ev) {
|
||||
if (!proxy_) {
|
||||
return false;
|
||||
}
|
||||
auto parameters = Glib::VariantContainerBase::create_tuple(
|
||||
{Glib::Variant<int>::create(ev->x_root + bar_.x_global),
|
||||
Glib::Variant<int>::create(ev->y_root + bar_.y_global)});
|
||||
@@ -491,6 +582,9 @@ bool Item::handleClick(GdkEventButton* const& ev) {
|
||||
}
|
||||
|
||||
bool Item::handleScroll(GdkEventScroll* const& ev) {
|
||||
if (!proxy_) {
|
||||
return false;
|
||||
}
|
||||
int dx = 0, dy = 0;
|
||||
switch (ev->direction) {
|
||||
case GDK_SCROLL_UP:
|
||||
|
||||
@@ -13,7 +13,8 @@ Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
box_(bar.orientation, 0),
|
||||
watcher_(SNI::Watcher::getInstance()),
|
||||
host_(nb_hosts_, config, bar, std::bind(&Tray::onAdd, this, std::placeholders::_1),
|
||||
std::bind(&Tray::onRemove, this, std::placeholders::_1)) {
|
||||
std::bind(&Tray::onRemove, this, std::placeholders::_1),
|
||||
std::bind(&Tray::queueUpdate, this)) {
|
||||
box_.set_name("tray");
|
||||
event_box_.add(box_);
|
||||
if (!id.empty()) {
|
||||
@@ -30,6 +31,8 @@ Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
dp.emit();
|
||||
}
|
||||
|
||||
void Tray::queueUpdate() { dp.emit(); }
|
||||
|
||||
void Tray::onAdd(std::unique_ptr<Item>& item) {
|
||||
if (config_["reverse-direction"].isBool() && config_["reverse-direction"].asBool()) {
|
||||
box_.pack_end(item->event_box);
|
||||
|
||||
@@ -31,7 +31,7 @@ Watcher::~Watcher() {
|
||||
|
||||
void Watcher::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
|
||||
GError* error = nullptr;
|
||||
waybar::util::ScopeGuard error_deleter([error]() {
|
||||
waybar::util::ScopeGuard error_deleter([&error]() {
|
||||
if (error) {
|
||||
g_error_free(error);
|
||||
}
|
||||
@@ -69,7 +69,7 @@ gboolean Watcher::handleRegisterHost(Watcher* obj, GDBusMethodInvocation* invoca
|
||||
if (watch != nullptr) {
|
||||
g_warning("Status Notifier Host with bus name '%s' and object path '%s' is already registered",
|
||||
bus_name, object_path);
|
||||
sn_watcher_complete_register_item(obj->watcher_, invocation);
|
||||
sn_watcher_complete_register_host(obj->watcher_, invocation);
|
||||
return TRUE;
|
||||
}
|
||||
watch = gfWatchNew(GF_WATCH_TYPE_HOST, service, bus_name, object_path, obj);
|
||||
@@ -98,8 +98,8 @@ gboolean Watcher::handleRegisterItem(Watcher* obj, GDBusMethodInvocation* invoca
|
||||
}
|
||||
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);
|
||||
spdlog::debug("Ignoring duplicate Status Notifier Item registration for '{}' at '{}'", bus_name,
|
||||
object_path);
|
||||
sn_watcher_complete_register_item(obj->watcher_, invocation);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -158,7 +158,7 @@ void Watcher::nameVanished(GDBusConnection* connection, const char* name, gpoint
|
||||
watch->watcher->hosts_ = g_slist_remove(watch->watcher->hosts_, watch);
|
||||
if (watch->watcher->hosts_ == nullptr) {
|
||||
sn_watcher_set_is_host_registered(watch->watcher->watcher_, FALSE);
|
||||
sn_watcher_emit_host_registered(watch->watcher->watcher_);
|
||||
sn_watcher_emit_host_unregistered(watch->watcher->watcher_);
|
||||
}
|
||||
} else if (watch->type == GF_WATCH_TYPE_ITEM) {
|
||||
watch->watcher->items_ = g_slist_remove(watch->watcher->items_, watch);
|
||||
@@ -167,6 +167,7 @@ void Watcher::nameVanished(GDBusConnection* connection, const char* name, gpoint
|
||||
sn_watcher_emit_item_unregistered(watch->watcher->watcher_, tmp);
|
||||
g_free(tmp);
|
||||
}
|
||||
gfWatchFree(watch);
|
||||
}
|
||||
|
||||
void Watcher::updateRegisteredItems(SnWatcher* obj) {
|
||||
|
||||
Reference in New Issue
Block a user