use std::sync::{
atomic::{AtomicBool, Ordering::Relaxed},
Mutex,
};
use winapi::{
shared::{
minwindef::{LPARAM, WPARAM},
windef::HWND,
},
um::winuser,
};
use crate::platform_impl::platform::{event_loop::ProcResult, keyboard::next_kbd_msg};
pub struct MinimalIme {
getting_ime_text: AtomicBool,
utf16parts: Mutex<Vec<u16>>,
}
impl Default for MinimalIme {
fn default() -> Self {
MinimalIme {
getting_ime_text: AtomicBool::new(false),
utf16parts: Mutex::new(Vec::with_capacity(16)),
}
}
}
impl MinimalIme {
pub(crate) fn process_message(
&self,
hwnd: HWND,
msg_kind: u32,
wparam: WPARAM,
_lparam: LPARAM,
result: &mut ProcResult,
) -> Option<String> {
match msg_kind {
winuser::WM_IME_ENDCOMPOSITION => {
self.getting_ime_text.store(true, Relaxed);
}
winuser::WM_CHAR | winuser::WM_SYSCHAR => {
if self.getting_ime_text.load(Relaxed) {
*result = ProcResult::Value(0);
self.utf16parts.lock().unwrap().push(wparam as u16);
let next_msg = next_kbd_msg(hwnd);
let more_char_coming = next_msg
.map(|m| matches!(m.message, winuser::WM_CHAR | winuser::WM_SYSCHAR))
.unwrap_or(false);
if !more_char_coming {
let mut utf16parts = self.utf16parts.lock().unwrap();
let result = String::from_utf16(&utf16parts).ok();
utf16parts.clear();
self.getting_ime_text.store(false, Relaxed);
return result;
}
}
}
_ => (),
}
None
}
}