From a51bddab9efa44c8398eb05ed61dc4cca83850e8 Mon Sep 17 00:00:00 2001 From: Austin Horstman Date: Sun, 5 Jul 2026 01:18:26 -0500 Subject: [PATCH] fix(label): compare markup cache by raw bytes, not collation 2190871a (perf(label): skip redundant markup updates) caches the last label/tooltip markup as Glib::ustring and skips set_markup() when the new markup compares equal. Glib::ustring::operator== goes through g_utf8_collate(), and under the UTF-8 locale GTK sets at startup, Unicode private-use codepoints carry no collation weight. All nerd-font icons live in the PUA, so two labels that differ only in their icon glyph collate as equal and the visual update is silently dropped. idle_inhibitor is the visible victim (#5169): clicking toggles the state class (highlight changes) but the {icon} glyph never switches between the activated/deactivated icons, while plain-text icons like "YES"/"NO" work. Any ALabel module whose consecutive updates differ only by a PUA glyph is affected. The module only started routing through this cache when db4941ef migrated it onto the shared setLabelMarkup()/setTooltipMarkup() helpers, which is why it broke in the latest batch of refactors. Store the cache as raw UTF-8 bytes (std::string via ustring::raw()) and compare those instead, so the skip only triggers on byte-identical markup. Reproduced and verified under a nested niri session: before the fix RTMIN+n toggled the state class but left the sleep glyph unchanged; after it the glyph flips as expected, and byte-identical updates are still skipped. --- include/ALabel.hpp | 7 +++++-- src/ALabel.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/ALabel.hpp b/include/ALabel.hpp index 201d640c..3e3690b1 100644 --- a/include/ALabel.hpp +++ b/include/ALabel.hpp @@ -87,8 +87,11 @@ class ALabel : public AModule { static void handleGtkMenuEvent(GtkMenuItem* menuitem, gpointer data); private: - std::optional last_label_markup_; - std::optional last_tooltip_markup_; + // Raw UTF-8 bytes, not Glib::ustring: ustring::operator== collates with + // g_utf8_collate(), which gives private-use codepoints (nerd-font icons) + // no collation weight, so two different icons compare equal. + std::optional last_label_markup_; + std::optional last_tooltip_markup_; }; } // namespace waybar diff --git a/src/ALabel.cpp b/src/ALabel.cpp index 84ac2052..752c80bd 100644 --- a/src/ALabel.cpp +++ b/src/ALabel.cpp @@ -147,22 +147,22 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st auto ALabel::update() -> void { AModule::update(); } bool ALabel::setLabelMarkup(const Glib::ustring& markup) { - if (last_label_markup_ == markup) { + if (last_label_markup_ == markup.raw()) { return false; } label_.set_markup(markup); - last_label_markup_ = markup; + last_label_markup_ = markup.raw(); return true; } bool ALabel::setTooltipMarkup(const Glib::ustring& markup) { - if (last_tooltip_markup_ == markup) { + if (last_tooltip_markup_ == markup.raw()) { return false; } label_.set_tooltip_markup(markup); - last_tooltip_markup_ = markup; + last_tooltip_markup_ = markup.raw(); return true; }