diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 5c9451a8..8f59f8e1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1295,6 +1295,7 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { 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; + static auto *const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue; // border const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow); @@ -1323,6 +1324,13 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive != -1 ? pWindow->m_sSpecialRenderData.alphaInactive * *PINACTIVEALPHA : *PINACTIVEALPHA; } + // dim + if (pWindow == m_pLastWindow) { + pWindow->m_fDimPercent = 0; + } else { + pWindow->m_fDimPercent = *PDIMSTRENGTH; + } + // shadow if (pWindow->m_iX11Type != 2 && !pWindow->m_bX11DoesntWantBorders) { if (pWindow == m_pLastWindow) { diff --git a/src/Window.cpp b/src/Window.cpp index d0ea4f24..e7abb6e1 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -9,6 +9,7 @@ CWindow::CWindow() { m_fAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE); m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE); m_cRealShadowColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW); + m_fDimPercent.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), (void*)this, AVARDAMAGE_ENTIRE); m_dWindowDecorations.emplace_back(std::make_unique(this)); // put the shadow so it's the first deco (has to be rendered first) } diff --git a/src/Window.hpp b/src/Window.hpp index 11cc709e..5e17d6c1 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -139,6 +139,9 @@ public: // animated shadow color CAnimatedVariable m_cRealShadowColor; + // animated tint + CAnimatedVariable m_fDimPercent; + // for toplevel monitor events uint64_t m_iLastToplevelMonitorID = -1; uint64_t m_iLastSurfaceMonitorID = -1; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index eb9c2032..728df7c9 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -83,6 +83,8 @@ void CConfigManager::setDefaultVars() { configValues["decoration:shadow_offset"].strValue = "0 0"; configValues["decoration:col.shadow"].intValue = 0xee1a1a1a; configValues["decoration:col.shadow_inactive"].intValue = INT_MAX; + configValues["decoration:dim_inactive"].intValue = 0; + configValues["decoration:dim_strength"].floatValue = 0.5f; configValues["dwindle:pseudotile"].intValue = 0; configValues["dwindle:col.group_border"].intValue = 0x66777700; @@ -195,6 +197,7 @@ void CConfigManager::setDefaultAnimationVars() { INITANIMCFG("fadeOut"); INITANIMCFG("fadeSwitch"); INITANIMCFG("fadeShadow"); + INITANIMCFG("fadeDim"); // border @@ -226,6 +229,7 @@ void CConfigManager::setDefaultAnimationVars() { CREATEANIMCFG("fadeOut", "fade"); CREATEANIMCFG("fadeSwitch", "fade"); CREATEANIMCFG("fadeShadow", "fade"); + CREATEANIMCFG("fadeDim", "fade"); CREATEANIMCFG("specialWorkspace", "workspaces"); } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 93ad18e5..5f0110ed 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -48,6 +48,7 @@ void Events::listener_mapWindow(void* owner, void* data) { 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 PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue; const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); @@ -282,8 +283,11 @@ void Events::listener_mapWindow(void* owner, void* data) { if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && PWINDOW->m_iX11Type != 2) { g_pCompositor->focusWindow(PWINDOW); PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA); - } else + PWINDOW->m_fDimPercent.setValueAndWarp(*PDIMSTRENGTH); + } else { PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA); + PWINDOW->m_fDimPercent.setValueAndWarp(0); + } Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 1f4b42e2..ec6e87e2 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -165,6 +165,8 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shRGBA.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample"); + m_RenderData.pCurrentMonData->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint"); + m_RenderData.pCurrentMonData->m_shRGBA.tint = glGetUniformLocation(prog, "tint"); prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBX); m_RenderData.pCurrentMonData->m_shRGBX.program = prog; @@ -179,6 +181,8 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shRGBX.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample"); + m_RenderData.pCurrentMonData->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint"); + m_RenderData.pCurrentMonData->m_shRGBX.tint = glGetUniformLocation(prog, "tint"); prog = createProgram(TEXVERTSRC, TEXFRAGSRCEXT); m_RenderData.pCurrentMonData->m_shEXT.program = prog; @@ -193,6 +197,8 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shEXT.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample"); + m_RenderData.pCurrentMonData->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint"); + m_RenderData.pCurrentMonData->m_shEXT.tint = glGetUniformLocation(prog, "tint"); prog = createProgram(TEXVERTSRC, FRAGBLUR1); m_RenderData.pCurrentMonData->m_shBLUR1.program = prog; @@ -367,15 +373,17 @@ void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowCustomUV) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowCustomUV); + renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowCustomUV, true); scissor((wlr_box*)nullptr); } -void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowCustomUV) { +void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowCustomUV, bool allowDim) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); + static auto *const PDIMINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:dim_inactive")->intValue; + // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; @@ -433,6 +441,14 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b glUniform1f(shader->radius, round); glUniform1i(shader->primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA)); + if (allowDim && m_pCurrentWindow && *PDIMINACTIVE && m_pCurrentWindow != g_pCompositor->m_pLastWindow) { + glUniform1i(shader->applyTint, 1); + const auto DIM = m_pCurrentWindow->m_fDimPercent.fl(); + glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM); + } else { + glUniform1i(shader->applyTint, 0); + } + glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); const float verts[] = { @@ -727,7 +743,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, // draw window glDisable(GL_STENCIL_TEST); - renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true); + renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true, true); } glStencilMask(-1); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 6575cf82..6eaa638c 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -134,7 +134,7 @@ private: // returns the out FB, can be either Mirror or MirrorSwap CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage); - void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false); + void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false, bool allowDim = false); void renderSplash(cairo_t *const, cairo_surface_t *const); diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index fc06d68b..cf31ed9c 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -29,6 +29,9 @@ public: GLint range; GLint shadowPower; + GLint applyTint; + GLint tint; + GLint getUniformLocation(const std::string&); private: diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 13cdc92a..da02e51f 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -205,6 +205,9 @@ uniform float radius; uniform int discardOpaque; +uniform int applyTint; +uniform vec3 tint; + uniform int primitiveMultisample; uniform int ignoreCorners; @@ -217,6 +220,12 @@ void main() { return; } + if (applyTint == 1) { + pixColor[0] = pixColor[0] * tint[0]; + pixColor[1] = pixColor[1] * tint[1]; + pixColor[2] = pixColor[2] * tint[2]; + } + vec2 pixCoord = fullSize * v_texcoord; )#" + ROUNDED_SHADER_FUNC("pixColor") + @@ -238,6 +247,9 @@ uniform float radius; uniform int discardOpaque; +uniform int applyTint; +uniform vec3 tint; + uniform int primitiveMultisample; uniform int ignoreCorners; @@ -249,10 +261,17 @@ void main() { } vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0); + + if (applyTint == 1) { + pixColor[0] = pixColor[0] * tint[0]; + pixColor[1] = pixColor[1] * tint[1]; + pixColor[2] = pixColor[2] * tint[2]; + } vec2 pixCoord = fullSize * v_texcoord; - )#" + ROUNDED_SHADER_FUNC("pixColor") + R"#( + )#" + ROUNDED_SHADER_FUNC("pixColor") + + R"#( gl_FragColor = pixColor * alpha; })#"; @@ -319,6 +338,9 @@ uniform float radius; uniform int discardOpaque; +uniform int applyTint; +uniform vec3 tint; + uniform int primitiveMultisample; uniform int ignoreCorners; @@ -331,9 +353,16 @@ void main() { return; } + if (applyTint == 1) { + pixColor[0] = pixColor[0] * tint[0]; + pixColor[1] = pixColor[1] * tint[1]; + pixColor[2] = pixColor[2] * tint[2]; + } + vec2 pixCoord = fullSize * v_texcoord; - )#" + ROUNDED_SHADER_FUNC("pixColor") + R"#( + )#" + ROUNDED_SHADER_FUNC("pixColor") + + R"#( gl_FragColor = pixColor * alpha; })#";