shell: implement surface_geometry_offset_from_toplevel for WorkspaceSet

This commit is contained in:
Skygrango 2026-05-13 19:46:29 +08:00 committed by Ian Douglas Scott
parent d829ec3815
commit e75c9c0c48

View file

@ -50,10 +50,13 @@ use smithay::{
},
utils::{IsAlive, Logical, Point, Rectangle, Serial, Size},
wayland::{
compositor::{SurfaceAttributes, with_states},
compositor::{SurfaceAttributes, get_parent, with_states},
seat::WaylandFocus,
session_lock::LockSurface,
shell::wlr_layer::{KeyboardInteractivity, Layer, LayerSurfaceCachedState},
shell::{
wlr_layer::{KeyboardInteractivity, Layer, LayerSurfaceCachedState},
xdg::{XDG_POPUP_ROLE, XdgPopupSurfaceData},
},
xdg_activation::XdgActivationState,
xwayland_keyboard_grab::XWaylandKeyboardGrab,
},
@ -728,6 +731,81 @@ impl WorkspaceSet {
self.post_remove_workspace(workspace_state, &previous_active_handle);
prefers
}
pub fn surface_geometry_offset_from_toplevel(
&self,
surface: &WlSurface,
) -> Option<(Rectangle<i32, Local>, Point<i32, Logical>)> {
let mut root = surface.clone();
loop {
while let Some(parent) = get_parent(&root) {
root = parent;
}
if smithay::wayland::compositor::get_role(&root) == Some(XDG_POPUP_ROLE)
&& let Some(parent) = with_states(&root, |states| {
states
.data_map
.get::<XdgPopupSurfaceData>()
.and_then(|m| m.lock().unwrap().parent.as_ref().cloned())
})
{
root = parent;
continue;
}
break;
}
self.sticky_layer
.mapped()
.find(|w| {
w.windows()
.any(|(w, _)| w.wl_surface().as_deref() == Some(&root))
})
.and_then(|w| {
w.surface_offset(surface).and_then(|offset| {
self.sticky_layer
.element_geometry(w)
.map(|geom| (geom, offset))
})
})
.or_else(|| {
self.workspaces.iter().find_map(|workspace| {
workspace
.get_fullscreen()
.and_then(|fullscreen| {
(fullscreen.wl_surface().as_deref() == Some(&root))
.then(|| {
fullscreen.surface_offset(surface).and_then(|offset| {
workspace.fullscreen_geometry().map(|geom| (geom, offset))
})
})
.flatten()
})
.or_else(|| {
workspace.mapped().find_map(|w| {
w.windows()
.any(|(w, _)| w.wl_surface().as_deref() == Some(&root))
.then(|| {
w.surface_offset(surface).and_then(|offset| {
workspace.element_geometry(w).map(|geom| (geom, offset))
})
})
.flatten()
})
})
})
})
.or_else(|| {
layer_map_for_output(&self.output).layers().find_map(|l| {
(l.wl_surface() == &root)
.then(|| {
CosmicSurface::surface_tree_offset(l.wl_surface(), surface)
.map(|offset| (l.geometry().as_local(), offset))
})
.flatten()
})
})
}
}
#[derive(Debug)]