From 4cf62c114e8fd2cc4fa47d07459e00c52f6dc1d3 Mon Sep 17 00:00:00 2001 From: Virt <41426325+VirtCode@users.noreply.github.com> Date: Fri, 25 Apr 2025 16:38:31 +0200 Subject: [PATCH] layerrules: add abovelock to render above lockscreen (#9793) --- src/Compositor.cpp | 7 +++++-- src/Compositor.hpp | 2 +- src/desktop/LayerRule.cpp | 6 ++++-- src/desktop/LayerRule.hpp | 3 ++- src/desktop/LayerSurface.cpp | 13 ++++++++++--- src/desktop/LayerSurface.hpp | 16 +++++++++------- src/managers/input/InputManager.cpp | 27 +++++++++++++++++++++------ src/render/Renderer.cpp | 19 ++++++++++++++++++- src/render/Renderer.hpp | 2 +- 9 files changed, 71 insertions(+), 24 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index d4e5bc435..a32ba056f 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1286,9 +1286,12 @@ SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& po return nullptr; } -SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { +SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound, + bool aboveLockscreen) { + for (auto const& ls : *layerSurfaces | std::views::reverse) { - if (!ls->m_mapped || ls->m_fadingOut || !ls->m_layerSurface || (ls->m_layerSurface && !ls->m_layerSurface->surface->mapped) || ls->m_alpha->value() == 0.f) + if (!ls->m_mapped || ls->m_fadingOut || !ls->m_layerSurface || (ls->m_layerSurface && !ls->m_layerSurface->surface->mapped) || ls->m_alpha->value() == 0.f || + (aboveLockscreen && (!ls->m_aboveLockscreen || !ls->m_aboveLockscreenInteractable))) continue; auto [surf, local] = ls->m_layerSurface->surface->at(pos - ls->m_geometry.pos(), true); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 32e652860..7c81c7779 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -85,7 +85,7 @@ class CCompositor { void focusSurface(SP<CWLSurfaceResource>, PHLWINDOW pWindowOwner = nullptr); bool monitorExists(PHLMONITOR); PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr); - SP<CWLSurfaceResource> vectorToLayerSurface(const Vector2D&, std::vector<PHLLSREF>*, Vector2D*, PHLLS*); + SP<CWLSurfaceResource> vectorToLayerSurface(const Vector2D&, std::vector<PHLLSREF>*, Vector2D*, PHLLS*, bool aboveLockscreen = false); SP<CWLSurfaceResource> vectorToLayerPopupSurface(const Vector2D&, PHLMONITOR monitor, Vector2D*, PHLLS*); SP<CWLSurfaceResource> vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl); Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP<CWLSurfaceResource>); diff --git a/src/desktop/LayerRule.cpp b/src/desktop/LayerRule.cpp index c03d89685..9b5f9da24 100644 --- a/src/desktop/LayerRule.cpp +++ b/src/desktop/LayerRule.cpp @@ -5,7 +5,7 @@ #include "../debug/Log.hpp" static const auto RULES = std::unordered_set<std::string>{"noanim", "blur", "blurpopups", "dimaround"}; -static const auto RULES_PREFIX = std::unordered_set<std::string>{"ignorealpha", "ignorezero", "xray", "animation", "order"}; +static const auto RULES_PREFIX = std::unordered_set<std::string>{"ignorealpha", "ignorezero", "xray", "animation", "order", "abovelock"}; CLayerRule::CLayerRule(const std::string& rule_, const std::string& ns_) : m_targetNamespace(ns_), m_rule(rule_) { const bool VALID = RULES.contains(m_rule) || std::any_of(RULES_PREFIX.begin(), RULES_PREFIX.end(), [&rule_](const auto& prefix) { return rule_.starts_with(prefix); }); @@ -31,8 +31,10 @@ CLayerRule::CLayerRule(const std::string& rule_, const std::string& ns_) : m_tar m_ruleType = RULE_ANIMATION; else if (m_rule.starts_with("order")) m_ruleType = RULE_ORDER; + else if (m_rule.starts_with("abovelock")) + m_ruleType = RULE_ABOVELOCK; else { Debug::log(ERR, "CLayerRule: didn't match a rule that was found valid?!"); m_ruleType = RULE_INVALID; } -} \ No newline at end of file +} diff --git a/src/desktop/LayerRule.hpp b/src/desktop/LayerRule.hpp index 46f843a62..0463196e2 100644 --- a/src/desktop/LayerRule.hpp +++ b/src/desktop/LayerRule.hpp @@ -14,6 +14,7 @@ class CLayerRule { RULE_BLUR, RULE_BLURPOPUPS, RULE_DIMAROUND, + RULE_ABOVELOCK, RULE_IGNOREALPHA, RULE_IGNOREZERO, RULE_XRAY, @@ -28,4 +29,4 @@ class CLayerRule { const std::string m_rule; CRuleRegexContainer m_targetNamespaceRegex; -}; \ No newline at end of file +}; diff --git a/src/desktop/LayerSurface.cpp b/src/desktop/LayerSurface.cpp index b44f652b4..96c6200ed 100644 --- a/src/desktop/LayerSurface.cpp +++ b/src/desktop/LayerSurface.cpp @@ -421,9 +421,8 @@ void CLayerSurface::applyRules() { } case CLayerRule::RULE_XRAY: { CVarList vars{rule->m_rule, 0, ' '}; - try { - m_xray = configStringToInt(vars[1]).value_or(false); - } catch (...) {} + m_xray = configStringToInt(vars[1]).value_or(false); + break; } case CLayerRule::RULE_ANIMATION: { @@ -438,6 +437,14 @@ void CLayerSurface::applyRules() { } catch (...) { Debug::log(ERR, "Invalid value passed to order"); } break; } + case CLayerRule::RULE_ABOVELOCK: { + m_aboveLockscreen = true; + + CVarList vars{rule->m_rule, 0, ' '}; + m_aboveLockscreenInteractable = configStringToInt(vars[1]).value_or(false); + + break; + } default: break; } } diff --git a/src/desktop/LayerSurface.hpp b/src/desktop/LayerSurface.hpp index 6282d55f1..b80d88de0 100644 --- a/src/desktop/LayerSurface.hpp +++ b/src/desktop/LayerSurface.hpp @@ -43,13 +43,15 @@ class CLayerSurface { bool m_noProcess = false; bool m_noAnimations = false; - bool m_forceBlur = false; - bool m_forceBlurPopups = false; - int64_t m_xray = -1; - bool m_ignoreAlpha = false; - float m_ignoreAlphaValue = 0.f; - bool m_dimAround = false; - int64_t m_order = 0; + bool m_forceBlur = false; + bool m_forceBlurPopups = false; + int64_t m_xray = -1; + bool m_ignoreAlpha = false; + float m_ignoreAlphaValue = 0.f; + bool m_dimAround = false; + int64_t m_order = 0; + bool m_aboveLockscreen = false; + bool m_aboveLockscreenInteractable = false; std::optional<std::string> m_animationStyle; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index c51b8e1c2..58ae6e933 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -2,6 +2,7 @@ #include "../../Compositor.hpp" #include <aquamarine/output/Output.hpp> #include <cstdint> +#include <hyprutils/math/Vector2D.hpp> #include <ranges> #include "../../config/ConfigValue.hpp" #include "../../config/ConfigManager.hpp" @@ -249,15 +250,29 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { g_pCompositor->setActiveMonitor(PMONITOR); if (g_pSessionLockManager->isSessionLocked()) { + + // set keyboard focus on session lock surface regardless of layers const auto PSESSIONLOCKSURFACE = g_pSessionLockManager->getSessionLockSurfaceForMonitor(PMONITOR->ID); - surfacePos = PMONITOR->vecPosition; + const auto foundLockSurface = PSESSIONLOCKSURFACE ? PSESSIONLOCKSURFACE->surface->surface() : nullptr; - foundSurface = PSESSIONLOCKSURFACE ? PSESSIONLOCKSURFACE->surface->surface() : nullptr; - g_pCompositor->focusSurface(foundSurface); + g_pCompositor->focusSurface(foundLockSurface); + + // search for interactable abovelock surfaces for pointer focus, or use session lock surface if not found + for (auto& lsl : PMONITOR->m_aLayerSurfaceLayers | std::views::reverse) { + foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &lsl, &surfaceCoords, &pFoundLayerSurface, true); + + if (foundSurface) + break; + } + + if (!foundSurface) { + surfaceCoords = mouseCoords - PMONITOR->vecPosition; + foundSurface = foundLockSurface; + } + + g_pSeatManager->setPointerFocus(foundSurface, surfaceCoords); + g_pSeatManager->sendPointerMotion(time, surfaceCoords); - const auto SURFACELOCAL = mouseCoords - surfacePos; - g_pSeatManager->setPointerFocus(foundSurface, SURFACELOCAL); - g_pSeatManager->sendPointerMotion(time, SURFACELOCAL); return; } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 364f7fdeb..fd2310275 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -690,10 +690,14 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, const T g_pHyprOpenGL->m_RenderData.currentWindow.reset(); } -void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, const Time::steady_tp& time, bool popups) { +void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, const Time::steady_tp& time, bool popups, bool lockscreen) { if (!pLayer) return; + // skip rendering based on abovelock rule and make sure to not render abovelock layers twice + if ((pLayer->m_aboveLockscreen && !lockscreen && g_pSessionLockManager->isSessionLocked()) || (lockscreen && !pLayer->m_aboveLockscreen)) + return; + static auto PDIMAROUND = CConfigValue<Hyprlang::FLOAT>("decoration:dim_around"); if (*PDIMAROUND && pLayer->m_dimAround && !m_bRenderingSnapshot && !popups) { @@ -998,6 +1002,19 @@ void CHyprRenderer::renderLockscreen(PHLMONITOR pMonitor, const Time::steady_tp& renderSessionLockMissing(pMonitor); } else { renderSessionLockSurface(PSLS, pMonitor, now); + + // render layers and then their popups for abovelock rule + for (auto const& lsl : pMonitor->m_aLayerSurfaceLayers) { + for (auto const& ls : lsl) { + renderLayer(ls.lock(), pMonitor, now, false, true); + } + } + for (auto const& lsl : pMonitor->m_aLayerSurfaceLayers) { + for (auto const& ls : lsl) { + renderLayer(ls.lock(), pMonitor, now, true, true); + } + } + g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 1d0df2a5b..553965a46 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -120,7 +120,7 @@ class CHyprRenderer { void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) void renderWindow(PHLWINDOW, PHLMONITOR, const Time::steady_tp&, bool, eRenderPassMode, bool ignorePosition = false, bool standalone = false); - void renderLayer(PHLLS, PHLMONITOR, const Time::steady_tp&, bool popups = false); + void renderLayer(PHLLS, PHLMONITOR, const Time::steady_tp&, bool popups = false, bool lockscreen = false); void renderSessionLockSurface(WP<SSessionLockSurface>, PHLMONITOR, const Time::steady_tp&); void renderDragIcon(PHLMONITOR, const Time::steady_tp&); void renderIMEPopup(CInputPopup*, PHLMONITOR, const Time::steady_tp&);