diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b9be9f18e34..e68d7f409bb 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2044,7 +2044,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with new {}", nextWorkspaceOnMonitorID); - g_pCompositor->createNewWorkspace(nextWorkspaceOnMonitorID, POLDMON->ID); + g_pCompositor->createNewWorkspace(nextWorkspaceOnMonitorID, POLDMON->ID, "", false); } Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with existing {}", nextWorkspaceOnMonitorID); @@ -2431,7 +2431,7 @@ bool CCompositor::cursorOnReservedArea() { return !VECINRECT(CURSORPOS, XY1.x, XY1.y, XY2.x, XY2.y); } -CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, const std::string& name) { +CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, const std::string& name, bool isEmpty) { const auto NAME = name == "" ? std::to_string(id) : name; auto monID = monid; @@ -2447,6 +2447,13 @@ CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, con PWORKSPACE->m_iID = id; PWORKSPACE->m_iMonitorID = monID; + if (isEmpty) { + const SWorkspaceRule workspaceRule = g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE); + if (!workspaceRule.onCreatedEmptyRunCmd.empty()) { + g_pKeybindManager->spawn(workspaceRule.onCreatedEmptyRunCmd); + } + } + return PWORKSPACE; } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 86460211c93..a0f4da8a33b 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -194,7 +194,7 @@ class CCompositor { Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); void forceReportSizesToWindowsOnWorkspace(const int&); bool cursorOnReservedArea(); - CWorkspace* createNewWorkspace(const int&, const int&, const std::string& name = ""); // will be deleted next frame if left empty and unfocused! + CWorkspace* createNewWorkspace(const int&, const int&, const std::string& name = "", bool isEmpty = true); // will be deleted next frame if left empty and unfocused! void renameWorkspace(const int&, const std::string& name = ""); void setActiveMonitor(CMonitor*); bool isWorkspaceSpecial(const int&); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2d19389e08f..c74f858d41b 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2,6 +2,7 @@ #include "../managers/KeybindManager.hpp" #include +#include #include #include #include @@ -1172,6 +1173,9 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std: rules = value.substr(WORKSPACE_DELIM + 1); } + const static std::string ruleOnCreatedEmtpy = "on-created-empty:"; + const static int ruleOnCreatedEmtpyLen = ruleOnCreatedEmtpy.length(); + auto assignRule = [&](std::string rule) { size_t delim = std::string::npos; if ((delim = rule.find("gapsin:")) != std::string::npos) @@ -1194,6 +1198,8 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std: wsRule.isDefault = configStringToInt(rule.substr(delim + 8)); else if ((delim = rule.find("persistent:")) != std::string::npos) wsRule.isPersistent = configStringToInt(rule.substr(delim + 11)); + else if ((delim = rule.find(ruleOnCreatedEmtpy)) != std::string::npos) + wsRule.onCreatedEmptyRunCmd = cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmtpyLen)); }; size_t pos = 0; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index e637979d275..23510c3e1dc 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -49,6 +49,7 @@ struct SWorkspaceRule { std::optional rounding; std::optional decorate; std::optional shadow; + std::string onCreatedEmptyRunCmd; }; struct SMonitorAdditionalReservedArea { diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 9d7995f7db1..fdc188fe1ad 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -503,34 +503,19 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { return result; } -static inline void ltrim(std::string& s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); -} - -int parseWorkspaceAndDefaultCmd(std::string inArgs, std::string& outWorkspaceName, std::string& outDefaultCmd) { - - std::string workspaceToToggle; - if (inArgs.contains(',')) { - const int commaIdx = inArgs.find_first_of(','); - workspaceToToggle = inArgs.substr(0, commaIdx); - outDefaultCmd = inArgs.substr(commaIdx + 1); - } else { - workspaceToToggle = inArgs; - } +std::string cleanCmdForWorkspace(const std::string& inWorkspaceName, std::string dirtyCmd) { - int workspaceID = getWorkspaceIDFromString(workspaceToToggle, outWorkspaceName); - ltrim(outDefaultCmd); + std::string cmd = removeBeginEndSpacesTabs(dirtyCmd); - if (!outDefaultCmd.empty()) { + if (!cmd.empty()) { std::string rules; - const std::string workspaceRule = "workspace " + outWorkspaceName; - std::string cmd = outDefaultCmd; + const std::string workspaceRule = "workspace " + inWorkspaceName; - if (outDefaultCmd[0] == '[') { - const int closingBracketIdx = outDefaultCmd.find_last_of(']'); - auto tmpRules = outDefaultCmd.substr(1, closingBracketIdx - 1); - cmd = outDefaultCmd.substr(closingBracketIdx + 1); + if (cmd[0] == '[') { + const int closingBracketIdx = cmd.find_last_of(']'); + auto tmpRules = cmd.substr(1, closingBracketIdx - 1); + cmd = cmd.substr(closingBracketIdx + 1); auto rulesList = CVarList(tmpRules, 0, ';'); @@ -551,10 +536,10 @@ int parseWorkspaceAndDefaultCmd(std::string inArgs, std::string& outWorkspaceNam rules = "[" + workspaceRule + "]"; } - outDefaultCmd = rules + " " + cmd; + return rules + " " + cmd; } - return workspaceID; + return {}; } float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2) { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 628a71faa24..8b3c671654e 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -20,7 +20,7 @@ std::string removeBeginEndSpacesTabs(std::string); bool isNumber(const std::string&, bool allowfloat = false); bool isDirection(const std::string&); int getWorkspaceIDFromString(const std::string&, std::string&); -int parseWorkspaceAndDefaultCmd(std::string, std::string&, std::string&); +std::string cleanCmdForWorkspace(const std::string&, std::string); float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); void logSystemInfo(); std::string execAndGet(const char*); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 9ac8db95878..14620f41d8b 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -801,7 +801,6 @@ void CKeybindManager::toggleActivePseudo(std::string args) { void CKeybindManager::changeworkspace(std::string args) { int workspaceToChangeTo = 0; std::string workspaceName = ""; - std::string defaultCmd = ""; // Workspace_back_and_forth being enabled means that an attempt to switch to // the current workspace will instead switch to the previous. @@ -828,7 +827,7 @@ void CKeybindManager::changeworkspace(std::string args) { PCURRENTWORKSPACE->m_sPrevWorkspace.name.empty() ? std::to_string(PCURRENTWORKSPACE->m_sPrevWorkspace.iID) : PCURRENTWORKSPACE->m_sPrevWorkspace.name; } } else { - workspaceToChangeTo = parseWorkspaceAndDefaultCmd(args, workspaceName, defaultCmd); + workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName); } if (workspaceToChangeTo == INT_MAX) { @@ -848,10 +847,6 @@ void CKeybindManager::changeworkspace(std::string args) { if (!pWorkspaceToChangeTo) { pWorkspaceToChangeTo = g_pCompositor->createNewWorkspace(BISWORKSPACECURRENT ? PCURRENTWORKSPACE->m_sPrevWorkspace.iID : workspaceToChangeTo, PMONITOR->ID, BISWORKSPACECURRENT ? PCURRENTWORKSPACE->m_sPrevWorkspace.name : workspaceName); - - if (!defaultCmd.empty()) { - spawn(defaultCmd); - } } if (!BISWORKSPACECURRENT && pWorkspaceToChangeTo->m_bIsSpecialWorkspace) { @@ -947,7 +942,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { pMonitor = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); g_pCompositor->setActiveMonitor(pMonitor); } else { - pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->m_iMonitorID, workspaceName); + pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->m_iMonitorID, workspaceName, false); pMonitor = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } @@ -998,7 +993,7 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { if (pWorkspace) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } else { - pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->m_iMonitorID, workspaceName); + pWorkspace = g_pCompositor->createNewWorkspace(WORKSPACEID, PWINDOW->m_iMonitorID, workspaceName, false); g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } @@ -1448,8 +1443,8 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) { static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; - std::string workspaceName, defaultCmd; - int workspaceID = parseWorkspaceAndDefaultCmd("special:" + args, workspaceName, defaultCmd); + std::string workspaceName = ""; + int workspaceID = getWorkspaceIDFromString("special:" + args, workspaceName); if (workspaceID == INT_MAX || !g_pCompositor->isWorkspaceSpecial(workspaceID)) { Debug::log(ERR, "Invalid workspace passed to special"); @@ -1477,9 +1472,6 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) { if (!PSPECIALWORKSPACE) { PSPECIALWORKSPACE = g_pCompositor->createNewWorkspace(workspaceID, PMONITOR->ID, workspaceName); - if (!defaultCmd.empty()) { - spawn(defaultCmd); - } } PMONITOR->setSpecialWorkspace(PSPECIALWORKSPACE);