Merge remote-tracking branch 'origin/master' into finitemonkey/master

This commit is contained in:
Alex
2026-07-03 21:59:43 +02:00
9 changed files with 104 additions and 18 deletions
+9
View File
@@ -4,6 +4,8 @@
#include <gtkmm/label.h> #include <gtkmm/label.h>
#include <json/json.h> #include <json/json.h>
#include <optional>
#include "AModule.hpp" #include "AModule.hpp"
namespace waybar { namespace waybar {
@@ -25,12 +27,19 @@ class ALabel : public AModule {
bool alt_ = false; bool alt_ = false;
std::string default_format_; std::string default_format_;
bool setLabelMarkup(const Glib::ustring& markup);
bool setTooltipMarkup(const Glib::ustring& markup);
bool handleToggle(GdkEventButton* const& e) override; bool handleToggle(GdkEventButton* const& e) override;
virtual std::string getState(uint8_t value, bool lesser = false); virtual std::string getState(uint8_t value, bool lesser = false);
std::map<std::string, GtkMenuItem*> submenus_; std::map<std::string, GtkMenuItem*> submenus_;
std::map<std::string, std::string> menuActionsMap_; std::map<std::string, std::string> menuActionsMap_;
static void handleGtkMenuEvent(GtkMenuItem* menuitem, gpointer data); static void handleGtkMenuEvent(GtkMenuItem* menuitem, gpointer data);
private:
std::optional<Glib::ustring> last_label_markup_;
std::optional<Glib::ustring> last_tooltip_markup_;
}; };
} // namespace waybar } // namespace waybar
+5
View File
@@ -57,6 +57,11 @@ Addressed by *wlr/taskbar*
default: false ++ default: false ++
If set to true, group tasks by their app_id. Cannot be used with 'active-first'. If set to true, group tasks by their app_id. Cannot be used with 'active-first'.
*expand*: ++
typeof: bool ++
default: false ++
If set to true, task buttons stretch to fill the available space in the taskbar and long titles are ellipsized to fit. Only takes effect on a horizontal bar; on a vertical bar the buttons keep their content-based size. If set to false, buttons are sized to their content.
*on-click*: ++ *on-click*: ++
typeof: string ++ typeof: string ++
The action which should be triggered when clicking on the application button with the left mouse button. The action which should be triggered when clicking on the application button with the left mouse button.
+1
View File
@@ -168,6 +168,7 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles(
# MODULE FORMAT # MODULE FORMAT
You can use PangoMarkupFormat (See https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat). You can use PangoMarkupFormat (See https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat).
Tooltip appearance is generally controlled globally via CSS and cannot be truly scoped per module. Some modules (such as the clock) provide limited workarounds for customization.
e.g. e.g.
+20
View File
@@ -139,6 +139,26 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
auto ALabel::update() -> void { AModule::update(); } auto ALabel::update() -> void { AModule::update(); }
bool ALabel::setLabelMarkup(const Glib::ustring& markup) {
if (last_label_markup_ == markup) {
return false;
}
label_.set_markup(markup);
last_label_markup_ = markup;
return true;
}
bool ALabel::setTooltipMarkup(const Glib::ustring& markup) {
if (last_tooltip_markup_ == markup) {
return false;
}
label_.set_tooltip_markup(markup);
last_tooltip_markup_ = markup;
return true;
}
std::string ALabel::getIcon(uint16_t percentage, const std::string& alt, uint16_t max) { std::string ALabel::getIcon(uint16_t percentage, const std::string& alt, uint16_t max) {
auto format_icons = config_["format-icons"]; auto format_icons = config_["format-icons"];
if (format_icons.isObject()) { if (format_icons.isObject()) {
+6 -1
View File
@@ -402,8 +402,13 @@ auto waybar::modules::Clock::get_calendar(const year_month_day& today, const yea
data = g_utf8_find_next_char(data, end); data = g_utf8_find_next_char(data, end);
} }
} }
// Note: the stream's default fill character is already a space (L' ' on
// libstdc++'s wide FormatStream, ' ' on libc++'s narrow one), so no
// std::setfill is needed. Passing std::setfill(' ')/std::setfill(L' ')
// here is not portable because the fill char type must match the
// FormatStream's char type, which differs between standard libraries.
os << Glib::ustring::format( os << Glib::ustring::format(
(cldWPos_ != WS::LEFT || line == 0) ? std::left : std::right, std::setfill(L' '), (cldWPos_ != WS::LEFT || line == 0) ? std::left : std::right,
std::setw(cldMonColLen_ + ((line < 2) ? cldWnLen_ - wideCharCount : 0)), std::setw(cldMonColLen_ + ((line < 2) ? cldWnLen_ - wideCharCount : 0)),
calendarLine); calendarLine);
+16 -5
View File
@@ -223,7 +223,11 @@ void Workspace::setActiveWindow(WindowAddress const& addr) {
} }
auto activeWindowPos = m_workspaceManager.activeWindowPosition(); auto activeWindowPos = m_workspaceManager.activeWindowPosition();
if (activeIdx.has_value() && activeWindowPos != Workspaces::ActiveWindowPosition::NONE) { const bool has_active_window =
activeIdx.has_value() &&
activeWindowPos != Workspaces::ActiveWindowPosition::NONE;
if (has_active_window) {
auto window = std::move(m_windowMap[*activeIdx]); auto window = std::move(m_windowMap[*activeIdx]);
m_windowMap.erase(m_windowMap.begin() + *activeIdx); m_windowMap.erase(m_windowMap.begin() + *activeIdx);
if (activeWindowPos == Workspaces::ActiveWindowPosition::FIRST) { if (activeWindowPos == Workspaces::ActiveWindowPosition::FIRST) {
@@ -238,7 +242,10 @@ void Workspace::insertWindow(WindowCreationPayload create_window_payload) {
if (!create_window_payload.isEmpty(m_workspaceManager)) { if (!create_window_payload.isEmpty(m_workspaceManager)) {
auto repr = create_window_payload.repr(m_workspaceManager); auto repr = create_window_payload.repr(m_workspaceManager);
if (!repr.empty() || m_workspaceManager.enableTaskbar()) { const bool should_display =
!repr.empty() || m_workspaceManager.enableTaskbar();
if (should_display) {
auto addr = create_window_payload.getAddress(); auto addr = create_window_payload.getAddress();
auto it = std::ranges::find_if( auto it = std::ranges::find_if(
m_windowMap, [&addr](const auto& window) { return window.address == addr; }); m_windowMap, [&addr](const auto& window) { return window.address == addr; });
@@ -250,7 +257,7 @@ void Workspace::insertWindow(WindowCreationPayload create_window_payload) {
} }
} }
} }
}; }
bool Workspace::onWindowOpened(WindowCreationPayload const& create_window_payload) { bool Workspace::onWindowOpened(WindowCreationPayload const& create_window_payload) {
if (create_window_payload.getWorkspaceName() == name()) { if (create_window_payload.getWorkspaceName() == name()) {
@@ -390,7 +397,9 @@ void Workspace::update(const std::string& workspace_icon) {
bool Workspace::isEmpty() const { bool Workspace::isEmpty() const {
auto ignore_list = m_workspaceManager.getIgnoredWindows(); auto ignore_list = m_workspaceManager.getIgnoredWindows();
if (ignore_list.empty()) { const bool no_ignore_rules = ignore_list.empty();
if (no_ignore_rules) {
return m_windows == 0; return m_windows == 0;
} }
// If there are windows but they are all ignored, consider the workspace empty // If there are windows but they are all ignored, consider the workspace empty
@@ -472,7 +481,9 @@ void Workspace::updateTaskbar(const std::string& workspace_icon) {
} }
auto formatAfter = m_workspaceManager.formatAfter(); auto formatAfter = m_workspaceManager.formatAfter();
if (!formatAfter.empty()) { const bool has_format_after = !formatAfter.empty();
if (has_format_after) {
m_labelAfter.set_markup(fmt::format(fmt::runtime(formatAfter), fmt::arg("id", id()), m_labelAfter.set_markup(fmt::format(fmt::runtime(formatAfter), fmt::arg("id", id()),
fmt::arg("name", name()), fmt::arg("name", name()),
fmt::arg("icon", workspace_icon))); fmt::arg("icon", workspace_icon)));
+7 -6
View File
@@ -85,7 +85,7 @@ void waybar::modules::MPD::setLabel() {
? config_["format-disconnected"].asString() ? config_["format-disconnected"].asString()
: "disconnected"; : "disconnected";
if (format.empty()) { if (format.empty()) {
label_.set_markup(format); setLabelMarkup(format);
label_.show(); label_.show();
} else { } else {
label_.hide(); label_.hide();
@@ -97,7 +97,7 @@ void waybar::modules::MPD::setLabel() {
? config_["tooltip-format-disconnected"].asString() ? config_["tooltip-format-disconnected"].asString()
: "MPD (disconnected)"; : "MPD (disconnected)";
// Nothing to format // Nothing to format
label_.set_tooltip_markup(tooltip_format); setTooltipMarkup(tooltip_format);
} }
return; return;
} }
@@ -124,8 +124,9 @@ void waybar::modules::MPD::setLabel() {
label_.get_style_context()->add_class("playing"); label_.get_style_context()->add_class("playing");
label_.get_style_context()->remove_class("paused"); label_.get_style_context()->remove_class("paused");
} else if (paused()) { } else if (paused()) {
format = config_["format-paused"].isString() ? config_["format-paused"].asString() if (config_["format-paused"].isString()) {
: config_["format"].asString(); format = config_["format-paused"].asString();
}
label_.get_style_context()->add_class("paused"); label_.get_style_context()->add_class("paused");
label_.get_style_context()->remove_class("playing"); label_.get_style_context()->remove_class("playing");
} }
@@ -168,7 +169,7 @@ void waybar::modules::MPD::setLabel() {
label_.hide(); label_.hide();
} else { } else {
label_.show(); label_.show();
label_.set_markup(text); setLabelMarkup(text);
} }
} catch (fmt::format_error const& e) { } catch (fmt::format_error const& e) {
spdlog::warn("mpd: format error: {}", e.what()); spdlog::warn("mpd: format error: {}", e.what());
@@ -188,7 +189,7 @@ void waybar::modules::MPD::setLabel() {
fmt::arg("stateIcon", stateIcon), fmt::arg("consumeIcon", consumeIcon), fmt::arg("stateIcon", stateIcon), fmt::arg("consumeIcon", consumeIcon),
fmt::arg("randomIcon", randomIcon), fmt::arg("repeatIcon", repeatIcon), fmt::arg("randomIcon", randomIcon), fmt::arg("repeatIcon", repeatIcon),
fmt::arg("singleIcon", singleIcon), fmt::arg("filename", filename), fmt::arg("uri", uri)); fmt::arg("singleIcon", singleIcon), fmt::arg("filename", filename), fmt::arg("uri", uri));
label_.set_tooltip_markup(tooltip_text); setTooltipMarkup(tooltip_text);
} catch (fmt::format_error const& e) { } catch (fmt::format_error const& e) {
spdlog::warn("mpd: format error (tooltip): {}", e.what()); spdlog::warn("mpd: format error (tooltip): {}", e.what());
} }
+2 -2
View File
@@ -94,12 +94,12 @@ auto Window::update() -> void {
old_app_id_ = app_id_; old_app_id_ = app_id_;
} }
label_.set_markup(waybar::util::rewriteString( setLabelMarkup(waybar::util::rewriteString(
fmt::format(fmt::runtime(format_), fmt::arg("title", window_), fmt::arg("app_id", app_id_), fmt::format(fmt::runtime(format_), fmt::arg("title", window_), fmt::arg("app_id", app_id_),
fmt::arg("shell", shell_), fmt::arg("marks", marks_)), fmt::arg("shell", shell_), fmt::arg("marks", marks_)),
config_["rewrite"])); config_["rewrite"]));
if (tooltipEnabled()) { if (tooltipEnabled()) {
label_.set_tooltip_markup(window_); setTooltipMarkup(window_);
} }
updateAppIcon(); updateAppIcon();
+34
View File
@@ -94,9 +94,35 @@ Task::Task(const waybar::Bar& bar, const Json::Value& config, Taskbar* tbar,
button.set_relief(Gtk::RELIEF_NONE); button.set_relief(Gtk::RELIEF_NONE);
/* When "expand" is enabled the buttons stretch to fill the taskbar and the
* titles ellipsize to fit within the available space. This only makes sense
* on a horizontal bar; on a vertical bar the box grows along the vertical
* axis, so ellipsizing/forcing width_chars(1) would truncate every title to
* "…". Keep the historical behavior (buttons sized to their content) as the
* default and when the bar is vertical. */
bool expand = config_["expand"].isBool() && config_["expand"].asBool();
bool horizontal = bar.orientation == Gtk::ORIENTATION_HORIZONTAL;
if (expand && horizontal) {
button.set_hexpand(true);
content_.set_hexpand(true);
text_before_.set_ellipsize(Pango::ELLIPSIZE_END);
text_before_.set_single_line_mode(true);
text_before_.set_width_chars(1);
text_before_.set_xalign(0.0);
text_after_.set_ellipsize(Pango::ELLIPSIZE_END);
text_after_.set_single_line_mode(true);
text_after_.set_width_chars(1);
text_after_.set_xalign(0.0);
content_.pack_start(text_before_, true, true, 0);
content_.pack_start(icon_, false, false, 0);
content_.pack_start(text_after_, true, true, 0);
} else {
content_.add(text_before_); content_.add(text_before_);
content_.add(icon_); content_.add(icon_);
content_.add(text_after_); content_.add(text_after_);
}
content_.show(); content_.show();
button.add(content_); button.add(content_);
@@ -718,7 +744,15 @@ void Taskbar::handle_finished() {
} }
void Taskbar::add_button(Gtk::Button& bt) { void Taskbar::add_button(Gtk::Button& bt) {
/* Only let the buttons expand to fill the taskbar when "expand" is enabled
* and the bar is horizontal (see the Task constructor for details). */
bool expand = config_["expand"].isBool() && config_["expand"].asBool();
bool horizontal = bar_.orientation == Gtk::ORIENTATION_HORIZONTAL;
if (expand && horizontal) {
box_.pack_start(bt, true, true);
} else {
box_.pack_start(bt, false, false); box_.pack_start(bt, false, false);
}
box_.get_style_context()->remove_class("empty"); box_.get_style_context()->remove_class("empty");
} }