aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/handlers/xdg_shell.rs10
-rw-r--r--src/niri.rs33
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();