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(
}
bool SwitchToUSKeyboardLayout() {
// For LoadKeyboardLayout - Prior to Windows 8: If the specified input
// locale identifier is not already loaded, the function loads and
// activates the input locale identifier for the current thread.
// Beginning in Windows 8: If the specified input locale identifier is not
// already loaded, the function loads and activates the input
// locale identifier for the system.
// For Windows 8 - Use ActivateKeyboardLayout instead of LoadKeyboardLayout
// Prior to Windows 8, calling LoadKeyboardLayout() with KLF_SETFORPROCESS
// activates specified keyboard layout for the entire process.
//
// Beginning in Windows 8: KLF_SETFORPROCESS flag is not used.
// LoadKeyboardLayout always activates an input locale identifier for
// the entire system if the current process owns the window with keyboard
// focus.
LPCTSTR kUsKeyboardLayout = TEXT("00000409");
HKL hkl =
::LoadKeyboardLayout(kUsKeyboardLayout, KLF_SETFORPROCESS | KLF_ACTIVATE);
if (IsWindows8OrGreater()) {
int size;
TCHAR active_keyboard[KL_NAMELENGTH];
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;
}
// Inspect only the low word that contains keyboard language identifier,
// ignoring the device identifier (Dvorak keyboard, etc) in the high word.
return LOWORD(hkl) == 0x0409;
}
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