Disable view source for Developer Tools.
[chromium-blink-merge.git] / ash / accelerators / accelerator_controller_unittest.cc
blob5ab57f8060ae9543e61e31587ff2a13f0f8d159c
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.
5 #include "ash/accelerators/accelerator_controller.h"
6 #include "ash/accelerators/accelerator_table.h"
7 #include "ash/accessibility_delegate.h"
8 #include "ash/ash_switches.h"
9 #include "ash/caps_lock_delegate.h"
10 #include "ash/display/display_manager.h"
11 #include "ash/ime_control_delegate.h"
12 #include "ash/shell.h"
13 #include "ash/shell_window_ids.h"
14 #include "ash/system/brightness_control_delegate.h"
15 #include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h"
16 #include "ash/system/tray/system_tray_delegate.h"
17 #include "ash/test/ash_test_base.h"
18 #include "ash/test/display_manager_test_api.h"
19 #include "ash/test/test_screenshot_delegate.h"
20 #include "ash/test/test_shell_delegate.h"
21 #include "ash/volume_control_delegate.h"
22 #include "ash/wm/window_state.h"
23 #include "ash/wm/window_util.h"
24 #include "base/command_line.h"
25 #include "ui/aura/root_window.h"
26 #include "ui/aura/test/test_window_delegate.h"
27 #include "ui/aura/test/test_windows.h"
28 #include "ui/aura/window.h"
29 #include "ui/events/event.h"
30 #include "ui/gfx/screen.h"
32 #if defined(USE_X11)
33 #include <X11/Xlib.h>
34 #include "ui/events/test/events_test_utils_x11.h"
35 #endif
37 namespace ash {
39 namespace {
41 class TestTarget : public ui::AcceleratorTarget {
42 public:
43 TestTarget() : accelerator_pressed_count_(0) {}
44 virtual ~TestTarget() {}
46 int accelerator_pressed_count() const {
47 return accelerator_pressed_count_;
50 void set_accelerator_pressed_count(int accelerator_pressed_count) {
51 accelerator_pressed_count_ = accelerator_pressed_count;
54 // Overridden from ui::AcceleratorTarget:
55 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
56 virtual bool CanHandleAccelerators() const OVERRIDE;
58 private:
59 int accelerator_pressed_count_;
61 DISALLOW_COPY_AND_ASSIGN(TestTarget);
64 class ReleaseAccelerator : public ui::Accelerator {
65 public:
66 ReleaseAccelerator(ui::KeyboardCode keycode, int modifiers)
67 : ui::Accelerator(keycode, modifiers) {
68 set_type(ui::ET_KEY_RELEASED);
72 class DummyVolumeControlDelegate : public VolumeControlDelegate {
73 public:
74 explicit DummyVolumeControlDelegate(bool consume)
75 : consume_(consume),
76 handle_volume_mute_count_(0),
77 handle_volume_down_count_(0),
78 handle_volume_up_count_(0) {
80 virtual ~DummyVolumeControlDelegate() {}
82 virtual bool HandleVolumeMute(const ui::Accelerator& accelerator) OVERRIDE {
83 ++handle_volume_mute_count_;
84 last_accelerator_ = accelerator;
85 return consume_;
87 virtual bool HandleVolumeDown(const ui::Accelerator& accelerator) OVERRIDE {
88 ++handle_volume_down_count_;
89 last_accelerator_ = accelerator;
90 return consume_;
92 virtual bool HandleVolumeUp(const ui::Accelerator& accelerator) OVERRIDE {
93 ++handle_volume_up_count_;
94 last_accelerator_ = accelerator;
95 return consume_;
98 int handle_volume_mute_count() const {
99 return handle_volume_mute_count_;
101 int handle_volume_down_count() const {
102 return handle_volume_down_count_;
104 int handle_volume_up_count() const {
105 return handle_volume_up_count_;
107 const ui::Accelerator& last_accelerator() const {
108 return last_accelerator_;
111 private:
112 const bool consume_;
113 int handle_volume_mute_count_;
114 int handle_volume_down_count_;
115 int handle_volume_up_count_;
116 ui::Accelerator last_accelerator_;
118 DISALLOW_COPY_AND_ASSIGN(DummyVolumeControlDelegate);
121 class DummyBrightnessControlDelegate : public BrightnessControlDelegate {
122 public:
123 explicit DummyBrightnessControlDelegate(bool consume)
124 : consume_(consume),
125 handle_brightness_down_count_(0),
126 handle_brightness_up_count_(0) {
128 virtual ~DummyBrightnessControlDelegate() {}
130 virtual bool HandleBrightnessDown(
131 const ui::Accelerator& accelerator) OVERRIDE {
132 ++handle_brightness_down_count_;
133 last_accelerator_ = accelerator;
134 return consume_;
136 virtual bool HandleBrightnessUp(const ui::Accelerator& accelerator) OVERRIDE {
137 ++handle_brightness_up_count_;
138 last_accelerator_ = accelerator;
139 return consume_;
141 virtual void SetBrightnessPercent(double percent, bool gradual) OVERRIDE {}
142 virtual void GetBrightnessPercent(
143 const base::Callback<void(double)>& callback) OVERRIDE {
144 callback.Run(100.0);
147 int handle_brightness_down_count() const {
148 return handle_brightness_down_count_;
150 int handle_brightness_up_count() const {
151 return handle_brightness_up_count_;
153 const ui::Accelerator& last_accelerator() const {
154 return last_accelerator_;
157 private:
158 const bool consume_;
159 int handle_brightness_down_count_;
160 int handle_brightness_up_count_;
161 ui::Accelerator last_accelerator_;
163 DISALLOW_COPY_AND_ASSIGN(DummyBrightnessControlDelegate);
166 class DummyImeControlDelegate : public ImeControlDelegate {
167 public:
168 explicit DummyImeControlDelegate(bool consume)
169 : consume_(consume),
170 handle_next_ime_count_(0),
171 handle_previous_ime_count_(0),
172 handle_switch_ime_count_(0) {
174 virtual ~DummyImeControlDelegate() {}
176 virtual bool HandleNextIme() OVERRIDE {
177 ++handle_next_ime_count_;
178 return consume_;
180 virtual bool HandlePreviousIme(const ui::Accelerator& accelerator) OVERRIDE {
181 ++handle_previous_ime_count_;
182 last_accelerator_ = accelerator;
183 return consume_;
185 virtual bool HandleSwitchIme(const ui::Accelerator& accelerator) OVERRIDE {
186 ++handle_switch_ime_count_;
187 last_accelerator_ = accelerator;
188 return consume_;
191 int handle_next_ime_count() const {
192 return handle_next_ime_count_;
194 int handle_previous_ime_count() const {
195 return handle_previous_ime_count_;
197 int handle_switch_ime_count() const {
198 return handle_switch_ime_count_;
200 const ui::Accelerator& last_accelerator() const {
201 return last_accelerator_;
203 virtual ui::Accelerator RemapAccelerator(
204 const ui::Accelerator& accelerator) OVERRIDE {
205 return ui::Accelerator(accelerator);
208 private:
209 const bool consume_;
210 int handle_next_ime_count_;
211 int handle_previous_ime_count_;
212 int handle_switch_ime_count_;
213 ui::Accelerator last_accelerator_;
215 DISALLOW_COPY_AND_ASSIGN(DummyImeControlDelegate);
218 class DummyKeyboardBrightnessControlDelegate
219 : public KeyboardBrightnessControlDelegate {
220 public:
221 explicit DummyKeyboardBrightnessControlDelegate(bool consume)
222 : consume_(consume),
223 handle_keyboard_brightness_down_count_(0),
224 handle_keyboard_brightness_up_count_(0) {
226 virtual ~DummyKeyboardBrightnessControlDelegate() {}
228 virtual bool HandleKeyboardBrightnessDown(
229 const ui::Accelerator& accelerator) OVERRIDE {
230 ++handle_keyboard_brightness_down_count_;
231 last_accelerator_ = accelerator;
232 return consume_;
235 virtual bool HandleKeyboardBrightnessUp(
236 const ui::Accelerator& accelerator) OVERRIDE {
237 ++handle_keyboard_brightness_up_count_;
238 last_accelerator_ = accelerator;
239 return consume_;
242 int handle_keyboard_brightness_down_count() const {
243 return handle_keyboard_brightness_down_count_;
246 int handle_keyboard_brightness_up_count() const {
247 return handle_keyboard_brightness_up_count_;
250 const ui::Accelerator& last_accelerator() const {
251 return last_accelerator_;
254 private:
255 const bool consume_;
256 int handle_keyboard_brightness_down_count_;
257 int handle_keyboard_brightness_up_count_;
258 ui::Accelerator last_accelerator_;
260 DISALLOW_COPY_AND_ASSIGN(DummyKeyboardBrightnessControlDelegate);
263 bool TestTarget::AcceleratorPressed(const ui::Accelerator& accelerator) {
264 ++accelerator_pressed_count_;
265 return true;
268 bool TestTarget::CanHandleAccelerators() const {
269 return true;
272 } // namespace
274 class AcceleratorControllerTest : public test::AshTestBase {
275 public:
276 AcceleratorControllerTest() {}
277 virtual ~AcceleratorControllerTest() {}
279 protected:
280 void EnableInternalDisplay() {
281 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()).
282 SetFirstDisplayAsInternalDisplay();
285 static AcceleratorController* GetController();
286 static bool ProcessWithContext(const ui::Accelerator& accelerator);
288 // Several functions to access ExitWarningHandler (as friend).
289 static void StubForTest(ExitWarningHandler* ewh) {
290 ewh->stub_timer_for_test_ = true;
292 static void Reset(ExitWarningHandler* ewh) {
293 ewh->state_ = ExitWarningHandler::IDLE;
295 static void SimulateTimerExpired(ExitWarningHandler* ewh) {
296 ewh->TimerAction();
298 static bool is_ui_shown(ExitWarningHandler* ewh) {
299 return !!ewh->widget_;
301 static bool is_idle(ExitWarningHandler* ewh) {
302 return ewh->state_ == ExitWarningHandler::IDLE;
304 static bool is_exiting(ExitWarningHandler* ewh) {
305 return ewh->state_ == ExitWarningHandler::EXITING;
308 private:
309 DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest);
312 AcceleratorController* AcceleratorControllerTest::GetController() {
313 return Shell::GetInstance()->accelerator_controller();
316 bool AcceleratorControllerTest::ProcessWithContext(
317 const ui::Accelerator& accelerator) {
318 AcceleratorController* controller = GetController();
319 controller->context()->UpdateContext(accelerator);
320 return controller->Process(accelerator);
323 #if !defined(OS_WIN)
324 // Double press of exit shortcut => exiting
325 TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestDoublePress) {
326 ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
327 ui::Accelerator release(press);
328 release.set_type(ui::ET_KEY_RELEASED);
329 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
330 ASSERT_TRUE(!!ewh);
331 StubForTest(ewh);
332 EXPECT_TRUE(is_idle(ewh));
333 EXPECT_FALSE(is_ui_shown(ewh));
334 EXPECT_TRUE(ProcessWithContext(press));
335 EXPECT_FALSE(ProcessWithContext(release));
336 EXPECT_FALSE(is_idle(ewh));
337 EXPECT_TRUE(is_ui_shown(ewh));
338 EXPECT_TRUE(ProcessWithContext(press)); // second press before timer.
339 EXPECT_FALSE(ProcessWithContext(release));
340 SimulateTimerExpired(ewh);
341 EXPECT_TRUE(is_exiting(ewh));
342 EXPECT_FALSE(is_ui_shown(ewh));
343 Reset(ewh);
346 // Single press of exit shortcut before timer => idle
347 TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestSinglePress) {
348 ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
349 ui::Accelerator release(press);
350 release.set_type(ui::ET_KEY_RELEASED);
351 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
352 ASSERT_TRUE(!!ewh);
353 StubForTest(ewh);
354 EXPECT_TRUE(is_idle(ewh));
355 EXPECT_FALSE(is_ui_shown(ewh));
356 EXPECT_TRUE(ProcessWithContext(press));
357 EXPECT_FALSE(ProcessWithContext(release));
358 EXPECT_FALSE(is_idle(ewh));
359 EXPECT_TRUE(is_ui_shown(ewh));
360 SimulateTimerExpired(ewh);
361 EXPECT_TRUE(is_idle(ewh));
362 EXPECT_FALSE(is_ui_shown(ewh));
363 Reset(ewh);
366 // Shutdown ash with exit warning bubble open should not crash.
367 TEST_F(AcceleratorControllerTest, LingeringExitWarningBubble) {
368 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
369 ASSERT_TRUE(!!ewh);
370 StubForTest(ewh);
372 // Trigger once to show the bubble.
373 ewh->HandleAccelerator();
374 EXPECT_FALSE(is_idle(ewh));
375 EXPECT_TRUE(is_ui_shown(ewh));
377 // Exit ash and there should be no crash
379 #endif // !defined(OS_WIN)
381 TEST_F(AcceleratorControllerTest, Register) {
382 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
383 TestTarget target;
384 GetController()->Register(accelerator_a, &target);
386 // The registered accelerator is processed.
387 EXPECT_TRUE(ProcessWithContext(accelerator_a));
388 EXPECT_EQ(1, target.accelerator_pressed_count());
391 TEST_F(AcceleratorControllerTest, RegisterMultipleTarget) {
392 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
393 TestTarget target1;
394 GetController()->Register(accelerator_a, &target1);
395 TestTarget target2;
396 GetController()->Register(accelerator_a, &target2);
398 // If multiple targets are registered with the same accelerator, the target
399 // registered later processes the accelerator.
400 EXPECT_TRUE(ProcessWithContext(accelerator_a));
401 EXPECT_EQ(0, target1.accelerator_pressed_count());
402 EXPECT_EQ(1, target2.accelerator_pressed_count());
405 TEST_F(AcceleratorControllerTest, Unregister) {
406 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
407 TestTarget target;
408 GetController()->Register(accelerator_a, &target);
409 const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
410 GetController()->Register(accelerator_b, &target);
412 // Unregistering a different accelerator does not affect the other
413 // accelerator.
414 GetController()->Unregister(accelerator_b, &target);
415 EXPECT_TRUE(ProcessWithContext(accelerator_a));
416 EXPECT_EQ(1, target.accelerator_pressed_count());
418 // The unregistered accelerator is no longer processed.
419 target.set_accelerator_pressed_count(0);
420 GetController()->Unregister(accelerator_a, &target);
421 EXPECT_FALSE(ProcessWithContext(accelerator_a));
422 EXPECT_EQ(0, target.accelerator_pressed_count());
425 TEST_F(AcceleratorControllerTest, UnregisterAll) {
426 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
427 TestTarget target1;
428 GetController()->Register(accelerator_a, &target1);
429 const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
430 GetController()->Register(accelerator_b, &target1);
431 const ui::Accelerator accelerator_c(ui::VKEY_C, ui::EF_NONE);
432 TestTarget target2;
433 GetController()->Register(accelerator_c, &target2);
434 GetController()->UnregisterAll(&target1);
436 // All the accelerators registered for |target1| are no longer processed.
437 EXPECT_FALSE(ProcessWithContext(accelerator_a));
438 EXPECT_FALSE(ProcessWithContext(accelerator_b));
439 EXPECT_EQ(0, target1.accelerator_pressed_count());
441 // UnregisterAll with a different target does not affect the other target.
442 EXPECT_TRUE(ProcessWithContext(accelerator_c));
443 EXPECT_EQ(1, target2.accelerator_pressed_count());
446 TEST_F(AcceleratorControllerTest, Process) {
447 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
448 TestTarget target1;
449 GetController()->Register(accelerator_a, &target1);
451 // The registered accelerator is processed.
452 EXPECT_TRUE(ProcessWithContext(accelerator_a));
453 EXPECT_EQ(1, target1.accelerator_pressed_count());
455 // The non-registered accelerator is not processed.
456 const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
457 EXPECT_FALSE(ProcessWithContext(accelerator_b));
460 TEST_F(AcceleratorControllerTest, IsRegistered) {
461 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
462 const ui::Accelerator accelerator_shift_a(ui::VKEY_A, ui::EF_SHIFT_DOWN);
463 TestTarget target;
464 GetController()->Register(accelerator_a, &target);
465 EXPECT_TRUE(GetController()->IsRegistered(accelerator_a));
466 EXPECT_FALSE(GetController()->IsRegistered(accelerator_shift_a));
467 GetController()->UnregisterAll(&target);
468 EXPECT_FALSE(GetController()->IsRegistered(accelerator_a));
471 TEST_F(AcceleratorControllerTest, WindowSnap) {
472 CommandLine::ForCurrentProcess()->AppendSwitch(
473 switches::kAshMultipleSnapWindowWidths);
475 scoped_ptr<aura::Window> window(
476 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
477 const ui::Accelerator dummy;
479 wm::WindowState* window_state = wm::GetWindowState(window.get());
481 window_state->Activate();
484 GetController()->PerformAction(WINDOW_SNAP_LEFT, dummy);
485 gfx::Rect snap_left = window->bounds();
486 GetController()->PerformAction(WINDOW_SNAP_LEFT, dummy);
487 EXPECT_NE(window->bounds().ToString(), snap_left.ToString());
488 GetController()->PerformAction(WINDOW_SNAP_LEFT, dummy);
489 EXPECT_NE(window->bounds().ToString(), snap_left.ToString());
491 // It should cycle back to the first snapped position.
492 GetController()->PerformAction(WINDOW_SNAP_LEFT, dummy);
493 EXPECT_EQ(window->bounds().ToString(), snap_left.ToString());
496 GetController()->PerformAction(WINDOW_SNAP_RIGHT, dummy);
497 gfx::Rect snap_right = window->bounds();
498 GetController()->PerformAction(WINDOW_SNAP_RIGHT, dummy);
499 EXPECT_NE(window->bounds().ToString(), snap_right.ToString());
500 GetController()->PerformAction(WINDOW_SNAP_RIGHT, dummy);
501 EXPECT_NE(window->bounds().ToString(), snap_right.ToString());
503 // It should cycle back to the first snapped position.
504 GetController()->PerformAction(WINDOW_SNAP_RIGHT, dummy);
505 EXPECT_EQ(window->bounds().ToString(), snap_right.ToString());
508 gfx::Rect normal_bounds = window_state->GetRestoreBoundsInParent();
510 GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy);
511 EXPECT_TRUE(window_state->IsMaximized());
512 EXPECT_NE(normal_bounds.ToString(), window->bounds().ToString());
514 GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy);
515 EXPECT_FALSE(window_state->IsMaximized());
516 // Window gets restored to its restore bounds since side-maximized state
517 // is treated as a "maximized" state.
518 EXPECT_EQ(normal_bounds.ToString(), window->bounds().ToString());
520 GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy);
521 GetController()->PerformAction(WINDOW_SNAP_LEFT, dummy);
522 EXPECT_FALSE(window_state->IsMaximized());
524 GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy);
525 GetController()->PerformAction(WINDOW_SNAP_RIGHT, dummy);
526 EXPECT_FALSE(window_state->IsMaximized());
528 GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy);
529 EXPECT_TRUE(window_state->IsMaximized());
530 GetController()->PerformAction(WINDOW_MINIMIZE, dummy);
531 EXPECT_FALSE(window_state->IsMaximized());
532 EXPECT_TRUE(window_state->IsMinimized());
533 window_state->Restore();
534 window_state->Activate();
537 GetController()->PerformAction(WINDOW_MINIMIZE, dummy);
538 EXPECT_TRUE(window_state->IsMinimized());
542 TEST_F(AcceleratorControllerTest, CenterWindowAccelerator) {
543 scoped_ptr<aura::Window> window(
544 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
545 const ui::Accelerator dummy;
546 wm::WindowState* window_state = wm::GetWindowState(window.get());
547 window_state->Activate();
549 // Center the window using accelerator.
550 GetController()->PerformAction(WINDOW_POSITION_CENTER, dummy);
551 gfx::Rect work_area =
552 Shell::GetScreen()->GetDisplayNearestWindow(window.get()).work_area();
553 gfx::Rect bounds = window->GetBoundsInScreen();
554 EXPECT_NEAR(bounds.x() - work_area.x(),
555 work_area.right() - bounds.right(),
557 EXPECT_NEAR(bounds.y() - work_area.y(),
558 work_area.bottom() - bounds.bottom(),
561 // Add the window to docked container and try to center it.
562 window->SetBounds(gfx::Rect(0, 0, 20, 20));
563 aura::Window* docked_container = Shell::GetContainer(
564 window->GetRootWindow(), internal::kShellWindowId_DockedContainer);
565 docked_container->AddChild(window.get());
566 gfx::Rect docked_bounds = window->GetBoundsInScreen();
567 GetController()->PerformAction(WINDOW_POSITION_CENTER, dummy);
568 // It should not get centered and should remain docked.
569 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
570 EXPECT_EQ(docked_bounds.ToString(), window->GetBoundsInScreen().ToString());
573 TEST_F(AcceleratorControllerTest, ControllerContext) {
574 ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
575 ui::Accelerator accelerator_a2(ui::VKEY_A, ui::EF_NONE);
576 ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
578 accelerator_a.set_type(ui::ET_KEY_PRESSED);
579 accelerator_a2.set_type(ui::ET_KEY_RELEASED);
580 accelerator_b.set_type(ui::ET_KEY_PRESSED);
582 EXPECT_FALSE(GetController()->context()->repeated());
583 EXPECT_EQ(ui::ET_UNKNOWN,
584 GetController()->context()->previous_accelerator().type());
586 GetController()->context()->UpdateContext(accelerator_a);
587 EXPECT_FALSE(GetController()->context()->repeated());
588 EXPECT_EQ(ui::ET_UNKNOWN,
589 GetController()->context()->previous_accelerator().type());
591 GetController()->context()->UpdateContext(accelerator_a2);
592 EXPECT_FALSE(GetController()->context()->repeated());
593 EXPECT_EQ(ui::ET_KEY_PRESSED,
594 GetController()->context()->previous_accelerator().type());
596 GetController()->context()->UpdateContext(accelerator_a2);
597 EXPECT_TRUE(GetController()->context()->repeated());
598 EXPECT_EQ(ui::ET_KEY_RELEASED,
599 GetController()->context()->previous_accelerator().type());
601 GetController()->context()->UpdateContext(accelerator_b);
602 EXPECT_FALSE(GetController()->context()->repeated());
603 EXPECT_EQ(ui::ET_KEY_RELEASED,
604 GetController()->context()->previous_accelerator().type());
607 #if defined(OS_WIN) && defined(USE_AURA)
608 // crbug.com/314674
609 #define MAYBE_SuppressToggleMaximized DISABLED_SuppressToggleMaximized
610 #else
611 #define MAYBE_SuppressToggleMaximized SuppressToggleMaximized
612 #endif
614 TEST_F(AcceleratorControllerTest, MAYBE_SuppressToggleMaximized) {
615 scoped_ptr<aura::Window> window(
616 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
617 wm::ActivateWindow(window.get());
618 const ui::Accelerator accelerator(ui::VKEY_A, ui::EF_NONE);
619 const ui::Accelerator empty_accelerator;
621 wm::WindowState* window_state = wm::GetWindowState(window.get());
623 // Toggling not suppressed.
624 GetController()->context()->UpdateContext(accelerator);
625 GetController()->PerformAction(TOGGLE_MAXIMIZED, accelerator);
626 EXPECT_TRUE(window_state->IsMaximized());
628 // The same accelerator - toggling suppressed.
629 GetController()->context()->UpdateContext(accelerator);
630 GetController()->PerformAction(TOGGLE_MAXIMIZED, accelerator);
631 EXPECT_TRUE(window_state->IsMaximized());
633 // Suppressed but not for gesture events.
634 GetController()->PerformAction(TOGGLE_MAXIMIZED, empty_accelerator);
635 EXPECT_FALSE(window_state->IsMaximized());
638 #if defined(OS_WIN) && defined(USE_AURA)
639 // crbug.com/317592
640 #define MAYBE_ProcessOnce DISABLED_ProcessOnce
641 #else
642 #define MAYBE_ProcessOnce ProcessOnce
643 #endif
645 #if defined(OS_WIN) || defined(USE_X11)
646 TEST_F(AcceleratorControllerTest, MAYBE_ProcessOnce) {
647 ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
648 TestTarget target;
649 GetController()->Register(accelerator_a, &target);
651 // The accelerator is processed only once.
652 aura::WindowEventDispatcher* dispatcher =
653 Shell::GetPrimaryRootWindow()->GetDispatcher();
654 #if defined(OS_WIN)
655 MSG msg1 = { NULL, WM_KEYDOWN, ui::VKEY_A, 0 };
656 ui::TranslatedKeyEvent key_event1(msg1, false);
657 EXPECT_TRUE(dispatcher->AsWindowTreeHostDelegate()->OnHostKeyEvent(
658 &key_event1));
660 MSG msg2 = { NULL, WM_CHAR, L'A', 0 };
661 ui::TranslatedKeyEvent key_event2(msg2, true);
662 EXPECT_FALSE(dispatcher->AsWindowTreeHostDelegate()->OnHostKeyEvent(
663 &key_event2));
665 MSG msg3 = { NULL, WM_KEYUP, ui::VKEY_A, 0 };
666 ui::TranslatedKeyEvent key_event3(msg3, false);
667 EXPECT_FALSE(dispatcher->AsWindowTreeHostDelegate()->OnHostKeyEvent(
668 &key_event3));
669 #elif defined(USE_X11)
670 ui::ScopedXI2Event key_event;
671 key_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, 0);
672 ui::TranslatedKeyEvent key_event1(key_event, false);
673 EXPECT_TRUE(dispatcher->AsWindowTreeHostDelegate()->OnHostKeyEvent(
674 &key_event1));
676 ui::TranslatedKeyEvent key_event2(key_event, true);
677 EXPECT_FALSE(dispatcher->AsWindowTreeHostDelegate()->OnHostKeyEvent(
678 &key_event2));
680 key_event.InitKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, 0);
681 ui::TranslatedKeyEvent key_event3(key_event, false);
682 EXPECT_FALSE(dispatcher->AsWindowTreeHostDelegate()->OnHostKeyEvent(
683 &key_event3));
684 #endif
685 EXPECT_EQ(1, target.accelerator_pressed_count());
687 #endif
689 TEST_F(AcceleratorControllerTest, GlobalAccelerators) {
690 // CycleBackward
691 EXPECT_TRUE(ProcessWithContext(
692 ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
693 // CycleForward
694 EXPECT_TRUE(ProcessWithContext(
695 ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN)));
696 // CycleLinear
697 EXPECT_TRUE(ProcessWithContext(
698 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_NONE)));
700 #if defined(OS_CHROMEOS)
701 // Take screenshot / partial screenshot
702 // True should always be returned regardless of the existence of the delegate.
704 test::TestScreenshotDelegate* delegate = GetScreenshotDelegate();
705 delegate->set_can_take_screenshot(false);
706 EXPECT_TRUE(ProcessWithContext(
707 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
708 EXPECT_TRUE(ProcessWithContext(
709 ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
710 EXPECT_TRUE(ProcessWithContext(
711 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1,
712 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
714 delegate->set_can_take_screenshot(true);
715 EXPECT_EQ(0, delegate->handle_take_screenshot_count());
716 EXPECT_TRUE(ProcessWithContext(
717 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
718 EXPECT_EQ(1, delegate->handle_take_screenshot_count());
719 EXPECT_TRUE(ProcessWithContext(
720 ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
721 EXPECT_EQ(2, delegate->handle_take_screenshot_count());
722 EXPECT_TRUE(ProcessWithContext(
723 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1,
724 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
725 EXPECT_EQ(2, delegate->handle_take_screenshot_count());
727 #endif
728 // DisableCapsLock
730 CapsLockDelegate* delegate = Shell::GetInstance()->caps_lock_delegate();
731 delegate->SetCapsLockEnabled(true);
732 EXPECT_TRUE(delegate->IsCapsLockEnabled());
733 // Handled only on key release.
734 EXPECT_FALSE(ProcessWithContext(
735 ui::Accelerator(ui::VKEY_LSHIFT, ui::EF_NONE)));
736 EXPECT_TRUE(delegate->IsCapsLockEnabled());
737 EXPECT_TRUE(ProcessWithContext(
738 ReleaseAccelerator(ui::VKEY_SHIFT, ui::EF_NONE)));
739 EXPECT_FALSE(delegate->IsCapsLockEnabled());
740 delegate->SetCapsLockEnabled(true);
741 EXPECT_FALSE(ProcessWithContext(
742 ui::Accelerator(ui::VKEY_RSHIFT, ui::EF_NONE)));
743 EXPECT_TRUE(delegate->IsCapsLockEnabled());
744 EXPECT_TRUE(ProcessWithContext(
745 ReleaseAccelerator(ui::VKEY_LSHIFT, ui::EF_NONE)));
746 EXPECT_FALSE(delegate->IsCapsLockEnabled());
747 delegate->SetCapsLockEnabled(true);
748 EXPECT_FALSE(ProcessWithContext(
749 ui::Accelerator(ui::VKEY_SHIFT, ui::EF_NONE)));
750 EXPECT_TRUE(delegate->IsCapsLockEnabled());
751 EXPECT_TRUE(ProcessWithContext(
752 ReleaseAccelerator(ui::VKEY_RSHIFT, ui::EF_NONE)));
753 EXPECT_FALSE(delegate->IsCapsLockEnabled());
755 // Do not handle when a shift pressed with other keys.
756 delegate->SetCapsLockEnabled(true);
757 EXPECT_FALSE(ProcessWithContext(
758 ui::Accelerator(ui::VKEY_A, ui::EF_SHIFT_DOWN)));
759 EXPECT_TRUE(delegate->IsCapsLockEnabled());
760 EXPECT_FALSE(ProcessWithContext(
761 ReleaseAccelerator(ui::VKEY_A, ui::EF_SHIFT_DOWN)));
762 EXPECT_TRUE(delegate->IsCapsLockEnabled());
764 // Do not handle when a shift pressed with other keys, and shift is
765 // released first.
766 delegate->SetCapsLockEnabled(true);
767 EXPECT_FALSE(ProcessWithContext(
768 ui::Accelerator(ui::VKEY_A, ui::EF_SHIFT_DOWN)));
769 EXPECT_TRUE(delegate->IsCapsLockEnabled());
770 EXPECT_FALSE(ProcessWithContext(
771 ReleaseAccelerator(ui::VKEY_LSHIFT, ui::EF_NONE)));
772 EXPECT_TRUE(delegate->IsCapsLockEnabled());
774 EXPECT_FALSE(ProcessWithContext(
775 ui::Accelerator(ui::VKEY_A, ui::EF_SHIFT_DOWN)));
776 EXPECT_TRUE(delegate->IsCapsLockEnabled());
777 EXPECT_FALSE(ProcessWithContext(
778 ReleaseAccelerator(ui::VKEY_SHIFT, ui::EF_NONE)));
779 EXPECT_TRUE(delegate->IsCapsLockEnabled());
781 EXPECT_FALSE(ProcessWithContext(
782 ui::Accelerator(ui::VKEY_A, ui::EF_SHIFT_DOWN)));
783 EXPECT_TRUE(delegate->IsCapsLockEnabled());
784 EXPECT_FALSE(ProcessWithContext(
785 ReleaseAccelerator(ui::VKEY_RSHIFT, ui::EF_NONE)));
786 EXPECT_TRUE(delegate->IsCapsLockEnabled());
788 // Do not consume shift keyup when caps lock is off.
789 delegate->SetCapsLockEnabled(false);
790 EXPECT_FALSE(ProcessWithContext(
791 ui::Accelerator(ui::VKEY_LSHIFT, ui::EF_NONE)));
792 EXPECT_FALSE(ProcessWithContext(
793 ReleaseAccelerator(ui::VKEY_LSHIFT, ui::EF_NONE)));
794 EXPECT_FALSE(ProcessWithContext(
795 ui::Accelerator(ui::VKEY_RSHIFT, ui::EF_NONE)));
796 EXPECT_FALSE(ProcessWithContext(
797 ReleaseAccelerator(ui::VKEY_RSHIFT, ui::EF_NONE)));
798 EXPECT_FALSE(ProcessWithContext(
799 ui::Accelerator(ui::VKEY_SHIFT, ui::EF_NONE)));
800 EXPECT_FALSE(ProcessWithContext(
801 ReleaseAccelerator(ui::VKEY_SHIFT, ui::EF_NONE)));
803 // ToggleCapsLock
805 CapsLockDelegate* delegate = Shell::GetInstance()->caps_lock_delegate();
806 delegate->SetCapsLockEnabled(true);
807 EXPECT_TRUE(delegate->IsCapsLockEnabled());
808 EXPECT_FALSE(ProcessWithContext(
809 ui::Accelerator(ui::VKEY_LWIN, ui::EF_ALT_DOWN)));
810 EXPECT_TRUE(ProcessWithContext(
811 ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_ALT_DOWN)));
812 EXPECT_FALSE(delegate->IsCapsLockEnabled());
813 EXPECT_FALSE(ProcessWithContext(
814 ui::Accelerator(ui::VKEY_LWIN, ui::EF_ALT_DOWN)));
815 EXPECT_TRUE(ProcessWithContext(
816 ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_ALT_DOWN)));
817 EXPECT_TRUE(delegate->IsCapsLockEnabled());
819 const ui::Accelerator volume_mute(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
820 const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
821 const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE);
823 DummyVolumeControlDelegate* delegate =
824 new DummyVolumeControlDelegate(false);
825 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
826 scoped_ptr<VolumeControlDelegate>(delegate).Pass());
827 EXPECT_EQ(0, delegate->handle_volume_mute_count());
828 EXPECT_FALSE(ProcessWithContext(volume_mute));
829 EXPECT_EQ(1, delegate->handle_volume_mute_count());
830 EXPECT_EQ(volume_mute, delegate->last_accelerator());
831 EXPECT_EQ(0, delegate->handle_volume_down_count());
832 EXPECT_FALSE(ProcessWithContext(volume_down));
833 EXPECT_EQ(1, delegate->handle_volume_down_count());
834 EXPECT_EQ(volume_down, delegate->last_accelerator());
835 EXPECT_EQ(0, delegate->handle_volume_up_count());
836 EXPECT_FALSE(ProcessWithContext(volume_up));
837 EXPECT_EQ(1, delegate->handle_volume_up_count());
838 EXPECT_EQ(volume_up, delegate->last_accelerator());
841 DummyVolumeControlDelegate* delegate = new DummyVolumeControlDelegate(true);
842 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
843 scoped_ptr<VolumeControlDelegate>(delegate).Pass());
844 EXPECT_EQ(0, delegate->handle_volume_mute_count());
845 EXPECT_TRUE(ProcessWithContext(volume_mute));
846 EXPECT_EQ(1, delegate->handle_volume_mute_count());
847 EXPECT_EQ(volume_mute, delegate->last_accelerator());
848 EXPECT_EQ(0, delegate->handle_volume_down_count());
849 EXPECT_TRUE(ProcessWithContext(volume_down));
850 EXPECT_EQ(1, delegate->handle_volume_down_count());
851 EXPECT_EQ(volume_down, delegate->last_accelerator());
852 EXPECT_EQ(0, delegate->handle_volume_up_count());
853 EXPECT_TRUE(ProcessWithContext(volume_up));
854 EXPECT_EQ(1, delegate->handle_volume_up_count());
855 EXPECT_EQ(volume_up, delegate->last_accelerator());
857 #if defined(OS_CHROMEOS)
858 // Brightness
859 // ui::VKEY_BRIGHTNESS_DOWN/UP are not defined on Windows.
860 const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
861 const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE);
863 EXPECT_FALSE(ProcessWithContext(brightness_down));
864 EXPECT_FALSE(ProcessWithContext(brightness_up));
865 DummyBrightnessControlDelegate* delegate =
866 new DummyBrightnessControlDelegate(true);
867 GetController()->SetBrightnessControlDelegate(
868 scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
869 EXPECT_FALSE(ProcessWithContext(brightness_down));
870 EXPECT_FALSE(ProcessWithContext(brightness_up));
872 // Enable internal display.
873 EnableInternalDisplay();
875 DummyBrightnessControlDelegate* delegate =
876 new DummyBrightnessControlDelegate(false);
877 GetController()->SetBrightnessControlDelegate(
878 scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
879 EXPECT_EQ(0, delegate->handle_brightness_down_count());
880 EXPECT_FALSE(ProcessWithContext(brightness_down));
881 EXPECT_EQ(1, delegate->handle_brightness_down_count());
882 EXPECT_EQ(brightness_down, delegate->last_accelerator());
883 EXPECT_EQ(0, delegate->handle_brightness_up_count());
884 EXPECT_FALSE(ProcessWithContext(brightness_up));
885 EXPECT_EQ(1, delegate->handle_brightness_up_count());
886 EXPECT_EQ(brightness_up, delegate->last_accelerator());
889 DummyBrightnessControlDelegate* delegate =
890 new DummyBrightnessControlDelegate(true);
891 GetController()->SetBrightnessControlDelegate(
892 scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
893 EXPECT_EQ(0, delegate->handle_brightness_down_count());
894 EXPECT_TRUE(ProcessWithContext(brightness_down));
895 EXPECT_EQ(1, delegate->handle_brightness_down_count());
896 EXPECT_EQ(brightness_down, delegate->last_accelerator());
897 EXPECT_EQ(0, delegate->handle_brightness_up_count());
898 EXPECT_TRUE(ProcessWithContext(brightness_up));
899 EXPECT_EQ(1, delegate->handle_brightness_up_count());
900 EXPECT_EQ(brightness_up, delegate->last_accelerator());
903 // Keyboard brightness
904 const ui::Accelerator alt_brightness_down(ui::VKEY_BRIGHTNESS_DOWN,
905 ui::EF_ALT_DOWN);
906 const ui::Accelerator alt_brightness_up(ui::VKEY_BRIGHTNESS_UP,
907 ui::EF_ALT_DOWN);
909 EXPECT_TRUE(ProcessWithContext(alt_brightness_down));
910 EXPECT_TRUE(ProcessWithContext(alt_brightness_up));
911 DummyKeyboardBrightnessControlDelegate* delegate =
912 new DummyKeyboardBrightnessControlDelegate(false);
913 GetController()->SetKeyboardBrightnessControlDelegate(
914 scoped_ptr<KeyboardBrightnessControlDelegate>(delegate).Pass());
915 EXPECT_EQ(0, delegate->handle_keyboard_brightness_down_count());
916 EXPECT_FALSE(ProcessWithContext(alt_brightness_down));
917 EXPECT_EQ(1, delegate->handle_keyboard_brightness_down_count());
918 EXPECT_EQ(alt_brightness_down, delegate->last_accelerator());
919 EXPECT_EQ(0, delegate->handle_keyboard_brightness_up_count());
920 EXPECT_FALSE(ProcessWithContext(alt_brightness_up));
921 EXPECT_EQ(1, delegate->handle_keyboard_brightness_up_count());
922 EXPECT_EQ(alt_brightness_up, delegate->last_accelerator());
925 DummyKeyboardBrightnessControlDelegate* delegate =
926 new DummyKeyboardBrightnessControlDelegate(true);
927 GetController()->SetKeyboardBrightnessControlDelegate(
928 scoped_ptr<KeyboardBrightnessControlDelegate>(delegate).Pass());
929 EXPECT_EQ(0, delegate->handle_keyboard_brightness_down_count());
930 EXPECT_TRUE(ProcessWithContext(alt_brightness_down));
931 EXPECT_EQ(1, delegate->handle_keyboard_brightness_down_count());
932 EXPECT_EQ(alt_brightness_down, delegate->last_accelerator());
933 EXPECT_EQ(0, delegate->handle_keyboard_brightness_up_count());
934 EXPECT_TRUE(ProcessWithContext(alt_brightness_up));
935 EXPECT_EQ(1, delegate->handle_keyboard_brightness_up_count());
936 EXPECT_EQ(alt_brightness_up, delegate->last_accelerator());
938 #endif
940 #if !defined(NDEBUG)
941 // ToggleDesktopBackgroundMode
942 EXPECT_TRUE(ProcessWithContext(
943 ui::Accelerator(ui::VKEY_B, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)));
944 #if !defined(OS_LINUX)
945 // ToggleDesktopFullScreen (not implemented yet on Linux)
946 EXPECT_TRUE(ProcessWithContext(
947 ui::Accelerator(ui::VKEY_F11, ui::EF_CONTROL_DOWN)));
948 #endif // OS_LINUX
949 #endif // !NDEBUG
951 #if !defined(OS_WIN)
952 // Exit
953 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
954 ASSERT_TRUE(!!ewh);
955 StubForTest(ewh);
956 EXPECT_TRUE(is_idle(ewh));
957 EXPECT_FALSE(is_ui_shown(ewh));
958 EXPECT_TRUE(ProcessWithContext(
959 ui::Accelerator(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
960 EXPECT_FALSE(is_idle(ewh));
961 EXPECT_TRUE(is_ui_shown(ewh));
962 SimulateTimerExpired(ewh);
963 EXPECT_TRUE(is_idle(ewh));
964 EXPECT_FALSE(is_ui_shown(ewh));
965 Reset(ewh);
966 #endif
968 // New tab
969 EXPECT_TRUE(ProcessWithContext(
970 ui::Accelerator(ui::VKEY_T, ui::EF_CONTROL_DOWN)));
972 // New incognito window
973 EXPECT_TRUE(ProcessWithContext(
974 ui::Accelerator(ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
976 // New window
977 EXPECT_TRUE(ProcessWithContext(
978 ui::Accelerator(ui::VKEY_N, ui::EF_CONTROL_DOWN)));
980 // Restore tab
981 EXPECT_TRUE(ProcessWithContext(
982 ui::Accelerator(ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
984 // Show task manager
985 EXPECT_TRUE(ProcessWithContext(
986 ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN)));
988 #if defined(OS_CHROMEOS)
989 // Open file manager
990 EXPECT_TRUE(ProcessWithContext(
991 ui::Accelerator(ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
993 // Lock screen
994 // NOTE: Accelerators that do not work on the lock screen need to be
995 // tested before the sequence below is invoked because it causes a side
996 // effect of locking the screen.
997 EXPECT_TRUE(ProcessWithContext(
998 ui::Accelerator(ui::VKEY_L, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
999 #endif
1002 TEST_F(AcceleratorControllerTest, GlobalAcceleratorsToggleAppList) {
1003 AccessibilityDelegate* delegate =
1004 ash::Shell::GetInstance()->accessibility_delegate();
1005 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1007 // The press event should not open the AppList, the release should instead.
1008 EXPECT_FALSE(ProcessWithContext(
1009 ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
1010 EXPECT_TRUE(ProcessWithContext(
1011 ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
1012 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1014 // When spoken feedback is on, the AppList should not toggle.
1015 delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
1016 EXPECT_FALSE(ProcessWithContext(
1017 ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
1018 EXPECT_FALSE(ProcessWithContext(
1019 ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
1020 delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
1021 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1023 EXPECT_FALSE(ProcessWithContext(
1024 ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
1025 EXPECT_TRUE(ProcessWithContext(
1026 ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
1027 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1029 // When spoken feedback is on, the AppList should not toggle.
1030 delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
1031 EXPECT_FALSE(ProcessWithContext(
1032 ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
1033 EXPECT_FALSE(ProcessWithContext(
1034 ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
1035 delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
1036 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1039 TEST_F(AcceleratorControllerTest, ImeGlobalAccelerators) {
1040 // Test IME shortcuts.
1042 const ui::Accelerator control_space(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
1043 const ui::Accelerator convert(ui::VKEY_CONVERT, ui::EF_NONE);
1044 const ui::Accelerator non_convert(ui::VKEY_NONCONVERT, ui::EF_NONE);
1045 const ui::Accelerator wide_half_1(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE);
1046 const ui::Accelerator wide_half_2(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE);
1047 const ui::Accelerator hangul(ui::VKEY_HANGUL, ui::EF_NONE);
1048 EXPECT_FALSE(ProcessWithContext(control_space));
1049 EXPECT_FALSE(ProcessWithContext(convert));
1050 EXPECT_FALSE(ProcessWithContext(non_convert));
1051 EXPECT_FALSE(ProcessWithContext(wide_half_1));
1052 EXPECT_FALSE(ProcessWithContext(wide_half_2));
1053 EXPECT_FALSE(ProcessWithContext(hangul));
1054 DummyImeControlDelegate* delegate = new DummyImeControlDelegate(true);
1055 GetController()->SetImeControlDelegate(
1056 scoped_ptr<ImeControlDelegate>(delegate).Pass());
1057 EXPECT_EQ(0, delegate->handle_previous_ime_count());
1058 EXPECT_TRUE(ProcessWithContext(control_space));
1059 EXPECT_EQ(1, delegate->handle_previous_ime_count());
1060 EXPECT_EQ(0, delegate->handle_switch_ime_count());
1061 EXPECT_TRUE(ProcessWithContext(convert));
1062 EXPECT_EQ(1, delegate->handle_switch_ime_count());
1063 EXPECT_TRUE(ProcessWithContext(non_convert));
1064 EXPECT_EQ(2, delegate->handle_switch_ime_count());
1065 EXPECT_TRUE(ProcessWithContext(wide_half_1));
1066 EXPECT_EQ(3, delegate->handle_switch_ime_count());
1067 EXPECT_TRUE(ProcessWithContext(wide_half_2));
1068 EXPECT_EQ(4, delegate->handle_switch_ime_count());
1069 EXPECT_TRUE(ProcessWithContext(hangul));
1070 EXPECT_EQ(5, delegate->handle_switch_ime_count());
1073 // Test IME shortcuts that are triggered on key release.
1075 const ui::Accelerator shift_alt_press(ui::VKEY_MENU,
1076 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1077 const ReleaseAccelerator shift_alt(ui::VKEY_MENU, ui::EF_SHIFT_DOWN);
1078 const ui::Accelerator alt_shift_press(ui::VKEY_SHIFT,
1079 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1080 const ReleaseAccelerator alt_shift(ui::VKEY_SHIFT, ui::EF_ALT_DOWN);
1082 DummyImeControlDelegate* delegate = new DummyImeControlDelegate(true);
1083 GetController()->SetImeControlDelegate(
1084 scoped_ptr<ImeControlDelegate>(delegate).Pass());
1085 EXPECT_EQ(0, delegate->handle_next_ime_count());
1086 EXPECT_FALSE(ProcessWithContext(shift_alt_press));
1087 EXPECT_TRUE(ProcessWithContext(shift_alt));
1088 EXPECT_EQ(1, delegate->handle_next_ime_count());
1089 EXPECT_FALSE(ProcessWithContext(alt_shift_press));
1090 EXPECT_TRUE(ProcessWithContext(alt_shift));
1091 EXPECT_EQ(2, delegate->handle_next_ime_count());
1093 // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is
1094 // released.
1095 const ui::Accelerator shift_alt_x_press(
1096 ui::VKEY_X,
1097 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1098 const ReleaseAccelerator shift_alt_x(ui::VKEY_X,
1099 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1101 EXPECT_FALSE(ProcessWithContext(shift_alt_press));
1102 EXPECT_FALSE(ProcessWithContext(shift_alt_x_press));
1103 EXPECT_FALSE(ProcessWithContext(shift_alt_x));
1104 EXPECT_FALSE(ProcessWithContext(shift_alt));
1105 EXPECT_EQ(2, delegate->handle_next_ime_count());
1107 // But we _should_ if X is either VKEY_RETURN or VKEY_SPACE.
1108 // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
1109 const ui::Accelerator shift_alt_return_press(
1110 ui::VKEY_RETURN,
1111 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1112 const ReleaseAccelerator shift_alt_return(
1113 ui::VKEY_RETURN,
1114 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1116 EXPECT_FALSE(ProcessWithContext(shift_alt_press));
1117 EXPECT_FALSE(ProcessWithContext(shift_alt_return_press));
1118 EXPECT_FALSE(ProcessWithContext(shift_alt_return));
1119 EXPECT_TRUE(ProcessWithContext(shift_alt));
1120 EXPECT_EQ(3, delegate->handle_next_ime_count());
1122 const ui::Accelerator shift_alt_space_press(
1123 ui::VKEY_SPACE,
1124 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1125 const ReleaseAccelerator shift_alt_space(
1126 ui::VKEY_SPACE,
1127 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1129 EXPECT_FALSE(ProcessWithContext(shift_alt_press));
1130 EXPECT_FALSE(ProcessWithContext(shift_alt_space_press));
1131 EXPECT_FALSE(ProcessWithContext(shift_alt_space));
1132 EXPECT_TRUE(ProcessWithContext(shift_alt));
1133 EXPECT_EQ(4, delegate->handle_next_ime_count());
1136 #if defined(OS_CHROMEOS)
1137 // Test IME shortcuts again with unnormalized accelerators (Chrome OS only).
1139 const ui::Accelerator shift_alt_press(ui::VKEY_MENU, ui::EF_SHIFT_DOWN);
1140 const ReleaseAccelerator shift_alt(ui::VKEY_MENU, ui::EF_SHIFT_DOWN);
1141 const ui::Accelerator alt_shift_press(ui::VKEY_SHIFT, ui::EF_ALT_DOWN);
1142 const ReleaseAccelerator alt_shift(ui::VKEY_SHIFT, ui::EF_ALT_DOWN);
1144 DummyImeControlDelegate* delegate = new DummyImeControlDelegate(true);
1145 GetController()->SetImeControlDelegate(
1146 scoped_ptr<ImeControlDelegate>(delegate).Pass());
1147 EXPECT_EQ(0, delegate->handle_next_ime_count());
1148 EXPECT_FALSE(ProcessWithContext(shift_alt_press));
1149 EXPECT_TRUE(ProcessWithContext(shift_alt));
1150 EXPECT_EQ(1, delegate->handle_next_ime_count());
1151 EXPECT_FALSE(ProcessWithContext(alt_shift_press));
1152 EXPECT_TRUE(ProcessWithContext(alt_shift));
1153 EXPECT_EQ(2, delegate->handle_next_ime_count());
1155 // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is
1156 // released.
1157 const ui::Accelerator shift_alt_x_press(
1158 ui::VKEY_X,
1159 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1160 const ReleaseAccelerator shift_alt_x(ui::VKEY_X,
1161 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1163 EXPECT_FALSE(ProcessWithContext(shift_alt_press));
1164 EXPECT_FALSE(ProcessWithContext(shift_alt_x_press));
1165 EXPECT_FALSE(ProcessWithContext(shift_alt_x));
1166 EXPECT_FALSE(ProcessWithContext(shift_alt));
1167 EXPECT_EQ(2, delegate->handle_next_ime_count());
1169 #endif
1172 // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
1173 TEST_F(AcceleratorControllerTest, ImeGlobalAcceleratorsWorkaround139556) {
1174 // The workaround for crbug.com/139556 depends on the fact that we don't
1175 // use Shift+Alt+Enter/Space with ET_KEY_PRESSED as an accelerator. Test it.
1176 const ui::Accelerator shift_alt_return_press(
1177 ui::VKEY_RETURN,
1178 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1179 EXPECT_FALSE(ProcessWithContext(shift_alt_return_press));
1180 const ui::Accelerator shift_alt_space_press(
1181 ui::VKEY_SPACE,
1182 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1183 EXPECT_FALSE(ProcessWithContext(shift_alt_space_press));
1186 TEST_F(AcceleratorControllerTest, ReservedAccelerators) {
1187 // (Shift+)Alt+Tab and Chrome OS top-row keys are reserved.
1188 EXPECT_TRUE(GetController()->IsReservedAccelerator(
1189 ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN)));
1190 EXPECT_TRUE(GetController()->IsReservedAccelerator(
1191 ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
1192 #if defined(OS_CHROMEOS)
1193 EXPECT_TRUE(GetController()->IsReservedAccelerator(
1194 ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE)));
1195 #endif
1196 // Others are not reserved.
1197 EXPECT_FALSE(GetController()->IsReservedAccelerator(
1198 ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
1199 EXPECT_FALSE(GetController()->IsReservedAccelerator(
1200 ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE)));
1201 EXPECT_FALSE(GetController()->IsReservedAccelerator(
1202 ui::Accelerator(ui::VKEY_A, ui::EF_NONE)));
1205 #if defined(OS_CHROMEOS)
1206 TEST_F(AcceleratorControllerTest, DisallowedAtModalWindow) {
1207 std::set<AcceleratorAction> all_actions;
1208 for (size_t i = 0 ; i < kAcceleratorDataLength; ++i)
1209 all_actions.insert(kAcceleratorData[i].action);
1210 #if !defined(NDEBUG)
1211 std::set<AcceleratorAction> all_desktop_actions;
1212 for (size_t i = 0 ; i < kDesktopAcceleratorDataLength; ++i)
1213 all_desktop_actions.insert(kDesktopAcceleratorData[i].action);
1214 #endif
1216 std::set<AcceleratorAction> actionsAllowedAtModalWindow;
1217 for (size_t k = 0 ; k < kActionsAllowedAtModalWindowLength; ++k)
1218 actionsAllowedAtModalWindow.insert(kActionsAllowedAtModalWindow[k]);
1219 for (std::set<AcceleratorAction>::const_iterator it =
1220 actionsAllowedAtModalWindow.begin();
1221 it != actionsAllowedAtModalWindow.end(); ++it) {
1222 EXPECT_TRUE(all_actions.find(*it) != all_actions.end()
1224 #if !defined(NDEBUG)
1225 || all_desktop_actions.find(*it) != all_desktop_actions.end()
1226 #endif
1228 << " action from kActionsAllowedAtModalWindow"
1229 << " not found in kAcceleratorData or kDesktopAcceleratorData. "
1230 << "action: " << *it;
1232 scoped_ptr<aura::Window> window(
1233 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1234 const ui::Accelerator dummy;
1235 wm::ActivateWindow(window.get());
1236 Shell::GetInstance()->SimulateModalWindowOpenForTesting(true);
1237 for (std::set<AcceleratorAction>::const_iterator it = all_actions.begin();
1238 it != all_actions.end(); ++it) {
1239 if (actionsAllowedAtModalWindow.find(*it) ==
1240 actionsAllowedAtModalWindow.end()) {
1241 EXPECT_TRUE(GetController()->PerformAction(*it, dummy))
1242 << " for action (disallowed at modal window): " << *it;
1245 // Testing of top row (F5-F10) accelerators that should still work
1246 // when a modal window is open
1248 // Screenshot
1250 test::TestScreenshotDelegate* delegate = GetScreenshotDelegate();
1251 delegate->set_can_take_screenshot(false);
1252 EXPECT_TRUE(ProcessWithContext(
1253 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
1254 EXPECT_TRUE(ProcessWithContext(
1255 ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
1256 EXPECT_TRUE(ProcessWithContext(
1257 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1,
1258 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
1259 delegate->set_can_take_screenshot(true);
1260 EXPECT_EQ(0, delegate->handle_take_screenshot_count());
1261 EXPECT_TRUE(ProcessWithContext(
1262 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
1263 EXPECT_EQ(1, delegate->handle_take_screenshot_count());
1264 EXPECT_TRUE(ProcessWithContext(
1265 ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
1266 EXPECT_EQ(2, delegate->handle_take_screenshot_count());
1267 EXPECT_TRUE(ProcessWithContext(
1268 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1,
1269 ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
1270 EXPECT_EQ(2, delegate->handle_take_screenshot_count());
1272 // Brightness
1273 const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
1274 const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE);
1276 EXPECT_FALSE(ProcessWithContext(brightness_down));
1277 EXPECT_FALSE(ProcessWithContext(brightness_up));
1278 DummyBrightnessControlDelegate* delegate =
1279 new DummyBrightnessControlDelegate(true);
1280 GetController()->SetBrightnessControlDelegate(
1281 scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
1282 EXPECT_FALSE(ProcessWithContext(brightness_down));
1283 EXPECT_FALSE(ProcessWithContext(brightness_up));
1285 EnableInternalDisplay();
1287 EXPECT_FALSE(ProcessWithContext(brightness_down));
1288 EXPECT_FALSE(ProcessWithContext(brightness_up));
1289 DummyBrightnessControlDelegate* delegate =
1290 new DummyBrightnessControlDelegate(false);
1291 GetController()->SetBrightnessControlDelegate(
1292 scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
1293 EXPECT_EQ(0, delegate->handle_brightness_down_count());
1294 EXPECT_FALSE(ProcessWithContext(brightness_down));
1295 EXPECT_EQ(1, delegate->handle_brightness_down_count());
1296 EXPECT_EQ(brightness_down, delegate->last_accelerator());
1297 EXPECT_EQ(0, delegate->handle_brightness_up_count());
1298 EXPECT_FALSE(ProcessWithContext(brightness_up));
1299 EXPECT_EQ(1, delegate->handle_brightness_up_count());
1300 EXPECT_EQ(brightness_up, delegate->last_accelerator());
1303 DummyBrightnessControlDelegate* delegate =
1304 new DummyBrightnessControlDelegate(true);
1305 GetController()->SetBrightnessControlDelegate(
1306 scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
1307 EXPECT_EQ(0, delegate->handle_brightness_down_count());
1308 EXPECT_TRUE(ProcessWithContext(brightness_down));
1309 EXPECT_EQ(1, delegate->handle_brightness_down_count());
1310 EXPECT_EQ(brightness_down, delegate->last_accelerator());
1311 EXPECT_EQ(0, delegate->handle_brightness_up_count());
1312 EXPECT_TRUE(ProcessWithContext(brightness_up));
1313 EXPECT_EQ(1, delegate->handle_brightness_up_count());
1314 EXPECT_EQ(brightness_up, delegate->last_accelerator());
1316 // Volume
1317 const ui::Accelerator volume_mute(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
1318 const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
1319 const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE);
1321 EXPECT_TRUE(ProcessWithContext(volume_mute));
1322 EXPECT_TRUE(ProcessWithContext(volume_down));
1323 EXPECT_TRUE(ProcessWithContext(volume_up));
1324 DummyVolumeControlDelegate* delegate =
1325 new DummyVolumeControlDelegate(false);
1326 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
1327 scoped_ptr<VolumeControlDelegate>(delegate).Pass());
1328 EXPECT_EQ(0, delegate->handle_volume_mute_count());
1329 EXPECT_FALSE(ProcessWithContext(volume_mute));
1330 EXPECT_EQ(1, delegate->handle_volume_mute_count());
1331 EXPECT_EQ(volume_mute, delegate->last_accelerator());
1332 EXPECT_EQ(0, delegate->handle_volume_down_count());
1333 EXPECT_FALSE(ProcessWithContext(volume_down));
1334 EXPECT_EQ(1, delegate->handle_volume_down_count());
1335 EXPECT_EQ(volume_down, delegate->last_accelerator());
1336 EXPECT_EQ(0, delegate->handle_volume_up_count());
1337 EXPECT_FALSE(ProcessWithContext(volume_up));
1338 EXPECT_EQ(1, delegate->handle_volume_up_count());
1339 EXPECT_EQ(volume_up, delegate->last_accelerator());
1342 DummyVolumeControlDelegate* delegate = new DummyVolumeControlDelegate(true);
1343 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
1344 scoped_ptr<VolumeControlDelegate>(delegate).Pass());
1345 EXPECT_EQ(0, delegate->handle_volume_mute_count());
1346 EXPECT_TRUE(ProcessWithContext(volume_mute));
1347 EXPECT_EQ(1, delegate->handle_volume_mute_count());
1348 EXPECT_EQ(volume_mute, delegate->last_accelerator());
1349 EXPECT_EQ(0, delegate->handle_volume_down_count());
1350 EXPECT_TRUE(ProcessWithContext(volume_down));
1351 EXPECT_EQ(1, delegate->handle_volume_down_count());
1352 EXPECT_EQ(volume_down, delegate->last_accelerator());
1353 EXPECT_EQ(0, delegate->handle_volume_up_count());
1354 EXPECT_TRUE(ProcessWithContext(volume_up));
1355 EXPECT_EQ(1, delegate->handle_volume_up_count());
1356 EXPECT_EQ(volume_up, delegate->last_accelerator());
1359 #endif
1361 TEST_F(AcceleratorControllerTest, DisallowedWithNoWindow) {
1362 const ui::Accelerator dummy;
1363 AccessibilityDelegate* delegate =
1364 ash::Shell::GetInstance()->accessibility_delegate();
1366 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
1367 delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE);
1368 EXPECT_TRUE(
1369 GetController()->PerformAction(kActionsNeedingWindow[i], dummy));
1370 EXPECT_EQ(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_WINDOW_NEEDED);
1373 // Make sure we don't alert if we do have a window.
1374 scoped_ptr<aura::Window> window(
1375 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1376 wm::ActivateWindow(window.get());
1377 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
1378 delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE);
1379 GetController()->PerformAction(kActionsNeedingWindow[i], dummy);
1380 EXPECT_EQ(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_NONE);
1383 // Don't alert if we have a minimized window either.
1384 GetController()->PerformAction(WINDOW_MINIMIZE, dummy);
1385 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
1386 delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE);
1387 GetController()->PerformAction(kActionsNeedingWindow[i], dummy);
1388 EXPECT_EQ(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_NONE);
1392 } // namespace ash