diff options
| author | Anubhav <57067794+imperishableSecret@users.noreply.github.com> | 2026-04-05 21:24:56 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-05 16:54:56 +0100 |
| commit | bf97fac9b9c7830a9374366d8a471efb48dae5fb (patch) | |
| tree | 18f75c564edbfb623a2c63bb4c24e640d67a76a4 /src/desktop | |
| parent | 8edb7c5663c9aea552074c5d9e36e6f688baf4b7 (diff) | |
subsurface: use geometry-aware damage and recurse into nested trees (#13933)
* subsurface: use geometry-aware damage and recurse into nested trees
Replace per-surface damageSurface() calls in recheckDamageForSubsurfaces()
with box-based damage that tracks each subsurface's last known global
position and size. When geometry changes, both the old and new areas are
damaged to correctly clear stale pixels and paint the new location.
Additionally, recurse into child subsurfaces so that nested subsurface
trees are properly damage-checked, with a depth limit of 32 to guard
against cycles. Cached geometry is invalidated on map/unmap to avoid
stale comparisons across surface lifecycle transitions.
* clang-format
Diffstat (limited to 'src/desktop')
| -rw-r--r-- | src/desktop/view/Subsurface.cpp | 33 | ||||
| -rw-r--r-- | src/desktop/view/Subsurface.hpp | 5 |
2 files changed, 33 insertions, 5 deletions
diff --git a/src/desktop/view/Subsurface.cpp b/src/desktop/view/Subsurface.cpp index c601c00e..c3c985df 100644 --- a/src/desktop/view/Subsurface.cpp +++ b/src/desktop/view/Subsurface.cpp @@ -128,10 +128,32 @@ void CSubsurface::checkSiblingDamage() { } } -void CSubsurface::recheckDamageForSubsurfaces() { +void CSubsurface::recheckDamageForSubsurfaces(int depth) { + if (depth > 32) + return; + for (auto const& n : m_children) { const auto COORDS = n->coordsGlobal(); - g_pHyprRenderer->damageSurface(n->wlSurface()->resource(), COORDS.x, COORDS.y); + const auto SIZE = n->size(); + + const bool GEOMETRYUNCHANGED = n->m_hasLastRecheckGeometry && COORDS.x == n->m_lastRecheckGlobalPos.x && COORDS.y == n->m_lastRecheckGlobalPos.y && + SIZE.x == n->m_lastRecheckGlobalSize.x && SIZE.y == n->m_lastRecheckGlobalSize.y; + + if (!GEOMETRYUNCHANGED) { + // damage the old area to clear stale pixels + if (n->m_hasLastRecheckGeometry) + g_pHyprRenderer->damageBox(CBox{n->m_lastRecheckGlobalPos, n->m_lastRecheckGlobalSize}.expand(4)); + + n->m_lastRecheckGlobalPos = COORDS; + n->m_lastRecheckGlobalSize = SIZE; + n->m_hasLastRecheckGeometry = true; + + // damage the new area + g_pHyprRenderer->damageBox(CBox{COORDS, SIZE}.expand(4)); + } + + // recurse into children to handle nested subsurface trees + n->recheckDamageForSubsurfaces(depth + 1); } } @@ -194,8 +216,9 @@ void CSubsurface::onNewSubsurface(SP<CWLSubsurfaceResource> pSubsurface) { } void CSubsurface::onMap() { - m_lastSize = m_wlSurface->resource()->m_current.size; - m_lastPosition = m_subsurface->m_position; + m_lastSize = m_wlSurface->resource()->m_current.size; + m_lastPosition = m_subsurface->m_position; + m_hasLastRecheckGeometry = false; const auto COORDS = coordsGlobal(); CBox box{COORDS, m_lastSize}; @@ -209,6 +232,8 @@ void CSubsurface::onMap() { void CSubsurface::onUnmap() { damageLastArea(); + m_hasLastRecheckGeometry = false; + if (m_wlSurface->resource() == Desktop::focusState()->surface()) g_pInputManager->releaseAllMouseButtons(); diff --git a/src/desktop/view/Subsurface.hpp b/src/desktop/view/Subsurface.hpp index ab74f48c..bb2f6780 100644 --- a/src/desktop/view/Subsurface.hpp +++ b/src/desktop/view/Subsurface.hpp @@ -40,7 +40,7 @@ namespace Desktop::View { void onMap(); void onUnmap(); - void recheckDamageForSubsurfaces(); + void recheckDamageForSubsurfaces(int depth = 0); WP<Desktop::View::CSubsurface> m_self; @@ -58,6 +58,9 @@ namespace Desktop::View { WP<CWLSubsurfaceResource> m_subsurface; Vector2D m_lastSize = {}; Vector2D m_lastPosition = {}; + Vector2D m_lastRecheckGlobalPos; + Vector2D m_lastRecheckGlobalSize; + bool m_hasLastRecheckGeometry = false; // if nullptr, means it's a dummy node WP<Desktop::View::CSubsurface> m_parent; |
