From df7f1fffcf56bcbd54d92c6085692236dd7ab968 Mon Sep 17 00:00:00 2001 From: Tom Benham Date: Mon, 4 Mar 2024 13:17:30 +0100 Subject: [PATCH] feat(hyprland/workspaces): added options `move-to-monitor` and `active-per-monitor` --- include/modules/hyprland/workspaces.hpp | 4 ++ man/waybar-hyprland-workspaces.5.scd | 15 ++++++ src/modules/hyprland/workspaces.cpp | 61 ++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 91ea1653..df72f343 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -126,6 +126,8 @@ class Workspaces : public AModule, public EventHandler { auto allOutputs() const -> bool { return m_allOutputs; } auto showSpecial() const -> bool { return m_showSpecial; } auto activeOnly() const -> bool { return m_activeOnly; } + auto moveToMonitor() const -> bool { return m_moveToMonitor; } + auto activePerMonitor() const -> bool { return m_activePerMonitor; } auto getBarOutput() const -> std::string { return m_bar.output->name; } @@ -182,6 +184,8 @@ class Workspaces : public AModule, public EventHandler { bool m_allOutputs = false; bool m_showSpecial = false; bool m_activeOnly = false; + bool m_moveToMonitor = false; + bool m_activePerMonitor = false; Json::Value m_persistentWorkspaceConfig; // Map for windows stored in workspaces not present in the current bar. diff --git a/man/waybar-hyprland-workspaces.5.scd b/man/waybar-hyprland-workspaces.5.scd index 12c1fe39..44218f9a 100644 --- a/man/waybar-hyprland-workspaces.5.scd +++ b/man/waybar-hyprland-workspaces.5.scd @@ -52,6 +52,21 @@ Addressed by *hyprland/workspaces* default: false ++ If set to true, only the active workspace will be shown. +*move-to-monitor*: ++ + typeof: bool ++ + default: false ++ + If set to true, open the workspace on the current monitor when clicking on a workspace button. + Otherwise, the workspace will open on the monitor where it was previously assigned. + Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland. + +*active-per-monitor*: ++ + typeof: bool ++ + default: false ++ + If set to true, each bar on each monitor will show its separate active + workspace being the currently focused workspace on this monitor. + Otherwise, all bars on all monitors will show the same active workspace + being the currently focused workspace on the currently focused monitor. + *ignore-workspaces*: ++ typeof: array ++ default: [] ++ diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 882e3806..458da823 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -83,6 +83,16 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void { m_activeOnly = configActiveOnly.asBool(); } + auto configMoveToMonitor = config_["move-to-monitor"]; + if (configMoveToMonitor.isBool()) { + m_moveToMonitor = configMoveToMonitor.asBool(); + } + + auto configActivePerMonitor = config_["active-per-monitor"]; + if (configActivePerMonitor.isBool()) { + m_activePerMonitor = configActivePerMonitor.asBool(); + } + auto configSortBy = config_["sort-by"]; if (configSortBy.isString()) { auto sortByStr = configSortBy.asString(); @@ -321,7 +331,14 @@ void Workspaces::onEvent(const std::string &ev) { } void Workspaces::onWorkspaceActivated(std::string const &payload) { - m_activeWorkspaceName = payload; + if (!m_activePerMonitor) { + m_activeWorkspaceName = payload; + return; + } + auto activeWorkspace = gIPC->getSocket1JsonReply("activeworkspace"); + if (m_bar.output->name == activeWorkspace["monitor"].asString()) { + m_activeWorkspaceName = payload; + } } void Workspaces::onSpecialWorkspaceActivated(std::string const &payload) { @@ -374,6 +391,16 @@ void Workspaces::onWorkspaceMoved(std::string const &payload) { if (m_bar.output->name == monitorName) { Json::Value clientsData = gIPC->getSocket1JsonReply("clients"); onWorkspaceCreated(workspaceName, clientsData); + if (m_activePerMonitor) { + for (Json::Value &monitor : gIPC->getSocket1JsonReply("monitors")) { + if (m_bar.output->name == monitor["name"].asString()) { + auto ws = monitor["activeWorkspace"]; + if (ws.isObject() && (ws["name"].isString())) { + m_activeWorkspaceName = ws["name"].asString(); + } + } + } + } } else { spdlog::debug("Removing workspace because it was moved to another monitor: {}"); onWorkspaceDestroyed(workspaceName); @@ -399,10 +426,13 @@ void Workspaces::onWorkspaceRenamed(std::string const &payload) { void Workspaces::onMonitorFocused(std::string const &payload) { spdlog::trace("Monitor focused: {}", payload); - m_activeWorkspaceName = payload.substr(payload.find(',') + 1); + auto monitorName = payload.substr(0, payload.find(',')); + if (!m_activePerMonitor || m_bar.output->name == monitorName) { + m_activeWorkspaceName = payload.substr(payload.find(',') + 1); + } for (Json::Value &monitor : gIPC->getSocket1JsonReply("monitors")) { - if (monitor["name"].asString() == payload.substr(0, payload.find(','))) { + if (monitor["name"].asString() == monitorName) { auto name = monitor["specialWorkspace"]["name"].asString(); m_activeSpecialWorkspaceName = !name.starts_with("special:") ? name : name.substr(8); } @@ -804,7 +834,18 @@ void Workspaces::extendOrphans(int workspaceId, Json::Value const &clientsJson) } void Workspaces::init() { - m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString(); + if (!m_activePerMonitor) { + m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString(); + } else { + for (Json::Value &monitor : gIPC->getSocket1JsonReply("monitors")) { + if (m_bar.output->name == monitor["name"].asString()) { + auto ws = monitor["activeWorkspace"]; + if (ws.isObject() && (ws["name"].isString())) { + m_activeWorkspaceName = ws["name"].asString(); + } + } + } + } initializeWorkspaces(); updateWindowCount(); @@ -1019,9 +1060,17 @@ bool Workspace::handleClicked(GdkEventButton *bt) const { if (bt->type == GDK_BUTTON_PRESS) { try { if (id() > 0) { // normal - gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id())); + if (m_workspaceManager.moveToMonitor()) { + gIPC->getSocket1Reply("dispatch focusworkspaceoncurrentmonitor " + std::to_string(id())); + } else { + gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id())); + } } else if (!isSpecial()) { // named (this includes persistent) - gIPC->getSocket1Reply("dispatch workspace name:" + name()); + if (m_workspaceManager.moveToMonitor()) { + gIPC->getSocket1Reply("dispatch focusworkspaceoncurrentmonitor name:" + name()); + } else { + gIPC->getSocket1Reply("dispatch workspace name:" + name()); + } } else if (id() != -99) { // named special gIPC->getSocket1Reply("dispatch togglespecialworkspace " + name()); } else { // special