mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-27 08:23:04 +03:00
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
This commit is contained in:
parent
d557f8e36c
commit
1e543b9755
@ -51,6 +51,7 @@ pub(crate) struct WindowsWindowInner {
|
|||||||
pub(crate) handle: AnyWindowHandle,
|
pub(crate) handle: AnyWindowHandle,
|
||||||
hide_title_bar: bool,
|
hide_title_bar: bool,
|
||||||
display: RefCell<Rc<WindowsDisplay>>,
|
display: RefCell<Rc<WindowsDisplay>>,
|
||||||
|
last_ime_input: RefCell<Option<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowsWindowInner {
|
impl WindowsWindowInner {
|
||||||
@ -110,6 +111,7 @@ impl WindowsWindowInner {
|
|||||||
let renderer = RefCell::new(BladeRenderer::new(gpu, extent));
|
let renderer = RefCell::new(BladeRenderer::new(gpu, extent));
|
||||||
let callbacks = RefCell::new(Callbacks::default());
|
let callbacks = RefCell::new(Callbacks::default());
|
||||||
let display = RefCell::new(display);
|
let display = RefCell::new(display);
|
||||||
|
let last_ime_input = RefCell::new(None);
|
||||||
Self {
|
Self {
|
||||||
hwnd,
|
hwnd,
|
||||||
origin,
|
origin,
|
||||||
@ -122,6 +124,7 @@ impl WindowsWindowInner {
|
|||||||
handle,
|
handle,
|
||||||
hide_title_bar,
|
hide_title_bar,
|
||||||
display,
|
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<isize> {
|
fn handle_ime_composition(&self, lparam: LPARAM) -> Option<isize> {
|
||||||
if lparam.0 as u32 & GCS_COMPSTR.0 > 0 {
|
if lparam.0 as u32 & GCS_COMPSTR.0 > 0 {
|
||||||
let Some((string, string_len)) = self.parse_ime_compostion_string() else {
|
let Some((string, string_len)) = self.parse_ime_compostion_string() else {
|
||||||
@ -747,11 +759,21 @@ impl WindowsWindowInner {
|
|||||||
Some(0..string_len),
|
Some(0..string_len),
|
||||||
);
|
);
|
||||||
self.input_handler.set(Some(input_handler));
|
self.input_handler.set(Some(input_handler));
|
||||||
None
|
*self.last_ime_input.borrow_mut() = Some(string);
|
||||||
} else {
|
|
||||||
// currently, we don't care other stuff
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
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<String> {
|
fn parse_ime_char(&self, wparam: WPARAM) -> Option<String> {
|
||||||
@ -771,6 +793,7 @@ impl WindowsWindowInner {
|
|||||||
};
|
};
|
||||||
input_handler.replace_text_in_range(None, &ime_char);
|
input_handler.replace_text_in_range(None, &ime_char);
|
||||||
self.input_handler.set(Some(input_handler));
|
self.input_handler.set(Some(input_handler));
|
||||||
|
*self.last_ime_input.borrow_mut() = None;
|
||||||
self.invalidate_client_area();
|
self.invalidate_client_area();
|
||||||
Some(0)
|
Some(0)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user