// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/test/chromedriver/keycode_text_conversion.h" #include #include #include #include "base/memory/scoped_ptr.h" #include "base/strings/utf_string_conversions.h" #include "chrome/test/chromedriver/chrome/ui_events.h" bool ConvertKeyCodeToText( ui::KeyboardCode key_code, int modifiers, std::string* text, std::string* error_msg) { UINT scan_code = ::MapVirtualKeyW(key_code, MAPVK_VK_TO_VSC); BYTE keyboard_state[256]; memset(keyboard_state, 0, 256); *error_msg = std::string(); if (modifiers & kShiftKeyModifierMask) keyboard_state[VK_SHIFT] |= 0x80; if (modifiers & kControlKeyModifierMask) keyboard_state[VK_CONTROL] |= 0x80; if (modifiers & kAltKeyModifierMask) keyboard_state[VK_MENU] |= 0x80; wchar_t chars[5]; int code = ::ToUnicode(key_code, scan_code, keyboard_state, chars, 4, 0); // |ToUnicode| converts some non-text key codes like F1 to various // control chars. Filter those out. if (code <= 0 || (code == 1 && iswcntrl(chars[0]))) *text = std::string(); else base::WideToUTF8(chars, code, text); return true; } bool ConvertCharToKeyCode( base::char16 key, ui::KeyboardCode* key_code, int *necessary_modifiers, std::string* error_msg) { short vkey_and_modifiers = ::VkKeyScanW(key); bool translated = vkey_and_modifiers != -1 && LOBYTE(vkey_and_modifiers) != 0xFF && HIBYTE(vkey_and_modifiers) != 0xFF; *error_msg = std::string(); if (translated) { *key_code = static_cast(LOBYTE(vkey_and_modifiers)); int win_modifiers = HIBYTE(vkey_and_modifiers); int modifiers = 0; if (win_modifiers & 0x01) modifiers |= kShiftKeyModifierMask; if (win_modifiers & 0x02) modifiers |= kControlKeyModifierMask; if (win_modifiers & 0x04) modifiers |= kAltKeyModifierMask; // Ignore bit 0x08: It is for Hankaku key. *necessary_modifiers = modifiers; } return translated; } 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 LPCTSTR kUsKeyboardLayout = TEXT("00000409"); if (IsWindows8OrGreater()) { int size; TCHAR active_keyboard[KL_NAMELENGTH]; if ((size = ::GetKeyboardLayoutList(0, NULL)) <= 0) return false; scoped_ptr 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; } }