From 7cd440135ae7fe69ef85841eba730ce7deaeeca2 Mon Sep 17 00:00:00 2001 From: hcpl Date: Thu, 5 Apr 2018 20:21:50 +0300 Subject: [PATCH] Try XOpenIM with different locale modifiers (#424) * Try XOpenIM with different locale modifiers Implements the solution suggested in https://github.com/tomaka/winit/issues/277#issuecomment-337751136. * Use empty XSetLocaleModifiers beforehand Also, for modifiers, convert from length-based UTF-8 strings to null-terminated bytestrings. * Add CHANGELOG entry and comments --- CHANGELOG.md | 1 + src/platform/linux/x11/mod.rs | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f3065c6..3d8d5b5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Added subclass to macos windows so they can be made resizable even with no decorations. - Dead keys now work properly on X11, no longer resulting in a panic. +- On X11, input method creation first tries to use the value from the user's `XMODIFIERS` environment variable, so application developers should no longer need to manually call `XSetLocaleModifiers`. If that fails, fallbacks are tried, which should prevent input method initialization from ever outright failing. # Version 0.11.3 (2018-03-28) diff --git a/src/platform/linux/x11/mod.rs b/src/platform/linux/x11/mod.rs index 7469a7a9..f8ab5096 100644 --- a/src/platform/linux/x11/mod.rs +++ b/src/platform/linux/x11/mod.rs @@ -1010,10 +1010,34 @@ impl Window { let im = unsafe { let _lock = GLOBAL_XOPENIM_LOCK.lock().unwrap(); - let im = (x_events_loop.display.xlib.XOpenIM)(x_events_loop.display.display, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()); + let mut im: ffi::XIM = ptr::null_mut(); + + // Setting an empty locale results in the user's XMODIFIERS environment variable being + // read, which should result in the user's configured input method (ibus, fcitx, etc.) + // being used. If that fails, we fall back to internal input methods which should + // always be available. + for modifiers in &[b"\0" as &[u8], b"@im=local\0", b"@im=\0"] { + if !im.is_null() { + break; + } + + (x_events_loop.display.xlib.XSetLocaleModifiers)(modifiers.as_ptr() as *const i8); + im = (x_events_loop.display.xlib.XOpenIM)( + x_events_loop.display.display, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ); + } + if im.is_null() { + // While it's possible to make IME optional and handle this more gracefully, it's + // not clear in what situations the fallbacks wouldn't work. Therefore, this panic + // is left here so that if it ever fails, someone will hopefully tell us about it, + // and we'd have a better grasp of what's necessary. panic!("XOpenIM failed"); } + im };