From 95246d81c1cec4a46852118ee884ed516db461e6 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 30 Jul 2022 17:15:57 +0300 Subject: [PATCH] On X11, fix crash when can't disable IME Fixes #2402. --- src/platform_impl/linux/x11/ime/context.rs | 13 ++++---- src/platform_impl/linux/x11/ime/mod.rs | 39 ++++++++++++++++------ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/platform_impl/linux/x11/ime/context.rs b/src/platform_impl/linux/x11/ime/context.rs index f0a751b7..a3109d57 100644 --- a/src/platform_impl/linux/x11/ime/context.rs +++ b/src/platform_impl/linux/x11/ime/context.rs @@ -1,12 +1,13 @@ -use std::mem::transmute; +use std::ffi::CStr; use std::os::raw::c_short; -use std::ptr; use std::sync::Arc; +use std::{mem, ptr}; + +use x11_dl::xlib::{XIMCallback, XIMPreeditCaretCallbackStruct, XIMPreeditDrawCallbackStruct}; + +use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventSender}; use super::{ffi, util, XConnection, XError}; -use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventSender}; -use std::ffi::CStr; -use x11_dl::xlib::{XIMCallback, XIMPreeditCaretCallbackStruct, XIMPreeditDrawCallbackStruct}; /// IME creation error. #[derive(Debug)] @@ -163,7 +164,7 @@ struct PreeditCallbacks { impl PreeditCallbacks { pub fn new(client_data: ffi::XPointer) -> PreeditCallbacks { let start_callback = create_xim_callback(client_data, unsafe { - transmute(preedit_start_callback as usize) + mem::transmute(preedit_start_callback as usize) }); let done_callback = create_xim_callback(client_data, preedit_done_callback); let caret_callback = create_xim_callback(client_data, preedit_caret_callback); diff --git a/src/platform_impl/linux/x11/ime/mod.rs b/src/platform_impl/linux/x11/ime/mod.rs index 4125c0ac..746ba9ea 100644 --- a/src/platform_impl/linux/x11/ime/mod.rs +++ b/src/platform_impl/linux/x11/ime/mod.rs @@ -120,7 +120,33 @@ impl Ime { // Create empty entry in map, so that when IME is rebuilt, this window has a context. None } else { - let event = if with_preedit { + let context = unsafe { + ImeContext::new( + &self.inner.xconn, + self.inner.im, + window, + None, + with_preedit, + self.inner.event_sender.clone(), + ) + .or_else(|_| { + debug!( + "failed to create an IME context {} preedit support", + if with_preedit { "with" } else { "without" } + ); + ImeContext::new( + &self.inner.xconn, + self.inner.im, + window, + None, + !with_preedit, + self.inner.event_sender.clone(), + ) + }) + }?; + + // Check the state on the context, since it could fail to enable or disable preedit. + let event = if context.is_allowed { ImeEvent::Enabled } else { // There's no IME without preedit. @@ -132,16 +158,7 @@ impl Ime { .send((window, event)) .expect("Failed to send enabled event"); - Some(unsafe { - ImeContext::new( - &self.inner.xconn, - self.inner.im, - window, - None, - with_preedit, - self.inner.event_sender.clone(), - ) - }?) + Some(context) }; self.inner.contexts.insert(window, context); Ok(!self.is_destroyed())