Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
Smit Barmase
8f1174c155
ime 2025-08-09 00:24:52 +05:30
2 changed files with 44 additions and 20 deletions

View file

@ -655,6 +655,20 @@ impl X11Client {
state.restore_xim(ximc, xim_handler);
drop(state);
// Create IC when IME becomes ready while we already have focus
{
let s = self.0.borrow();
let need_enable = s
.xim_handler
.as_ref()
.map(|h| h.ready && !h.connected && s.keyboard_focused_window.is_some())
.unwrap_or(false);
drop(s);
if need_enable {
self.enable_ime();
}
}
if let Some(event) = xim_callback_event {
self.handle_xim_callback_event(event);
}
@ -682,22 +696,25 @@ impl X11Client {
let Some((mut ximc, mut xim_handler)) = state.take_xim() else {
return;
};
let window_id = state.keyboard_focused_window;
if window_id.is_none() {
// no focus -> nothing to bind to; put XIM back and bail
state.restore_xim(ximc, xim_handler);
return;
}
let window_id = window_id.unwrap();
// ensure handler.window is the actual focused window
xim_handler.window = window_id;
let mut ic_attributes = ximc
.build_ic_attributes()
.push(AttributeName::InputStyle, InputStyle::PREEDIT_CALLBACKS)
.push(AttributeName::ClientWindow, xim_handler.window)
.push(AttributeName::FocusWindow, xim_handler.window);
let window_id = state.keyboard_focused_window;
drop(state);
if let Some(window_id) = window_id {
let Some(window) = self.get_window(window_id) else {
log::error!("Failed to get window for IME positioning");
let mut state = self.0.borrow_mut();
state.ximc = Some(ximc);
state.xim_handler = Some(xim_handler);
return;
};
if let Some(window) = self.get_window(window_id) {
if let Some(area) = window.get_ime_area() {
ic_attributes =
ic_attributes.nested_list(xim::AttributeName::PreeditAttributes, |b| {
@ -710,9 +727,17 @@ impl X11Client {
);
});
}
} else {
log::error!("Failed to get window for IME positioning");
}
ximc.create_ic(xim_handler.im_id, ic_attributes.build())
.ok();
// if we already have an IC, just rebind its window/spot; else create it
if xim_handler.connected {
let _ = ximc.set_ic_values(xim_handler.im_id, xim_handler.ic_id, ic_attributes.build());
} else {
let _ = ximc.create_ic(xim_handler.im_id, ic_attributes.build());
}
let mut state = self.0.borrow_mut();
state.restore_xim(ximc, xim_handler);
}

View file

@ -13,6 +13,7 @@ pub struct XimHandler {
pub im_id: u16,
pub ic_id: u16,
pub connected: bool,
pub ready: bool,
pub window: xproto::Window,
pub last_callback_event: Option<XimCallbackEvent>,
}
@ -23,6 +24,7 @@ impl XimHandler {
im_id: Default::default(),
ic_id: Default::default(),
connected: false,
ready: false,
window: Default::default(),
last_callback_event: None,
}
@ -42,17 +44,14 @@ impl<C: Client<XEvent = xproto::KeyPressEvent>> ClientHandler<C> for XimHandler
fn handle_get_im_values(
&mut self,
client: &mut C,
input_method_id: u16,
_client: &mut C,
_input_method_id: u16,
_attributes: AHashMap<AttributeName, Vec<u8>>,
) -> Result<(), ClientError> {
let ic_attributes = client
.build_ic_attributes()
.push(AttributeName::InputStyle, InputStyle::PREEDIT_CALLBACKS)
.push(AttributeName::ClientWindow, self.window)
.push(AttributeName::FocusWindow, self.window)
.build();
client.create_ic(input_method_id, ic_attributes)
// IM is ready, but we don't know the real window yet.
// Defer IC creation to client.enable_ime().
self.ready = true;
Ok(())
}
fn handle_create_ic(