1// Copyright 2014 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 "ash/sticky_keys/sticky_keys_overlay.h"
6
7#include "ash/shell.h"
8#include "ash/sticky_keys/sticky_keys_controller.h"
9#include "ash/test/ash_test_base.h"
10#include "base/memory/scoped_ptr.h"
11#include "ui/aura/window_tree_host.h"
12#include "ui/events/event.h"
13#include "ui/events/event_processor.h"
14
15namespace ash {
16
17class StickyKeysOverlayTest : public test::AshTestBase {
18 public:
19  StickyKeysOverlayTest() :
20      controller_(NULL),
21      overlay_(NULL) {}
22
23  virtual ~StickyKeysOverlayTest() {}
24
25  virtual void SetUp() OVERRIDE {
26    test::AshTestBase::SetUp();
27
28    controller_ = Shell::GetInstance()->sticky_keys_controller();
29    controller_->Enable(true);
30    overlay_ = controller_->GetOverlayForTest();
31    ASSERT_TRUE(overlay_);
32  }
33
34  void PressAndReleaseKey(ui::KeyboardCode code) {
35    SendKeyEvent(ui::ET_KEY_PRESSED, code);
36    SendKeyEvent(ui::ET_KEY_RELEASED, code);
37  }
38
39  void SendKeyEvent(ui::EventType type, ui::KeyboardCode code) {
40    ui::KeyEvent event(type, code, 0, false);
41    ui::Event::DispatcherApi dispatcher(&event);
42    dispatcher.set_target(Shell::GetInstance()->GetPrimaryRootWindow());
43
44    ui::EventDispatchDetails details = Shell::GetPrimaryRootWindow()->
45        GetHost()->event_processor()->OnEventFromSource(&event);
46    CHECK(!details.dispatcher_destroyed);
47  }
48
49  StickyKeysController* controller_;
50  StickyKeysOverlay* overlay_;
51};
52
53TEST_F(StickyKeysOverlayTest, OverlayVisibility) {
54  StickyKeysOverlay overlay;
55  EXPECT_FALSE(overlay.is_visible());
56  overlay.Show(true);
57  EXPECT_TRUE(overlay.is_visible());
58}
59
60TEST_F(StickyKeysOverlayTest, ModifierKeyState) {
61  StickyKeysOverlay overlay;
62  overlay.SetModifierKeyState(ui::EF_SHIFT_DOWN, STICKY_KEY_STATE_DISABLED);
63  overlay.SetModifierKeyState(ui::EF_ALT_DOWN, STICKY_KEY_STATE_LOCKED);
64  overlay.SetModifierKeyState(ui::EF_CONTROL_DOWN, STICKY_KEY_STATE_ENABLED);
65
66  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
67            overlay.GetModifierKeyState(ui::EF_SHIFT_DOWN));
68  EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
69            overlay.GetModifierKeyState(ui::EF_ALT_DOWN));
70  EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
71            overlay.GetModifierKeyState(ui::EF_CONTROL_DOWN));
72}
73
74TEST_F(StickyKeysOverlayTest, OneModifierEnabled) {
75  EXPECT_FALSE(overlay_->is_visible());
76  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
77            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
78
79  // Pressing modifier key should show overlay.
80  PressAndReleaseKey(ui::VKEY_CONTROL);
81  EXPECT_TRUE(overlay_->is_visible());
82  EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
83            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
84
85  // Pressing a normal key should hide overlay.
86  PressAndReleaseKey(ui::VKEY_T);
87  EXPECT_FALSE(overlay_->is_visible());
88  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
89            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
90}
91
92TEST_F(StickyKeysOverlayTest, TwoModifiersEnabled) {
93  EXPECT_FALSE(overlay_->is_visible());
94  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
95            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
96  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
97            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
98
99  // Pressing two modifiers should show overlay.
100  PressAndReleaseKey(ui::VKEY_SHIFT);
101  PressAndReleaseKey(ui::VKEY_CONTROL);
102  EXPECT_TRUE(overlay_->is_visible());
103  EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
104            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
105  EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
106            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
107
108  // Pressing a normal key should hide overlay.
109  PressAndReleaseKey(ui::VKEY_N);
110  EXPECT_FALSE(overlay_->is_visible());
111  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
112            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
113  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
114            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
115}
116
117TEST_F(StickyKeysOverlayTest, LockedModifier) {
118  EXPECT_FALSE(overlay_->is_visible());
119  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
120            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
121
122  // Pressing a modifier key twice should lock modifier and show overlay.
123  PressAndReleaseKey(ui::VKEY_LMENU);
124  PressAndReleaseKey(ui::VKEY_LMENU);
125  EXPECT_TRUE(overlay_->is_visible());
126  EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
127            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
128
129  // Pressing a normal key should not hide overlay.
130  PressAndReleaseKey(ui::VKEY_D);
131  EXPECT_TRUE(overlay_->is_visible());
132  EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
133            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
134}
135
136TEST_F(StickyKeysOverlayTest, LockedAndNormalModifier) {
137  EXPECT_FALSE(overlay_->is_visible());
138  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
139            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
140  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
141            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
142
143  // Pressing a modifier key twice should lock modifier and show overlay.
144  PressAndReleaseKey(ui::VKEY_CONTROL);
145  PressAndReleaseKey(ui::VKEY_CONTROL);
146  EXPECT_TRUE(overlay_->is_visible());
147  EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
148            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
149
150  // Pressing another modifier key should still show overlay.
151  PressAndReleaseKey(ui::VKEY_SHIFT);
152  EXPECT_TRUE(overlay_->is_visible());
153  EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
154            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
155  EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
156            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
157
158  // Pressing a normal key should not hide overlay but disable normal modifier.
159  PressAndReleaseKey(ui::VKEY_D);
160  EXPECT_TRUE(overlay_->is_visible());
161  EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
162            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
163  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
164            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
165}
166
167TEST_F(StickyKeysOverlayTest, ModifiersDisabled) {
168  EXPECT_FALSE(overlay_->is_visible());
169  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
170            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
171  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
172            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
173  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
174            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
175
176  // Enable modifiers.
177  PressAndReleaseKey(ui::VKEY_CONTROL);
178  PressAndReleaseKey(ui::VKEY_SHIFT);
179  PressAndReleaseKey(ui::VKEY_SHIFT);
180  PressAndReleaseKey(ui::VKEY_LMENU);
181
182  EXPECT_TRUE(overlay_->is_visible());
183  EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
184            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
185  EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
186            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
187  EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
188            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
189
190  // Disable modifiers and overlay should be hidden.
191  PressAndReleaseKey(ui::VKEY_CONTROL);
192  PressAndReleaseKey(ui::VKEY_CONTROL);
193  PressAndReleaseKey(ui::VKEY_SHIFT);
194  PressAndReleaseKey(ui::VKEY_LMENU);
195  PressAndReleaseKey(ui::VKEY_LMENU);
196
197  EXPECT_FALSE(overlay_->is_visible());
198  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
199            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
200  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
201            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
202  EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
203            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
204}
205
206TEST_F(StickyKeysOverlayTest, ModifierVisibility) {
207  // All but AltGr and Mod3 should initially be visible.
208  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
209  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
210  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
211  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
212  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
213
214  // Turn all modifiers on.
215  controller_->SetModifiersEnabled(true, true);
216  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
217  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
218  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
219  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
220  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
221
222  // Turn off Mod3.
223  controller_->SetModifiersEnabled(false, true);
224  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
225  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
226
227  // Turn off AltGr.
228  controller_->SetModifiersEnabled(true, false);
229  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
230  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
231
232  // Turn off AltGr and Mod3.
233  controller_->SetModifiersEnabled(false, false);
234  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
235  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
236}
237
238}  // namespace ash
239