diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index b9e6f48a..35cf64e0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -53,6 +53,7 @@ void CConfigManager::setDefaultVars() { configValues["decoration:shadow_range"].intValue = 4; configValues["decoration:shadow_render_power"].intValue = 3; configValues["decoration:shadow_ignore_window"].intValue = 1; + configValues["decoration:shadow_offset"].strValue = "0 0"; configValues["decoration:col.shadow"].intValue = 0xee1a1a1a; configValues["dwindle:pseudotile"].intValue = 0; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index ce9dd788..d082799f 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -135,8 +135,8 @@ float getPlusMinusKeywordResult(std::string source, float relative) { return result; } -bool isNumber(const std::string& str) { - return std::ranges::all_of(str.begin(), str.end(), [](char c) { return isdigit(c) != 0 || c == '-'; }); +bool isNumber(const std::string& str, bool allowfloat) { + return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); }); } bool isDirection(const std::string& arg) { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 8470eb81..733b7ca9 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -7,7 +7,7 @@ void wlr_signal_emit_safe(struct wl_signal *signal, void *data); std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string void scaleBox(wlr_box*, float); std::string removeBeginEndSpacesTabs(std::string); -bool isNumber(const std::string&); +bool isNumber(const std::string&, bool allowfloat = false); bool isDirection(const std::string&); int getWorkspaceIDFromString(const std::string&, std::string&); float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 2ceefdd4..e8f1a1f1 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -47,7 +47,7 @@ void CAnimationManager::tick() { wlr_box WLRBOXPREV = {0,0,0,0}; if (PWINDOW) { - WLRBOXPREV = {(int)PWINDOW->m_vRealPosition.vec().x - (int)*PBORDERSIZE - 1, (int)PWINDOW->m_vRealPosition.vec().y - (int)*PBORDERSIZE - 1, (int)PWINDOW->m_vRealSize.vec().x + 2 * (int)*PBORDERSIZE + 2, (int)PWINDOW->m_vRealSize.vec().y + 2 * (int)*PBORDERSIZE + 2}; + WLRBOXPREV = PWINDOW->getFullWindowBoundingBox(); } else if (PWORKSPACE) { const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y}; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index a0e6483d..efd5476a 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -858,7 +858,6 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue; static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue; - static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue; const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4); @@ -892,7 +891,6 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl glUniform1f(glGetUniformLocation(m_shSHADOW.program, "radius"), range + round); glUniform1f(glGetUniformLocation(m_shSHADOW.program, "range"), range); glUniform1f(glGetUniformLocation(m_shSHADOW.program, "shadowPower"), SHADOWPOWER); - glUniform1i(glGetUniformLocation(m_shSHADOW.program, "ignoreWindow"), *PSHADOWIGNOREWINDOW); glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 6933e687..f9c629bb 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -45,13 +45,29 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) { static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue; static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; + static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue; + static auto *const PSHADOWOFFSET = &g_pConfigManager->getConfigValuePtr("decoration:shadow_offset")->strValue; if (*PSHADOWS != 1) return; // disabled - // update the extents if needed - if (*PSHADOWSIZE != m_seExtents.topLeft.x) - m_seExtents = {{*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}, {*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}}; + // get the real offset + Vector2D offset; + try { + if (const auto SPACEPOS = PSHADOWOFFSET->find(' '); SPACEPOS != std::string::npos) { + const auto X = PSHADOWOFFSET->substr(0, SPACEPOS); + const auto Y = PSHADOWOFFSET->substr(SPACEPOS + 1); + + if (isNumber(X, true) && isNumber(Y, true)) { + offset = Vector2D(std::stof(X), std::stof(Y)); + } + } + } catch (std::exception& e) { + return; // cannot parse + } + + // update the extents + m_seExtents = {{*PSHADOWSIZE + 2 - offset.x, *PSHADOWSIZE + 2 - offset.y}, {*PSHADOWSIZE + 2 + offset.x, *PSHADOWSIZE + 2 + offset.y}}; m_vLastWindowPos = m_pWindow->m_vRealPosition.vec(); m_vLastWindowSize = m_pWindow->m_vRealSize.vec(); @@ -61,6 +77,29 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) { fullBox.x -= pMonitor->vecPosition.x; fullBox.y -= pMonitor->vecPosition.y; + + if (*PSHADOWIGNOREWINDOW) { + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + + glEnable(GL_STENCIL_TEST); + + glStencilFunc(GL_ALWAYS, 1, -1); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + wlr_box windowBox = {m_vLastWindowPos.x, m_vLastWindowPos.y, m_vLastWindowSize.x, m_vLastWindowSize.y}; + g_pHyprOpenGL->renderRect(&windowBox, CColor(0,0,0,0), *PROUNDING); + + glStencilFunc(GL_NOTEQUAL, 1, -1); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + } g_pHyprOpenGL->renderRoundedShadow(&fullBox, *PROUNDING, *PSHADOWSIZE, a); + + if (*PSHADOWIGNOREWINDOW) { + // cleanup + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + glDisable(GL_STENCIL_TEST); + } } diff --git a/src/render/shaders/Shadow.hpp b/src/render/shaders/Shadow.hpp index f54124fa..dca194c0 100644 --- a/src/render/shaders/Shadow.hpp +++ b/src/render/shaders/Shadow.hpp @@ -13,7 +13,6 @@ uniform vec2 fullSize; uniform float radius; uniform float range; uniform float shadowPower; -uniform int ignoreWindow; float pixAlphaRoundedDistance(float distanceToCorner) { if (distanceToCorner > radius) { @@ -75,7 +74,7 @@ void main() { } } - if (pixColor[3] == 0.0 || (ignoreWindow == 1 && pixColor[3] == originalAlpha)) { + if (pixColor[3] == 0.0) { discard; return; }