diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index da6ba1c50..14726df80 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 8c8cd1470..5568d082d 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<CHyprDropShadowDecoration>(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 26046aa0b..c159340c8 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 e67eda30c..005508786 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 a87fff4f2..d8fd3c4c5 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 053267e3d..a8743afd1 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 a8c669d72..07e4dfff1 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 f9f7d0e3a..e3e67a652 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 c03c71177..97a0dc700 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*);