diff --git a/src/events/Popups.cpp b/src/events/Popups.cpp index dde2d46df..457a95fe9 100644 --- a/src/events/Popups.cpp +++ b/src/events/Popups.cpp @@ -134,7 +134,7 @@ void Events::listener_mapPopupXDG(void* owner, void* data) { Debug::log(LOG, "New XDG Popup mapped at %d %d", (int)PPOPUP->lx, (int)PPOPUP->ly); - PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP); + PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP, PPOPUP->parentWindow); Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %x", PPOPUP->pSurfaceTree); } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 47cb5b240..35b61db85 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -186,7 +186,7 @@ void Events::listener_mapWindow(void* owner, void* data) { if (!PWINDOW->m_bNoFocus) g_pCompositor->focusWindow(PWINDOW); - PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW); + PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW); Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree); diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index 86373ced3..7ec3635ae 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -20,12 +20,13 @@ void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) { } } -SSurfaceTreeNode* createTree(wlr_surface* pSurface) { +SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) { SubsurfaceTree::surfaceTreeNodes.push_back(SSurfaceTreeNode()); const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.back(); PNODE->pSurface = pSurface; + PNODE->pWindowOwner = pWindow; PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode"); PNODE->hyprListener_commit.initCallback(&pSurface->events.commit, &Events::listener_commitSubsurface, PNODE, "SurfaceTreeNode"); @@ -42,16 +43,21 @@ SSurfaceTreeNode* createTree(wlr_surface* pSurface) { return PNODE; } -SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface) { - const auto PNODE = createTree(surface); +SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface, CWindow* pWindow) { + const auto PNODE = createTree(surface, pWindow); PNODE->pParent = pParent; PNODE->pSubsurface = pSubsurface; + Debug::log(LOG, "Creating a subsurface Node! (pWindow: %x)", pWindow); + return PNODE; } -SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data) { - const auto PNODE = createTree(pSurface); +SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data, CWindow* pWindow) { + const auto PNODE = createTree(pSurface, pWindow); + + Debug::log(LOG, "Creating a surfaceTree Root! (pWindow: %x)", pWindow); + PNODE->offsetfn = fn; PNODE->globalOffsetData = data; @@ -120,6 +126,8 @@ void Events::listener_newSubsurfaceNode(void* owner, void* data) { PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface"); PNEWSUBSURFACE->hyprListener_destroy.initCallback(&PSUBSURFACE->events.destroy, &Events::listener_destroySubsurface, PNEWSUBSURFACE, "Subsurface"); + PNEWSUBSURFACE->pWindowOwner = pNode->pWindowOwner; + wlr_subsurface* existingWlrSubsurface; wl_list_for_each(existingWlrSubsurface, &PSUBSURFACE->surface->current.subsurfaces_below, current.link) { listener_newSubsurfaceNode(pNode, existingWlrSubsurface); @@ -134,7 +142,7 @@ void Events::listener_mapSubsurface(void* owner, void* data) { Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface); - subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface); + subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner); } void Events::listener_unmapSubsurface(void* owner, void* data) { @@ -162,6 +170,14 @@ void Events::listener_unmapSubsurface(void* owner, void* data) { void Events::listener_commitSubsurface(void* owner, void* data) { SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner; + // no damaging if it's not visible + if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) { + if (g_pConfigManager->getInt("debug:log_damage")) + Debug::log(LOG, "Refusing to commit damage from %x because it's invisible.", pNode->pWindowOwner); + return; + } + + int lx = 0, ly = 0; addSurfaceGlobalOffset(pNode, &lx, &ly); diff --git a/src/helpers/SubsurfaceTree.hpp b/src/helpers/SubsurfaceTree.hpp index 32a3013e8..52f54f161 100644 --- a/src/helpers/SubsurfaceTree.hpp +++ b/src/helpers/SubsurfaceTree.hpp @@ -4,6 +4,7 @@ #include struct SSubsurface; +class CWindow; typedef void (*applyGlobalOffsetFn)(void *, int *, int *); @@ -21,6 +22,7 @@ struct SSurfaceTreeNode { applyGlobalOffsetFn offsetfn; void *globalOffsetData; + CWindow* pWindowOwner = nullptr; bool operator==(const SSurfaceTreeNode& rhs) { return pSurface == rhs.pSurface; @@ -37,13 +39,15 @@ struct SSubsurface { DYNLISTENER(unmap); DYNLISTENER(destroy); + CWindow* pWindowOwner = nullptr; + bool operator==(const SSubsurface& rhs) { return pSubsurface == rhs.pSubsurface; } }; namespace SubsurfaceTree { - SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*); + SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*, CWindow* pWindow = nullptr); void destroySurfaceTree(SSurfaceTreeNode*); inline std::list surfaceTreeNodes; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 86528f53c..1386d1c71 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -31,7 +31,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output); } -bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) { +bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) { wlr_box geometry = pWindow->getFullWindowBoundingBox(); if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry)) @@ -52,6 +52,27 @@ bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) { return false; } +bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) { + + if (!g_pCompositor->windowValidMapped(pWindow)) + return false; + + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); + + if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID)) + return true; + + for (auto& m : g_pCompositor->m_lMonitors) { + if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m.ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())) + return true; + + if (m.specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) + return true; + } + + return false; +} + void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) { CWindow* pWorkspaceWindow = nullptr; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index ba7d54b33..24caa09d3 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -29,6 +29,8 @@ public: void damageBox(const int& x, const int& y, const int& w, const int& h); void damageMonitor(SMonitor*); void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false); + bool shouldRenderWindow(CWindow*, SMonitor*); + bool shouldRenderWindow(CWindow*); DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);