diff options
Diffstat (limited to 'src/desktop/Window.cpp')
| -rw-r--r-- | src/desktop/Window.cpp | 418 |
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}; +} |
