diff --git a/include/modules/hyprland/workspace.hpp b/include/modules/hyprland/workspace.hpp index cd3485c5..519c347b 100644 --- a/include/modules/hyprland/workspace.hpp +++ b/include/modules/hyprland/workspace.hpp @@ -31,7 +31,7 @@ class Workspace { explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager, const Json::Value& clients_data = Json::Value::nullRef); ~Workspace(); - std::string& selectIcon(std::map& icons_map); + std::string& selectString(std::map& string_map); Gtk::Button& button() { return m_button; }; int id() const { return m_id; }; @@ -74,7 +74,7 @@ class Workspace { bool onWindowOpened(WindowCreationPayload const& create_window_payload); std::optional closeWindow(WindowAddress const& addr); - void update(const std::string& workspace_icon); + void update(const std::string& workspace_icon, const std::string& workspace_tooltip); private: Workspaces& m_workspaceManager; diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 453849d8..4be7fd44 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -179,6 +179,8 @@ class Workspaces : public AModule, public EventHandler { std::string m_formatAfter; std::map m_iconsMap; + std::map m_tooltipMap; + bool m_withTooltip = false; util::RegexCollection m_windowRewriteRules; bool m_anyWindowRewriteRuleUsesTitle = false; std::string m_formatWindowSeparator; diff --git a/man/waybar-hyprland-workspaces.5.scd b/man/waybar-hyprland-workspaces.5.scd index 350ee745..e296b6b9 100644 --- a/man/waybar-hyprland-workspaces.5.scd +++ b/man/waybar-hyprland-workspaces.5.scd @@ -195,6 +195,15 @@ This setting is ignored if *workspace-taskbar.enable* is set to true. If set to special-centered, workspaces will sort by default with special workspaces in the center. If none of those, workspaces will sort with default behavior. +*tooltip*: ++ + typeof: bool ++ + default: true ++ + Option to disable tooltip on hover. + +*tooltips*: ++ + typeof: array ++ + Based on the workspace ID and state, the corresponding tooltip gets selected. Selection works the same as *format-icons* do. Format replacements are supported. See *icons*. + *expand*: ++ typeof: bool ++ default: false ++ @@ -284,6 +293,51 @@ Additional to workspace name matching, the following *format-icons* can be set. } ``` +``` +"hyprland/workspaces": { + "format": "{icon}", + "format-window-separator": ", ", + "tooltip": true, + "tooltips": { + "default": "{name}: {windows}", + "empty": "" // Will result in no tooltip + } + "format-icons": { + "1": "", + "2": "", + "3": "", + "4": "", + "5": "", + "active": "", + "default": "" + }, + // Window rewrites omitted for brevity +} +``` + +``` +"hyprland/workspaces": { + "format": "{icon}", + "format-window-separator": ", ", + "tooltip": true, + "tooltips": { + "1": "This is the first workspace", + "2": "This is the second", + "2": "And this is the third" + } + "format-icons": { + "1": "", + "2": "", + "3": "", + "4": "", + "5": "", + "active": "", + "default": "" + }, + // Window rewrites omitted for brevity +} +``` + # Style - *#workspaces* diff --git a/src/modules/hyprland/workspace.cpp b/src/modules/hyprland/workspace.cpp index aa0243bf..ade7a10f 100644 --- a/src/modules/hyprland/workspace.cpp +++ b/src/modules/hyprland/workspace.cpp @@ -296,8 +296,8 @@ bool Workspace::onWindowOpened(WindowCreationPayload const& create_window_payloa return false; } -std::string& Workspace::selectIcon(std::map& icons_map) { - spdlog::trace("Selecting icon for workspace {}", name()); +std::string& Workspace::selectString(std::map& icons_map) { + spdlog::trace("Selecting string for workspace {}", name()); if (isUrgent()) { auto urgentNamedIconIt = icons_map.find("urgent:" + name()); if (urgentNamedIconIt != icons_map.end()) { @@ -379,7 +379,7 @@ std::string& Workspace::selectIcon(std::map& icons_map return m_name; } -void Workspace::update(const std::string& workspace_icon) { +void Workspace::update(const std::string& workspace_icon, const std::string& workspace_tooltip) { if (this->m_workspaceManager.persistentOnly() && !this->isPersistent()) { m_button.hide(); return; @@ -489,6 +489,12 @@ void Workspace::update(const std::string& workspace_icon) { } } + if (!workspace_tooltip.empty()) { + m_button.set_tooltip_text( + fmt::format(fmt::runtime(workspace_tooltip), fmt::arg("id", id()), fmt::arg("name", name()), + fmt::arg("icon", workspace_icon), fmt::arg("windows", windows))); + } + auto formatBefore = m_workspaceManager.formatBefore(); m_labelBefore.set_markup(fmt::format(fmt::runtime(formatBefore), fmt::arg("id", id()), fmt::arg("name", name()), fmt::arg("icon", workspace_icon), diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 031938be..46402055 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -675,6 +675,15 @@ auto Workspaces::parseConfig(const Json::Value& config) -> void { populateIconsMap(config["format-icons"]); } + m_withTooltip = tooltipEnabled(); + if (m_withTooltip && m_tooltipMap.empty()) { + const Json::Value& tooltipFormats = config["tooltips"]; + for (const auto& name : tooltipFormats.getMemberNames()) { + m_tooltipMap.emplace(name, tooltipFormats[name].asString()); + } + m_tooltipMap.emplace("", ""); + } + populateBoolConfig(config, "all-outputs", m_allOutputs); populateBoolConfig(config, "show-special", m_showSpecial); populateBoolConfig(config, "special-visible-only", m_specialVisibleOnly); @@ -1155,7 +1164,11 @@ void Workspaces::updateWorkspaceStates() { visibleWorkspaces.end()); std::string& workspaceIcon = m_iconsMap[""]; if (m_withIcon) { - workspaceIcon = workspace->selectIcon(m_iconsMap); + workspaceIcon = workspace->selectString(m_iconsMap); + } + std::string& workspaceTooltip = m_tooltipMap[""]; + if (m_withTooltip) { + workspaceTooltip = workspace->selectString(m_tooltipMap); } auto updatedWorkspace = std::ranges::find_if(updatedWorkspaces, [&workspace](const auto& w) { auto wNameRaw = w["name"].asString(); @@ -1165,7 +1178,7 @@ void Workspaces::updateWorkspaceStates() { if (updatedWorkspace != updatedWorkspaces.end()) { workspace->setOutput((*updatedWorkspace)["monitor"].asString()); } - workspace->update(workspaceIcon); + workspace->update(workspaceIcon, workspaceTooltip); } }