On Windows, implement 'Window::set_ime_position' with IMM API

This commit is contained in:
moko256 2020-12-10 05:16:59 +09:00 committed by GitHub
parent c5620efc9c
commit db038d943c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 4 deletions

View file

@ -1,5 +1,6 @@
# Unreleased # Unreleased
- On Windows, implement `Window::set_ime_position`.
- **Breaking:** On Windows, Renamed `WindowBuilderExtWindows`'s `is_dark_mode` to `theme`. - **Breaking:** On Windows, Renamed `WindowBuilderExtWindows`'s `is_dark_mode` to `theme`.
- On Windows, add `WindowBuilderExtWindows::with_theme` to set a preferred theme. - On Windows, add `WindowBuilderExtWindows::with_theme` to set a preferred theme.
- On Windows, fix bug causing message boxes to appear delayed. - On Windows, fix bug causing message boxes to appear delayed.

View file

@ -65,6 +65,7 @@ features = [
"commctrl", "commctrl",
"dwmapi", "dwmapi",
"errhandlingapi", "errhandlingapi",
"imm",
"hidusage", "hidusage",
"libloaderapi", "libloaderapi",
"objbase", "objbase",

View file

@ -0,0 +1,54 @@
use simple_logger::SimpleLogger;
use winit::{
dpi::PhysicalPosition,
event::{ElementState, Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
fn main() {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
window.set_title("A fantastic window!");
println!("Ime position will system default");
println!("Click to set ime position to cursor's");
let mut cursor_position = PhysicalPosition::new(0.0, 0.0);
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent {
event: WindowEvent::CursorMoved { position, .. },
..
} => {
cursor_position = position;
}
Event::WindowEvent {
event:
WindowEvent::MouseInput {
state: ElementState::Released,
..
},
..
} => {
println!(
"Setting ime position to {}, {}",
cursor_position.x, cursor_position.y
);
window.set_ime_position(cursor_position);
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
return;
}
_ => (),
}
});
}

View file

@ -18,7 +18,9 @@ use winapi::{
windef::{HWND, POINT, RECT}, windef::{HWND, POINT, RECT},
}, },
um::{ um::{
combaseapi, dwmapi, libloaderapi, combaseapi, dwmapi,
imm::{CFS_POINT, COMPOSITIONFORM},
libloaderapi,
objbase::COINIT_APARTMENTTHREADED, objbase::COINIT_APARTMENTTHREADED,
ole2, ole2,
oleidl::LPDROPTARGET, oleidl::LPDROPTARGET,
@ -616,9 +618,25 @@ impl Window {
self.window_state.lock().taskbar_icon = taskbar_icon; self.window_state.lock().taskbar_icon = taskbar_icon;
} }
pub(crate) fn set_ime_position_physical(&self, x: i32, y: i32) {
if unsafe { winuser::GetSystemMetrics(winuser::SM_IMMENABLED) } != 0 {
let mut composition_form = COMPOSITIONFORM {
dwStyle: CFS_POINT,
ptCurrentPos: POINT { x, y },
rcArea: unsafe { mem::zeroed() },
};
unsafe {
let himc = winapi::um::imm::ImmGetContext(self.window.0);
winapi::um::imm::ImmSetCompositionWindow(himc, &mut composition_form);
winapi::um::imm::ImmReleaseContext(self.window.0, himc);
}
}
}
#[inline] #[inline]
pub fn set_ime_position(&self, _position: Position) { pub fn set_ime_position(&self, spot: Position) {
warn!("`Window::set_ime_position` is ignored on Windows") let (x, y) = spot.to_physical::<i32>(self.scale_factor()).into();
self.set_ime_position_physical(x, y);
} }
#[inline] #[inline]

View file

@ -677,7 +677,7 @@ impl Window {
/// ///
/// ## Platform-specific /// ## Platform-specific
/// ///
/// - **iOS / Android / Web / Windows:** Unsupported. /// - **iOS / Android / Web:** Unsupported.
#[inline] #[inline]
pub fn set_ime_position<P: Into<Position>>(&self, position: P) { pub fn set_ime_position<P: Into<Position>>(&self, position: P) {
self.window.set_ime_position(position.into()) self.window.set_ime_position(position.into())