summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authornyx <nnyyxxxx@protonmail.com>2025-03-07 20:12:02 -0500
committerGitHub <noreply@github.com>2025-03-08 02:12:02 +0100
commitb80b64cd6c913f8c8ac820a1e4ca615a62ff958f (patch)
treee6a6eda202efc6e5995245b3d6b8d0fa2650f7ca /src
parent4082e876d522dc6ed7118d62cdaa729f84c1b755 (diff)
windowrules: add option to allow size persistence between app launches (#9422)
Diffstat (limited to 'src')
-rw-r--r--src/config/ConfigManager.cpp15
-rw-r--r--src/config/ConfigManager.hpp52
-rw-r--r--src/desktop/Window.cpp9
-rw-r--r--src/desktop/Window.hpp2
-rw-r--r--src/desktop/WindowRule.cpp4
-rw-r--r--src/desktop/WindowRule.hpp1
-rw-r--r--src/layout/IHyprLayout.cpp12
7 files changed, 79 insertions, 16 deletions
diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index 12b43b37..f0383d50 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -2954,3 +2954,18 @@ std::string SConfigOptionDescription::jsonify() const {
void CConfigManager::ensurePersistentWorkspacesPresent() {
g_pCompositor->ensurePersistentWorkspacesPresent(m_vWorkspaceRules);
}
+
+void CConfigManager::storeFloatingSize(PHLWINDOW window, const Vector2D& size) {
+ Debug::log(LOG, "storing floating size {}x{} for window {}::{}", size.x, size.y, window->m_szClass, window->m_szTitle);
+ SFloatCache id{window};
+ m_mStoredFloatingSizes[id] = size;
+}
+
+std::optional<Vector2D> CConfigManager::getStoredFloatingSize(PHLWINDOW window) {
+ SFloatCache id{window};
+ if (m_mStoredFloatingSizes.contains(id)) {
+ Debug::log(LOG, "got stored size {}x{} for window {}::{}", m_mStoredFloatingSizes[id].x, m_mStoredFloatingSizes[id].y, window->m_szClass, window->m_szTitle);
+ return m_mStoredFloatingSizes[id];
+ }
+ return std::nullopt;
+}
diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp
index d9ea413e..7ce378b1 100644
--- a/src/config/ConfigManager.hpp
+++ b/src/config/ConfigManager.hpp
@@ -138,6 +138,27 @@ struct SFirstExecRequest {
bool withRules = false;
};
+struct SFloatCache {
+ size_t hash;
+
+ SFloatCache(PHLWINDOW window) {
+ hash = std::hash<std::string>{}(window->m_szClass) ^ (std::hash<std::string>{}(window->m_szTitle) << 1);
+ }
+
+ bool operator==(const SFloatCache& other) const {
+ return hash == other.hash;
+ }
+};
+
+namespace std {
+ template <>
+ struct hash<SFloatCache> {
+ size_t operator()(const SFloatCache& id) const {
+ return id.hash;
+ }
+ };
+}
+
class CConfigManager {
public:
CConfigManager();
@@ -232,6 +253,9 @@ class CConfigManager {
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
bool m_bLastConfigVerificationWasSuccessful = true;
+ void storeFloatingSize(PHLWINDOW window, const Vector2D& size);
+ std::optional<Vector2D> getStoredFloatingSize(PHLWINDOW window);
+
private:
UP<Hyprlang::CConfig> m_pConfig;
@@ -267,19 +291,21 @@ class CConfigManager {
uint32_t m_configValueNumber = 0;
// internal methods
- void updateBlurredLS(const std::string&, const bool);
- void setDefaultAnimationVars();
- std::optional<std::string> resetHLConfig();
- std::optional<std::string> generateConfig(std::string configPath);
- std::optional<std::string> verifyConfigExists();
- void postConfigReload(const Hyprlang::CParseResult& result);
- SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
-
- void registerConfigVar(const char* name, const Hyprlang::INT& val);
- void registerConfigVar(const char* name, const Hyprlang::FLOAT& val);
- void registerConfigVar(const char* name, const Hyprlang::VEC2& val);
- void registerConfigVar(const char* name, const Hyprlang::STRING& val);
- void registerConfigVar(const char* name, Hyprlang::CUSTOMTYPE&& val);
+ void updateBlurredLS(const std::string&, const bool);
+ void setDefaultAnimationVars();
+ std::optional<std::string> resetHLConfig();
+ std::optional<std::string> generateConfig(std::string configPath);
+ std::optional<std::string> verifyConfigExists();
+ void postConfigReload(const Hyprlang::CParseResult& result);
+ SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
+
+ void registerConfigVar(const char* name, const Hyprlang::INT& val);
+ void registerConfigVar(const char* name, const Hyprlang::FLOAT& val);
+ void registerConfigVar(const char* name, const Hyprlang::VEC2& val);
+ void registerConfigVar(const char* name, const Hyprlang::STRING& val);
+ void registerConfigVar(const char* name, Hyprlang::CUSTOMTYPE&& val);
+
+ std::unordered_map<SFloatCache, Vector2D> m_mStoredFloatingSizes;
friend struct SConfigOptionDescription;
};
diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp
index ceb5eb18..b7a3f8f6 100644
--- a/src/desktop/Window.cpp
+++ b/src/desktop/Window.cpp
@@ -791,6 +791,10 @@ void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
}
break;
}
+ case CWindowRule::RULE_PERSISTENTSIZE: {
+ m_sWindowData.persistentSize = CWindowOverridableVar(true, PRIORITY_WINDOW_RULE);
+ break;
+ }
default: break;
}
}
@@ -1323,6 +1327,11 @@ void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::
*m_vRealPosition = m_vRealPosition->goal() + DELTA / 2.0;
*m_vRealSize = NEWSIZE;
+
+ if (m_bIsFloating && !m_bIsX11 && std::any_of(m_vMatchedRules.begin(), m_vMatchedRules.end(), [](const auto& r) { return r->ruleType == CWindowRule::RULE_PERSISTENTSIZE; })) {
+ Debug::log(LOG, "clamped window {}::{} to {}x{} (persistentsize)", m_szClass, m_szTitle, m_vRealSize->value().x, m_vRealSize->value().y);
+ g_pConfigManager->storeFloatingSize(m_pSelf.lock(), m_vRealSize->value());
+ }
}
bool CWindow::isFullscreen() {
diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp
index ec3c0b21..3ed4ce75 100644
--- a/src/desktop/Window.hpp
+++ b/src/desktop/Window.hpp
@@ -198,6 +198,8 @@ struct SWindowData {
CWindowOverridableVar<CGradientValueData> activeBorderColor;
CWindowOverridableVar<CGradientValueData> inactiveBorderColor;
+
+ CWindowOverridableVar<bool> persistentSize;
};
struct SInitialWorkspaceToken {
diff --git a/src/desktop/WindowRule.cpp b/src/desktop/WindowRule.cpp
index cf3004b0..23269085 100644
--- a/src/desktop/WindowRule.cpp
+++ b/src/desktop/WindowRule.cpp
@@ -5,7 +5,7 @@
#include "../config/ConfigManager.hpp"
static const auto RULES = std::unordered_set<std::string>{
- "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused",
+ "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused", "persistentsize",
};
static const auto RULES_PREFIX = std::unordered_set<std::string>{
"animation", "bordercolor", "bordersize", "center", "content", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize",
@@ -39,6 +39,8 @@ CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool
ruleType = RULE_TILE;
else if (rule == "renderunfocused")
ruleType = RULE_RENDERUNFOCUSED;
+ else if (rule == "persistentsize")
+ ruleType = RULE_PERSISTENTSIZE;
else if (rule.starts_with("animation"))
ruleType = RULE_ANIMATION;
else if (rule.starts_with("bordercolor"))
diff --git a/src/desktop/WindowRule.hpp b/src/desktop/WindowRule.hpp
index 50e221f3..192d8aa7 100644
--- a/src/desktop/WindowRule.hpp
+++ b/src/desktop/WindowRule.hpp
@@ -37,6 +37,7 @@ class CWindowRule {
RULE_WORKSPACE,
RULE_PROP,
RULE_CONTENT,
+ RULE_PERSISTENTSIZE,
};
eRuleType ruleType = RULE_INVALID;
diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp
index e84ffb21..dc6de9e3 100644
--- a/src/layout/IHyprLayout.cpp
+++ b/src/layout/IHyprLayout.cpp
@@ -14,9 +14,17 @@
#include "../managers/HookSystemManager.hpp"
void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
- CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow);
+ CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow);
- if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
+ const bool HASPERSISTENTSIZE =
+ std::any_of(pWindow->m_vMatchedRules.begin(), pWindow->m_vMatchedRules.end(), [](const auto& rule) { return rule->ruleType == CWindowRule::RULE_PERSISTENTSIZE; });
+
+ const auto STOREDSIZE = HASPERSISTENTSIZE ? g_pConfigManager->getStoredFloatingSize(pWindow) : std::nullopt;
+
+ if (STOREDSIZE.has_value()) {
+ Debug::log(LOG, "using stored size {}x{} for new window {}::{}", STOREDSIZE->x, STOREDSIZE->y, pWindow->m_szClass, pWindow->m_szTitle);
+ pWindow->m_vLastFloatingSize = STOREDSIZE.value();
+ } else if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
const auto PMONITOR = pWindow->m_pMonitor.lock();
pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f;
} else