Merge pull request #3017 from 0x000C0A71/master

[hyprland/workspaces] Add tooltips to hyprland/workspaces
This commit is contained in:
Alexis Rouillard
2026-07-04 01:12:10 +02:00
committed by GitHub
5 changed files with 82 additions and 7 deletions
+2 -2
View File
@@ -31,7 +31,7 @@ class Workspace {
explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager, explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager,
const Json::Value& clients_data = Json::Value::nullRef); const Json::Value& clients_data = Json::Value::nullRef);
~Workspace(); ~Workspace();
std::string& selectIcon(std::map<std::string, std::string>& icons_map); std::string& selectString(std::map<std::string, std::string>& string_map);
Gtk::Button& button() { return m_button; }; Gtk::Button& button() { return m_button; };
int id() const { return m_id; }; int id() const { return m_id; };
@@ -74,7 +74,7 @@ class Workspace {
bool onWindowOpened(WindowCreationPayload const& create_window_payload); bool onWindowOpened(WindowCreationPayload const& create_window_payload);
std::optional<WindowRepr> closeWindow(WindowAddress const& addr); std::optional<WindowRepr> closeWindow(WindowAddress const& addr);
void update(const std::string& workspace_icon); void update(const std::string& workspace_icon, const std::string& workspace_tooltip);
private: private:
Workspaces& m_workspaceManager; Workspaces& m_workspaceManager;
+2
View File
@@ -179,6 +179,8 @@ class Workspaces : public AModule, public EventHandler {
std::string m_formatAfter; std::string m_formatAfter;
std::map<std::string, std::string> m_iconsMap; std::map<std::string, std::string> m_iconsMap;
std::map<std::string, std::string> m_tooltipMap;
bool m_withTooltip = false;
util::RegexCollection m_windowRewriteRules; util::RegexCollection m_windowRewriteRules;
bool m_anyWindowRewriteRuleUsesTitle = false; bool m_anyWindowRewriteRuleUsesTitle = false;
std::string m_formatWindowSeparator; std::string m_formatWindowSeparator;
+54
View File
@@ -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 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. 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*: ++ *expand*: ++
typeof: bool ++ typeof: bool ++
default: false ++ 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 # Style
- *#workspaces* - *#workspaces*
+9 -3
View File
@@ -296,8 +296,8 @@ bool Workspace::onWindowOpened(WindowCreationPayload const& create_window_payloa
return false; return false;
} }
std::string& Workspace::selectIcon(std::map<std::string, std::string>& icons_map) { std::string& Workspace::selectString(std::map<std::string, std::string>& icons_map) {
spdlog::trace("Selecting icon for workspace {}", name()); spdlog::trace("Selecting string for workspace {}", name());
if (isUrgent()) { if (isUrgent()) {
auto urgentNamedIconIt = icons_map.find("urgent:" + name()); auto urgentNamedIconIt = icons_map.find("urgent:" + name());
if (urgentNamedIconIt != icons_map.end()) { if (urgentNamedIconIt != icons_map.end()) {
@@ -379,7 +379,7 @@ std::string& Workspace::selectIcon(std::map<std::string, std::string>& icons_map
return m_name; 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()) { if (this->m_workspaceManager.persistentOnly() && !this->isPersistent()) {
m_button.hide(); m_button.hide();
return; 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(); auto formatBefore = m_workspaceManager.formatBefore();
m_labelBefore.set_markup(fmt::format(fmt::runtime(formatBefore), fmt::arg("id", id()), m_labelBefore.set_markup(fmt::format(fmt::runtime(formatBefore), fmt::arg("id", id()),
fmt::arg("name", name()), fmt::arg("icon", workspace_icon), fmt::arg("name", name()), fmt::arg("icon", workspace_icon),
+15 -2
View File
@@ -675,6 +675,15 @@ auto Workspaces::parseConfig(const Json::Value& config) -> void {
populateIconsMap(config["format-icons"]); 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, "all-outputs", m_allOutputs);
populateBoolConfig(config, "show-special", m_showSpecial); populateBoolConfig(config, "show-special", m_showSpecial);
populateBoolConfig(config, "special-visible-only", m_specialVisibleOnly); populateBoolConfig(config, "special-visible-only", m_specialVisibleOnly);
@@ -1155,7 +1164,11 @@ void Workspaces::updateWorkspaceStates() {
visibleWorkspaces.end()); visibleWorkspaces.end());
std::string& workspaceIcon = m_iconsMap[""]; std::string& workspaceIcon = m_iconsMap[""];
if (m_withIcon) { 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 updatedWorkspace = std::ranges::find_if(updatedWorkspaces, [&workspace](const auto& w) {
auto wNameRaw = w["name"].asString(); auto wNameRaw = w["name"].asString();
@@ -1165,7 +1178,7 @@ void Workspaces::updateWorkspaceStates() {
if (updatedWorkspace != updatedWorkspaces.end()) { if (updatedWorkspace != updatedWorkspaces.end()) {
workspace->setOutput((*updatedWorkspace)["monitor"].asString()); workspace->setOutput((*updatedWorkspace)["monitor"].asString());
} }
workspace->update(workspaceIcon); workspace->update(workspaceIcon, workspaceTooltip);
} }
} }