Skip to content

Commit b80b64c

Browse files
author
nyx
authored
windowrules: add option to allow size persistence between app launches (#9422)
1 parent 4082e87 commit b80b64c

File tree

7 files changed

+79
-16
lines changed

7 files changed

+79
-16
lines changed

src/config/ConfigManager.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2954,3 +2954,18 @@ std::string SConfigOptionDescription::jsonify() const {
29542954
void CConfigManager::ensurePersistentWorkspacesPresent() {
29552955
g_pCompositor->ensurePersistentWorkspacesPresent(m_vWorkspaceRules);
29562956
}
2957+
2958+
void CConfigManager::storeFloatingSize(PHLWINDOW window, const Vector2D& size) {
2959+
Debug::log(LOG, "storing floating size {}x{} for window {}::{}", size.x, size.y, window->m_szClass, window->m_szTitle);
2960+
SFloatCache id{window};
2961+
m_mStoredFloatingSizes[id] = size;
2962+
}
2963+
2964+
std::optional<Vector2D> CConfigManager::getStoredFloatingSize(PHLWINDOW window) {
2965+
SFloatCache id{window};
2966+
if (m_mStoredFloatingSizes.contains(id)) {
2967+
Debug::log(LOG, "got stored size {}x{} for window {}::{}", m_mStoredFloatingSizes[id].x, m_mStoredFloatingSizes[id].y, window->m_szClass, window->m_szTitle);
2968+
return m_mStoredFloatingSizes[id];
2969+
}
2970+
return std::nullopt;
2971+
}

src/config/ConfigManager.hpp

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,27 @@ struct SFirstExecRequest {
138138
bool withRules = false;
139139
};
140140

141+
struct SFloatCache {
142+
size_t hash;
143+
144+
SFloatCache(PHLWINDOW window) {
145+
hash = std::hash<std::string>{}(window->m_szClass) ^ (std::hash<std::string>{}(window->m_szTitle) << 1);
146+
}
147+
148+
bool operator==(const SFloatCache& other) const {
149+
return hash == other.hash;
150+
}
151+
};
152+
153+
namespace std {
154+
template <>
155+
struct hash<SFloatCache> {
156+
size_t operator()(const SFloatCache& id) const {
157+
return id.hash;
158+
}
159+
};
160+
}
161+
141162
class CConfigManager {
142163
public:
143164
CConfigManager();
@@ -232,6 +253,9 @@ class CConfigManager {
232253
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
233254
bool m_bLastConfigVerificationWasSuccessful = true;
234255

256+
void storeFloatingSize(PHLWINDOW window, const Vector2D& size);
257+
std::optional<Vector2D> getStoredFloatingSize(PHLWINDOW window);
258+
235259
private:
236260
UP<Hyprlang::CConfig> m_pConfig;
237261

@@ -267,19 +291,21 @@ class CConfigManager {
267291
uint32_t m_configValueNumber = 0;
268292

269293
// internal methods
270-
void updateBlurredLS(const std::string&, const bool);
271-
void setDefaultAnimationVars();
272-
std::optional<std::string> resetHLConfig();
273-
std::optional<std::string> generateConfig(std::string configPath);
274-
std::optional<std::string> verifyConfigExists();
275-
void postConfigReload(const Hyprlang::CParseResult& result);
276-
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
277-
278-
void registerConfigVar(const char* name, const Hyprlang::INT& val);
279-
void registerConfigVar(const char* name, const Hyprlang::FLOAT& val);
280-
void registerConfigVar(const char* name, const Hyprlang::VEC2& val);
281-
void registerConfigVar(const char* name, const Hyprlang::STRING& val);
282-
void registerConfigVar(const char* name, Hyprlang::CUSTOMTYPE&& val);
294+
void updateBlurredLS(const std::string&, const bool);
295+
void setDefaultAnimationVars();
296+
std::optional<std::string> resetHLConfig();
297+
std::optional<std::string> generateConfig(std::string configPath);
298+
std::optional<std::string> verifyConfigExists();
299+
void postConfigReload(const Hyprlang::CParseResult& result);
300+
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
301+
302+
void registerConfigVar(const char* name, const Hyprlang::INT& val);
303+
void registerConfigVar(const char* name, const Hyprlang::FLOAT& val);
304+
void registerConfigVar(const char* name, const Hyprlang::VEC2& val);
305+
void registerConfigVar(const char* name, const Hyprlang::STRING& val);
306+
void registerConfigVar(const char* name, Hyprlang::CUSTOMTYPE&& val);
307+
308+
std::unordered_map<SFloatCache, Vector2D> m_mStoredFloatingSizes;
283309

284310
friend struct SConfigOptionDescription;
285311
};

src/desktop/Window.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,10 @@ void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
791791
}
792792
break;
793793
}
794+
case CWindowRule::RULE_PERSISTENTSIZE: {
795+
m_sWindowData.persistentSize = CWindowOverridableVar(true, PRIORITY_WINDOW_RULE);
796+
break;
797+
}
794798
default: break;
795799
}
796800
}
@@ -1323,6 +1327,11 @@ void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::
13231327

