windows: Implement keyboard_layout_change (#30624)

Part of #29144

Release Notes:

- N/A
This commit is contained in:
张小白 2025-05-13 18:02:56 +08:00 committed by GitHub
parent 7cad943fde
commit 9426caa061
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 33 additions and 4 deletions

View file

@ -93,6 +93,7 @@ pub(crate) fn handle_msg(
WM_IME_COMPOSITION => handle_ime_composition(handle, lparam, state_ptr),
WM_SETCURSOR => handle_set_cursor(lparam, state_ptr),
WM_SETTINGCHANGE => handle_system_settings_changed(handle, lparam, state_ptr),
WM_INPUTLANGCHANGE => handle_input_language_changed(lparam, state_ptr),
WM_GPUI_CURSOR_STYLE_CHANGED => handle_cursor_changed(lparam, state_ptr),
_ => None,
};
@ -1279,6 +1280,18 @@ fn handle_system_theme_changed(
Some(0)
}
fn handle_input_language_changed(
lparam: LPARAM,
state_ptr: Rc<WindowsWindowStatePtr>,
) -> Option<isize> {
let thread = state_ptr.main_thread_id_win32;
let validation = state_ptr.validation_number;
unsafe {
PostThreadMessageW(thread, WM_INPUTLANGCHANGE, WPARAM(validation), lparam).log_err();
}
Some(0)
}
fn parse_syskeydown_msg_keystroke(wparam: WPARAM) -> Option<Keystroke> {
let modifiers = current_modifiers();
let vk_code = wparam.loword();

View file

@ -33,8 +33,8 @@ use crate::{platform::blade::BladeContext, *};
pub(crate) struct WindowsPlatform {
state: RefCell<WindowsPlatformState>,
raw_window_handles: RwLock<SmallVec<[HWND; 4]>>,
gpu_context: BladeContext,
// The below members will never change throughout the entire lifecycle of the app.
gpu_context: BladeContext,
icon: HICON,
main_receiver: flume::Receiver<Runnable>,
background_executor: BackgroundExecutor,
@ -62,6 +62,7 @@ struct PlatformCallbacks {
app_menu_action: Option<Box<dyn FnMut(&dyn Action)>>,
will_open_app_menu: Option<Box<dyn FnMut()>>,
validate_app_menu_command: Option<Box<dyn FnMut(&dyn Action) -> bool>>,
keyboard_layout_change: Option<Box<dyn FnMut()>>,
}
impl WindowsPlatformState {
@ -201,6 +202,19 @@ impl WindowsPlatform {
}
}
fn handle_input_lang_change(&self) {
let mut lock = self.state.borrow_mut();
if let Some(mut callback) = lock.callbacks.keyboard_layout_change.take() {
drop(lock);
callback();
self.state
.borrow_mut()
.callbacks
.keyboard_layout_change
.get_or_insert(callback);
}
}
// Returns true if the app should quit.
fn handle_events(&self) -> bool {
let mut msg = MSG::default();
@ -208,7 +222,8 @@ impl WindowsPlatform {
while PeekMessageW(&mut msg, None, 0, 0, PM_REMOVE).as_bool() {
match msg.message {
WM_QUIT => return true,
WM_GPUI_CLOSE_ONE_WINDOW
WM_INPUTLANGCHANGE
| WM_GPUI_CLOSE_ONE_WINDOW
| WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD
| WM_GPUI_DOCK_MENU_ACTION => {
if self.handle_gpui_evnets(msg.message, msg.wParam, msg.lParam, &msg) {
@ -247,6 +262,7 @@ impl WindowsPlatform {
}
WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD => self.run_foreground_task(),
WM_GPUI_DOCK_MENU_ACTION => self.handle_dock_action_event(lparam.0 as _),
WM_INPUTLANGCHANGE => self.handle_input_lang_change(),
_ => unreachable!(),
}
false
@ -305,8 +321,8 @@ impl Platform for WindowsPlatform {
)
}
fn on_keyboard_layout_change(&self, _callback: Box<dyn FnMut()>) {
// todo(windows)
fn on_keyboard_layout_change(&self, callback: Box<dyn FnMut()>) {
self.state.borrow_mut().callbacks.keyboard_layout_change = Some(callback);
}
fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>) {