atagen

monolith

public
Star0
Watch0

Commit d24854a5fbbc

tarball

atagen <boss@atagen.co>2026-10-19 10:59 UTC

1 file changed+15-2
constraints: keep a pointer lock while a popup of its window has the keyboard

constraint_eligible compared subsurface roots, and a popup is the root of its own tree, so a popup holding keyboard focus released the lock on the window it belongs to.
Modified file: crates/monolith/src/constraints.rs+15 additions−2 deletions
@@ -6,6 +6,7 @@
66 use crate::idle::root_surface;
77 use crate::state::State;
88 use smithay::backend::input::InputTime;
9+use smithay::desktop::find_popup_root_surface;
910 use smithay::desktop::utils::bbox_from_surface_tree;
1011 use smithay::input::pointer::PointerHandle;
1112 use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
@@ -104,6 +105,18 @@ impl State {
104105 .map(|(_, origin)| origin)
105106 }
106107
108+ /// The surface a popup hangs off, or the root of the subsurface tree
109+ /// `surface` is in, so a popup holding the keyboard keeps its window's
110+ /// constraint alive.
111+ fn constraint_root(&self, surface: &WlSurface) -> WlSurface {
112+ let root = root_surface(surface);
113+ self.wm
114+ .popups
115+ .find_popup(&root)
116+ .and_then(|popup| find_popup_root_surface(&popup).ok())
117+ .unwrap_or(root)
118+ }
119+
107120 fn constraint_eligible(&self, surface: &WlSurface) -> bool {
108121 !self.services.lock.active()
109122 && self.input.drag.is_none()
@@ -112,8 +125,8 @@ impl State {
112125 .seat
113126 .get_keyboard()
114127 .and_then(|k| k.current_focus())
115- .and_then(|f| f.wl_surface().map(|s| root_surface(&s)))
116- .is_some_and(|root| root == root_surface(surface))
128+ .and_then(|f| f.wl_surface().map(|s| self.constraint_root(&s)))
129+ .is_some_and(|root| root == self.constraint_root(surface))
117130 }
118131
119132 /// Activates the pointer focus's constraint once it may apply, and