fix urgent window icons

This commit is contained in:
2025-12-17 23:34:12 +01:00
parent 11ccd55a52
commit 9b0a036925
11 changed files with 172 additions and 194 deletions

View File

@@ -15,12 +15,12 @@
#include <vector>
namespace {
constexpr const char *kWatcherBusName = "org.kde.StatusNotifierWatcher";
constexpr const char *kWatcherObjectPath = "/StatusNotifierWatcher";
constexpr const char *kWatcherInterface = "org.kde.StatusNotifierWatcher";
constexpr const char *kItemInterface = "org.kde.StatusNotifierItem";
constexpr const char *kWatcherBusName = "org.kde.StatusNotifierWatcher";
constexpr const char *kWatcherObjectPath = "/StatusNotifierWatcher";
constexpr const char *kWatcherInterface = "org.kde.StatusNotifierWatcher";
constexpr const char *kItemInterface = "org.kde.StatusNotifierItem";
constexpr const char *kDBusPropertiesIface = "org.freedesktop.DBus.Properties";
constexpr const char *kDBusMenuInterface = "com.canonical.dbusmenu";
constexpr const char *kDBusMenuInterface = "com.canonical.dbusmenu";
const char *kWatcherIntrospection =
R"(<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
@@ -55,25 +55,25 @@ ParsedService parse_service_identifier(const Glib::ustring &sender,
ParsedService parsed;
if (service.empty()) {
parsed.busName = sender;
parsed.busName = sender;
parsed.objectPath = "/StatusNotifierItem";
return parsed;
}
if (service.front() == '/') {
parsed.busName = sender;
parsed.busName = sender;
parsed.objectPath = service;
return parsed;
}
const auto slash = service.find('/');
if (slash == std::string::npos) {
parsed.busName = service;
parsed.busName = service;
parsed.objectPath = "/StatusNotifierItem";
return parsed;
}
parsed.busName = service.substr(0, slash);
parsed.busName = service.substr(0, slash);
parsed.objectPath = service.substr(slash);
if (parsed.busName.empty()) {
@@ -90,8 +90,8 @@ ParsedService parse_service_identifier(const Glib::ustring &sender,
GVariant *create_property_list_variant() {
GVariantBuilder builder;
g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
const char *properties[] = {"label", "label-markup", "enabled",
"visible", "children-display", "type",
const char *properties[] = {"label", "label-markup", "enabled",
"visible", "children-display", "type",
"toggle-type", "toggle-state"};
for (const char *prop : properties) {
g_variant_builder_add(&builder, "s", prop);
@@ -106,7 +106,7 @@ void call_about_to_show(const Glib::RefPtr<Gio::DBus::Connection> &connection,
return;
}
GError *error = nullptr;
GError *error = nullptr;
GVariant *result = g_dbus_connection_call_sync(
connection->gobj(), busName.c_str(), menuPath.c_str(),
kDBusMenuInterface, "AboutToShow", g_variant_new("(i)", id), nullptr,
@@ -137,7 +137,7 @@ GVariant *call_get_layout(const Glib::RefPtr<Gio::DBus::Connection> &connection,
GVariant *params = g_variant_new("(ii@as)", 0, -1, properties);
g_variant_ref_sink(properties);
GError *error = nullptr;
GError *error = nullptr;
GVariant *result = g_dbus_connection_call_sync(
connection->gobj(), busName.c_str(), menuPath.c_str(),
kDBusMenuInterface, "GetLayout", params, nullptr,
@@ -174,15 +174,15 @@ void parse_menu_node(GVariant *tuple, TrayService::MenuNode &outNode) {
return;
}
int id = 0;
GVariant *propsVariant = nullptr;
int id = 0;
GVariant *propsVariant = nullptr;
GVariant *childrenVariant = nullptr;
g_variant_get(tuple, "(i@a{sv}@av)", &id, &propsVariant, &childrenVariant);
outNode.id = id;
outNode.enabled = true;
outNode.visible = true;
outNode.id = id;
outNode.enabled = true;
outNode.visible = true;
outNode.separator = false;
outNode.label.clear();
@@ -190,7 +190,7 @@ void parse_menu_node(GVariant *tuple, TrayService::MenuNode &outNode) {
GVariantIter iter;
g_variant_iter_init(&iter, propsVariant);
const gchar *key = nullptr;
GVariant *value = nullptr;
GVariant *value = nullptr;
while (g_variant_iter_next(&iter, "{sv}", &key, &value)) {
if (!key || !value) {
@@ -214,13 +214,13 @@ void parse_menu_node(GVariant *tuple, TrayService::MenuNode &outNode) {
if (std::strcmp(key, "label") == 0) {
if (g_variant_is_of_type(unboxed, G_VARIANT_TYPE_STRING)) {
const gchar *str = g_variant_get_string(unboxed, nullptr);
outNode.label = str ? str : "";
outNode.label = str ? str : "";
}
} else if (std::strcmp(key, "label-markup") == 0 &&
outNode.label.empty()) {
if (g_variant_is_of_type(unboxed, G_VARIANT_TYPE_STRING)) {
const gchar *str = g_variant_get_string(unboxed, nullptr);
outNode.label = str ? str : "";
outNode.label = str ? str : "";
}
} else if (std::strcmp(key, "enabled") == 0) {
if (g_variant_is_of_type(unboxed, G_VARIANT_TYPE_BOOLEAN)) {
@@ -362,7 +362,7 @@ void TrayService::activate(const std::string &id, int32_t x, int32_t y) {
return;
}
GError *error = nullptr;
GError *error = nullptr;
GVariant *result = g_dbus_connection_call_sync(
connection->gobj(), it->second->publicData.busName.c_str(),
it->second->publicData.objectPath.c_str(), kItemInterface, "Activate",
@@ -387,7 +387,7 @@ void TrayService::secondaryActivate(const std::string &id, int32_t x,
return;
}
GError *error = nullptr;
GError *error = nullptr;
GVariant *result = g_dbus_connection_call_sync(
connection->gobj(), it->second->publicData.busName.c_str(),
it->second->publicData.objectPath.c_str(), kItemInterface,
@@ -411,7 +411,7 @@ void TrayService::contextMenu(const std::string &id, int32_t x, int32_t y) {
return;
}
GError *error = nullptr;
GError *error = nullptr;
GVariant *result = g_dbus_connection_call_sync(
connection->gobj(), it->second->publicData.busName.c_str(),
it->second->publicData.objectPath.c_str(), kItemInterface,
@@ -566,7 +566,7 @@ bool TrayService::activate_menu_item(const std::string &id, int itemId) {
"(isvu)", itemId, "clicked", g_variant_new_variant(emptyData),
static_cast<guint32>(g_get_monotonic_time() / 1000));
GError *error = nullptr;
GError *error = nullptr;
GVariant *result = g_dbus_connection_call_sync(
connection->gobj(), item.publicData.busName.c_str(),
item.publicData.menuPath.c_str(), kDBusMenuInterface, "Event", params,
@@ -723,16 +723,16 @@ void TrayService::register_item(const Glib::ustring &sender,
}
const std::string id = parsed.busName + parsed.objectPath;
auto existing = items.find(id);
auto existing = items.find(id);
if (existing != items.end()) {
refresh_item(*existing->second);
itemUpdatedSignal.emit(existing->second->publicData);
return;
}
auto item = std::make_unique<TrackedItem>();
item->publicData.id = id;
item->publicData.busName = parsed.busName;
auto item = std::make_unique<TrackedItem>();
item->publicData.id = id;
item->publicData.busName = parsed.busName;
item->publicData.objectPath = parsed.objectPath;
refresh_item(*item);
@@ -789,7 +789,7 @@ void TrayService::refresh_item(TrackedItem &item) {
return;
}
GError *error = nullptr;
GError *error = nullptr;
GVariant *reply = g_dbus_connection_call_sync(
connection->gobj(), item.publicData.busName.c_str(),
item.publicData.objectPath.c_str(), kDBusPropertiesIface, "GetAll",
@@ -816,7 +816,7 @@ void TrayService::refresh_item(TrackedItem &item) {
g_variant_iter_init(&iter, dictVariant);
const gchar *key = nullptr;
GVariant *value = nullptr;
GVariant *value = nullptr;
Glib::RefPtr<Gdk::Paintable> iconTexture;
Glib::RefPtr<Gdk::Paintable> attentionTexture;
@@ -836,23 +836,23 @@ void TrayService::refresh_item(TrackedItem &item) {
if (std::strcmp(key, "Title") == 0) {
const gchar *str = g_variant_get_string(value, nullptr);
title = str ? str : "";
title = str ? str : "";
} else if (std::strcmp(key, "Status") == 0) {
const gchar *str = g_variant_get_string(value, nullptr);
status = str ? str : "";
status = str ? str : "";
} else if (std::strcmp(key, "Menu") == 0) {
if (g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH)) {
const gchar *str = g_variant_get_string(value, nullptr);
menuPath = str ? str : "";
menuPath = str ? str : "";
} else {
const gchar *str = g_variant_get_string(value, nullptr);
menuPath = str ? str : "";
menuPath = str ? str : "";
}
} else if (std::strcmp(key, "IconName") == 0) {
const gchar *str = g_variant_get_string(value, nullptr);
iconName = str ? str : "";
iconName = str ? str : "";
} else if (std::strcmp(key, "AttentionIconName") == 0) {
const gchar *str = g_variant_get_string(value, nullptr);
const gchar *str = g_variant_get_string(value, nullptr);
attentionIconName = str ? str : "";
} else if (std::strcmp(key, "IconPixmap") == 0) {
iconTexture = parse_icon_pixmap(value);
@@ -864,10 +864,10 @@ void TrayService::refresh_item(TrackedItem &item) {
}
g_variant_unref(dictVariant);
const bool menuPathChanged = (item.publicData.menuPath != menuPath);
item.publicData.title = title;
item.publicData.status = status;
item.publicData.menuPath = menuPath;
const bool menuPathChanged = (item.publicData.menuPath != menuPath);
item.publicData.title = title;
item.publicData.status = status;
item.publicData.menuPath = menuPath;
item.publicData.menuAvailable = !menuPath.empty();
if (menuPathChanged || !item.publicData.menuAvailable) {
@@ -1029,7 +1029,7 @@ Glib::RefPtr<Gdk::Paintable> TrayService::parse_icon_pixmap(GVariant *variant) {
return {};
}
int32_t width = 0;
int32_t width = 0;
int32_t height = 0;
g_variant_get_child(entry, 0, "i", &width);
g_variant_get_child(entry, 1, "i", &height);
@@ -1045,7 +1045,7 @@ Glib::RefPtr<Gdk::Paintable> TrayService::parse_icon_pixmap(GVariant *variant) {
return {};
}
gsize rawLength = 0;
gsize rawLength = 0;
const guint8 *rawBytes = static_cast<const guint8 *>(
g_variant_get_fixed_array(bytesVariant, &rawLength, sizeof(guint8)));
if (!rawBytes || rawLength < static_cast<gsize>(width * height * 4)) {
@@ -1062,16 +1062,16 @@ Glib::RefPtr<Gdk::Paintable> TrayService::parse_icon_pixmap(GVariant *variant) {
const guint32 *pixels = reinterpret_cast<const guint32 *>(rawBytes);
for (std::size_t idx = 0; idx < pixelCount; ++idx) {
const guint32 pixel = pixels[idx];
const guint8 a = static_cast<guint8>((pixel >> 24) & 0xFF);
const guint8 r = static_cast<guint8>((pixel >> 16) & 0xFF);
const guint8 g = static_cast<guint8>((pixel >> 8) & 0xFF);
const guint8 b = static_cast<guint8>(pixel & 0xFF);
const guint8 a = static_cast<guint8>((pixel >> 24) & 0xFF);
const guint8 r = static_cast<guint8>((pixel >> 16) & 0xFF);
const guint8 g = static_cast<guint8>((pixel >> 8) & 0xFF);
const guint8 b = static_cast<guint8>(pixel & 0xFF);
const std::size_t base = idx * 4;
rgba[base + 0] = r;
rgba[base + 1] = g;
rgba[base + 2] = b;
rgba[base + 3] = a;
rgba[base + 0] = r;
rgba[base + 1] = g;
rgba[base + 2] = b;
rgba[base + 3] = a;
}
auto pixbuf =
@@ -1082,9 +1082,9 @@ Glib::RefPtr<Gdk::Paintable> TrayService::parse_icon_pixmap(GVariant *variant) {
return {};
}
auto *dest = pixbuf->get_pixels();
auto *dest = pixbuf->get_pixels();
const int destRowstride = pixbuf->get_rowstride();
const int srcRowstride = width * 4;
const int srcRowstride = width * 4;
for (int y = 0; y < height; ++y) {
std::memcpy(dest + y * destRowstride,