From ea70f773d358ea782e9817e638a7836244cf6f27 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Tue, 13 Feb 2024 07:49:58 +0400 Subject: [PATCH] On X11, don't require XIM to be present In general, we may want to use xinput v2 for keyboard input in such cases, so we have compose going, but for now just don't crash if there's no XIM. --- CHANGELOG.md | 1 + .../linux/x11/event_processor.rs | 39 ++++++++++++------- src/platform_impl/linux/x11/mod.rs | 18 +++++---- src/platform_impl/linux/x11/window.rs | 6 +-- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87a7522e8b..6e14386f2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Unreleased` header. # Unreleased +- On X11, don't require XIM to run. - Fix compatibility with 32-bit platforms without 64-bit atomics. - On X11, fix swapped instance and general class names. - **Breaking:** Removed unnecessary generic parameter `T` from `EventLoopWindowTarget`. diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index d7d3b5c557..9e88f1d4ee 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -74,7 +74,11 @@ impl EventProcessor { // Handle IME requests. while let Ok(request) = self.ime_receiver.try_recv() { - let ime = window_target.ime.get_mut(); + let ime = match window_target.ime.as_mut() { + Some(ime) => ime, + None => continue, + }; + let ime = ime.get_mut(); match request { ImeRequest::Position(window_id, x, y) => { ime.send_xim_spot(window_id, x, y); @@ -792,10 +796,11 @@ impl EventProcessor { // Since all XIM stuff needs to happen from the same thread, we destroy the input // context here instead of when dropping the window. - wt.ime - .borrow_mut() - .remove_context(window as XWindow) - .expect("Failed to destroy input context"); + if let Some(ime) = wt.ime.as_ref() { + ime.borrow_mut() + .remove_context(window as XWindow) + .expect("Failed to destroy input context"); + } callback( &self.target, @@ -922,7 +927,11 @@ impl EventProcessor { }, }, ); - } else if let Some(ic) = wt.ime.borrow().get_context(window as XWindow) { + } else if let Some(ic) = wt + .ime + .as_ref() + .and_then(|ime| ime.borrow().get_context(window as XWindow)) + { let written = wt.xconn.lookup_utf8(ic, xev); if !written.is_empty() { let event = Event::WindowEvent { @@ -1191,10 +1200,11 @@ impl EventProcessor { // Set the timestamp. wt.xconn.set_timestamp(xev.time as xproto::Timestamp); - wt.ime - .borrow_mut() - .focus(xev.event) - .expect("Failed to focus input context"); + if let Some(ime) = wt.ime.as_ref() { + ime.borrow_mut() + .focus(xev.event) + .expect("Failed to focus input context"); + } if self.active_window == Some(window) { return; @@ -1262,10 +1272,11 @@ impl EventProcessor { return; } - wt.ime - .borrow_mut() - .unfocus(xev.event) - .expect("Failed to unfocus input context"); + if let Some(ime) = wt.ime.as_ref() { + ime.borrow_mut() + .unfocus(xev.event) + .expect("Failed to unfocus input context"); + } if self.active_window.take() == Some(window) { let window_id = mkwid(window); diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 4d733897a6..8f1db698ca 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -133,7 +133,7 @@ pub struct EventLoopWindowTarget { control_flow: Cell, exit: Cell>, root: xproto::Window, - ime: RefCell, + ime: Option>, windows: RefCell>>, redraw_sender: WakeSender, activation_sender: WakeSender, @@ -209,13 +209,15 @@ impl EventLoop { setlocale(LC_CTYPE, default_locale); } } - let ime = RefCell::new({ - let result = Ime::new(Arc::clone(&xconn), ime_event_sender); - if let Err(ImeCreationError::OpenFailure(ref state)) = result { - panic!("Failed to open input method: {state:#?}"); - } - result.expect("Failed to set input method destruction callback") - }); + + let ime = Ime::new(Arc::clone(&xconn), ime_event_sender); + if let Err(ImeCreationError::OpenFailure(state)) = ime.as_ref() { + warn!("Failed to open input method: {state:#?}"); + } else if let Err(err) = ime.as_ref() { + warn!("Failed to set input method destruction callback: {err:?}"); + } + + let ime = ime.ok().map(RefCell::new); let randr_event_offset = xconn .select_xrandr_input(root) diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index ecae94a08d..12eedb589a 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -555,9 +555,9 @@ impl UnownedWindow { leap!(xconn.select_xinput_events(window.xwindow, super::ALL_MASTER_DEVICES, mask)) .ignore_error(); - { - let result = event_loop - .ime + // Try to create input context for the window. + if let Some(ime) = event_loop.ime.as_ref() { + let result = ime .borrow_mut() .create_context(window.xwindow as ffi::Window, false); leap!(result);