windows: Refactor the current ime implementation (#32224)

张小白 created

Release Notes:

- N/A

Change summary

crates/gpui/src/platform/windows/events.rs | 84 +++++++----------------
1 file changed, 27 insertions(+), 57 deletions(-)

Detailed changes

crates/gpui/src/platform/windows/events.rs 🔗

@@ -691,43 +691,36 @@ fn handle_ime_composition_inner(
     lparam: LPARAM,
     state_ptr: Rc<WindowsWindowStatePtr>,
 ) -> Option<isize> {
-    let mut ime_input = None;
-    if lparam.0 as u32 & GCS_COMPSTR.0 > 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 {
+    let lparam = lparam.0 as u32;
+    if lparam == 0 {
         // Japanese IME may send this message with lparam = 0, which indicates that
         // there is no composition string.
         with_input_handler(&state_ptr, |input_handler| {
             input_handler.replace_text_in_range(None, "");
         })?;
-        return Some(0);
-    }
+        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);
+        }
 
-    // currently, we don't care other stuff
-    None
+        // currently, we don't care other stuff
+        None
+    }
 }
 
 /// 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 {
-        let string_len = ImmGetCompositionStringW(ctx, GCS_COMPSTR, None, 0);
+        let string_len = ImmGetCompositionStringW(ctx, comp_type, None, 0);
         if string_len >= 0 {
             let mut buffer = vec![0u8; string_len as usize + 2];
             ImmGetCompositionStringW(
                 ctx,
-                GCS_COMPSTR,
+                comp_type,
                 Some(buffer.as_mut_ptr() 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 }
 }
 
-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]
 fn is_virtual_key_pressed(vkey: VIRTUAL_KEY) -> bool {
     unsafe { GetKeyState(vkey.0 as i32) < 0 }