windows: Refactor the current ime implementation (#32224)

Release Notes:

- N/A
This commit is contained in:
张小白 2025-06-06 15:31:45 +08:00 committed by GitHub
parent ce8854007f
commit 54e64b2407
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -691,43 +691,36 @@ fn handle_ime_composition_inner(
lparam: LPARAM, lparam: LPARAM,
state_ptr: Rc<WindowsWindowStatePtr>, state_ptr: Rc<WindowsWindowStatePtr>,
) -> Option<isize> { ) -> Option<isize> {
let mut ime_input = None; let lparam = lparam.0 as u32;
if lparam.0 as u32 & GCS_COMPSTR.0 > 0 { if lparam == 0 {
let comp_string = parse_ime_composition_string(ctx)?;
with_input_handler(&state_ptr, |input_handler| {
input_handler.replace_and_mark_text_in_range(None, &comp_string, None);
})?;
ime_input = Some(comp_string);
}
if lparam.0 as u32 & GCS_CURSORPOS.0 > 0 {
let comp_string = &ime_input?;
let caret_pos = retrieve_composition_cursor_position(ctx);
with_input_handler(&state_ptr, |input_handler| {
input_handler.replace_and_mark_text_in_range(
None,
comp_string,
Some(caret_pos..caret_pos),
);
})?;
}
if lparam.0 as u32 & GCS_RESULTSTR.0 > 0 {
let comp_result = parse_ime_composition_result(ctx)?;
with_input_handler(&state_ptr, |input_handler| {
input_handler.replace_text_in_range(None, &comp_result);
})?;
return Some(0);
}
if lparam.0 == 0 {
// Japanese IME may send this message with lparam = 0, which indicates that // Japanese IME may send this message with lparam = 0, which indicates that
// there is no composition string. // there is no composition string.
with_input_handler(&state_ptr, |input_handler| { with_input_handler(&state_ptr, |input_handler| {
input_handler.replace_text_in_range(None, ""); input_handler.replace_text_in_range(None, "");
})?; })?;
Some(0)
} else {
if lparam & GCS_COMPSTR.0 > 0 {
let comp_string = parse_ime_composition_string(ctx, GCS_COMPSTR)?;
let caret_pos = (lparam & GCS_CURSORPOS.0 > 0).then(|| {
let pos = retrieve_composition_cursor_position(ctx);
pos..pos
});
with_input_handler(&state_ptr, |input_handler| {
input_handler.replace_and_mark_text_in_range(None, &comp_string, caret_pos);
})?;
}
if lparam & GCS_RESULTSTR.0 > 0 {
let comp_result = parse_ime_composition_string(ctx, GCS_RESULTSTR)?;
with_input_handler(&state_ptr, |input_handler| {
input_handler.replace_text_in_range(None, &comp_result);
})?;
return Some(0); return Some(0);
} }
// currently, we don't care other stuff // currently, we don't care other stuff
None None
}
} }
/// SEE: https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize /// SEE: https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize
@ -1354,14 +1347,14 @@ fn parse_normal_key(
}) })
} }
fn parse_ime_composition_string(ctx: HIMC) -> Option<String> { fn parse_ime_composition_string(ctx: HIMC, comp_type: IME_COMPOSITION_STRING) -> Option<String> {
unsafe { unsafe {
let string_len = ImmGetCompositionStringW(ctx, GCS_COMPSTR, None, 0); let string_len = ImmGetCompositionStringW(ctx, comp_type, None, 0);
if string_len >= 0 { if string_len >= 0 {
let mut buffer = vec![0u8; string_len as usize + 2]; let mut buffer = vec![0u8; string_len as usize + 2];
ImmGetCompositionStringW( ImmGetCompositionStringW(
ctx, ctx,
GCS_COMPSTR, comp_type,
Some(buffer.as_mut_ptr() as _), Some(buffer.as_mut_ptr() as _),
string_len as _, string_len as _,
); );
@ -1381,29 +1374,6 @@ fn retrieve_composition_cursor_position(ctx: HIMC) -> usize {
unsafe { ImmGetCompositionStringW(ctx, GCS_CURSORPOS, None, 0) as usize } unsafe { ImmGetCompositionStringW(ctx, GCS_CURSORPOS, None, 0) as usize }
} }
fn parse_ime_composition_result(ctx: HIMC) -> Option<String> {
unsafe {
let string_len = ImmGetCompositionStringW(ctx, GCS_RESULTSTR, None, 0);
if string_len >= 0 {
let mut buffer = vec![0u8; string_len as usize + 2];
ImmGetCompositionStringW(
ctx,
GCS_RESULTSTR,
Some(buffer.as_mut_ptr() as _),
string_len as _,
);
let wstring = std::slice::from_raw_parts::<u16>(
buffer.as_mut_ptr().cast::<u16>(),
string_len as usize / 2,
);
let string = String::from_utf16_lossy(wstring);
Some(string)
} else {
None
}
}
}
#[inline] #[inline]
fn is_virtual_key_pressed(vkey: VIRTUAL_KEY) -> bool { fn is_virtual_key_pressed(vkey: VIRTUAL_KEY) -> bool {
unsafe { GetKeyState(vkey.0 as i32) < 0 } unsafe { GetKeyState(vkey.0 as i32) < 0 }