diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-01-23 17:05:08 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-01-23 17:05:08 +0400 |
| commit | f5642ab73376582d80da1edbabff8fd5a15632cb (patch) | |
| tree | ed32658c3a0691da62e970760b8747927ccb9f6f | |
| parent | ab9706cb30c26dafe46c807f0cf073e594c84ef0 (diff) | |
| download | niri-f5642ab73376582d80da1edbabff8fd5a15632cb.tar.gz niri-f5642ab73376582d80da1edbabff8fd5a15632cb.tar.bz2 niri-f5642ab73376582d80da1edbabff8fd5a15632cb.zip | |
Ignore popup grabs when IME keyboard grab is active
Doing this properly will require more refactors, potentially in Smithay.
For now let's just ignore popup grabs to make popups work.
| -rw-r--r-- | src/handlers/xdg_shell.rs | 10 | ||||
| -rw-r--r-- | src/niri.rs | 33 |
2 files changed, 33 insertions, 10 deletions
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 221ca222..a8023a69 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -13,6 +13,7 @@ use smithay::reexports::wayland_server::protocol::wl_seat::WlSeat; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; use smithay::utils::{Logical, Rectangle, Serial}; use smithay::wayland::compositor::{send_surface_state, with_states}; +use smithay::wayland::input_method::InputMethodSeat; use smithay::wayland::shell::kde::decoration::{KdeDecorationHandler, KdeDecorationState}; use smithay::wayland::shell::wlr_layer::Layer; use smithay::wayland::shell::xdg::decoration::XdgDecorationHandler; @@ -94,6 +95,15 @@ impl XdgShellHandler for State { } fn grab(&mut self, surface: PopupSurface, _seat: WlSeat, serial: Serial) { + // HACK: ignore grabs (pretend they work without actually grabbing) if the input method has + // a grab. It will likely need refactors in Smithay to support properly since grabs just + // replace each other. + // FIXME: do this properly. + if self.niri.seat.input_method().keyboard_grabbed() { + trace!("ignoring popup grab because IME has keyboard grabbed"); + return; + } + let popup = PopupKind::Xdg(surface); let Ok(root) = find_popup_root_surface(&popup) else { return; diff --git a/src/niri.rs b/src/niri.rs index e275c1ae..4e9bf257 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -66,7 +66,7 @@ use smithay::wayland::compositor::{ }; use smithay::wayland::cursor_shape::CursorShapeManagerState; use smithay::wayland::dmabuf::DmabufState; -use smithay::wayland::input_method::InputMethodManagerState; +use smithay::wayland::input_method::{InputMethodManagerState, InputMethodSeat}; use smithay::wayland::output::OutputManagerState; use smithay::wayland::pointer_constraints::{with_pointer_constraint, PointerConstraintsState}; use smithay::wayland::pointer_gestures::PointerGesturesState; @@ -326,7 +326,7 @@ impl State { self.niri.cursor_manager.check_cursor_image_surface_alive(); self.niri.refresh_pointer_outputs(); self.niri.popups.cleanup(); - self.niri.refresh_popup_grab(); + self.refresh_popup_grab(); self.update_keyboard_focus(); self.refresh_pointer_focus(); @@ -420,6 +420,27 @@ impl State { self.move_cursor(center(geo).to_f64()); } + pub fn refresh_popup_grab(&mut self) { + let keyboard_grabbed = self.niri.seat.input_method().keyboard_grabbed(); + + if let Some(grab) = &mut self.niri.popup_grab { + if grab.grab.has_ended() { + self.niri.popup_grab = None; + } else if keyboard_grabbed { + // HACK: remove popup grab if IME grabbed the keyboard, because we can't yet do + // popup grabs together with an IME grab. + // FIXME: do this properly. + grab.grab.ungrab(PopupUngrabStrategy::All); + self.niri.seat.get_pointer().unwrap().unset_grab( + self, + SERIAL_COUNTER.next_serial(), + get_monotonic_time().as_millis() as u32, + ); + self.niri.popup_grab = None; + } + } + } + pub fn update_keyboard_focus(&mut self) { let focus = if self.niri.is_locked() { self.niri.lock_surface_focus() @@ -1560,14 +1581,6 @@ impl Niri { state.lock_surface.as_ref().map(|s| s.wl_surface()).cloned() } - pub fn refresh_popup_grab(&mut self) { - if let Some(grab) = &self.popup_grab { - if grab.grab.has_ended() { - self.popup_grab = None; - } - } - } - /// Schedules an immediate redraw on all outputs if one is not already scheduled. pub fn queue_redraw_all(&mut self) { let outputs: Vec<_> = self.output_state.keys().cloned().collect(); |
