910e62b5创建于 1月15日历史提交
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/base/accelerators/accelerator.h"

#include <string>

#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event.h"
#include "ui/events/types/event_type.h"

namespace ui {

TEST(AcceleratorTest, Repeat) {
  const Accelerator accelerator_a(VKEY_A, EF_NONE);
  EXPECT_FALSE(accelerator_a.IsRepeat());

  const Accelerator accelerator_b(VKEY_B, EF_IS_REPEAT);
  EXPECT_TRUE(accelerator_b.IsRepeat());

  const Accelerator accelerator_b_copy(accelerator_b);
  EXPECT_TRUE(accelerator_b_copy.IsRepeat());
}

TEST(AcceleratorTest, TimeStamp) {
  const Accelerator accelerator_a(VKEY_A, EF_NONE);
  EXPECT_EQ(base::TimeTicks(), accelerator_a.time_stamp());

  const base::TimeTicks event_time = base::TimeTicks() + base::Milliseconds(1);
  KeyEvent keyevent(EventType::kKeyPressed, VKEY_SPACE, EF_NONE, event_time);

  const Accelerator accelerator_b(keyevent);
  EXPECT_EQ(event_time, accelerator_b.time_stamp());
}

// Crash on Android builders. https://crbug.com/980267
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_GetShortcutText DISABLED_GetShortcutText
#else
#define MAYBE_GetShortcutText GetShortcutText
#endif
TEST(AcceleratorTest, MAYBE_GetShortcutText) {
  struct {
    KeyboardCode code;
    int modifiers;
    const char16_t* expected_long;
    const char16_t* expected_short;
  } keys[] = {
      {VKEY_Q, EF_CONTROL_DOWN | EF_SHIFT_DOWN, u"Ctrl+Shift+Q", u"⌃⇧Q"},
      {VKEY_A, EF_ALT_DOWN | EF_SHIFT_DOWN, u"Alt+Shift+A", u"⌥⇧A"},
      // Regression test for https://crbug.com/867732:
      {VKEY_OEM_COMMA, EF_CONTROL_DOWN, u"Ctrl+Comma", u"⌃,"},
#if BUILDFLAG(IS_MAC)
      {VKEY_T, EF_COMMAND_DOWN | EF_CONTROL_DOWN, nullptr, u"⌃⌘T"},
#endif
#if BUILDFLAG(IS_LINUX)
      {VKEY_T, EF_COMMAND_DOWN | EF_CONTROL_DOWN, u"Super+Ctrl+T", nullptr},
#endif
  };

  for (const auto& key : keys) {
    std::u16string text =
        Accelerator(key.code, key.modifiers).GetShortcutText();
#if BUILDFLAG(IS_MAC)
    EXPECT_EQ(text, key.expected_short);
#else
    EXPECT_EQ(text, key.expected_long);
#endif
  }
}

TEST(AcceleratorTest, ShortcutTextForUnknownKey) {
  const Accelerator accelerator(VKEY_UNKNOWN, EF_NONE);
  EXPECT_EQ(std::u16string(), accelerator.GetShortcutText());
}

TEST(AcceleratorTest, VerifyToKeyEventConstructor) {
  const Accelerator accelerator(VKEY_Z, EF_COMMAND_DOWN,
                                Accelerator::KeyState::RELEASED,
                                base::TimeTicks());
  KeyEvent key_event = accelerator.ToKeyEvent();
  // Check key event fields to verift if the right constructor is called.
  EXPECT_EQ(key_event.key_code(), VKEY_Z);
  EXPECT_EQ(key_event.Clone()->type(), ui::EventType::kKeyReleased);
  EXPECT_FALSE(key_event.is_char());
}

TEST(AcceleratorTest, ConversionFromKeyEvent) {
  ui::KeyEvent key_event(
      ui::EventType::kKeyPressed, ui::VKEY_F,
      ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_DOWN);
  Accelerator accelerator(key_event);

  EXPECT_EQ(accelerator.key_code(), ui::VKEY_F);
  EXPECT_EQ(accelerator.modifiers(),
            ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_DOWN);
}

#if BUILDFLAG(IS_MAC)
class AcceleratorTestMac : public testing::Test {
 public:
  AcceleratorTestMac() = default;
  ~AcceleratorTestMac() override = default;

  // Returns a "short" vector representation of the modifier flags in
  // |modifier_mask|.
  std::vector<std::u16string> ShortFormStringForModifiers(int modifier_flags) {
    ui::KeyEvent key_event(ui::EventType::kKeyPressed, ui::VKEY_F,
                           modifier_flags);
    Accelerator accelerator(key_event);

    return accelerator.GetShortFormModifiers();
  }
};

// Checks that a string representation exists for all modifier masks that make
// sense on the Mac.
TEST_F(AcceleratorTestMac, ModifierFlagsShortFormRepresentation) {
  int modifier_flag = 1 << 0;
  while (modifier_flag) {
    // If |modifier_flag| is a valid modifier flag and it's not EF_ALTGR_DOWN
    // (the Linux Alt key on the right side of the keyboard), confirm that
    // a string representation for the modifier flag exists.
    if (Accelerator::MaskOutKeyEventFlags(modifier_flag) &&
        modifier_flag != EF_ALTGR_DOWN) {
      EXPECT_GT(this->ShortFormStringForModifiers(modifier_flag).size(), 0UL);
    }
    modifier_flag <<= 1;
  }
}
#endif

#if BUILDFLAG(IS_CHROMEOS)
TEST(AcceleratorTest, ConversionFromKeyEvent_Ash) {
  ui::KeyEvent key_event(ui::EventType::kKeyPressed, ui::VKEY_F,
                         ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN);
  Accelerator accelerator(key_event);

  EXPECT_EQ(accelerator.key_code(), ui::VKEY_F);
  EXPECT_EQ(accelerator.modifiers(), ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN);

  // Code is set when converting from a KeyEvent.
  EXPECT_EQ(accelerator.code(), DomCode::US_F);

  // Test resetting code.
  accelerator.reset_code();
  EXPECT_EQ(accelerator.code(), DomCode::NONE);
}
#endif  // BUILDFLAG(IS_CHROMEOS)

}  // namespace ui