diff --git a/winit-win32/src/event_loop.rs b/winit-win32/src/event_loop.rs index 8f1008f98d..4be6164354 100644 --- a/winit-win32/src/event_loop.rs +++ b/winit-win32/src/event_loop.rs @@ -51,12 +51,12 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{ SystemParametersInfoW, TranslateMessage, WHEEL_DELTA, WINDOWPOS, 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_XBUTTONDOWN, WM_XBUTTONUP, WMSZ_BOTTOM, + 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, WMSZ_BOTTOM, WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT, WMSZ_LEFT, WMSZ_RIGHT, WMSZ_TOP, WMSZ_TOPLEFT, WMSZ_TOPRIGHT, WNDCLASSEXW, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE, @@ -1508,6 +1508,21 @@ unsafe fn public_window_callback_inner( result = ProcResult::Value(unsafe { DefWindowProcW(window, msg, wparam, lparam) }); }, + 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 { diff --git a/winit/src/changelog/unreleased.md b/winit/src/changelog/unreleased.md index 729bfd639b..3114fe5be0 100644 --- a/winit/src/changelog/unreleased.md +++ b/winit/src/changelog/unreleased.md @@ -57,6 +57,10 @@ changelog entry. ### Fixed +- On Windows, fix a freeze that occurs when the keyboard layout is switched by + tools such as Punto Switcher. The `WM_INPUTLANGCHANGE` message is now handled + to refresh the cached keyboard layout, while still deferring to + `DefWindowProc` for normal propagation. - On Redox, handle `EINTR` when reading from `event_socket` instead of panicking. - On Wayland, switch from using the `ahash` hashing algorithm to `foldhash`. - On macOS, fix borderless game presentation options not sticking after switching spaces.