Add configurable offline layout correction and latest Windows release

This commit is contained in:
2026-10-27 23:50:04 +02:00
parent f683e4178c
commit f1af998029
25 changed files with 142458 additions and 27 deletions
+47 -1
View File
@@ -107,9 +107,55 @@ wchar_t physicalKey(DWORD scan, bool shift)
return (shift ? physicalLayout().shifted : physicalLayout().normal)[i];
return 0;
}
static HWND inputWindow(HWND w)
{
if (!w || !IsWindow(w))
return nullptr;
GUITHREADINFO info{sizeof(info)};
DWORD thread = w == GetForegroundWindow() ? 0 : GetWindowThreadProcessId(w, nullptr);
if (GetGUIThreadInfo(thread, &info) && info.hwndFocus &&
(info.hwndFocus == w || IsChild(w, info.hwndFocus) || GetAncestor(info.hwndFocus, GA_ROOT) == w))
return info.hwndFocus;
return w;
}
HKL windowLayout(HWND w)
{
return GetKeyboardLayout(GetWindowThreadProcessId(w, nullptr));
HWND input = inputWindow(w);
return input ? GetKeyboardLayout(GetWindowThreadProcessId(input, nullptr)) : nullptr;
}
bool switchWindowLayout(HWND target, HKL layout, const std::function<bool()> &valid)
{
HWND input = inputWindow(target);
auto unchanged = [&]
{ return input && valid() && GetForegroundWindow() == target && inputWindow(target) == input; };
if (!layout || !unchanged())
return false;
if (windowLayout(target) == layout)
return true;
// Windows directs layout requests to the focused control, which can belong
// to a different UI thread/process than a Teams/WebView top-level window.
if (!PostMessageW(input, WM_INPUTLANGCHANGEREQUEST, 0, (LPARAM)layout))
return false;
for (int i = 0; i < 30; ++i)
{
if (!unchanged())
return false;
if (windowLayout(target) == layout)
return true;
// Some hosts handle this at their top level instead of the focused child.
if (i == 14 && input != target)
PostMessageW(target, WM_INPUTLANGCHANGEREQUEST, 0, (LPARAM)layout);
Sleep(10);
}
return unchanged() && windowLayout(target) == layout;
}
void showRequestedWindow(HWND window)
{
ShowWindow(window, SW_SHOW);
// STARTF_USESHOWWINDOW can override the process's first ShowWindow with
// SW_HIDE. An explicit user request must still make the window visible.
if (!IsWindowVisible(window))
ShowWindow(window, SW_SHOW);
}
bool activateWindow(HWND window)
{