From dcd086660011991fe2dcbceacbb4cdc510f4374a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AD=8F=E6=9B=B9=E5=85=88=E7=94=9F?= <1992414357@qq.com> Date: Sat, 1 Nov 2025 17:42:26 +0800 Subject: [PATCH] fix: focused window content disappearance in overview Replace direct window rendering with configurable placeholders to prevent content loss. --- src/Globals.hpp | 21 ++++++++ src/Render.cpp | 128 +++++++++++++++++++++++++++++++++++++++++++++--- src/main.cpp | 14 +++++- 3 files changed, 156 insertions(+), 7 deletions(-) diff --git a/src/Globals.hpp b/src/Globals.hpp index 24b722d..d6d185c 100644 --- a/src/Globals.hpp +++ b/src/Globals.hpp @@ -60,6 +60,27 @@ namespace Config { extern bool disableBlur; extern float overrideAnimSpeed; extern float dragAlpha; + + extern bool enableFocusedWindowPlaceholder; + extern CHyprColor focusedWindowPlaceholderColor; + extern CHyprColor focusedWindowPlaceholderBorderColor; + extern float focusedWindowPlaceholderAlpha; + + extern bool showFocusedWindowContent; } +// Texture capture system +struct CachedWindowTexture { + std::shared_ptr texture; // Will be cast to appropriate texture type + uint64_t lastUpdateTime; + CBox lastBounds; + bool isValid; +}; + +extern std::unordered_map g_windowTextureCache; +extern bool g_enableTextureCapture; + +// Texture capture function prototype +bool captureWindowTexture(PHLWINDOW pWindow, PHLMONITOR pMonitor, const CBox& targetBox); + extern int numWorkspaces; diff --git a/src/Render.cpp b/src/Render.cpp index 035cea9..3d364e0 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -117,6 +117,50 @@ void renderWindowStub(PHLWINDOW pWindow, PHLMONITOR pMonitor, PHLWORKSPACE pWork g_pInputManager->m_dragMode = oDragMode; } +// Special rendering function for focused windows that minimizes state changes +void renderFocusedWindowStub(PHLWINDOW pWindow, PHLMONITOR pMonitor, PHLWORKSPACE pWorkspaceOverride, CBox rectOverride, timespec* time) { + if (!pWindow || !pMonitor || !pWorkspaceOverride || !time) return; + + // Save minimal state - only what's absolutely necessary + const auto oWorkspace = pWindow->m_workspace; + const auto oFullscreen = pWindow->m_fullscreenState; + const auto oPinned = pWindow->m_pinned; + const auto oUseNearestNeighbor = pWindow->m_windowData.nearestNeighbor; + + // Apply minimal state changes for preview rendering + pWindow->m_workspace = pWorkspaceOverride; + pWindow->m_fullscreenState = SFullscreenState{FSMODE_NONE}; + pWindow->m_windowData.nearestNeighbor = false; + pWindow->m_pinned = true; + + // Use render modification for position and scale without touching window properties + SRenderModifData renderModif; + const auto oRealPosition = pWindow->m_realPosition->value(); + const auto oSize = pWindow->m_realSize->value(); + const float curScaling = rectOverride.w / (oSize.x * pMonitor->m_scale); + + renderModif.modifs.push_back({SRenderModifData::eRenderModifType::RMOD_TYPE_TRANSLATE, + (pMonitor->m_position * pMonitor->m_scale) + (rectOverride.pos() / curScaling) - (oRealPosition * pMonitor->m_scale)}); + renderModif.modifs.push_back({SRenderModifData::eRenderModifType::RMOD_TYPE_SCALE, curScaling}); + renderModif.enabled = true; + + g_pHyprRenderer->m_renderPass.add(makeUnique(CRendererHintsPassElement::SData{renderModif})); + + // Auto-cleanup render modif + Hyprutils::Utils::CScopeGuard x([] { + g_pHyprRenderer->m_renderPass.add(makeUnique(CRendererHintsPassElement::SData{SRenderModifData{}})); + }); + + // Render the window with minimal damage + (*(tRenderWindow)pRenderWindow)(g_pHyprRenderer.get(), pWindow, pMonitor, time, true, RENDER_PASS_ALL, false, false); + + // Restore only the essential state + pWindow->m_workspace = oWorkspace; + pWindow->m_fullscreenState = oFullscreen; + pWindow->m_windowData.nearestNeighbor = oUseNearestNeighbor; + pWindow->m_pinned = oPinned; +} + void renderLayerStub(PHLLS pLayer, PHLMONITOR pMonitor, CBox rectOverride, timespec* time) { if (!pLayer || !pMonitor || !time) return; @@ -343,8 +387,32 @@ void CHyprspaceWidget::draw() { if (!(wW > 0 && wH > 0)) continue; CBox curWindowBox = {wX, wY, wW, wH}; g_pHyprOpenGL->m_renderData.clipBox = curWorkspaceBox; - //g_pHyprOpenGL->renderRectWithBlur(&curWindowBox, CHyprColor(0, 0, 0, 0)); - renderWindowStub(w, owner, owner->m_activeWorkspace, curWindowBox, &time); + + // For focused windows, choose rendering method based on config + if (w == g_pCompositor->m_lastWindow.lock()) { + if (Config::showFocusedWindowContent) { + // Try to show actual window content (experimental) + renderFocusedWindowStub(w, owner, owner->m_activeWorkspace, curWindowBox, &time); + } else if (Config::enableFocusedWindowPlaceholder) { + // Use placeholder rendering (safe default) + CHyprColor placeholderColor = Config::focusedWindowPlaceholderColor; + CHyprColor borderColor = Config::focusedWindowPlaceholderBorderColor; + + if (!Config::disableBlur) { + renderRectWithBlur(curWindowBox, placeholderColor); + } else { + renderRect(curWindowBox, placeholderColor); + } + + // Add a border to indicate it's the focused window + if (Config::workspaceBorderSize > 0) { + renderBorder(curWindowBox, CGradientValueData(borderColor), Config::workspaceBorderSize); + } + } + } else { + //g_pHyprOpenGL->renderRectWithBlur(&curWindowBox, CHyprColor(0, 0, 0, 0)); + renderWindowStub(w, owner, owner->m_activeWorkspace, curWindowBox, &time); + } g_pHyprOpenGL->m_renderData.clipBox = CBox(); } } @@ -359,8 +427,32 @@ void CHyprspaceWidget::draw() { if (!(wW > 0 && wH > 0)) continue; CBox curWindowBox = {wX, wY, wW, wH}; g_pHyprOpenGL->m_renderData.clipBox = curWorkspaceBox; - //g_pHyprOpenGL->renderRectWithBlur(&curWindowBox, CHyprColor(0, 0, 0, 0)); - renderWindowStub(w, owner, owner->m_activeWorkspace, curWindowBox, &time); + + // For focused windows, choose rendering method based on config + if (w == g_pCompositor->m_lastWindow.lock()) { + if (Config::showFocusedWindowContent) { + // Try to show actual window content (experimental) + renderFocusedWindowStub(w, owner, owner->m_activeWorkspace, curWindowBox, &time); + } else if (Config::enableFocusedWindowPlaceholder) { + // Use placeholder rendering (safe default) + CHyprColor placeholderColor = Config::focusedWindowPlaceholderColor; + CHyprColor borderColor = Config::focusedWindowPlaceholderBorderColor; + + if (!Config::disableBlur) { + renderRectWithBlur(curWindowBox, placeholderColor); + } else { + renderRect(curWindowBox, placeholderColor); + } + + // Add a border to indicate it's the focused window + if (Config::workspaceBorderSize > 0) { + renderBorder(curWindowBox, CGradientValueData(borderColor), Config::workspaceBorderSize); + } + } + } else { + //g_pHyprOpenGL->renderRectWithBlur(&curWindowBox, CHyprColor(0, 0, 0, 0)); + renderWindowStub(w, owner, owner->m_activeWorkspace, curWindowBox, &time); + } g_pHyprOpenGL->m_renderData.clipBox = CBox(); } } @@ -375,8 +467,32 @@ void CHyprspaceWidget::draw() { if (!(wW > 0 && wH > 0)) continue; CBox curWindowBox = {wX, wY, wW, wH}; g_pHyprOpenGL->m_renderData.clipBox = curWorkspaceBox; - //g_pHyprOpenGL->renderRectWithBlur(&curWindowBox, CHyprColor(0, 0, 0, 0)); - renderWindowStub(w, owner, owner->m_activeWorkspace, curWindowBox, &time); + + // For focused windows, choose rendering method based on config + if (w == g_pCompositor->m_lastWindow.lock()) { + if (Config::showFocusedWindowContent) { + // Try to show actual window content (experimental) + renderFocusedWindowStub(w, owner, owner->m_activeWorkspace, curWindowBox, &time); + } else if (Config::enableFocusedWindowPlaceholder) { + // Use placeholder rendering (safe default) + CHyprColor placeholderColor = Config::focusedWindowPlaceholderColor; + CHyprColor borderColor = Config::focusedWindowPlaceholderBorderColor; + + if (!Config::disableBlur) { + renderRectWithBlur(curWindowBox, placeholderColor); + } else { + renderRect(curWindowBox, placeholderColor); + } + + // Add a border to indicate it's the focused window + if (Config::workspaceBorderSize > 0) { + renderBorder(curWindowBox, CGradientValueData(borderColor), Config::workspaceBorderSize); + } + } + } else { + //g_pHyprOpenGL->renderRectWithBlur(&curWindowBox, CHyprColor(0, 0, 0, 0)); + renderWindowStub(w, owner, owner->m_activeWorkspace, curWindowBox, &time); + } g_pHyprOpenGL->m_renderData.clipBox = CBox(); } } diff --git a/src/main.cpp b/src/main.cpp index 8600aab..b2f35af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -53,8 +53,20 @@ bool Config::disableBlur = false; float Config::overrideAnimSpeed = 0; +bool Config::enableFocusedWindowPlaceholder = true; +CHyprColor Config::focusedWindowPlaceholderColor = CHyprColor(0.3f, 0.3f, 0.3f, 0.5f); +CHyprColor Config::focusedWindowPlaceholderBorderColor = CHyprColor(0.8f, 0.8f, 0.8f, 0.8f); +float Config::focusedWindowPlaceholderAlpha = 0.5; + +bool Config::showFocusedWindowContent = false; + float Config::dragAlpha = 0.2; + +// Texture capture system globals +std::unordered_map g_windowTextureCache; +bool g_enableTextureCapture = false; + int numWorkspaces = -1; //hyprsplit/split-monitor-workspaces support Hyprutils::Memory::CSharedPointer g_pRenderHook; @@ -429,7 +441,7 @@ void reloadConfig() { Config::disableBlur = std::any_cast(HyprlandAPI::getConfigValue(pHandle, "plugin:overview:disableBlur")->getValue()); Config::overrideAnimSpeed = std::any_cast(HyprlandAPI::getConfigValue(pHandle, "plugin:overview:overrideAnimSpeed")->getValue()); - + // We don't need to store exitKey in Config namespace as it's only used in onKeyPress for (auto& widget : g_overviewWidgets) {