diff --git a/src/Window.cpp b/src/Window.cpp index 41562291a..85608f6f7 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -687,6 +687,22 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { m_eIdleInhibitMode = IDLEINHIBIT_FULLSCREEN; else Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE); + } else if (r.szRule.starts_with("maxsize")) { + try { + m_sAdditionalConfigData.maxSize = configStringToVector2D(r.szRule.substr(8)); + m_vRealSize = Vector2D(std::min((double)m_sAdditionalConfigData.maxSize.toUnderlying().x, m_vRealSize.goal().x), + std::min((double)m_sAdditionalConfigData.maxSize.toUnderlying().y, m_vRealSize.goal().y)); + g_pXWaylandManager->setWindowSize(this, m_vRealSize.goal()); + setHidden(false); + } catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r.szRule, e.what()); } + } else if (r.szRule.starts_with("minsize")) { + try { + m_sAdditionalConfigData.minSize = configStringToVector2D(r.szRule.substr(8)); + m_vRealSize = Vector2D(std::max((double)m_sAdditionalConfigData.minSize.toUnderlying().x, m_vRealSize.goal().x), + std::max((double)m_sAdditionalConfigData.minSize.toUnderlying().y, m_vRealSize.goal().y)); + g_pXWaylandManager->setWindowSize(this, m_vRealSize.goal()); + setHidden(false); + } catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); } } } @@ -701,6 +717,8 @@ void CWindow::updateDynamicRules() { m_sAdditionalConfigData.forceNoDim = false; if (!m_sAdditionalConfigData.forceOpaqueOverridden) m_sAdditionalConfigData.forceOpaque = false; + m_sAdditionalConfigData.maxSize = Vector2D(std::numeric_limits::max(), std::numeric_limits::max()); + m_sAdditionalConfigData.minSize = Vector2D(1, 1); m_sAdditionalConfigData.forceNoAnims = false; m_sAdditionalConfigData.animationStyle = std::string(""); m_sAdditionalConfigData.rounding = -1; diff --git a/src/Window.hpp b/src/Window.hpp index aeb674d1e..5fcb951f5 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -142,26 +142,28 @@ struct SWindowSpecialRenderData { }; struct SWindowAdditionalConfigData { - std::string animationStyle = std::string(""); - CWindowOverridableVar rounding = -1; // -1 means no - CWindowOverridableVar forceNoBlur = false; - CWindowOverridableVar forceOpaque = false; - CWindowOverridableVar forceOpaqueOverridden = false; // if true, a rule will not change the forceOpaque state. This is for the force opaque dispatcher. - CWindowOverridableVar forceAllowsInput = false; - CWindowOverridableVar forceNoAnims = false; - CWindowOverridableVar forceNoBorder = false; - CWindowOverridableVar forceNoShadow = false; - CWindowOverridableVar forceNoDim = false; - CWindowOverridableVar noFocus = false; - CWindowOverridableVar windowDanceCompat = false; - CWindowOverridableVar noMaxSize = false; - CWindowOverridableVar dimAround = false; - CWindowOverridableVar forceRGBX = false; - CWindowOverridableVar keepAspectRatio = false; - CWindowOverridableVar xray = -1; // -1 means unset, takes precedence over the renderdata one - CWindowOverridableVar borderSize = -1; // -1 means unset, takes precedence over the renderdata one - CWindowOverridableVar forceTearing = false; - CWindowOverridableVar nearestNeighbor = false; + std::string animationStyle = std::string(""); + CWindowOverridableVar rounding = -1; // -1 means no + CWindowOverridableVar forceNoBlur = false; + CWindowOverridableVar forceOpaque = false; + CWindowOverridableVar forceOpaqueOverridden = false; // if true, a rule will not change the forceOpaque state. This is for the force opaque dispatcher. + CWindowOverridableVar forceAllowsInput = false; + CWindowOverridableVar forceNoAnims = false; + CWindowOverridableVar forceNoBorder = false; + CWindowOverridableVar forceNoShadow = false; + CWindowOverridableVar forceNoDim = false; + CWindowOverridableVar noFocus = false; + CWindowOverridableVar windowDanceCompat = false; + CWindowOverridableVar noMaxSize = false; + CWindowOverridableVar maxSize = Vector2D(std::numeric_limits::max(), std::numeric_limits::max()); + CWindowOverridableVar minSize = Vector2D(1, 1); + CWindowOverridableVar dimAround = false; + CWindowOverridableVar forceRGBX = false; + CWindowOverridableVar keepAspectRatio = false; + CWindowOverridableVar xray = -1; // -1 means unset, takes precedence over the renderdata one + CWindowOverridableVar borderSize = -1; // -1 means unset, takes precedence over the renderdata one + CWindowOverridableVar forceTearing = false; + CWindowOverridableVar nearestNeighbor = false; }; struct SWindowRule { diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index c6864573b..594d002f9 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1147,11 +1147,8 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { bool lock = false; - if (vars.size() > 4) { - if (vars[4].starts_with("lock")) { - lock = true; - } - } + if (request.ends_with("lock")) + lock = true; try { if (PROP == "animationstyle") { @@ -1180,6 +1177,22 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { PWINDOW->m_sAdditionalConfigData.windowDanceCompat.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else if (PROP == "nomaxsize") { PWINDOW->m_sAdditionalConfigData.noMaxSize.forceSetIgnoreLocked(configStringToInt(VAL), lock); + } else if (PROP == "maxsize") { + PWINDOW->m_sAdditionalConfigData.maxSize.forceSetIgnoreLocked(configStringToVector2D(VAL + " " + vars[4]), lock); + if (lock) { + PWINDOW->m_vRealSize = Vector2D(std::min((double)PWINDOW->m_sAdditionalConfigData.maxSize.toUnderlying().x, PWINDOW->m_vRealSize.goal().x), + std::min((double)PWINDOW->m_sAdditionalConfigData.maxSize.toUnderlying().y, PWINDOW->m_vRealSize.goal().y)); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); + PWINDOW->setHidden(false); + } + } else if (PROP == "minsize") { + PWINDOW->m_sAdditionalConfigData.minSize.forceSetIgnoreLocked(configStringToVector2D(VAL + " " + vars[4]), lock); + if (lock) { + PWINDOW->m_vRealSize = Vector2D(std::max((double)PWINDOW->m_sAdditionalConfigData.minSize.toUnderlying().x, PWINDOW->m_vRealSize.goal().x), + std::max((double)PWINDOW->m_sAdditionalConfigData.minSize.toUnderlying().y, PWINDOW->m_vRealSize.goal().y)); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); + PWINDOW->setHidden(false); + } } else if (PROP == "dimaround") { PWINDOW->m_sAdditionalConfigData.dimAround.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else if (PROP == "alphaoverride") { diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 0bf84f10a..84040ad57 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -328,34 +328,6 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->setHidden(false); } catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); } - } else if (r.szRule.starts_with("minsize")) { - try { - const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); - const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); - const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - - const auto SIZE = - Vector2D(std::max((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goal().x), std::max((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goal().y)); - - PWINDOW->m_vRealSize = SIZE; - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - - PWINDOW->setHidden(false); - } catch (...) { Debug::log(LOG, "Rule minsize failed, rule: {} -> {}", r.szRule, r.szValue); } - } else if (r.szRule.starts_with("maxsize")) { - try { - const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); - const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); - const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1); - - const auto SIZE = - Vector2D(std::min((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goal().x), std::min((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goal().y)); - - PWINDOW->m_vRealSize = SIZE; - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); - - PWINDOW->setHidden(false); - } catch (...) { Debug::log(LOG, "Rule maxsize failed, rule: {} -> {}", r.szRule, r.szValue); } } else if (r.szRule.starts_with("move")) { try { auto value = r.szRule.substr(r.szRule.find(' ') + 1); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 2905ce2bd..860d84566 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -722,6 +722,32 @@ int64_t configStringToInt(const std::string& VALUE) { return std::stoll(VALUE); } +Vector2D configStringToVector2D(const std::string& VALUE) { + std::istringstream iss(VALUE); + std::string token; + + if (!std::getline(iss, token, ' ') && !std::getline(iss, token, ',')) + throw std::invalid_argument("Invalid string format"); + + if (!isNumber(token)) + throw std::invalid_argument("Invalid x value"); + + long long x = std::stoll(token); + + if (!std::getline(iss, token)) + throw std::invalid_argument("Invalid string format"); + + if (!isNumber(token)) + throw std::invalid_argument("Invalid y value"); + + long long y = std::stoll(token); + + if (std::getline(iss, token)) + throw std::invalid_argument("Invalid string format"); + + return Vector2D(x, y); +} + double normalizeAngleRad(double ang) { if (ang > M_PI * 2) { while (ang > M_PI * 2) diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 23fc6e5ac..d8a86b951 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -28,6 +28,7 @@ void logSystemInfo(); std::string execAndGet(const char*); int64_t getPPIDof(int64_t pid); int64_t configStringToInt(const std::string&); +Vector2D configStringToVector2D(const std::string&); std::optional getPlusMinusKeywordResult(std::string in, float relative); void matrixProjection(float mat[9], int w, int h, wl_output_transform tr); double normalizeAngleRad(double ang); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 26a30ecfe..7269bab72 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -358,8 +358,8 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { } else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) { if (DRAGGINGWINDOW->m_bIsFloating) { - Vector2D MINSIZE = g_pXWaylandManager->getMinSizeForWindow(DRAGGINGWINDOW).clamp({20, 20}); - Vector2D MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW); + Vector2D MINSIZE = g_pXWaylandManager->getMinSizeForWindow(DRAGGINGWINDOW).clamp(DRAGGINGWINDOW->m_sAdditionalConfigData.minSize.toUnderlying()); + Vector2D MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW).clamp({}, DRAGGINGWINDOW->m_sAdditionalConfigData.maxSize.toUnderlying()); Vector2D newSize = m_vBeginDragSizeXY; Vector2D newPos = m_vBeginDragPositionXY;