summaryrefslogtreecommitdiff
path: root/src/desktop
diff options
context:
space:
mode:
authorAnubhav <57067794+imperishableSecret@users.noreply.github.com>2026-04-05 21:24:56 +0530
committerGitHub <noreply@github.com>2026-04-05 16:54:56 +0100
commitbf97fac9b9c7830a9374366d8a471efb48dae5fb (patch)
tree18f75c564edbfb623a2c63bb4c24e640d67a76a4 /src/desktop
parent8edb7c5663c9aea552074c5d9e36e6f688baf4b7 (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.cpp33
-rw-r--r--src/desktop/view/Subsurface.hpp5
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;