summaryrefslogtreecommitdiff
path: root/src/desktop/Window.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/desktop/Window.cpp')
-rw-r--r--src/desktop/Window.cpp418
1 files changed, 158 insertions, 260 deletions
diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp
index 8671c003..b2712886 100644
--- a/src/desktop/Window.cpp
+++ b/src/desktop/Window.cpp
@@ -24,6 +24,7 @@
#include "../protocols/FractionalScale.hpp"
#include "../xwayland/XWayland.hpp"
#include "../helpers/Color.hpp"
+#include "../helpers/math/Expression.hpp"
#include "../events/Events.hpp"
#include "../managers/XWaylandManager.hpp"
#include "../render/Renderer.hpp"
@@ -41,8 +42,9 @@ using enum NContentType::eContentType;
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
- pWindow->m_self = pWindow;
- pWindow->m_isX11 = true;
+ pWindow->m_self = pWindow;
+ pWindow->m_isX11 = true;
+ pWindow->m_ruleApplicator = makeUnique<Desktop::Rule::CWindowRuleApplicator>(pWindow);
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
@@ -67,6 +69,7 @@ PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
pWindow->m_self = pWindow;
resource->m_toplevel->m_window = pWindow;
+ pWindow->m_ruleApplicator = makeUnique<Desktop::Rule::CWindowRuleApplicator>(pWindow);
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
@@ -138,7 +141,7 @@ SBoxExtents CWindow::getFullWindowExtents() {
const int BORDERSIZE = getRealBorderSize();
- if (m_windowData.dimAround.valueOrDefault()) {
+ if (m_ruleApplicator->dimAround().valueOrDefault()) {
if (const auto PMONITOR = m_monitor.lock(); PMONITOR)
return {.topLeft = {m_realPosition->value().x - PMONITOR->m_position.x, m_realPosition->value().y - PMONITOR->m_position.y},
.bottomRight = {PMONITOR->m_size.x - (m_realPosition->value().x - PMONITOR->m_position.x),
@@ -191,7 +194,7 @@ SBoxExtents CWindow::getFullWindowExtents() {
}
CBox CWindow::getFullWindowBoundingBox() {
- if (m_windowData.dimAround.valueOrDefault()) {
+ if (m_ruleApplicator->dimAround().valueOrDefault()) {
if (const auto PMONITOR = m_monitor.lock(); PMONITOR)
return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y};
}
@@ -251,7 +254,7 @@ SBoxExtents CWindow::getWindowExtentsUnified(uint64_t properties) {
}
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
- if (m_windowData.dimAround.valueOrDefault()) {
+ if (m_ruleApplicator->dimAround().valueOrDefault()) {
const auto PMONITOR = m_monitor.lock();
if (PMONITOR)
return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y};
@@ -636,222 +639,6 @@ bool CWindow::isHidden() {
return m_hidden;
}
-void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
- const eOverridePriority priority = r->m_execRule ? PRIORITY_SET_PROP : PRIORITY_WINDOW_RULE;
- static auto PCLAMP_TILED = CConfigValue<Hyprlang::INT>("misc:size_limits_tiled");
-
- switch (r->m_ruleType) {
- case CWindowRule::RULE_TAG: {
- CVarList vars{r->m_rule, 0, 's', true};
-
- if (vars.size() == 2 && vars[0] == "tag")
- m_tags.applyTag(vars[1], true);
- else
- Debug::log(ERR, "Tag rule invalid: {}", r->m_rule);
- break;
- }
- case CWindowRule::RULE_OPACITY: {
- try {
- CVarList vars(r->m_rule, 0, ' ');
-
- int opacityIDX = 0;
-
- for (auto const& r : vars) {
- if (r == "opacity")
- continue;
-
- if (r == "override") {
- if (opacityIDX == 1)
- m_windowData.alpha = CWindowOverridableVar(SAlphaValue{.alpha = m_windowData.alpha.value().alpha, .overridden = true}, priority);
- else if (opacityIDX == 2)
- m_windowData.alphaInactive = CWindowOverridableVar(SAlphaValue{.alpha = m_windowData.alphaInactive.value().alpha, .overridden = true}, priority);
- else if (opacityIDX == 3)
- m_windowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{.alpha = m_windowData.alphaFullscreen.value().alpha, .overridden = true}, priority);
- } else {
- if (opacityIDX == 0) {
- m_windowData.alpha = CWindowOverridableVar(SAlphaValue{.alpha = std::stof(r), .overridden = false}, priority);
- } else if (opacityIDX == 1) {
- m_windowData.alphaInactive = CWindowOverridableVar(SAlphaValue{.alpha = std::stof(r), .overridden = false}, priority);
- } else if (opacityIDX == 2) {
- m_windowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{.alpha = std::stof(r), .overridden = false}, priority);
- } else {
- throw std::runtime_error("more than 3 alpha values");
- }
-
- opacityIDX++;
- }
- }
-
- if (opacityIDX == 1) {
- m_windowData.alphaInactive = m_windowData.alpha;
- m_windowData.alphaFullscreen = m_windowData.alpha;
- }
- } catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"{}\" failed with: {}", r->m_rule, e.what()); }
- break;
- }
- case CWindowRule::RULE_ANIMATION: {
- auto STYLE = r->m_rule.substr(r->m_rule.find_first_of(' ') + 1);
- m_windowData.animationStyle = CWindowOverridableVar(STYLE, priority);
- break;
- }
- case CWindowRule::RULE_BORDERCOLOR: {
- try {
- // Each vector will only get used if it has at least one color
- CGradientValueData activeBorderGradient = {};
- CGradientValueData inactiveBorderGradient = {};
- bool active = true;
- CVarList colorsAndAngles = CVarList(trim(r->m_rule.substr(r->m_rule.find_first_of(' ') + 1)), 0, 's', true);
-
- // Basic form has only two colors, everything else can be parsed as a gradient
- if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) {
- m_windowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority);
- m_windowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority);
- return;
- }
-
- for (auto const& token : colorsAndAngles) {
- // The first angle, or an explicit "0deg", splits the two gradients
- if (active && token.contains("deg")) {
- activeBorderGradient.m_angle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
- active = false;
- } else if (token.contains("deg"))
- inactiveBorderGradient.m_angle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
- else if (active)
- activeBorderGradient.m_colors.emplace_back(configStringToInt(token).value_or(0));
- else
- inactiveBorderGradient.m_colors.emplace_back(configStringToInt(token).value_or(0));
- }
-
- activeBorderGradient.updateColorsOk();
-
- // Includes sanity checks for the number of colors in each gradient
- if (activeBorderGradient.m_colors.size() > 10 || inactiveBorderGradient.m_colors.size() > 10)
- Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r->m_rule);
- else if (activeBorderGradient.m_colors.empty())
- Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r->m_rule);
- else if (inactiveBorderGradient.m_colors.empty())
- m_windowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority);
- else {
- m_windowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority);
- m_windowData.inactiveBorderColor = CWindowOverridableVar(inactiveBorderGradient, priority);
- }
- } catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", r->m_rule, e.what()); }
- break;
- }
- case CWindowRule::RULE_IDLEINHIBIT: {
- auto IDLERULE = r->m_rule.substr(r->m_rule.find_first_of(' ') + 1);
-
- if (IDLERULE == "none")
- m_idleInhibitMode = IDLEINHIBIT_NONE;
- else if (IDLERULE == "always")
- m_idleInhibitMode = IDLEINHIBIT_ALWAYS;
- else if (IDLERULE == "focus")
- m_idleInhibitMode = IDLEINHIBIT_FOCUS;
- else if (IDLERULE == "fullscreen")
- m_idleInhibitMode = IDLEINHIBIT_FULLSCREEN;
- else
- Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE);
- break;
- }
- case CWindowRule::RULE_MAXSIZE: {
- try {
- if (!m_isFloating && !sc<bool>(*PCLAMP_TILED))
- return;
- const auto VEC = configStringToVector2D(r->m_rule.substr(8));
- if (VEC.x < 1 || VEC.y < 1) {
- Debug::log(ERR, "Invalid size for maxsize");
- return;
- }
-
- m_windowData.maxSize = CWindowOverridableVar(VEC, priority);
- clampWindowSize(std::nullopt, m_windowData.maxSize.value());
-
- } catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r->m_rule, e.what()); }
- break;
- }
- case CWindowRule::RULE_MINSIZE: {
- try {
- if (!m_isFloating && !sc<bool>(*PCLAMP_TILED))
- return;
- const auto VEC = configStringToVector2D(r->m_rule.substr(8));
- if (VEC.x < 1 || VEC.y < 1) {
- Debug::log(ERR, "Invalid size for minsize");
- return;
- }
-
- m_windowData.minSize = CWindowOverridableVar(VEC, priority);
- clampWindowSize(m_windowData.minSize.value(), std::nullopt);
-
- if (m_groupData.pNextWindow.expired())
- setHidden(false);
- } catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r->m_rule, e.what()); }
- break;
- }
- case CWindowRule::RULE_RENDERUNFOCUSED: {
- m_windowData.renderUnfocused = CWindowOverridableVar(true, priority);
- g_pHyprRenderer->addWindowToRenderUnfocused(m_self.lock());
- break;
- }
- case CWindowRule::RULE_PROP: {
- const CVarList VARS(r->m_rule, 0, ' ');
- if (auto search = NWindowProperties::intWindowProperties.find(VARS[1]); search != NWindowProperties::intWindowProperties.end()) {
- try {
- *(search->second(m_self.lock())) = CWindowOverridableVar(sc<Hyprlang::INT>(std::stoi(VARS[2])), priority);
- } catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); }
- } else if (auto search = NWindowProperties::floatWindowProperties.find(VARS[1]); search != NWindowProperties::floatWindowProperties.end()) {
- try {
- *(search->second(m_self.lock())) = CWindowOverridableVar(std::stof(VARS[2]), priority);
- } catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); }
- } else if (auto search = NWindowProperties::boolWindowProperties.find(VARS[1]); search != NWindowProperties::boolWindowProperties.end()) {
- try {
- *(search->second(m_self.lock())) = CWindowOverridableVar(VARS[2].empty() ? true : sc<bool>(std::stoi(VARS[2])), priority);
- } catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); }
- }
- break;
- }
- case CWindowRule::RULE_PERSISTENTSIZE: {
- m_windowData.persistentSize = CWindowOverridableVar(true, PRIORITY_WINDOW_RULE);
- break;
- }
- case CWindowRule::RULE_NOVRR: {
- m_windowData.noVRR = CWindowOverridableVar(true, priority);
- break;
- }
- default: break;
- }
-}
-
-void CWindow::updateDynamicRules() {
- m_windowData.alpha.unset(PRIORITY_WINDOW_RULE);
- m_windowData.alphaInactive.unset(PRIORITY_WINDOW_RULE);
- m_windowData.alphaFullscreen.unset(PRIORITY_WINDOW_RULE);
-
- unsetWindowData(PRIORITY_WINDOW_RULE);
-
- m_windowData.animationStyle.unset(PRIORITY_WINDOW_RULE);
- m_windowData.maxSize.unset(PRIORITY_WINDOW_RULE);
- m_windowData.minSize.unset(PRIORITY_WINDOW_RULE);
-
- m_windowData.activeBorderColor.unset(PRIORITY_WINDOW_RULE);
- m_windowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE);
-
- m_windowData.renderUnfocused.unset(PRIORITY_WINDOW_RULE);
- m_windowData.noVRR.unset(PRIORITY_WINDOW_RULE);
-
- m_idleInhibitMode = IDLEINHIBIT_NONE;
-
- m_tags.removeDynamicTags();
-
- m_matchedRules = g_pConfigManager->getMatchingRules(m_self.lock());
- for (const auto& r : m_matchedRules) {
- applyDynamicRule(r);
- }
-
- EMIT_HOOK_EVENT("windowUpdateRules", m_self.lock());
-
- g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
-}
-
// check if the point is "hidden" under a rounded corner of the window
// it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize)
// otherwise behaviour is undefined
@@ -924,6 +711,8 @@ void CWindow::createGroup() {
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("1,{:x}", rc<uintptr_t>(this))});
}
+
+ m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
}
void CWindow::destroyGroup() {
@@ -943,6 +732,7 @@ void CWindow::destroyGroup() {
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("0,{:x}", rc<uintptr_t>(this))});
+ m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
return;
}
@@ -969,6 +759,7 @@ void CWindow::destroyGroup() {
g_pKeybindManager->m_groupsLocked = true;
for (auto const& w : members) {
g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
+ w->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
w->updateWindowDecos();
}
g_pKeybindManager->m_groupsLocked = GROUPSLOCKEDPREV;
@@ -982,6 +773,8 @@ void CWindow::destroyGroup() {
if (!addresses.empty())
addresses.pop_back();
+
+ m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("0,{}", addresses)});
}
@@ -1217,16 +1010,16 @@ float CWindow::rounding() {
static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding");
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
- float roundingPower = m_windowData.roundingPower.valueOr(*PROUNDINGPOWER);
- float rounding = m_windowData.rounding.valueOr(*PROUNDING) * (roundingPower / 2.0); /* Make perceived roundness consistent. */
+ float roundingPower = m_ruleApplicator->roundingPower().valueOr(*PROUNDINGPOWER);
+ float rounding = m_ruleApplicator->rounding().valueOr(*PROUNDING) * (roundingPower / 2.0); /* Make perceived roundness consistent. */
- return m_windowData.noRounding.valueOrDefault() ? 0 : rounding;
+ return rounding;
}
float CWindow::roundingPower() {
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
- return m_windowData.roundingPower.valueOr(std::clamp(*PROUNDINGPOWER, 1.F, 10.F));
+ return m_ruleApplicator->roundingPower().valueOr(std::clamp(*PROUNDINGPOWER, 1.F, 10.F));
}
void CWindow::updateWindowData() {
@@ -1236,50 +1029,43 @@ void CWindow::updateWindowData() {
}
void CWindow::updateWindowData(const SWorkspaceRule& workspaceRule) {
- static auto PNOBORDERONFLOATING = CConfigValue<Hyprlang::INT>("general:no_border_on_floating");
-
- if (*PNOBORDERONFLOATING)
- m_windowData.noBorder = CWindowOverridableVar(m_isFloating, PRIORITY_LAYOUT);
- else
- m_windowData.noBorder.unset(PRIORITY_LAYOUT);
-
- m_windowData.borderSize.matchOptional(workspaceRule.borderSize, PRIORITY_WORKSPACE_RULE);
- m_windowData.decorate.matchOptional(workspaceRule.decorate, PRIORITY_WORKSPACE_RULE);
- m_windowData.noBorder.matchOptional(workspaceRule.noBorder, PRIORITY_WORKSPACE_RULE);
- m_windowData.noRounding.matchOptional(workspaceRule.noRounding, PRIORITY_WORKSPACE_RULE);
- m_windowData.noShadow.matchOptional(workspaceRule.noShadow, PRIORITY_WORKSPACE_RULE);
+ m_ruleApplicator->borderSize().matchOptional(workspaceRule.borderSize, Desktop::Types::PRIORITY_WORKSPACE_RULE);
+ m_ruleApplicator->decorate().matchOptional(workspaceRule.decorate, Desktop::Types::PRIORITY_WORKSPACE_RULE);
+ m_ruleApplicator->borderSize().matchOptional(workspaceRule.noBorder ? std::optional<Hyprlang::INT>(0) : std::nullopt, Desktop::Types::PRIORITY_WORKSPACE_RULE);
+ m_ruleApplicator->rounding().matchOptional(workspaceRule.noRounding.value_or(false) ? std::optional<Hyprlang::INT>(0) : std::nullopt, Desktop::Types::PRIORITY_WORKSPACE_RULE);
+ m_ruleApplicator->noShadow().matchOptional(workspaceRule.noShadow, Desktop::Types::PRIORITY_WORKSPACE_RULE);
}
int CWindow::getRealBorderSize() {
- if (m_windowData.noBorder.valueOrDefault() || (m_workspace && isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) || !m_windowData.decorate.valueOrDefault())
+ if ((m_workspace && isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) || !m_ruleApplicator->decorate().valueOrDefault())
return 0;
static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
- return m_windowData.borderSize.valueOr(*PBORDERSIZE);
+ return m_ruleApplicator->borderSize().valueOr(*PBORDERSIZE);
}
float CWindow::getScrollMouse() {
static auto PINPUTSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:scroll_factor");
- return m_windowData.scrollMouse.valueOr(*PINPUTSCROLLFACTOR);
+ return m_ruleApplicator->scrollMouse().valueOr(*PINPUTSCROLLFACTOR);
}
float CWindow::getScrollTouchpad() {
static auto PTOUCHPADSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:touchpad:scroll_factor");
- return m_windowData.scrollTouchpad.valueOr(*PTOUCHPADSCROLLFACTOR);
+ return m_ruleApplicator->scrollTouchpad().valueOr(*PTOUCHPADSCROLLFACTOR);
}
bool CWindow::isScrollMouseOverridden() {
- return m_windowData.scrollMouse.hasValue();
+ return m_ruleApplicator->scrollMouse().hasValue();
}
bool CWindow::isScrollTouchpadOverridden() {
- return m_windowData.scrollTouchpad.hasValue();
+ return m_ruleApplicator->scrollTouchpad().hasValue();
}
bool CWindow::canBeTorn() {
static auto PTEARING = CConfigValue<Hyprlang::INT>("general:allow_tearing");
- return m_windowData.tearing.valueOr(m_tearingHint) && *PTEARING;
+ return m_ruleApplicator->tearing().valueOr(m_tearingHint) && *PTEARING;
}
void CWindow::setSuspended(bool suspend) {
@@ -1454,7 +1240,8 @@ void CWindow::activate(bool force) {
g_pEventManager->postEvent(SHyprIPCEvent{.event = "urgent", .data = std::format("{:x}", rc<uintptr_t>(this))});
EMIT_HOOK_EVENT("urgent", m_self.lock());
- if (!force && (!m_windowData.focusOnActivate.valueOr(*PFOCUSONACTIVATE) || (m_suppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_suppressedEvents & SUPPRESS_ACTIVATE)))
+ if (!force &&
+ (!m_ruleApplicator->focusOnActivate().valueOr(*PFOCUSONACTIVATE) || (m_suppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_suppressedEvents & SUPPRESS_ACTIVATE)))
return;
if (!m_isMapped) {
@@ -1539,8 +1326,7 @@ void CWindow::onUpdateMeta() {
}
if (doUpdate) {
- updateDynamicRules();
- g_pCompositor->updateWindowAnimatedDecorationValues(m_self.lock());
+ m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_TITLE | Desktop::Rule::RULE_PROP_CLASS);
updateToplevel();
}
}
@@ -1718,18 +1504,6 @@ PHLWINDOW CWindow::getSwallower() {
return candidates[0];
}
-void CWindow::unsetWindowData(eOverridePriority priority) {
- for (auto const& element : NWindowProperties::boolWindowProperties) {
- element.second(m_self.lock())->unset(priority);
- }
- for (auto const& element : NWindowProperties::intWindowProperties) {
- element.second(m_self.lock())->unset(priority);
- }
- for (auto const& element : NWindowProperties::floatWindowProperties) {
- element.second(m_self.lock())->unset(priority);
- }
-}
-
bool CWindow::isX11OverrideRedirect() {
return m_xwaylandSurface && m_xwaylandSurface->m_overrideRedirect;
}
@@ -1753,7 +1527,7 @@ Vector2D CWindow::requestedMinSize() {
Vector2D CWindow::requestedMaxSize() {
constexpr int NO_MAX_SIZE_LIMIT = 99999;
- if (((m_isX11 && !m_xwaylandSurface->m_sizeHints) || (!m_isX11 && (!m_xdgSurface || !m_xdgSurface->m_toplevel)) || m_windowData.noMaxSize.valueOrDefault()))
+ if (((m_isX11 && !m_xwaylandSurface->m_sizeHints) || (!m_isX11 && (!m_xdgSurface || !m_xdgSurface->m_toplevel)) || m_ruleApplicator->noMaxSize().valueOrDefault()))
return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT);
Vector2D maxSize = m_isX11 ? Vector2D(m_xwaylandSurface->m_sizeHints->max_width, m_xwaylandSurface->m_sizeHints->max_height) : m_xdgSurface->m_toplevel->layoutMaxSize();
@@ -1951,3 +1725,127 @@ Vector2D CWindow::getReportedSize() {
return m_wlSurface->resource()->m_current.ackedSize;
return m_reportedSize;
}
+
+void CWindow::updateDecorationValues() {
+ static auto PACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.active_border");
+ static auto PINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.inactive_border");
+ static auto PNOGROUPACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.nogroup_border_active");
+ static auto PNOGROUPINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.nogroup_border");
+ static auto PGROUPACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_active");
+ static auto PGROUPINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_inactive");
+ static auto PGROUPACTIVELOCKEDCOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_locked_active");
+ static auto PGROUPINACTIVELOCKEDCOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_locked_inactive");
+ static auto PINACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:inactive_opacity");
+ static auto PACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:active_opacity");
+ static auto PFULLSCREENALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:fullscreen_opacity");
+ static auto PSHADOWCOL = CConfigValue<Hyprlang::INT>("decoration:shadow:color");
+ static auto PSHADOWCOLINACTIVE = CConfigValue<Hyprlang::INT>("decoration:shadow:color_inactive");
+ static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
+ static auto PDIMENABLED = CConfigValue<Hyprlang::INT>("decoration:dim_inactive");
+ static auto PDIMMODAL = CConfigValue<Hyprlang::INT>("decoration:dim_modal");
+
+ auto* const ACTIVECOL = sc<CGradientValueData*>((PACTIVECOL.ptr())->getData());
+ auto* const INACTIVECOL = sc<CGradientValueData*>((PINACTIVECOL.ptr())->getData());
+ auto* const NOGROUPACTIVECOL = sc<CGradientValueData*>((PNOGROUPACTIVECOL.ptr())->getData());
+ auto* const NOGROUPINACTIVECOL = sc<CGradientValueData*>((PNOGROUPINACTIVECOL.ptr())->getData());
+ auto* const GROUPACTIVECOL = sc<CGradientValueData*>((PGROUPACTIVECOL.ptr())->getData());
+ auto* const GROUPINACTIVECOL = sc<CGradientValueData*>((PGROUPINACTIVECOL.ptr())->getData());
+ auto* const GROUPACTIVELOCKEDCOL = sc<CGradientValueData*>((PGROUPACTIVELOCKEDCOL.ptr())->getData());
+ auto* const GROUPINACTIVELOCKEDCOL = sc<CGradientValueData*>((PGROUPINACTIVELOCKEDCOL.ptr())->getData());
+
+ auto setBorderColor = [&](CGradientValueData grad) -> void {
+ if (grad == m_realBorderColor)
+ return;
+
+ m_realBorderColorPrevious = m_realBorderColor;
+ m_realBorderColor = grad;
+ m_borderFadeAnimationProgress->setValueAndWarp(0.f);
+ *m_borderFadeAnimationProgress = 1.f;
+ };
+
+ const bool IS_SHADOWED_BY_MODAL = m_xdgSurface && m_xdgSurface->m_toplevel && m_xdgSurface->m_toplevel->anyChildModal();
+
+ // border
+ const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(m_self.lock());
+ if (RENDERDATA.isBorderGradient)
+ setBorderColor(*RENDERDATA.borderGradient);
+ else {
+ const bool GROUPLOCKED = m_groupData.pNextWindow.lock() ? getGroupHead()->m_groupData.locked : false;
+ if (m_self == g_pCompositor->m_lastWindow) {
+ const auto* const ACTIVECOLOR =
+ !m_groupData.pNextWindow.lock() ? (!m_groupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
+ setBorderColor(m_ruleApplicator->activeBorderColor().valueOr(*ACTIVECOLOR));
+ } else {
+ const auto* const INACTIVECOLOR =
+ !m_groupData.pNextWindow.lock() ? (!m_groupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
+ setBorderColor(m_ruleApplicator->inactiveBorderColor().valueOr(*INACTIVECOLOR));
+ }
+ }
+
+ // opacity
+ const auto PWORKSPACE = m_workspace;
+ if (isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) {
+ *m_activeInactiveAlpha = m_ruleApplicator->alphaFullscreen().valueOrDefault().applyAlpha(*PFULLSCREENALPHA);
+ } else {
+ if (m_self == g_pCompositor->m_lastWindow)
+ *m_activeInactiveAlpha = m_ruleApplicator->alpha().valueOrDefault().applyAlpha(*PACTIVEALPHA);
+ else
+ *m_activeInactiveAlpha = m_ruleApplicator->alphaInactive().valueOrDefault().applyAlpha(*PINACTIVEALPHA);
+ }
+
+ // dim
+ float goalDim = 1.F;
+ if (m_self == g_pCompositor->m_lastWindow.lock() || m_ruleApplicator->noDim().valueOrDefault() || !*PDIMENABLED)
+ goalDim = 0;
+ else
+ goalDim = *PDIMSTRENGTH;
+
+ if (IS_SHADOWED_BY_MODAL && *PDIMMODAL)
+ goalDim += (1.F - goalDim) / 2.F;
+
+ *m_dimPercent = goalDim;
+
+ // shadow
+ if (!isX11OverrideRedirect() && !m_X11DoesntWantBorders) {
+ if (m_self == g_pCompositor->m_lastWindow)
+ *m_realShadowColor = CHyprColor(*PSHADOWCOL);
+ else
+ *m_realShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != -1 ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
+ } else
+ m_realShadowColor->setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow
+
+ updateWindowDecos();
+}
+
+std::optional<double> CWindow::calculateSingleExpr(const std::string& s) {
+ const auto PMONITOR = m_monitor ? m_monitor : g_pCompositor->m_lastMonitor;
+ const auto CURSOR_LOCAL = g_pInputManager->getMouseCoordsInternal() - (PMONITOR ? PMONITOR->m_position : Vector2D{});
+
+ Math::CExpression expr;
+ expr.addVariable("window_w", m_realSize->goal().x);
+ expr.addVariable("window_h", m_realSize->goal().y);
+ expr.addVariable("window_x", m_realPosition->goal().x - (PMONITOR ? PMONITOR->m_position.x : 0));
+ expr.addVariable("window_y", m_realPosition->goal().y - (PMONITOR ? PMONITOR->m_position.y : 0));
+
+ expr.addVariable("monitor_w", PMONITOR ? PMONITOR->m_size.x : 1920);
+ expr.addVariable("monitor_h", PMONITOR ? PMONITOR->m_size.y : 1080);
+
+ expr.addVariable("cursor_x", CURSOR_LOCAL.x);
+ expr.addVariable("cursor_y", CURSOR_LOCAL.y);
+
+ return expr.compute(s);
+}
+
+std::optional<Vector2D> CWindow::calculateExpression(const std::string& s) {
+ auto spacePos = s.find(' ');
+ if (spacePos == std::string::npos)
+ return std::nullopt;
+
+ const auto LHS = calculateSingleExpr(s.substr(0, spacePos));
+ const auto RHS = calculateSingleExpr(s.substr(spacePos + 1));
+
+ if (!LHS || !RHS)
+ return std::nullopt;
+
+ return Vector2D{*LHS, *RHS};
+}