From 0c8acbf39e4ce88adea5ff9f2eebaab7c6bb9cf0 Mon Sep 17 00:00:00 2001 From: Nick Janetakis Date: Mon, 2 Mar 2026 19:10:55 -0500 Subject: [PATCH 1/4] Add support for optional CSS classes --- src/modules/clock.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 5fe5407b..88f2ec69 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -187,6 +187,52 @@ auto waybar::modules::Clock::update() -> void { } m_tlpText_ = fmt_lib::vformat(m_locale_, m_tlpText_, fmt_lib::make_format_args(now)); + + // Pango doesn't support CSS classes but to continue using it while staying + // backwards compatible this approach uses post-posting to replace fake + // classes with attributes Pango does understand. + // + // The benefit of this approach is anyone using the original styling choices + // can continue doing that and folks can optionally opt into using classes. + // + // It's also forwards compatible to where if this implemention ever changes + // to support proper classes anyone using them will continue to work. + auto context = label_.get_style_context(); + + const std::vector> calendar_class_map = { + {"calendar-today", "today"}, + {"calendar-days", "days"}, + {"calendar-weeks", "weeks"}, + {"calendar-weekdays", "weekdays"}, + {"calendar-months", "months"} + }; + + for (const auto& [css_class, json_key] : calendar_class_map) { + try { + context->add_class(css_class); + Gdk::RGBA color = context->get_color(); + context->remove_class(css_class); + + std::string hex = fmt::format("#{:02x}{:02x}{:02x}", + static_cast(color.get_red() * 255), + static_cast(color.get_green() * 255), + static_cast(color.get_blue() * 255)); + + std::string search = "class='" + json_key + "'"; + std::string replace = "color='" + hex + "'"; + + for (size_t pos = 0; (pos = m_tlpText_.find(search, pos)) != std::string::npos; pos += replace.length()) { + m_tlpText_.replace(pos, search.length(), replace); + } + } catch (const Glib::Error& e) { + spdlog::warn("Clock: Failed to fetch CSS color for {}: {}", css_class, e.what().raw()); + continue; + } catch (...) { + // Catch-all for any other weirdness. + continue; + } + } + m_tooltip_->set_markup(m_tlpText_); label_.trigger_tooltip_query(); } From c85f2a23de79198fd67b46b09d0fe9a90cfb4797 Mon Sep 17 00:00:00 2001 From: Nick Janetakis Date: Mon, 2 Mar 2026 21:29:15 -0500 Subject: [PATCH 2/4] Add readability improvements and optimizations Replace the inner loop with regex_replace. We're already using this elsewhere and the performance difference isn't worth the loss of human readability. Use static const to pre-calc the search string. --- src/modules/clock.cpp | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 88f2ec69..ec8b71e7 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -199,31 +199,26 @@ auto waybar::modules::Clock::update() -> void { // to support proper classes anyone using them will continue to work. auto context = label_.get_style_context(); - const std::vector> calendar_class_map = { - {"calendar-today", "today"}, - {"calendar-days", "days"}, - {"calendar-weeks", "weeks"}, - {"calendar-weekdays", "weekdays"}, - {"calendar-months", "months"} + static const std::vector> calendar_class_map = { + {"calendar-today", "class='today'"}, + {"calendar-days", "class='days'"}, + {"calendar-weeks", "class='weeks'"}, + {"calendar-weekdays", "class='weekdays'"}, + {"calendar-months", "class='months'"} }; - for (const auto& [css_class, json_key] : calendar_class_map) { + for (const auto& [css_class, search_str] : calendar_class_map) { try { context->add_class(css_class); - Gdk::RGBA color = context->get_color(); + const Gdk::RGBA color = context->get_color(); context->remove_class(css_class); - std::string hex = fmt::format("#{:02x}{:02x}{:02x}", - static_cast(color.get_red() * 255), + const std::string replace_str = fmt::format("color='#{:02x}{:02x}{:02x}'", + static_cast(color.get_red() * 255, static_cast(color.get_green() * 255), static_cast(color.get_blue() * 255)); - std::string search = "class='" + json_key + "'"; - std::string replace = "color='" + hex + "'"; - - for (size_t pos = 0; (pos = m_tlpText_.find(search, pos)) != std::string::npos; pos += replace.length()) { - m_tlpText_.replace(pos, search.length(), replace); - } + m_tlpText_ = std::regex_replace(m_tlpText_, std::regex(search_str), replace_str); } catch (const Glib::Error& e) { spdlog::warn("Clock: Failed to fetch CSS color for {}: {}", css_class, e.what().raw()); continue; From e736a934ba2f6a5754428e8d61dbf84316eae96a Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 3 Jul 2026 22:10:13 +0200 Subject: [PATCH 3/4] fix(clock): correct parentheses in fmt::format for calendar tooltip color --- src/modules/clock.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 5d09f72f..df3c2cc6 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -214,7 +214,7 @@ auto waybar::modules::Clock::update() -> void { context->remove_class(css_class); const std::string replace_str = fmt::format("color='#{:02x}{:02x}{:02x}'", - static_cast(color.get_red() * 255, + static_cast(color.get_red() * 255), static_cast(color.get_green() * 255), static_cast(color.get_blue() * 255)); From 573ad779bad545269ef52380a5cf5e9788b5c0a6 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 3 Jul 2026 22:21:03 +0200 Subject: [PATCH 4/4] Apply clang-format to clock.cpp --- src/modules/clock.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index df3c2cc6..bdeaf889 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -200,12 +200,11 @@ auto waybar::modules::Clock::update() -> void { auto context = label_.get_style_context(); static const std::vector> calendar_class_map = { - {"calendar-today", "class='today'"}, - {"calendar-days", "class='days'"}, - {"calendar-weeks", "class='weeks'"}, + {"calendar-today", "class='today'"}, + {"calendar-days", "class='days'"}, + {"calendar-weeks", "class='weeks'"}, {"calendar-weekdays", "class='weekdays'"}, - {"calendar-months", "class='months'"} - }; + {"calendar-months", "class='months'"}}; for (const auto& [css_class, search_str] : calendar_class_map) { try { @@ -213,18 +212,17 @@ auto waybar::modules::Clock::update() -> void { const Gdk::RGBA color = context->get_color(); context->remove_class(css_class); - const std::string replace_str = fmt::format("color='#{:02x}{:02x}{:02x}'", - static_cast(color.get_red() * 255), - static_cast(color.get_green() * 255), - static_cast(color.get_blue() * 255)); + const std::string replace_str = fmt::format( + "color='#{:02x}{:02x}{:02x}'", static_cast(color.get_red() * 255), + static_cast(color.get_green() * 255), static_cast(color.get_blue() * 255)); m_tlpText_ = std::regex_replace(m_tlpText_, std::regex(search_str), replace_str); } catch (const Glib::Error& e) { - spdlog::warn("Clock: Failed to fetch CSS color for {}: {}", css_class, e.what().raw()); - continue; + spdlog::warn("Clock: Failed to fetch CSS color for {}: {}", css_class, e.what().raw()); + continue; } catch (...) { - // Catch-all for any other weirdness. - continue; + // Catch-all for any other weirdness. + continue; } }