From 1e543b9755d1f0cd89f7860946c0a87cac6151e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B0=8F=E7=99=BD?= <364772080@qq.com> Date: Fri, 22 Mar 2024 03:10:22 +0800 Subject: [PATCH] windows: implement `IME` caret movement and editing while composing (#9659) https://github.com/zed-industries/zed/assets/14981363/598440f7-0364-4053-9f44-710291f8aa92 Release Notes: - N/A --- crates/gpui/src/platform/windows/window.rs | 31 +++++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index 698149ddb19c30ba94cf1d0f4d2b039f8e306cb6..416a4580b4a58726d01bb1e45b3c9aa37b6414f8 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -51,6 +51,7 @@ pub(crate) struct WindowsWindowInner { pub(crate) handle: AnyWindowHandle, hide_title_bar: bool, display: RefCell>, + last_ime_input: RefCell>, } impl WindowsWindowInner { @@ -110,6 +111,7 @@ impl WindowsWindowInner { let renderer = RefCell::new(BladeRenderer::new(gpu, extent)); let callbacks = RefCell::new(Callbacks::default()); let display = RefCell::new(display); + let last_ime_input = RefCell::new(None); Self { hwnd, origin, @@ -122,6 +124,7 @@ impl WindowsWindowInner { handle, hide_title_bar, display, + last_ime_input, } } @@ -733,6 +736,15 @@ impl WindowsWindowInner { } } + fn retrieve_composition_cursor_position(&self) -> usize { + unsafe { + let ctx = ImmGetContext(self.hwnd); + let ret = ImmGetCompositionStringW(ctx, GCS_CURSORPOS, None, 0); + ImmReleaseContext(self.hwnd, ctx); + ret as usize + } + } + fn handle_ime_composition(&self, lparam: LPARAM) -> Option { if lparam.0 as u32 & GCS_COMPSTR.0 > 0 { let Some((string, string_len)) = self.parse_ime_compostion_string() else { @@ -747,11 +759,21 @@ impl WindowsWindowInner { Some(0..string_len), ); self.input_handler.set(Some(input_handler)); - None - } else { - // currently, we don't care other stuff - None + *self.last_ime_input.borrow_mut() = Some(string); } + if lparam.0 as u32 & GCS_CURSORPOS.0 > 0 { + let Some(ref comp_string) = *self.last_ime_input.borrow() else { + return None; + }; + let caret_pos = self.retrieve_composition_cursor_position(); + let Some(mut input_handler) = self.input_handler.take() else { + return None; + }; + input_handler.replace_and_mark_text_in_range(None, comp_string, Some(0..caret_pos)); + self.input_handler.set(Some(input_handler)); + } + // currently, we don't care other stuff + None } fn parse_ime_char(&self, wparam: WPARAM) -> Option { @@ -771,6 +793,7 @@ impl WindowsWindowInner { }; input_handler.replace_text_in_range(None, &ime_char); self.input_handler.set(Some(input_handler)); + *self.last_ime_input.borrow_mut() = None; self.invalidate_client_area(); Some(0) }