13241328
*m_vRealPosition = m_vRealPosition->goal() + DELTA / 2.0;
13251329
*m_vRealSize = NEWSIZE;
1330+
1331+
if (m_bIsFloating && !m_bIsX11 && std::any_of(m_vMatchedRules.begin(), m_vMatchedRules.end(), [](const auto& r) { return r->ruleType == CWindowRule::RULE_PERSISTENTSIZE; })) {
1332+
Debug::log(LOG, "clamped window {}::{} to {}x{} (persistentsize)", m_szClass, m_szTitle, m_vRealSize->value().x, m_vRealSize->value().y);
1333+
g_pConfigManager->storeFloatingSize(m_pSelf.lock(), m_vRealSize->value());
1334+
}
13261335
}
13271336

13281337
bool CWindow::isFullscreen() {

src/desktop/Window.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ struct SWindowData {
198198

199199
CWindowOverridableVar<CGradientValueData> activeBorderColor;
200200
CWindowOverridableVar<CGradientValueData> inactiveBorderColor;
201+
202+
CWindowOverridableVar<bool> persistentSize;
201203
};
202204

203205
struct SInitialWorkspaceToken {

src/desktop/WindowRule.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include "../config/ConfigManager.hpp"
66

77
static const auto RULES = std::unordered_set<std::string>{
8-
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused",
8+
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused", "persistentsize",
99
};
1010
static const auto RULES_PREFIX = std::unordered_set<std::string>{
1111
"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
3939
ruleType = RULE_TILE;
4040
else if (rule == "renderunfocused")
4141
ruleType = RULE_RENDERUNFOCUSED;
42+
else if (rule == "persistentsize")
43+
ruleType = RULE_PERSISTENTSIZE;
4244
else if (rule.starts_with("animation"))
4345
ruleType = RULE_ANIMATION;
4446
else if (rule.starts_with("bordercolor"))

src/desktop/WindowRule.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class CWindowRule {
3737
RULE_WORKSPACE,
3838
RULE_PROP,
3939
RULE_CONTENT,
40+
RULE_PERSISTENTSIZE,
4041
};
4142

4243
eRuleType ruleType = RULE_INVALID;

src/layout/IHyprLayout.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,17 @@
1414
#include "../managers/HookSystemManager.hpp"
1515

1616
void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
17-
CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow);
17+
CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow);
1818

19-
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
19+
const bool HASPERSISTENTSIZE =
20+
std::any_of(pWindow->m_vMatchedRules.begin(), pWindow->m_vMatchedRules.end(), [](const auto& rule) { return rule->ruleType == CWindowRule::RULE_PERSISTENTSIZE; });
21+
22+
const auto STOREDSIZE = HASPERSISTENTSIZE ? g_pConfigManager->getStoredFloatingSize(pWindow) : std::nullopt;
23+
24+
if (STOREDSIZE.has_value()) {
25+
Debug::log(LOG, "using stored size {}x{} for new window {}::{}", STOREDSIZE->x, STOREDSIZE->y, pWindow->m_szClass, pWindow->m_szTitle);
26+
pWindow->m_vLastFloatingSize = STOREDSIZE.value();
27+
} else if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
2028
const auto PMONITOR = pWindow->m_pMonitor.lock();
2129
pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f;
2230
} else

0 commit comments

Comments
 (0)