diff --git a/src/Compositor.cpp b/src/Compositor.cpp index da6ba1c5..14726df8 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1170,7 +1170,8 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { static auto *const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue; static auto *const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue; static auto *const PFULLSCREENALPHA = &g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity")->floatValue; - + static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue; + static auto *const PSHADOWCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow_inactive")->intValue; // border const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow); @@ -1198,6 +1199,13 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { else pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive != -1 ? pWindow->m_sSpecialRenderData.alphaInactive * *PINACTIVEALPHA : *PINACTIVEALPHA; } + + // shadow + if (pWindow == m_pLastWindow) { + pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL); + } else { + pWindow->m_cRealShadowColor = CColor(*PSHADOWCOLINACTIVE != INT_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); + } } void CCompositor::moveWindowToWorkspace(CWindow* pWindow, const std::string& work) { diff --git a/src/Window.cpp b/src/Window.cpp index 8c8cd147..5568d082 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -8,6 +8,7 @@ CWindow::CWindow() { m_cRealBorderColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_BORDER); m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE); m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE); + m_cRealShadowColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_SHADOW); m_dWindowDecorations.emplace_back(std::make_unique(this)); // put the shadow so it's the first deco (has to be rendered first) } @@ -103,3 +104,12 @@ pid_t CWindow::getPID() { return PID; } + +IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) { + for (auto& wd : m_dWindowDecorations) { + if (wd->getDecorationType() == type) + return wd.get(); + } + + return nullptr; +} \ No newline at end of file diff --git a/src/Window.hpp b/src/Window.hpp index 26046aa0..c159340c 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -113,6 +113,9 @@ public: // for alpha CAnimatedVariable m_fActiveInactiveAlpha; + // animated shadow color + CAnimatedVariable m_cRealShadowColor; + // For the list lookup bool operator==(const CWindow& rhs) { return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut; @@ -123,5 +126,6 @@ public: wlr_box getWindowIdealBoundingBoxIgnoreReserved(); void updateWindowDecos(); pid_t getPID(); + IHyprWindowDecoration* getDecorationByType(eDecorationType); }; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e67eda30..00550878 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -70,6 +70,7 @@ void CConfigManager::setDefaultVars() { configValues["decoration:shadow_ignore_window"].intValue = 1; configValues["decoration:shadow_offset"].strValue = "0 0"; configValues["decoration:col.shadow"].intValue = 0xee1a1a1a; + configValues["decoration:col.shadow_inactive"].intValue = INT_MAX; configValues["dwindle:pseudotile"].intValue = 0; configValues["dwindle:col.group_border"].intValue = 0x66777700; diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index a87fff4f..d8fd3c4c 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -13,7 +13,8 @@ enum ANIMATEDVARTYPE { enum AVARDAMAGEPOLICY { AVARDAMAGE_INVALID = -1, AVARDAMAGE_ENTIRE = 0, - AVARDAMAGE_BORDER + AVARDAMAGE_BORDER, + AVARDAMAGE_SHADOW }; class CAnimationManager; diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 053267e3..a8743afd 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -31,6 +31,7 @@ void CAnimationManager::tick() { static auto *const PANIMSPEED = &g_pConfigManager->getConfigValuePtr("animations:speed")->floatValue; static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; static auto *const BEZIERSTR = &g_pConfigManager->getConfigValuePtr("animations:curve")->strValue; + static auto *const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; auto DEFAULTBEZIER = m_mBezierCurves.find(*BEZIERSTR); if (DEFAULTBEZIER == m_mBezierCurves.end()) @@ -42,6 +43,11 @@ void CAnimationManager::tick() { if (!av->isBeingAnimated()) continue; + if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) { + av->warp(); + continue; + } + // get speed const auto SPEED = *av->m_pSpeed == 0 ? *PANIMSPEED : *av->m_pSpeed; @@ -181,6 +187,36 @@ void CAnimationManager::tick() { g_pHyprRenderer->damageBox(WLRBOXNEW.x + WLRBOXNEW.width - ROUNDINGSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // right g_pHyprRenderer->damageBox(WLRBOXNEW.x, WLRBOXNEW.y + WLRBOXNEW.height - ROUNDINGSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // bottom + break; + } case AVARDAMAGE_SHADOW: { + RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!"); + + static auto* const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue; + static auto* const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue; + + const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW); + + if (PDECO) { + const auto EXTENTS = PDECO->getWindowDecorationExtents(); + + wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x + EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y + EXTENTS.topLeft.y, + PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y}; + + if (!*PSHADOWIGNOREWINDOW) { + // easy, damage the entire box + g_pHyprRenderer->damageBox(&dmg); + } else { + pixman_region32_t rg; + pixman_region32_init_rect(&rg, dmg.x, dmg.y, dmg.width, dmg.height); + pixman_region32_t wb; + pixman_region32_init_rect(&wb, PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y); + pixman_region32_subtract(&rg, &rg, &wb); + g_pHyprRenderer->damageRegion(&rg); + pixman_region32_fini(&rg); + pixman_region32_fini(&wb); + } + } + break; } default: { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index a8c669d7..07e4dfff 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -857,13 +857,13 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, float a) { RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); + RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!"); - static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue; static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue; const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4); - const auto col = CColor(*PSHADOWCOL); + const auto col = m_pCurrentWindow->m_cRealShadowColor.col(); float matrix[9]; wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f9f7d0e3..e3e67a65 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -693,6 +693,13 @@ void CHyprRenderer::damageBox(const int& x, const int& y, const int& w, const in damageBox(&box); } +void CHyprRenderer::damageRegion(pixman_region32_t* rg) { + PIXMAN_DAMAGE_FOREACH(rg) { + const auto RECT = RECTSARR[i]; + damageBox(RECT.x1, RECT.y1, RECT.x2 - RECT.x1, RECT.y2 - RECT.y1); + } +} + void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) { if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface)) return; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index c03c7117..97a0dc70 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -33,6 +33,7 @@ public: void damageWindow(CWindow*); void damageBox(wlr_box*); void damageBox(const int& x, const int& y, const int& w, const int& h); + void damageRegion(pixman_region32_t*); void damageMonitor(SMonitor*); bool applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false); bool shouldRenderWindow(CWindow*, SMonitor*);