x11: Fix preedit for CJK and partially fix unresponsive keyboard with xim (#17373)

Closes #15833
Related to [#12495
comment](https://github.com/zed-industries/zed/pull/12495#issuecomment-2328356125)

Destroying and recreating the Input context was the only way to reset
the IME but it's making the keyboard unresponsive sometimes due to a XIM
error.

The keyboard will still be unresponsive if you close your IME while
using zed, but I don't know how to fix this.

* Fixed preedit drawing for CJK
* Fixed unresponsive keyboard by properly implementing reset_ic in
`xim-rs`

Release Notes:

- N/A
This commit is contained in:
Fernando Tagawa 2024-09-16 21:46:03 -03:00 committed by GitHub
parent bc5ed1334f
commit d7c45ccf2f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 15 additions and 36 deletions

6
Cargo.lock generated
View file

@ -14079,7 +14079,7 @@ dependencies = [
[[package]]
name = "xim"
version = "0.4.0"
source = "git+https://github.com/npmania/xim-rs?rev=27132caffc5b9bc9c432ca4afad184ab6e7c16af#27132caffc5b9bc9c432ca4afad184ab6e7c16af"
source = "git+https://github.com/XDeme1/xim-rs?rev=d50d461764c2213655cd9cf65a0ea94c70d3c4fd#d50d461764c2213655cd9cf65a0ea94c70d3c4fd"
dependencies = [
"ahash 0.8.11",
"hashbrown 0.14.5",
@ -14092,7 +14092,7 @@ dependencies = [
[[package]]
name = "xim-ctext"
version = "0.3.0"
source = "git+https://github.com/npmania/xim-rs?rev=27132caffc5b9bc9c432ca4afad184ab6e7c16af#27132caffc5b9bc9c432ca4afad184ab6e7c16af"
source = "git+https://github.com/XDeme1/xim-rs?rev=d50d461764c2213655cd9cf65a0ea94c70d3c4fd#d50d461764c2213655cd9cf65a0ea94c70d3c4fd"
dependencies = [
"encoding_rs",
]
@ -14100,7 +14100,7 @@ dependencies = [
[[package]]
name = "xim-parser"
version = "0.2.1"
source = "git+https://github.com/npmania/xim-rs?rev=27132caffc5b9bc9c432ca4afad184ab6e7c16af#27132caffc5b9bc9c432ca4afad184ab6e7c16af"
source = "git+https://github.com/XDeme1/xim-rs?rev=d50d461764c2213655cd9cf65a0ea94c70d3c4fd#d50d461764c2213655cd9cf65a0ea94c70d3c4fd"
dependencies = [
"bitflags 2.6.0",
]

View file

@ -143,7 +143,7 @@ xkbcommon = { git = "https://github.com/ConradIrwin/xkbcommon-rs", rev = "fcbb46
"wayland",
"x11",
] }
xim = { git = "https://github.com/npmania/xim-rs", rev = "27132caffc5b9bc9c432ca4afad184ab6e7c16af", features = [
xim = { git = "https://github.com/XDeme1/xim-rs", rev = "d50d461764c2213655cd9cf65a0ea94c70d3c4fd", features = [
"x11rb-xcb",
"x11rb-client",
] }

View file

@ -201,9 +201,7 @@ impl X11ClientStatePtr {
.build_ic_attributes()
.push(
xim::AttributeName::InputStyle,
xim::InputStyle::PREEDIT_CALLBACKS
| xim::InputStyle::STATUS_NOTHING
| xim::InputStyle::PREEDIT_POSITION,
xim::InputStyle::PREEDIT_CALLBACKS,
)
.push(xim::AttributeName::ClientWindow, xim_handler.window)
.push(xim::AttributeName::FocusWindow, xim_handler.window)
@ -572,12 +570,7 @@ impl X11Client {
let mut xim_handler = state.xim_handler.take().unwrap();
let mut ic_attributes = ximc
.build_ic_attributes()
.push(
AttributeName::InputStyle,
InputStyle::PREEDIT_CALLBACKS
| InputStyle::STATUS_NOTHING
| InputStyle::PREEDIT_NONE,
)
.push(AttributeName::InputStyle, InputStyle::PREEDIT_CALLBACKS)
.push(AttributeName::ClientWindow, xim_handler.window)
.push(AttributeName::FocusWindow, xim_handler.window);
@ -605,12 +598,12 @@ impl X11Client {
state.ximc = Some(ximc);
}
pub fn disable_ime(&self) {
pub fn reset_ime(&self) {
let mut state = self.0.borrow_mut();
state.composing = false;
if let Some(mut ximc) = state.ximc.take() {
let xim_handler = state.xim_handler.as_ref().unwrap();
ximc.destroy_ic(xim_handler.im_id, xim_handler.ic_id).ok();
ximc.reset_ic(xim_handler.im_id, xim_handler.ic_id).ok();
state.ximc = Some(ximc);
}
}
@ -768,6 +761,9 @@ impl X11Client {
window.set_active(true);
let mut state = self.0.borrow_mut();
state.keyboard_focused_window = Some(event.event);
if let Some(handler) = state.xim_handler.as_mut() {
handler.window = event.event;
}
drop(state);
self.enable_ime();
}
@ -781,7 +777,7 @@ impl X11Client {
}
state.pre_edit_text.take();
drop(state);
self.disable_ime();
self.reset_ime();
window.handle_ime_delete();
}
Event::XkbNewKeyboardNotify(_) | Event::MapNotify(_) => {
@ -940,8 +936,7 @@ impl X11Client {
if state.composing && state.ximc.is_some() {
drop(state);
self.disable_ime();
self.enable_ime();
self.reset_ime();
window.handle_ime_unmark();
state = self.0.borrow_mut();
} else if let Some(text) = state.pre_edit_text.take() {
@ -1199,9 +1194,7 @@ impl X11Client {
.build_ic_attributes()
.push(
xim::AttributeName::InputStyle,
xim::InputStyle::PREEDIT_CALLBACKS
| xim::InputStyle::STATUS_NOTHING
| xim::InputStyle::PREEDIT_POSITION,
xim::InputStyle::PREEDIT_CALLBACKS,
)
.push(xim::AttributeName::ClientWindow, xim_handler.window)
.push(xim::AttributeName::FocusWindow, xim_handler.window)

View file

@ -48,12 +48,7 @@ impl<C: Client<XEvent = xproto::KeyPressEvent>> ClientHandler<C> for XimHandler
) -> Result<(), ClientError> {
let ic_attributes = client
.build_ic_attributes()
.push(
AttributeName::InputStyle,
InputStyle::PREEDIT_CALLBACKS
| InputStyle::STATUS_NOTHING
| InputStyle::PREEDIT_NONE,
)
.push(AttributeName::InputStyle, InputStyle::PREEDIT_CALLBACKS)
.push(AttributeName::ClientWindow, self.window)
.push(AttributeName::FocusWindow, self.window)
.build();
@ -110,15 +105,6 @@ impl<C: Client<XEvent = xproto::KeyPressEvent>> ClientHandler<C> for XimHandler
client.disconnect()
}
fn handle_destroy_ic(
&mut self,
client: &mut C,
input_method_id: u16,
_input_context_id: u16,
) -> Result<(), ClientError> {
client.close(input_method_id)
}
fn handle_preedit_draw(
&mut self,
_client: &mut C,