From 84d2a9d297ab89331d56950b1d54913dbb1c4bde Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 8 Jun 2026 15:15:58 -0700 Subject: [PATCH] shell: Fix definition of `surface_tree_offset()` Using `with_surface_tree_downward()` is wrong because it will traverse other branches of the surface tree than the one containing `surface`, and add their offsets. It's simple enough to instead walk up the surface tree. --- src/shell/element/surface.rs | 46 +++++++++++++----------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/src/shell/element/surface.rs b/src/shell/element/surface.rs index c976b38b..8495fe30 100644 --- a/src/shell/element/surface.rs +++ b/src/shell/element/surface.rs @@ -46,7 +46,7 @@ use smithay::{ }, wayland::{ compositor::{ - SubsurfaceCachedState, SurfaceData, TraversalAction, with_states, + SubsurfaceCachedState, SurfaceData, TraversalAction, get_parent, with_states, with_surface_tree_downward, }, seat::WaylandFocus, @@ -675,38 +675,24 @@ impl CosmicSurface { root: &WlSurface, surface: &WlSurface, ) -> Option> { - if root == surface { - return Some(Point::default()); - } - - let found = AtomicBool::new(false); - let mut found_offset = Point::::default(); - - with_surface_tree_downward( - root, - Point::::default(), - |s, states, parent_offset| { - let mut offset = *parent_offset; - if s != root { - offset += states + let mut offset = Point::::default(); + let mut parent = surface.clone(); + loop { + if parent == *root { + return Some(offset); + } else if let Some(s) = get_parent(&parent) { + offset += with_states(&parent, |states| { + states .cached_state .get::() .current() - .location; - } - TraversalAction::DoChildren(offset) - }, - |s, _, offset| { - if s == surface { - found_offset = *offset; - found.store(true, Ordering::SeqCst); - } - }, - |_, _, _| !found.load(Ordering::SeqCst), - ); - - if found.load(Ordering::SeqCst) { - return Some(found_offset); + .location + }); + parent = s; + } else { + // `parent` is now root of subsurface tree; `surface` is not a subsurface child of `root` + break; + } } for (popup, popup_offset) in PopupManager::popups_for_surface(root) {