diff options
| -rw-r--r-- | src/handlers/xdg_shell.rs | 23 | ||||
| -rw-r--r-- | src/niri.rs | 5 |
2 files changed, 23 insertions, 5 deletions
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 2c9f5daf..0d16e5f6 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -360,6 +360,17 @@ impl XdgShellHandler for State { let keyboard = seat.get_keyboard().unwrap(); let pointer = seat.get_pointer().unwrap(); + let can_receive_keyboard_focus = self + .niri + .layout + .active_output() + .and_then(|output| { + layer_map_for_output(output) + .layer_for_surface(&root, WindowSurfaceType::TOPLEVEL) + .map(|layer_surface| layer_surface.can_receive_keyboard_focus()) + }) + .unwrap_or(true); + let keyboard_grab_mismatches = keyboard.is_grabbed() && !(keyboard.has_grab(serial) || grab @@ -368,15 +379,21 @@ impl XdgShellHandler for State { let pointer_grab_mismatches = pointer.is_grabbed() && !(pointer.has_grab(serial) || grab.previous_serial().map_or(true, |s| pointer.has_grab(s))); - if keyboard_grab_mismatches || pointer_grab_mismatches { + if (can_receive_keyboard_focus && keyboard_grab_mismatches) || pointer_grab_mismatches { grab.ungrab(PopupUngrabStrategy::All); return; } trace!("new grab for root {:?}", root); - keyboard.set_grab(self, PopupKeyboardGrab::new(&grab), serial); + if can_receive_keyboard_focus { + keyboard.set_grab(self, PopupKeyboardGrab::new(&grab), serial); + } pointer.set_grab(self, PopupPointerGrab::new(&grab), serial, Focus::Keep); - self.niri.popup_grab = Some(PopupGrabState { root, grab }); + self.niri.popup_grab = Some(PopupGrabState { + root, + grab, + has_keyboard_grab: can_receive_keyboard_focus, + }); } fn maximize_request(&mut self, surface: ToplevelSurface) { diff --git a/src/niri.rs b/src/niri.rs index 2c5cbe48..7d81bbc6 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -409,6 +409,7 @@ pub enum RedrawState { pub struct PopupGrabState { pub root: WlSurface, pub grab: PopupGrab<State>, + pub has_keyboard_grab: bool, } // The surfaces here are always toplevel surfaces focused as far as niri's logic is concerned, even @@ -865,7 +866,7 @@ impl State { let layer_grab = self.niri.popup_grab.as_ref().and_then(|g| { layers .layer_for_surface(&g.root, WindowSurfaceType::TOPLEVEL) - .map(|l| (&g.root, l.layer())) + .and_then(|l| l.can_receive_keyboard_focus().then(|| (&g.root, l.layer()))) }); let grab_on_layer = |layer: Layer| { layer_grab @@ -984,7 +985,7 @@ impl State { } if let Some(grab) = self.niri.popup_grab.as_mut() { - if Some(&grab.root) != focus.surface() { + if grab.has_keyboard_grab && Some(&grab.root) != focus.surface() { trace!( "grab root {:?} is not the new focus {:?}, ungrabbing", grab.root, |
