Skip to content

Commit

Permalink
On X11, don't require XIM to be present
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kchibisov authored Feb 13, 2024
1 parent 83012f4 commit ea70f77
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
39 changes: 25 additions & 14 deletions src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
18 changes: 10 additions & 8 deletions src/platform_impl/linux/x11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ pub struct EventLoopWindowTarget {
control_flow: Cell<ControlFlow>,
exit: Cell<Option<i32>>,
root: xproto::Window,
ime: RefCell<Ime>,
ime: Option<RefCell<Ime>>,
windows: RefCell<HashMap<WindowId, Weak<UnownedWindow>>>,
redraw_sender: WakeSender<WindowId>,
activation_sender: WakeSender<ActivationToken>,
Expand Down Expand Up @@ -209,13 +209,15 @@ impl<T: 'static> EventLoop<T> {
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)
Expand Down
6 changes: 3 additions & 3 deletions src/platform_impl/linux/x11/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit ea70f77

Please sign in to comment.