Skip to content

Commit

Permalink
On X11, fix IME crashing without available styles
Browse files Browse the repository at this point in the history
  • Loading branch information
kchibisov committed Oct 9, 2022
1 parent adfa5bd commit ccddaf0
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 29 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ And please only add new entries to the top of this list, right below the `# Unre

# Unreleased

# 0.27.3 (2022-9-10)
- On X11, fix XIM not picking IME when no styles advertised.

# 0.27.3

- On Windows, added `WindowExtWindows::set_undecorated_shadow` and `WindowBuilderExtWindows::with_undecorated_shadow` to draw the drop shadow behind a borderless window.
- On Windows, fixed default window features (ie snap, animations, shake, etc.) when decorations are disabled.
Expand Down
58 changes: 33 additions & 25 deletions src/platform_impl/linux/x11/ime/input_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,62 +41,70 @@ unsafe fn open_im(xconn: &Arc<XConnection>, locale_modifiers: &CStr) -> Option<f
#[derive(Debug)]
pub struct InputMethod {
pub im: ffi::XIM,
pub preedit_style: Style,
pub none_style: Style,
_name: String,
}

#[derive(Debug, Default)]
pub struct InputMethodStyles {
pub preedit_style: Option<Style>,
pub none_style: Option<Style>,
}

impl InputMethod {
fn new(xconn: &Arc<XConnection>, im: ffi::XIM, name: String) -> Option<Self> {
fn new(xconn: &Arc<XConnection>, im: ffi::XIM, name: String) -> Self {
let res = Self { im, _name: name };
let _ = res.query_styles(xconn);
res
}

// XXX checking this during creation is not desired, since we don't want to filter
// ime based on styles since IME could be reloading, etc, so we ask for that when needed.
pub(crate) fn query_styles(&self, xconn: &Arc<XConnection>) -> InputMethodStyles {
let mut styles: *mut XIMStyles = std::ptr::null_mut();

// Query the styles supported by the XIM.
unsafe {
if !(xconn.xlib.XGetIMValues)(
im,
self.im,
ffi::XNQueryInputStyle_0.as_ptr() as *const _,
(&mut styles) as *mut _,
std::ptr::null_mut::<()>(),
)
.is_null()
{
return None;
return InputMethodStyles::default();
}
}

let mut preedit_style = None;
let mut none_style = None;

println!("==========================");
unsafe {
std::slice::from_raw_parts((*styles).supported_styles, (*styles).count_styles as _)
.iter()
.for_each(|style| match *style {
XIM_PREEDIT_STYLE => {
preedit_style = Some(Style::Preedit(*style));
}
XIM_NOTHING_STYLE if preedit_style.is_none() => {
preedit_style = Some(Style::Nothing(*style))
.for_each(|style| {
println!("{style:x}");
match *style {
XIM_PREEDIT_STYLE => {
preedit_style = Some(Style::Preedit(*style));
}
XIM_NOTHING_STYLE if preedit_style.is_none() => {
preedit_style = Some(Style::Nothing(*style))
}
XIM_NONE_STYLE => none_style = Some(Style::None(*style)),
_ => (),
}
XIM_NONE_STYLE => none_style = Some(Style::None(*style)),
_ => (),
});

(xconn.xlib.XFree)(styles.cast());
};
println!("==========================");

if preedit_style.is_none() && none_style.is_none() {
return None;
}

let preedit_style = preedit_style.unwrap_or_else(|| none_style.unwrap());
let none_style = none_style.unwrap_or(preedit_style);

Some(InputMethod {
im,
_name: name,
InputMethodStyles {
preedit_style,
none_style,
})
}
}
}

Expand Down Expand Up @@ -257,7 +265,7 @@ impl PotentialInputMethod {
pub fn open_im(&mut self, xconn: &Arc<XConnection>) -> Option<InputMethod> {
let im = unsafe { open_im(xconn, &self.name.c_string) };
self.successful = Some(im.is_some());
im.and_then(|im| InputMethod::new(xconn, im, self.name.string.clone()))
im.map(|im| InputMethod::new(xconn, im, self.name.string.clone()))
}
}

Expand Down
8 changes: 5 additions & 3 deletions src/platform_impl/linux/x11/ime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,13 @@ impl Ime {
None
} else {
let im = self.inner.im.as_ref().unwrap();
let styles = im.query_styles(&self.inner.xconn);
let style = if with_preedit {
im.preedit_style
styles.preedit_style.or(styles.none_style)
} else {
im.none_style
};
styles.none_style.or(styles.preedit_style)
}
.unwrap_or_default();

let context = unsafe {
ImeContext::new(
Expand Down

0 comments on commit ccddaf0

Please sign in to comment.