diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index c42c259352..0490a50e51 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -217,6 +217,9 @@ changelog entry. ### Fixed +- On Windows, fix freeze when switching keyboard layout with tools like Punto Switcher. The + `WM_INPUTLANGCHANGE` message is now handled to refresh the cached keyboard layout, while still + deferring to `DefWindowProc` for normal propagation. - On Orbital, `MonitorHandle::name()` now returns `None` instead of a dummy name. - On iOS, fixed `SurfaceResized` and `Window::surface_size` not reporting the size of the actual surface. - On macOS, fixed the scancode conversion for audio volume keys. diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index abbaeaa3b9..88cef21622 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -49,12 +49,12 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{ WMSZ_BOTTOMRIGHT, WMSZ_LEFT, WMSZ_RIGHT, WMSZ_TOP, WMSZ_TOPLEFT, WMSZ_TOPRIGHT, WM_CAPTURECHANGED, WM_CLOSE, WM_CREATE, WM_DESTROY, WM_DPICHANGED, WM_ENTERSIZEMOVE, WM_EXITSIZEMOVE, WM_GETMINMAXINFO, WM_IME_COMPOSITION, WM_IME_ENDCOMPOSITION, - WM_IME_SETCONTEXT, WM_IME_STARTCOMPOSITION, WM_INPUT, WM_KEYDOWN, WM_KEYUP, WM_KILLFOCUS, - WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MENUCHAR, WM_MOUSEHWHEEL, - WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_NCACTIVATE, WM_NCCALCSIZE, WM_NCCREATE, WM_NCDESTROY, - WM_NCLBUTTONDOWN, WM_PAINT, WM_POINTERDOWN, WM_POINTERUP, WM_POINTERUPDATE, WM_RBUTTONDOWN, - WM_RBUTTONUP, WM_SETCURSOR, WM_SETFOCUS, WM_SETTINGCHANGE, WM_SIZE, WM_SIZING, WM_SYSCOMMAND, - WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TOUCH, WM_WINDOWPOSCHANGED, WM_WINDOWPOSCHANGING, + WM_IME_SETCONTEXT, WM_IME_STARTCOMPOSITION, WM_INPUT, WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, + WM_KILLFOCUS, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MENUCHAR, + WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_NCACTIVATE, WM_NCCALCSIZE, WM_NCCREATE, + WM_NCDESTROY, WM_NCLBUTTONDOWN, WM_PAINT, WM_POINTERDOWN, WM_POINTERUP, WM_POINTERUPDATE, + WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SETCURSOR, WM_SETFOCUS, WM_SETTINGCHANGE, WM_SIZE, WM_SIZING, + WM_SYSCOMMAND, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TOUCH, WM_WINDOWPOSCHANGED, WM_WINDOWPOSCHANGING, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSEXW, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE, }; @@ -1569,6 +1569,21 @@ unsafe fn public_window_callback_inner( result = ProcResult::DefWindowProc(wparam); }, + WM_INPUTLANGCHANGE => { + // Refresh the cached keyboard layout for the newly activated input + // language. This message is sent (by Windows or by layout switchers + // such as Punto Switcher) after the layout changes. Refreshing the + // cache here prevents a freeze that otherwise occurs when switching + // layout via such tools. We still defer to `DefWindowProc` so the + // message keeps propagating to first-level child windows, as the + // Win32 documentation requires. + { + let mut layouts = LAYOUT_CACHE.lock().unwrap(); + layouts.get_current_layout(); + } + result = ProcResult::DefWindowProc(wparam); + }, + // this is necessary for us to maintain minimize/restore state WM_SYSCOMMAND => { if wparam == SC_RESTORE as usize {