mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-07 15:41:58 -07:00
windowrules: add option to allow size persistence between app launches (#9422)
This commit is contained in:
@@ -2954,3 +2954,18 @@ std::string SConfigOptionDescription::jsonify() const {
|
|||||||
void CConfigManager::ensurePersistentWorkspacesPresent() {
|
void CConfigManager::ensurePersistentWorkspacesPresent() {
|
||||||
g_pCompositor->ensurePersistentWorkspacesPresent(m_vWorkspaceRules);
|
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;
|
||||||
|
}
|
||||||
|
@@ -138,6 +138,27 @@ struct SFirstExecRequest {
|
|||||||
bool withRules = false;
|
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 {
|
class CConfigManager {
|
||||||
public:
|
public:
|
||||||
CConfigManager();
|
CConfigManager();
|
||||||
@@ -232,6 +253,9 @@ class CConfigManager {
|
|||||||
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
|
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
|
||||||
bool m_bLastConfigVerificationWasSuccessful = true;
|
bool m_bLastConfigVerificationWasSuccessful = true;
|
||||||
|
|
||||||
|
void storeFloatingSize(PHLWINDOW window, const Vector2D& size);
|
||||||
|
std::optional<Vector2D> getStoredFloatingSize(PHLWINDOW window);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UP<Hyprlang::CConfig> m_pConfig;
|
UP<Hyprlang::CConfig> m_pConfig;
|
||||||
|
|
||||||
@@ -281,6 +305,8 @@ class CConfigManager {
|
|||||||
void registerConfigVar(const char* name, const Hyprlang::STRING& val);
|
void registerConfigVar(const char* name, const Hyprlang::STRING& val);
|
||||||
void registerConfigVar(const char* name, Hyprlang::CUSTOMTYPE&& val);
|
void registerConfigVar(const char* name, Hyprlang::CUSTOMTYPE&& val);
|
||||||
|
|
||||||
|
std::unordered_map<SFloatCache, Vector2D> m_mStoredFloatingSizes;
|
||||||
|
|
||||||
friend struct SConfigOptionDescription;
|
friend struct SConfigOptionDescription;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -791,6 +791,10 @@ void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CWindowRule::RULE_PERSISTENTSIZE: {
|
||||||
|
m_sWindowData.persistentSize = CWindowOverridableVar(true, PRIORITY_WINDOW_RULE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: 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_vRealPosition = m_vRealPosition->goal() + DELTA / 2.0;
|
||||||
*m_vRealSize = NEWSIZE;
|
*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() {
|
bool CWindow::isFullscreen() {
|
||||||
|
@@ -198,6 +198,8 @@ struct SWindowData {
|
|||||||
|
|
||||||
CWindowOverridableVar<CGradientValueData> activeBorderColor;
|
CWindowOverridableVar<CGradientValueData> activeBorderColor;
|
||||||
CWindowOverridableVar<CGradientValueData> inactiveBorderColor;
|
CWindowOverridableVar<CGradientValueData> inactiveBorderColor;
|
||||||
|
|
||||||
|
CWindowOverridableVar<bool> persistentSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SInitialWorkspaceToken {
|
struct SInitialWorkspaceToken {
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
#include "../config/ConfigManager.hpp"
|
#include "../config/ConfigManager.hpp"
|
||||||
|
|
||||||
static const auto RULES = std::unordered_set<std::string>{
|
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>{
|
static const auto RULES_PREFIX = std::unordered_set<std::string>{
|
||||||
"animation", "bordercolor", "bordersize", "center", "content", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize",
|
"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;
|
ruleType = RULE_TILE;
|
||||||
else if (rule == "renderunfocused")
|
else if (rule == "renderunfocused")
|
||||||
ruleType = RULE_RENDERUNFOCUSED;
|
ruleType = RULE_RENDERUNFOCUSED;
|
||||||
|
else if (rule == "persistentsize")
|
||||||
|
ruleType = RULE_PERSISTENTSIZE;
|
||||||
else if (rule.starts_with("animation"))
|
else if (rule.starts_with("animation"))
|
||||||
ruleType = RULE_ANIMATION;
|
ruleType = RULE_ANIMATION;
|
||||||
else if (rule.starts_with("bordercolor"))
|
else if (rule.starts_with("bordercolor"))
|
||||||
|
@@ -37,6 +37,7 @@ class CWindowRule {
|
|||||||
RULE_WORKSPACE,
|
RULE_WORKSPACE,
|
||||||
RULE_PROP,
|
RULE_PROP,
|
||||||
RULE_CONTENT,
|
RULE_CONTENT,
|
||||||
|
RULE_PERSISTENTSIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
eRuleType ruleType = RULE_INVALID;
|
eRuleType ruleType = RULE_INVALID;
|
||||||
|
@@ -16,7 +16,15 @@
|
|||||||
void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
|
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();
|
const auto PMONITOR = pWindow->m_pMonitor.lock();
|
||||||
pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f;
|
pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f;
|
||||||
} else
|
} else
|
||||||
|
Reference in New Issue
Block a user