// Copyright (c) 2011 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 "content/test/mock_keyboard_driver_win.h"

#include "base/basictypes.h"
#include "base/logging.h"
#include "content/test/mock_keyboard.h"

namespace content {

MockKeyboardDriverWin::MockKeyboardDriverWin() {
  // Save the keyboard layout and status of the application.
  // This class changes the keyboard layout and status of this application.
  // This change may break succeeding tests. To prevent this possible break, we
  // should save the layout and status here to restore when this instance is
  // destroyed.
  original_keyboard_layout_ = GetKeyboardLayout(0);
  active_keyboard_layout_ = original_keyboard_layout_;
  GetKeyboardState(&original_keyboard_states_[0]);

  const UINT num_keyboard_layouts = GetKeyboardLayoutList(0, NULL);
  DCHECK(num_keyboard_layouts > 0);

  orig_keyboard_layouts_list_.resize(num_keyboard_layouts);
  GetKeyboardLayoutList(num_keyboard_layouts, &orig_keyboard_layouts_list_[0]);

  memset(&keyboard_states_[0], 0, sizeof(keyboard_states_));
}

MockKeyboardDriverWin::~MockKeyboardDriverWin() {
  // Unload the keyboard-layout driver, restore the keyboard state, and reset
  // the keyboard layout for succeeding tests.
  MaybeUnloadActiveLayout();
  SetKeyboardState(&original_keyboard_states_[0]);
  ActivateKeyboardLayout(original_keyboard_layout_, KLF_RESET);
}

void MockKeyboardDriverWin::MaybeUnloadActiveLayout() {
  // Workaround for http://crbug.com/12093
  // Only unload a keyboard layout if it was loaded by this mock driver.
  // Contrary to the documentation on MSDN unloading a keyboard layout
  // previously loaded by the system causes that layout to stop working.
  // We have confirmation of this behavior on XP & Vista.
  for (size_t i = 0; i < orig_keyboard_layouts_list_.size(); ++i) {
    if (orig_keyboard_layouts_list_[i] == active_keyboard_layout_)
      return;
  }

  // If we got here, this keyboard layout wasn't loaded by the system so it's
  // safe to unload it ourselve's.
  UnloadKeyboardLayout(active_keyboard_layout_);
  active_keyboard_layout_ = original_keyboard_layout_;
}

bool MockKeyboardDriverWin::SetLayout(int layout) {
  // Unload the current keyboard-layout driver and load a new keyboard-layout
  // driver for mapping a virtual key-code to a Unicode character.
  MaybeUnloadActiveLayout();

  // Scan the mapping table and retrieve a Language ID for the input layout.
  // Load the keyboard-layout driver when we find a Language ID.
  // This Language IDs are copied from the registry
  //   "HKLM\SYSTEM\CurrentControlSet\Control\Keyboard layouts".
  // TODO(hbono): Add more keyboard-layout drivers.
  static const struct {
    const wchar_t* language;
    MockKeyboard::Layout keyboard_layout;
  } kLanguageIDs[] = {
    {L"00000401", MockKeyboard::LAYOUT_ARABIC},
    {L"00000402", MockKeyboard::LAYOUT_BULGARIAN},
    {L"00000404", MockKeyboard::LAYOUT_CHINESE_TRADITIONAL},
    {L"00000405", MockKeyboard::LAYOUT_CZECH},
    {L"00000406", MockKeyboard::LAYOUT_DANISH},
    {L"00000407", MockKeyboard::LAYOUT_GERMAN},
    {L"00000408", MockKeyboard::LAYOUT_GREEK},
    {L"00000409", MockKeyboard::LAYOUT_UNITED_STATES},
    {L"0000040a", MockKeyboard::LAYOUT_SPANISH},
    {L"0000040b", MockKeyboard::LAYOUT_FINNISH},
    {L"0000040c", MockKeyboard::LAYOUT_FRENCH},
    {L"0000040d", MockKeyboard::LAYOUT_HEBREW},
    {L"0000040e", MockKeyboard::LAYOUT_HUNGARIAN},
    {L"00000410", MockKeyboard::LAYOUT_ITALIAN},
    {L"00000411", MockKeyboard::LAYOUT_JAPANESE},
    {L"00000412", MockKeyboard::LAYOUT_KOREAN},
    {L"00000415", MockKeyboard::LAYOUT_POLISH},
    {L"00000416", MockKeyboard::LAYOUT_PORTUGUESE_BRAZILIAN},
    {L"00000418", MockKeyboard::LAYOUT_ROMANIAN},
    {L"00000419", MockKeyboard::LAYOUT_RUSSIAN},
    {L"0000041a", MockKeyboard::LAYOUT_CROATIAN},
    {L"0000041b", MockKeyboard::LAYOUT_SLOVAK},
    {L"0000041e", MockKeyboard::LAYOUT_THAI},
    {L"0000041d", MockKeyboard::LAYOUT_SWEDISH},
    {L"0000041f", MockKeyboard::LAYOUT_TURKISH_Q},
    {L"0000042a", MockKeyboard::LAYOUT_VIETNAMESE},
    {L"00000439", MockKeyboard::LAYOUT_DEVANAGARI_INSCRIPT},
    {L"00000816", MockKeyboard::LAYOUT_PORTUGUESE},
    {L"00001409", MockKeyboard::LAYOUT_UNITED_STATES_DVORAK},
    {L"00001009", MockKeyboard::LAYOUT_CANADIAN_FRENCH},
  };

  for (size_t i = 0; i < arraysize(kLanguageIDs); ++i) {
    if (layout == kLanguageIDs[i].keyboard_layout) {
      HKL new_keyboard_layout = LoadKeyboardLayout(kLanguageIDs[i].language,
                                                   KLF_ACTIVATE);
      // loaded_keyboard_layout_ must always have a valid keyboard handle
      // so we only assign upon success.
      if (new_keyboard_layout) {
        active_keyboard_layout_ = new_keyboard_layout;
        return true;
      }

      return false;
    }
  }

  // Return false if there are not any matching drivers.
  return false;
}

bool MockKeyboardDriverWin::SetModifiers(int modifiers) {
  // Over-write the keyboard status with our modifier-key status.
  // WebInputEventFactory::keyboardEvent() uses GetKeyState() to retrive
  // modifier-key status. So, we update the modifier-key status with this
  // SetKeyboardState() call before creating NativeWebKeyboardEvent
  // instances.
  memset(&keyboard_states_[0], 0, sizeof(keyboard_states_));
  static const struct {
    int key_code;
    int mask;
  } kModifierMasks[] = {
    {VK_SHIFT,    MockKeyboard::LEFT_SHIFT | MockKeyboard::RIGHT_SHIFT},
    {VK_CONTROL,  MockKeyboard::LEFT_CONTROL | MockKeyboard::RIGHT_CONTROL},
    {VK_MENU,     MockKeyboard::LEFT_ALT | MockKeyboard::RIGHT_ALT},
    {VK_LSHIFT,   MockKeyboard::LEFT_SHIFT},
    {VK_LCONTROL, MockKeyboard::LEFT_CONTROL},
    {VK_LMENU,    MockKeyboard::LEFT_ALT},
    {VK_RSHIFT,   MockKeyboard::RIGHT_SHIFT},
    {VK_RCONTROL, MockKeyboard::RIGHT_CONTROL},
    {VK_RMENU,    MockKeyboard::RIGHT_ALT},
  };
  for (size_t i = 0; i < arraysize(kModifierMasks); ++i) {
    const int kKeyDownMask = 0x80;
    if (modifiers & kModifierMasks[i].mask)
      keyboard_states_[kModifierMasks[i].key_code] = kKeyDownMask;
  }
  SetKeyboardState(&keyboard_states_[0]);

  return true;
}

int MockKeyboardDriverWin::GetCharacters(int key_code,
                                         std::wstring* output) {
  // Retrieve Unicode characters composed from the input key-code and
  // the mofifiers.
  CHECK(output);
  wchar_t code[16];
  int length = ToUnicodeEx(key_code, MapVirtualKey(key_code, 0),
                           &keyboard_states_[0], &code[0], arraysize(code), 0,
                           active_keyboard_layout_);
  if (length > 0)
    output->assign(code);
  return length;
}

}  // namespace content
