diff --git a/src/Compositor.cpp b/src/Compositor.cpp index ab478a87..5241fde8 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1814,6 +1814,15 @@ void CCompositor::updateAllWindowsAnimatedDecorationValues() { } } +void CCompositor::updateWorkspaceWindows(const int64_t& id) { + for (auto& w : m_vWindows) { + if (!w->m_bIsMapped || w->m_iWorkspaceID != id) + continue; + + w->updateDynamicRules(); + } +} + void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { // optimization static auto* const ACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.active_border")->data.get(); @@ -2643,6 +2652,9 @@ void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorks if (FULLSCREEN) setWindowFullscreen(pWindow, true, FULLSCREENMODE); + + g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID); + g_pCompositor->updateWorkspaceWindows(pWindow->m_iWorkspaceID); } CWindow* CCompositor::getForceFocus() { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 65550154..8703f3f1 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -172,6 +172,7 @@ class CCompositor { CWindow* getConstraintWindow(SMouse*); CMonitor* getMonitorInDirection(const char&); void updateAllWindowsAnimatedDecorationValues(); + void updateWorkspaceWindows(const int64_t& id); void updateWindowAnimatedDecorationValues(CWindow*); int getNextAvailableMonitorID(std::string const& name); void moveWorkspaceToMonitor(CWorkspace*, CMonitor*); diff --git a/src/Window.cpp b/src/Window.cpp index da0912ee..11627d5c 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -448,6 +448,8 @@ void CWindow::onUnmap() { if (PMONITOR && PMONITOR->solitaryClient == this) PMONITOR->solitaryClient = nullptr; + + g_pCompositor->updateWorkspaceWindows(m_iWorkspaceID); } void CWindow::onMap() { @@ -485,6 +487,8 @@ void CWindow::onMap() { "CWindow"); m_vReportedSize = m_vPendingReportedSize; + + g_pCompositor->updateWorkspaceWindows(m_iWorkspaceID); } void CWindow::onBorderAngleAnimEnd(void* ptr) { diff --git a/src/Window.hpp b/src/Window.hpp index cff26052..8d5f22e5 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -151,12 +151,13 @@ struct SWindowRule { bool v2 = false; std::string szTitle; std::string szClass; - int bX11 = -1; // -1 means "ANY" - int bFloating = -1; - int bFullscreen = -1; - int bPinned = -1; - int bFocus = -1; - std::string szWorkspace = ""; // empty means any + int bX11 = -1; // -1 means "ANY" + int bFloating = -1; + int bFullscreen = -1; + int bPinned = -1; + int bFocus = -1; + int iOnWorkspace = -1; + std::string szWorkspace = ""; // empty means any }; class CWindow { diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 8ecfa87b..fb5c7b02 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1026,17 +1026,28 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s rule.szRule = RULE; rule.szValue = VALUE; - const auto TITLEPOS = VALUE.find("title:"); - const auto CLASSPOS = VALUE.find("class:"); - const auto X11POS = VALUE.find("xwayland:"); - const auto FLOATPOS = VALUE.find("floating:"); - const auto FULLSCREENPOS = VALUE.find("fullscreen:"); - const auto PINNEDPOS = VALUE.find("pinned:"); - const auto WORKSPACEPOS = VALUE.find("workspace:"); - const auto FOCUSPOS = VALUE.find("focus:"); + const auto TITLEPOS = VALUE.find("title:"); + const auto CLASSPOS = VALUE.find("class:"); + const auto X11POS = VALUE.find("xwayland:"); + const auto FLOATPOS = VALUE.find("floating:"); + const auto FULLSCREENPOS = VALUE.find("fullscreen:"); + const auto PINNEDPOS = VALUE.find("pinned:"); + const auto FOCUSPOS = VALUE.find("focus:"); + const auto ONWORKSPACEPOS = VALUE.find("onworkspace:"); + + // find workspacepos that isn't onworkspacepos + size_t WORKSPACEPOS = std::string::npos; + size_t currentPos = 0; + while (currentPos != std::string::npos) { + if (currentPos > 0 && VALUE[currentPos - 1] != 'n') { + WORKSPACEPOS = currentPos; + break; + } + currentPos = VALUE.find("workspace:", currentPos + 1); + } if (TITLEPOS == std::string::npos && CLASSPOS == std::string::npos && X11POS == std::string::npos && FLOATPOS == std::string::npos && FULLSCREENPOS == std::string::npos && - PINNEDPOS == std::string::npos && WORKSPACEPOS == std::string::npos && FOCUSPOS == std::string::npos) { + PINNEDPOS == std::string::npos && WORKSPACEPOS == std::string::npos && FOCUSPOS == std::string::npos && ONWORKSPACEPOS == std::string::npos) { Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE); parseError = "Invalid rulev2 syntax: " + VALUE; return; @@ -1059,6 +1070,8 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s min = FULLSCREENPOS; if (PINNEDPOS > pos && PINNEDPOS < min) min = PINNEDPOS; + if (ONWORKSPACEPOS > pos && ONWORKSPACEPOS < min) + min = ONWORKSPACEPOS; if (WORKSPACEPOS > pos && WORKSPACEPOS < min) min = WORKSPACEPOS; if (FOCUSPOS > pos && FOCUSPOS < min) @@ -1098,6 +1111,9 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s if (FOCUSPOS != std::string::npos) rule.bFocus = extract(FOCUSPOS + 6) == "1" ? 1 : 0; + if (ONWORKSPACEPOS != std::string::npos) + rule.iOnWorkspace = configStringToInt(extract(ONWORKSPACEPOS + 12)); + if (RULE == "unset") { std::erase_if(m_dWindowRules, [&](const SWindowRule& other) { if (!other.v2) { @@ -1127,6 +1143,9 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s if (rule.bFocus != -1 && rule.bFocus != other.bFocus) return false; + if (rule.iOnWorkspace != -1 && rule.iOnWorkspace != other.iOnWorkspace) + return false; + return true; } }); @@ -2012,6 +2031,11 @@ std::vector CConfigManager::getMatchingRules(CWindow* pWindow) { continue; } + if (rule.iOnWorkspace != -1) { + if (rule.iOnWorkspace != g_pCompositor->getWindowsOnWorkspace(pWindow->m_iWorkspaceID)) + continue; + } + if (!rule.szWorkspace.empty()) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);