Commit c76d5aef authored by Peter Kvitek's avatar Peter Kvitek Committed by Commit Bot

[chromedriver] Fixed US keyboard layout selection on Windows.

The previous code used to activate all existing keyboard layouts one
by one, then retrieve activated keyboard layout name and compare it
to US keyboard layout identifier.  The comparison failed since on
modern Windows keyboard layout name includes keyboard device identifier
(like Dvorak keyboard, etc) in the high word and this caused the last
checked keyboard layout to be left active. That layout is rarely
a US layout, which caused character to virtual key conversion API
::VkKeyScan() to fail on ASCII character keys.

The new code uses LoadKeyboardLayout() API that loads and activates
the specified keyboard layout (US English) or leaves system default
language of the system, if US English layout does not exist.

Bug: 783703
Change-Id: I2cdc1d4984131e455d30a16dbbd9c66c209e686e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2521836
Commit-Queue: Shengfa Lin <shengfa@google.com>
Reviewed-by: default avatarShengfa Lin <shengfa@google.com>
Cr-Commit-Position: refs/heads/master@{#825423}
parent c74a002a
...@@ -63,34 +63,18 @@ bool ConvertCharToKeyCode( ...@@ -63,34 +63,18 @@ bool ConvertCharToKeyCode(
} }
bool SwitchToUSKeyboardLayout() { bool SwitchToUSKeyboardLayout() {
// For LoadKeyboardLayout - Prior to Windows 8: If the specified input // Prior to Windows 8, calling LoadKeyboardLayout() with KLF_SETFORPROCESS
// locale identifier is not already loaded, the function loads and // activates specified keyboard layout for the entire process.
// activates the input locale identifier for the current thread. //
// Beginning in Windows 8: If the specified input locale identifier is not // Beginning in Windows 8: KLF_SETFORPROCESS flag is not used.
// already loaded, the function loads and activates the input // LoadKeyboardLayout always activates an input locale identifier for
// locale identifier for the system. // the entire system if the current process owns the window with keyboard
// For Windows 8 - Use ActivateKeyboardLayout instead of LoadKeyboardLayout // focus.
LPCTSTR kUsKeyboardLayout = TEXT("00000409"); LPCTSTR kUsKeyboardLayout = TEXT("00000409");
HKL hkl =
::LoadKeyboardLayout(kUsKeyboardLayout, KLF_SETFORPROCESS | KLF_ACTIVATE);
if (IsWindows8OrGreater()) { // Inspect only the low word that contains keyboard language identifier,
int size; // ignoring the device identifier (Dvorak keyboard, etc) in the high word.
TCHAR active_keyboard[KL_NAMELENGTH]; return LOWORD(hkl) == 0x0409;
if ((size = ::GetKeyboardLayoutList(0, NULL)) <= 0)
return false;
std::unique_ptr<HKL[]> keyboard_handles_list(new HKL[size]);
::GetKeyboardLayoutList(size, keyboard_handles_list.get());
for (int keyboard_index = 0; keyboard_index < size; keyboard_index++) {
::ActivateKeyboardLayout(keyboard_handles_list[keyboard_index],
KLF_SETFORPROCESS);
::GetKeyboardLayoutName(active_keyboard);
if (wcscmp(active_keyboard, kUsKeyboardLayout) == 0)
return true;
}
return false;
} else {
return ::LoadKeyboardLayout(kUsKeyboardLayout, KLF_ACTIVATE) != NULL;
}
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment