1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/base/accelerators/accelerator_manager.h"
6
7#include "base/compiler_specific.h"
8#include "testing/gtest/include/gtest/gtest.h"
9#include "ui/events/event_constants.h"
10#include "ui/events/keycodes/keyboard_codes.h"
11
12namespace ui {
13namespace test {
14
15namespace {
16
17class TestTarget : public AcceleratorTarget {
18 public:
19  TestTarget() : accelerator_pressed_count_(0) {}
20  virtual ~TestTarget() {}
21
22  int accelerator_pressed_count() const {
23    return accelerator_pressed_count_;
24  }
25
26  void set_accelerator_pressed_count(int accelerator_pressed_count) {
27    accelerator_pressed_count_ = accelerator_pressed_count;
28  }
29
30  // Overridden from AcceleratorTarget:
31  virtual bool AcceleratorPressed(const Accelerator& accelerator) OVERRIDE;
32  virtual bool CanHandleAccelerators() const OVERRIDE;
33
34 private:
35  int accelerator_pressed_count_;
36
37  DISALLOW_COPY_AND_ASSIGN(TestTarget);
38};
39
40bool TestTarget::AcceleratorPressed(const Accelerator& accelerator) {
41  ++accelerator_pressed_count_;
42  return true;
43}
44
45bool TestTarget::CanHandleAccelerators() const {
46  return true;
47}
48
49Accelerator GetAccelerator(KeyboardCode code, int mask) {
50  return Accelerator(code, mask);
51}
52
53}  // namespace
54
55class AcceleratorManagerTest : public testing::Test {
56 public:
57  AcceleratorManagerTest() {}
58  virtual ~AcceleratorManagerTest() {}
59
60  AcceleratorManager manager_;
61};
62
63TEST_F(AcceleratorManagerTest, Register) {
64  const Accelerator accelerator_a(VKEY_A, EF_NONE);
65  TestTarget target;
66  manager_.Register(accelerator_a, AcceleratorManager::kNormalPriority,
67                    &target);
68
69  // The registered accelerator is processed.
70  EXPECT_TRUE(manager_.Process(accelerator_a));
71  EXPECT_EQ(1, target.accelerator_pressed_count());
72}
73
74TEST_F(AcceleratorManagerTest, RegisterMultipleTarget) {
75  const Accelerator accelerator_a(VKEY_A, EF_NONE);
76  TestTarget target1;
77  manager_.Register(accelerator_a, AcceleratorManager::kNormalPriority,
78                    &target1);
79  TestTarget target2;
80  manager_.Register(accelerator_a, AcceleratorManager::kNormalPriority,
81                    &target2);
82
83  // If multiple targets are registered with the same accelerator, the target
84  // registered later processes the accelerator.
85  EXPECT_TRUE(manager_.Process(accelerator_a));
86  EXPECT_EQ(0, target1.accelerator_pressed_count());
87  EXPECT_EQ(1, target2.accelerator_pressed_count());
88}
89
90TEST_F(AcceleratorManagerTest, Unregister) {
91  const Accelerator accelerator_a(VKEY_A, EF_NONE);
92  TestTarget target;
93  manager_.Register(accelerator_a, AcceleratorManager::kNormalPriority,
94                    &target);
95  const Accelerator accelerator_b(VKEY_B, EF_NONE);
96  manager_.Register(accelerator_b, AcceleratorManager::kNormalPriority,
97                    &target);
98
99  // Unregistering a different accelerator does not affect the other
100  // accelerator.
101  manager_.Unregister(accelerator_b, &target);
102  EXPECT_TRUE(manager_.Process(accelerator_a));
103  EXPECT_EQ(1, target.accelerator_pressed_count());
104
105  // The unregistered accelerator is no longer processed.
106  target.set_accelerator_pressed_count(0);
107  manager_.Unregister(accelerator_a, &target);
108  EXPECT_FALSE(manager_.Process(accelerator_a));
109  EXPECT_EQ(0, target.accelerator_pressed_count());
110}
111
112TEST_F(AcceleratorManagerTest, UnregisterAll) {
113  const Accelerator accelerator_a(VKEY_A, EF_NONE);
114  TestTarget target1;
115  manager_.Register(accelerator_a, AcceleratorManager::kNormalPriority,
116                    &target1);
117  const Accelerator accelerator_b(VKEY_B, EF_NONE);
118  manager_.Register(accelerator_b, AcceleratorManager::kNormalPriority,
119                    &target1);
120  const Accelerator accelerator_c(VKEY_C, EF_NONE);
121  TestTarget target2;
122  manager_.Register(accelerator_c, AcceleratorManager::kNormalPriority,
123                    &target2);
124  manager_.UnregisterAll(&target1);
125
126  // All the accelerators registered for |target1| are no longer processed.
127  EXPECT_FALSE(manager_.Process(accelerator_a));
128  EXPECT_FALSE(manager_.Process(accelerator_b));
129  EXPECT_EQ(0, target1.accelerator_pressed_count());
130
131  // UnregisterAll with a different target does not affect the other target.
132  EXPECT_TRUE(manager_.Process(accelerator_c));
133  EXPECT_EQ(1, target2.accelerator_pressed_count());
134}
135
136TEST_F(AcceleratorManagerTest, Process) {
137  TestTarget target;
138
139  // Test all 2*2*2 cases (shift/control/alt = on/off).
140  for (int mask = 0; mask < 2 * 2 * 2; ++mask) {
141    Accelerator accelerator(GetAccelerator(VKEY_A, mask));
142    const base::string16 text = accelerator.GetShortcutText();
143    manager_.Register(accelerator, AcceleratorManager::kNormalPriority,
144                      &target);
145
146    // The registered accelerator is processed.
147    const int last_count = target.accelerator_pressed_count();
148    EXPECT_TRUE(manager_.Process(accelerator)) << text;
149    EXPECT_EQ(last_count + 1, target.accelerator_pressed_count()) << text;
150
151    // The non-registered accelerators are not processed.
152    accelerator.set_type(ET_UNKNOWN);
153    EXPECT_FALSE(manager_.Process(accelerator)) << text;  // different type
154    accelerator.set_type(ET_TRANSLATED_KEY_PRESS);
155    EXPECT_FALSE(manager_.Process(accelerator)) << text;  // different type
156    accelerator.set_type(ET_KEY_RELEASED);
157    EXPECT_FALSE(manager_.Process(accelerator)) << text;  // different type
158    accelerator.set_type(ET_TRANSLATED_KEY_RELEASE);
159    EXPECT_FALSE(manager_.Process(accelerator)) << text;  // different type
160
161    EXPECT_FALSE(manager_.Process(GetAccelerator(VKEY_UNKNOWN, mask)))
162        << text;  // different vkey
163    EXPECT_FALSE(manager_.Process(GetAccelerator(VKEY_B, mask)))
164        << text;  // different vkey
165    EXPECT_FALSE(manager_.Process(GetAccelerator(VKEY_SHIFT, mask)))
166        << text;  // different vkey
167
168    for (int test_mask = 0; test_mask < 2 * 2 * 2; ++test_mask) {
169      if (test_mask == mask)
170        continue;
171      const Accelerator test_accelerator(GetAccelerator(VKEY_A, test_mask));
172      const base::string16 test_text = test_accelerator.GetShortcutText();
173      EXPECT_FALSE(manager_.Process(test_accelerator))
174          << text << ", " << test_text;  // different modifiers
175    }
176
177    EXPECT_EQ(last_count + 1, target.accelerator_pressed_count()) << text;
178    manager_.UnregisterAll(&target);
179  }
180}
181
182}  // namespace test
183}  // namespace ui
184