diff --git a/src/Compositor.cpp b/src/Compositor.cpp index be03edac0..212e514b6 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2547,9 +2547,8 @@ void CCompositor::warpCursorTo(const Vector2D& pos, bool force) { } void CCompositor::closeWindow(PHLWINDOW pWindow) { - if (pWindow && validMapped(pWindow)) { + if (pWindow && validMapped(pWindow)) g_pXWaylandManager->sendCloseWindow(pWindow); - } } PHLLS CCompositor::getLayerSurfaceFromSurface(SP pSurface) { diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 8a6590bd4..cc62dd3b9 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -311,6 +311,9 @@ class CWindow { // ANR PHLANIMVAR m_notRespondingTint; + // For the noclosefor windowrule + Time::steady_tp m_closeableSince = Time::steadyNow(); + // For the list lookup bool operator==(const CWindow& rhs) const { return m_xdgSurface == rhs.m_xdgSurface && m_xwaylandSurface == rhs.m_xwaylandSurface && m_position == rhs.m_position && m_size == rhs.m_size && diff --git a/src/desktop/WindowRule.cpp b/src/desktop/WindowRule.cpp index 245d15830..db1b0dde5 100644 --- a/src/desktop/WindowRule.cpp +++ b/src/desktop/WindowRule.cpp @@ -8,9 +8,9 @@ static const auto RULES = std::unordered_set{ "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused", "persistentsize", }; static const auto RULES_PREFIX = std::unordered_set{ - "animation", "bordercolor", "bordersize", "center", "content", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", - "monitor", "move", "opacity", "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", - "size", "suppressevent", "tag", "workspace", "xray", + "animation", "bordercolor", "bordersize", "center", "content", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", + "move", "noclosefor", "opacity", "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", "size", + "suppressevent", "tag", "workspace", "xray", }; CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : m_value(value), m_rule(rule), m_v2(isV2), m_execRule(isExecRule) { @@ -79,6 +79,8 @@ CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool m_ruleType = RULE_PROP; else if (rule.starts_with("content")) m_ruleType = RULE_CONTENT; + else if (rule.starts_with("noclosefor")) + m_ruleType = RULE_NOCLOSEFOR; else { // check if this is a prop. const CVarList VARS(rule, 0, 's', true); diff --git a/src/desktop/WindowRule.hpp b/src/desktop/WindowRule.hpp index 084c67f94..9af3909aa 100644 --- a/src/desktop/WindowRule.hpp +++ b/src/desktop/WindowRule.hpp @@ -37,7 +37,8 @@ class CWindowRule { RULE_WORKSPACE, RULE_PROP, RULE_CONTENT, - RULE_PERSISTENTSIZE + RULE_PERSISTENTSIZE, + RULE_NOCLOSEFOR, }; eRuleType m_ruleType = RULE_INVALID; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 3cff25165..9e0d2be5c 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -315,6 +315,12 @@ void Events::listener_mapWindow(void* owner, void* data) { } catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); } break; } + case CWindowRule::RULE_NOCLOSEFOR: { + const CVarList VARS(r->m_rule, 0, ' '); + try { + PWINDOW->m_closeableSince = Time::steadyNow() + std::chrono::milliseconds(std::stoull(VARS[1])); + } catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); } + } default: break; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index f30f65a18..7f0045e0c 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1037,6 +1037,9 @@ SDispatchResult CKeybindManager::killActive(std::string args) { } SDispatchResult CKeybindManager::closeActive(std::string args) { + if (g_pCompositor->m_lastWindow && g_pCompositor->m_lastWindow->m_closeableSince > Time::steadyNow()) + return {.success = false, .error = "can't close window, it's not closeable yet (noclosefor)"}; + g_pCompositor->closeWindow(g_pCompositor->m_lastWindow.lock()); return {}; @@ -1050,6 +1053,9 @@ SDispatchResult CKeybindManager::closeWindow(std::string args) { return {.success = false, .error = "closeWindow: no window found"}; } + if (PWINDOW->m_closeableSince > Time::steadyNow()) + return {.success = false, .error = "can't close window, it's not closeable yet (noclosefor)"}; + g_pCompositor->closeWindow(PWINDOW); return {};