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
This commit is contained in:
hcpl 2018-04-05 20:21:50 +03:00 committed by Francesca Frangipane
parent f3ab8af813
commit 7cd440135a
2 changed files with 26 additions and 1 deletions

View file

@ -2,6 +2,7 @@
- Added subclass to macos windows so they can be made resizable even with no decorations. - 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. - 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) # Version 0.11.3 (2018-03-28)

View file

@ -1010,10 +1010,34 @@ impl Window {
let im = unsafe { let im = unsafe {
let _lock = GLOBAL_XOPENIM_LOCK.lock().unwrap(); 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() { 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"); panic!("XOpenIM failed");
} }
im im
}; };