Ignore locale if unsupported by X11 backend (#1445)

This restores default portable 'C' locale when target locale is unsupported
by X11 backend (Xlib).

When target locale is unsupported by X11, some locale-dependent Xlib
functions like `XSetLocaleModifiers` fail or have no effect triggering
later failures and panics.

When target locale is not valid, `setLocale` should normally leave the
locale unchanged (`setLocale` returns 'C'). However, in some situations,
locale is accepted by `setLocale` (`setLocale` returns the new locale)
but the accepted locale is unsupported by Xlib (`XSupportsLocale` returns
`false`).

Fix #636
This commit is contained in:
Julien Sanchez 2020-02-10 06:37:06 +01:00 committed by GitHub
parent 96df858961
commit a1b65f7080
3 changed files with 22 additions and 1 deletions

View file

@ -2,6 +2,7 @@
- On Wayland, fix coordinates in touch events when scale factor isn't 1.
- On Wayland, fix color from `close_button_icon_color` not applying.
- Ignore locale if unsupported by X11 backend
# 0.21.0 (2020-02-04)

View file

@ -21,7 +21,8 @@ unsafe fn open_im(xconn: &Arc<XConnection>, locale_modifiers: &CStr) -> Option<f
// XSetLocaleModifiers returns...
// * The current locale modifiers if it's given a NULL pointer.
// * The new locale modifiers if we succeeded in setting them.
// * NULL if the locale modifiers string is malformed.
// * NULL if the locale modifiers string is malformed or if the
// current locale is not supported by Xlib.
(xconn.xlib.XSetLocaleModifiers)(locale_modifiers.as_ptr());
let im = (xconn.xlib.XOpenIM)(

View file

@ -29,6 +29,7 @@ use std::{
mem::{self, MaybeUninit},
ops::Deref,
os::raw::*,
ptr,
rc::Rc,
slice,
sync::{mpsc, Arc, Mutex, Weak},
@ -105,7 +106,25 @@ impl<T: 'static> EventLoop<T> {
// Input methods will open successfully without setting the locale, but it won't be
// possible to actually commit pre-edit sequences.
unsafe {
// Remember default locale to restore it if target locale is unsupported
// by Xlib
let default_locale = setlocale(LC_CTYPE, ptr::null());
setlocale(LC_CTYPE, b"\0".as_ptr() as *const _);
// Check if set locale is supported by Xlib.
// If not, calls to some Xlib functions like `XSetLocaleModifiers`
// will fail.
let locale_supported = (xconn.xlib.XSupportsLocale)() == 1;
if !locale_supported {
let unsupported_locale = setlocale(LC_CTYPE, ptr::null());
warn!(
"Unsupported locale \"{}\". Restoring default locale \"{}\".",
CStr::from_ptr(unsupported_locale).to_string_lossy(),
CStr::from_ptr(default_locale).to_string_lossy()
);
// Restore default locale
setlocale(LC_CTYPE, default_locale);
}
}
let ime = RefCell::new({
let result = Ime::new(Arc::clone(&xconn));