From 501521cf788477166cccf241b84984bc4e4c05e9 Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Thu, 24 Sep 2026 16:59:26 +0100 Subject: [PATCH] fix: constrain layer shell popups to output --- compositor/src/handlers/layer_shell.rs | 1 + compositor/src/handlers/xdg_shell.rs | 42 +++++++++++++++++--------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/compositor/src/handlers/layer_shell.rs b/compositor/src/handlers/layer_shell.rs index 355b22c..e4db791 100644 --- a/compositor/src/handlers/layer_shell.rs +++ b/compositor/src/handlers/layer_shell.rs @@ -47,6 +47,7 @@ impl WlrLayerShellHandler for Ferese { } fn new_popup(&mut self, _parent: LayerSurface, popup: PopupSurface) { + self.unconstrain_popup(&popup); if let Err(error) = self.popups.track_popup(PopupKind::Xdg(popup)) { tracing::warn!(?error, "failed to track layer-shell popup"); } diff --git a/compositor/src/handlers/xdg_shell.rs b/compositor/src/handlers/xdg_shell.rs index 7ede5c6..384cf4d 100644 --- a/compositor/src/handlers/xdg_shell.rs +++ b/compositor/src/handlers/xdg_shell.rs @@ -1,7 +1,7 @@ use smithay::{ desktop::{ PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab, Space, Window, - find_popup_root_surface, get_popup_toplevel_coords, + WindowSurfaceType, find_popup_root_surface, get_popup_toplevel_coords, }, input::{ Seat, @@ -310,30 +310,42 @@ pub fn handle_commit(popups: &mut PopupManager, space: &mut Space, surfa } impl Ferese { - fn unconstrain_popup(&self, popup: &PopupSurface) { + pub(crate) fn unconstrain_popup(&self, popup: &PopupSurface) { let Ok(root) = find_popup_root_surface(&PopupKind::Xdg(popup.clone())) else { return; }; - let Some(window) = self.space.elements().find(|window| { + let window = self.space.elements().find(|window| { window .toplevel() .is_some_and(|toplevel| toplevel.wl_surface() == &root) - }) else { - return; - }; - let Some(output) = self.space.outputs().next() else { - return; - }; - let Some(output_geometry) = self.space.output_geometry(output) else { - return; - }; - let Some(window_geometry) = self.space.element_geometry(window) else { + }); + let geometry = (|| { + if let Some(window) = window { + let output = self.space.outputs().next()?; + let output_geometry = self.space.output_geometry(output)?; + let window_geometry = self.space.element_geometry(window)?; + + Some((output_geometry, window_geometry.loc)) + } else { + let layer = self + .space + .layer_for_surface(&root, WindowSurfaceType::TOPLEVEL)?; + + self.space.outputs().find_map(|output| { + let output_geometry = self.space.output_geometry(output)?; + let layer_geometry = + smithay::desktop::layer_map_for_output(output).layer_geometry(&layer)?; + + Some((output_geometry, output_geometry.loc + layer_geometry.loc)) + }) + } + })(); + let Some((mut target, root_location)) = geometry else { return; }; - let mut target = output_geometry; target.loc -= get_popup_toplevel_coords(&PopupKind::Xdg(popup.clone())); - target.loc -= window_geometry.loc; + target.loc -= root_location; popup.with_pending_state(|state| { state.geometry = state.positioner.get_unconstrained_geometry(target); });