Add ICU message format support
[chromium-blink-merge.git] / ash / accelerators / accelerator_controller_unittest.cc
blob100e5ef0e51aa3d93f8b025c28723ce931ca4425
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"
7 #include "ash/accelerators/accelerator_table.h"
8 #include "ash/accessibility_delegate.h"
9 #include "ash/ash_switches.h"
10 #include "ash/display/display_manager.h"
11 #include "ash/ime_control_delegate.h"
12 #include "ash/screen_util.h"
13 #include "ash/shell.h"
14 #include "ash/shell_window_ids.h"
15 #include "ash/system/brightness_control_delegate.h"
16 #include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h"
17 #include "ash/system/tray/system_tray_delegate.h"
18 #include "ash/test/ash_test_base.h"
19 #include "ash/test/display_manager_test_api.h"
20 #include "ash/test/test_screenshot_delegate.h"
21 #include "ash/test/test_session_state_animator.h"
22 #include "ash/test/test_shelf_delegate.h"
23 #include "ash/test/test_shell_delegate.h"
24 #include "ash/test/test_volume_control_delegate.h"
25 #include "ash/volume_control_delegate.h"
26 #include "ash/wm/lock_state_controller.h"
27 #include "ash/wm/panels/panel_layout_manager.h"
28 #include "ash/wm/window_state.h"
29 #include "ash/wm/window_util.h"
30 #include "ash/wm/wm_event.h"
31 #include "base/command_line.h"
32 #include "ui/aura/client/aura_constants.h"
33 #include "ui/aura/test/test_window_delegate.h"
34 #include "ui/aura/test/test_windows.h"
35 #include "ui/aura/window.h"
36 #include "ui/events/event.h"
37 #include "ui/events/event_processor.h"
38 #include "ui/events/test/event_generator.h"
39 #include "ui/gfx/screen.h"
40 #include "ui/views/widget/widget.h"
42 #if defined(USE_X11)
43 #include <X11/Xlib.h>
44 #include "ui/events/test/events_test_utils_x11.h"
45 #endif
47 namespace ash {
49 namespace {
51 class TestTarget : public ui::AcceleratorTarget {
52 public:
53 TestTarget() : accelerator_pressed_count_(0), accelerator_repeat_count_(0) {}
54 ~TestTarget() override {}
56 int accelerator_pressed_count() const {
57 return accelerator_pressed_count_;
60 int accelerator_repeat_count() const { return accelerator_repeat_count_; }
62 void reset() {
63 accelerator_pressed_count_ = 0;
64 accelerator_repeat_count_ = 0;
67 // Overridden from ui::AcceleratorTarget:
68 bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
69 bool CanHandleAccelerators() const override;
71 private:
72 int accelerator_pressed_count_;
73 int accelerator_repeat_count_;
75 DISALLOW_COPY_AND_ASSIGN(TestTarget);
78 class ReleaseAccelerator : public ui::Accelerator {
79 public:
80 ReleaseAccelerator(ui::KeyboardCode keycode, int modifiers)
81 : ui::Accelerator(keycode, modifiers) {
82 set_type(ui::ET_KEY_RELEASED);
86 class DummyBrightnessControlDelegate : public BrightnessControlDelegate {
87 public:
88 DummyBrightnessControlDelegate()
89 : handle_brightness_down_count_(0), handle_brightness_up_count_(0) {}
90 ~DummyBrightnessControlDelegate() override {}
92 void HandleBrightnessDown(const ui::Accelerator& accelerator) override {
93 ++handle_brightness_down_count_;
94 last_accelerator_ = accelerator;
96 void HandleBrightnessUp(const ui::Accelerator& accelerator) override {
97 ++handle_brightness_up_count_;
98 last_accelerator_ = accelerator;
100 void SetBrightnessPercent(double percent, bool gradual) override {}
101 void GetBrightnessPercent(
102 const base::Callback<void(double)>& callback) override {
103 callback.Run(100.0);
106 int handle_brightness_down_count() const {
107 return handle_brightness_down_count_;
109 int handle_brightness_up_count() const {
110 return handle_brightness_up_count_;
112 const ui::Accelerator& last_accelerator() const {
113 return last_accelerator_;
116 private:
117 int handle_brightness_down_count_;
118 int handle_brightness_up_count_;
119 ui::Accelerator last_accelerator_;
121 DISALLOW_COPY_AND_ASSIGN(DummyBrightnessControlDelegate);
124 class DummyImeControlDelegate : public ImeControlDelegate {
125 public:
126 DummyImeControlDelegate()
127 : handle_next_ime_count_(0),
128 handle_previous_ime_count_(0),
129 handle_switch_ime_count_(0) {}
130 ~DummyImeControlDelegate() override {}
132 bool CanCycleIme() override { return true; }
133 void HandleNextIme() override { ++handle_next_ime_count_; }
134 void HandlePreviousIme() override {
135 ++handle_previous_ime_count_;
137 bool CanSwitchIme(const ui::Accelerator& accelerator) override {
138 return true;
140 void HandleSwitchIme(const ui::Accelerator& accelerator) override {
141 ++handle_switch_ime_count_;
144 int handle_next_ime_count() const {
145 return handle_next_ime_count_;
147 int handle_previous_ime_count() const {
148 return handle_previous_ime_count_;
150 int handle_switch_ime_count() const {
151 return handle_switch_ime_count_;
153 ui::Accelerator RemapAccelerator(
154 const ui::Accelerator& accelerator) override {
155 return ui::Accelerator(accelerator);
158 private:
159 int handle_next_ime_count_;
160 int handle_previous_ime_count_;
161 int handle_switch_ime_count_;
163 DISALLOW_COPY_AND_ASSIGN(DummyImeControlDelegate);
166 class DummyKeyboardBrightnessControlDelegate
167 : public KeyboardBrightnessControlDelegate {
168 public:
169 DummyKeyboardBrightnessControlDelegate()
170 : handle_keyboard_brightness_down_count_(0),
171 handle_keyboard_brightness_up_count_(0) {}
172 ~DummyKeyboardBrightnessControlDelegate() override {}
174 void HandleKeyboardBrightnessDown(
175 const ui::Accelerator& accelerator) override {
176 ++handle_keyboard_brightness_down_count_;
177 last_accelerator_ = accelerator;
180 void HandleKeyboardBrightnessUp(const ui::Accelerator& accelerator) override {
181 ++handle_keyboard_brightness_up_count_;
182 last_accelerator_ = accelerator;
185 int handle_keyboard_brightness_down_count() const {
186 return handle_keyboard_brightness_down_count_;
189 int handle_keyboard_brightness_up_count() const {
190 return handle_keyboard_brightness_up_count_;
193 const ui::Accelerator& last_accelerator() const {
194 return last_accelerator_;
197 private:
198 int handle_keyboard_brightness_down_count_;
199 int handle_keyboard_brightness_up_count_;
200 ui::Accelerator last_accelerator_;
202 DISALLOW_COPY_AND_ASSIGN(DummyKeyboardBrightnessControlDelegate);
205 bool TestTarget::AcceleratorPressed(const ui::Accelerator& accelerator) {
206 if (accelerator.IsRepeat())
207 ++accelerator_repeat_count_;
208 else
209 ++accelerator_pressed_count_;
210 return true;
213 bool TestTarget::CanHandleAccelerators() const {
214 return true;
217 } // namespace
219 class AcceleratorControllerTest : public test::AshTestBase {
220 public:
221 AcceleratorControllerTest() {}
222 ~AcceleratorControllerTest() override {}
224 protected:
225 void EnableInternalDisplay() {
226 test::DisplayManagerTestApi().SetFirstDisplayAsInternalDisplay();
229 static AcceleratorController* GetController();
231 static bool ProcessInController(const ui::Accelerator& accelerator) {
232 GetController()->accelerator_history()->
233 StoreCurrentAccelerator(accelerator);
234 return GetController()->Process(accelerator);
237 static const ui::Accelerator& GetPreviousAccelerator() {
238 return GetController()->accelerator_history()->
239 previous_accelerator();
242 static const ui::Accelerator& GetCurrentAccelerator() {
243 return GetController()->accelerator_history()->
244 current_accelerator();
247 // Several functions to access ExitWarningHandler (as friend).
248 static void StubForTest(ExitWarningHandler* ewh) {
249 ewh->stub_timer_for_test_ = true;
251 static void Reset(ExitWarningHandler* ewh) {
252 ewh->state_ = ExitWarningHandler::IDLE;
254 static void SimulateTimerExpired(ExitWarningHandler* ewh) {
255 ewh->TimerAction();
257 static bool is_ui_shown(ExitWarningHandler* ewh) {
258 return !!ewh->widget_;
260 static bool is_idle(ExitWarningHandler* ewh) {
261 return ewh->state_ == ExitWarningHandler::IDLE;
263 static bool is_exiting(ExitWarningHandler* ewh) {
264 return ewh->state_ == ExitWarningHandler::EXITING;
266 aura::Window* CreatePanel() {
267 aura::Window* window =
268 CreateTestWindowInShellWithDelegateAndType(NULL,
269 ui::wm::WINDOW_TYPE_PANEL, 0, gfx::Rect(5, 5, 20, 20));
270 test::TestShelfDelegate* shelf_delegate =
271 test::TestShelfDelegate::instance();
272 shelf_delegate->AddShelfItem(window);
273 PanelLayoutManager* manager = static_cast<PanelLayoutManager*>(
274 Shell::GetContainer(window->GetRootWindow(),
275 kShellWindowId_PanelContainer)->layout_manager());
276 manager->Relayout();
277 return window;
280 private:
281 DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest);
284 AcceleratorController* AcceleratorControllerTest::GetController() {
285 return Shell::GetInstance()->accelerator_controller();
288 #if !defined(OS_WIN)
289 // Double press of exit shortcut => exiting
290 TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestDoublePress) {
291 ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
292 ui::Accelerator release(press);
293 release.set_type(ui::ET_KEY_RELEASED);
294 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
295 ASSERT_TRUE(ewh);
296 StubForTest(ewh);
297 EXPECT_TRUE(is_idle(ewh));
298 EXPECT_FALSE(is_ui_shown(ewh));
299 EXPECT_TRUE(ProcessInController(press));
300 EXPECT_FALSE(ProcessInController(release));
301 EXPECT_FALSE(is_idle(ewh));
302 EXPECT_TRUE(is_ui_shown(ewh));
303 EXPECT_TRUE(ProcessInController(press)); // second press before timer.
304 EXPECT_FALSE(ProcessInController(release));
305 SimulateTimerExpired(ewh);
306 EXPECT_TRUE(is_exiting(ewh));
307 EXPECT_FALSE(is_ui_shown(ewh));
308 Reset(ewh);
311 // Single press of exit shortcut before timer => idle
312 TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestSinglePress) {
313 ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
314 ui::Accelerator release(press);
315 release.set_type(ui::ET_KEY_RELEASED);
316 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
317 ASSERT_TRUE(ewh);
318 StubForTest(ewh);
319 EXPECT_TRUE(is_idle(ewh));
320 EXPECT_FALSE(is_ui_shown(ewh));
321 EXPECT_TRUE(ProcessInController(press));
322 EXPECT_FALSE(ProcessInController(release));
323 EXPECT_FALSE(is_idle(ewh));
324 EXPECT_TRUE(is_ui_shown(ewh));
325 SimulateTimerExpired(ewh);
326 EXPECT_TRUE(is_idle(ewh));
327 EXPECT_FALSE(is_ui_shown(ewh));
328 Reset(ewh);
331 // Shutdown ash with exit warning bubble open should not crash.
332 TEST_F(AcceleratorControllerTest, LingeringExitWarningBubble) {
333 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
334 ASSERT_TRUE(ewh);
335 StubForTest(ewh);
337 // Trigger once to show the bubble.
338 ewh->HandleAccelerator();
339 EXPECT_FALSE(is_idle(ewh));
340 EXPECT_TRUE(is_ui_shown(ewh));
342 // Exit ash and there should be no crash
344 #endif // !defined(OS_WIN)
346 TEST_F(AcceleratorControllerTest, Register) {
347 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
348 TestTarget target;
349 GetController()->Register(accelerator_a, &target);
351 // The registered accelerator is processed.
352 EXPECT_TRUE(ProcessInController(accelerator_a));
353 EXPECT_EQ(1, target.accelerator_pressed_count());
356 TEST_F(AcceleratorControllerTest, RegisterMultipleTarget) {
357 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
358 TestTarget target1;
359 GetController()->Register(accelerator_a, &target1);
360 TestTarget target2;
361 GetController()->Register(accelerator_a, &target2);
363 // If multiple targets are registered with the same accelerator, the target
364 // registered later processes the accelerator.
365 EXPECT_TRUE(ProcessInController(accelerator_a));
366 EXPECT_EQ(0, target1.accelerator_pressed_count());
367 EXPECT_EQ(1, target2.accelerator_pressed_count());
370 TEST_F(AcceleratorControllerTest, Unregister) {
371 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
372 TestTarget target;
373 GetController()->Register(accelerator_a, &target);
374 const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
375 GetController()->Register(accelerator_b, &target);
377 // Unregistering a different accelerator does not affect the other
378 // accelerator.
379 GetController()->Unregister(accelerator_b, &target);
380 EXPECT_TRUE(ProcessInController(accelerator_a));
381 EXPECT_EQ(1, target.accelerator_pressed_count());
383 // The unregistered accelerator is no longer processed.
384 target.reset();
385 GetController()->Unregister(accelerator_a, &target);
386 EXPECT_FALSE(ProcessInController(accelerator_a));
387 EXPECT_EQ(0, target.accelerator_pressed_count());
390 TEST_F(AcceleratorControllerTest, UnregisterAll) {
391 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
392 TestTarget target1;
393 GetController()->Register(accelerator_a, &target1);
394 const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
395 GetController()->Register(accelerator_b, &target1);
396 const ui::Accelerator accelerator_c(ui::VKEY_C, ui::EF_NONE);
397 TestTarget target2;
398 GetController()->Register(accelerator_c, &target2);
399 GetController()->UnregisterAll(&target1);
401 // All the accelerators registered for |target1| are no longer processed.
402 EXPECT_FALSE(ProcessInController(accelerator_a));
403 EXPECT_FALSE(ProcessInController(accelerator_b));
404 EXPECT_EQ(0, target1.accelerator_pressed_count());
406 // UnregisterAll with a different target does not affect the other target.
407 EXPECT_TRUE(ProcessInController(accelerator_c));
408 EXPECT_EQ(1, target2.accelerator_pressed_count());
411 TEST_F(AcceleratorControllerTest, Process) {
412 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
413 TestTarget target1;
414 GetController()->Register(accelerator_a, &target1);
416 // The registered accelerator is processed.
417 EXPECT_TRUE(ProcessInController(accelerator_a));
418 EXPECT_EQ(1, target1.accelerator_pressed_count());
420 // The non-registered accelerator is not processed.
421 const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
422 EXPECT_FALSE(ProcessInController(accelerator_b));
425 TEST_F(AcceleratorControllerTest, IsRegistered) {
426 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
427 const ui::Accelerator accelerator_shift_a(ui::VKEY_A, ui::EF_SHIFT_DOWN);
428 TestTarget target;
429 GetController()->Register(accelerator_a, &target);
430 EXPECT_TRUE(GetController()->IsRegistered(accelerator_a));
431 EXPECT_FALSE(GetController()->IsRegistered(accelerator_shift_a));
432 GetController()->UnregisterAll(&target);
433 EXPECT_FALSE(GetController()->IsRegistered(accelerator_a));
436 TEST_F(AcceleratorControllerTest, WindowSnap) {
437 scoped_ptr<aura::Window> window(
438 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
439 wm::WindowState* window_state = wm::GetWindowState(window.get());
441 window_state->Activate();
444 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
445 gfx::Rect expected_bounds = wm::GetDefaultLeftSnappedWindowBoundsInParent(
446 window.get());
447 EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString());
450 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT);
451 gfx::Rect expected_bounds = wm::GetDefaultRightSnappedWindowBoundsInParent(
452 window.get());
453 EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString());
456 gfx::Rect normal_bounds = window_state->GetRestoreBoundsInParent();
458 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED);
459 EXPECT_TRUE(window_state->IsMaximized());
460 EXPECT_NE(normal_bounds.ToString(), window->bounds().ToString());
462 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED);
463 EXPECT_FALSE(window_state->IsMaximized());
464 // Window gets restored to its restore bounds since side-maximized state
465 // is treated as a "maximized" state.
466 EXPECT_EQ(normal_bounds.ToString(), window->bounds().ToString());
468 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED);
469 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
470 EXPECT_FALSE(window_state->IsMaximized());
472 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED);
473 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT);
474 EXPECT_FALSE(window_state->IsMaximized());
476 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED);
477 EXPECT_TRUE(window_state->IsMaximized());
478 GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE);
479 EXPECT_FALSE(window_state->IsMaximized());
480 EXPECT_TRUE(window_state->IsMinimized());
481 window_state->Restore();
482 window_state->Activate();
485 GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE);
486 EXPECT_TRUE(window_state->IsMinimized());
490 TEST_F(AcceleratorControllerTest, WindowSnapLeftDockLeftRestore) {
491 scoped_ptr<aura::Window> window0(
492 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
493 scoped_ptr<aura::Window> window1(
494 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
495 wm::WindowState* window1_state = wm::GetWindowState(window1.get());
496 window1_state->Activate();
498 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
499 gfx::Rect normal_bounds = window1_state->GetRestoreBoundsInParent();
500 gfx::Rect expected_bounds = wm::GetDefaultLeftSnappedWindowBoundsInParent(
501 window1.get());
502 EXPECT_EQ(expected_bounds.ToString(), window1->bounds().ToString());
503 EXPECT_TRUE(window1_state->IsSnapped());
504 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
505 EXPECT_FALSE(window1_state->IsNormalOrSnapped());
506 EXPECT_TRUE(window1_state->IsDocked());
507 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
508 EXPECT_FALSE(window1_state->IsDocked());
509 EXPECT_EQ(normal_bounds.ToString(), window1->bounds().ToString());
512 TEST_F(AcceleratorControllerTest, WindowSnapRightDockRightRestore) {
513 scoped_ptr<aura::Window> window0(
514 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
515 scoped_ptr<aura::Window> window1(
516 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
518 wm::WindowState* window1_state = wm::GetWindowState(window1.get());
519 window1_state->Activate();
521 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT);
522 gfx::Rect normal_bounds = window1_state->GetRestoreBoundsInParent();
523 gfx::Rect expected_bounds =
524 wm::GetDefaultRightSnappedWindowBoundsInParent(window1.get());
525 EXPECT_EQ(expected_bounds.ToString(), window1->bounds().ToString());
526 EXPECT_TRUE(window1_state->IsSnapped());
527 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT);
528 EXPECT_FALSE(window1_state->IsNormalOrSnapped());
529 EXPECT_TRUE(window1_state->IsDocked());
530 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT);
531 EXPECT_FALSE(window1_state->IsDocked());
532 EXPECT_EQ(normal_bounds.ToString(), window1->bounds().ToString());
535 TEST_F(AcceleratorControllerTest, WindowSnapLeftDockLeftSnapRight) {
536 scoped_ptr<aura::Window> window0(
537 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
538 scoped_ptr<aura::Window> window1(
539 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
541 wm::WindowState* window1_state = wm::GetWindowState(window1.get());
542 window1_state->Activate();
544 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
545 gfx::Rect expected_bounds =
546 wm::GetDefaultLeftSnappedWindowBoundsInParent(window1.get());
547 gfx::Rect expected_bounds2 =
548 wm::GetDefaultRightSnappedWindowBoundsInParent(window1.get());
549 EXPECT_EQ(expected_bounds.ToString(), window1->bounds().ToString());
550 EXPECT_TRUE(window1_state->IsSnapped());
551 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
552 EXPECT_FALSE(window1_state->IsNormalOrSnapped());
553 EXPECT_TRUE(window1_state->IsDocked());
554 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT);
555 EXPECT_FALSE(window1_state->IsDocked());
556 EXPECT_TRUE(window1_state->IsSnapped());
557 EXPECT_EQ(expected_bounds2.ToString(), window1->bounds().ToString());
560 TEST_F(AcceleratorControllerTest, WindowDockLeftMinimizeWindowWithRestore) {
561 scoped_ptr<aura::Window> window0(
562 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
563 scoped_ptr<aura::Window> window1(
564 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
566 wm::WindowState* window1_state = wm::GetWindowState(window1.get());
567 window1_state->Activate();
569 scoped_ptr<aura::Window> window2(
570 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
572 wm::WindowState* window2_state = wm::GetWindowState(window2.get());
574 scoped_ptr<aura::Window> window3(
575 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
577 wm::WindowState* window3_state = wm::GetWindowState(window3.get());
578 window3_state->Activate();
580 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
581 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
582 gfx::Rect window3_docked_bounds = window3->bounds();
584 window2_state->Activate();
585 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
586 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
587 window1_state->Activate();
588 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
589 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
591 EXPECT_TRUE(window3_state->IsDocked());
592 EXPECT_TRUE(window2_state->IsDocked());
593 EXPECT_TRUE(window1_state->IsDocked());
594 EXPECT_TRUE(window3_state->IsMinimized());
596 window1_state->Activate();
597 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
598 window2_state->Activate();
599 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
600 window3_state->Unminimize();
601 EXPECT_FALSE(window1_state->IsDocked());
602 EXPECT_FALSE(window2_state->IsDocked());
603 EXPECT_TRUE(window3_state->IsDocked());
604 EXPECT_EQ(window3_docked_bounds.ToString(), window3->bounds().ToString());
607 TEST_F(AcceleratorControllerTest, WindowPanelDockLeftDockRightRestore) {
608 scoped_ptr<aura::Window> window0(
609 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
611 scoped_ptr<aura::Window> window(CreatePanel());
612 wm::WindowState* window_state = wm::GetWindowState(window.get());
613 window_state->Activate();
615 gfx::Rect window_restore_bounds2 = window->bounds();
616 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT);
617 gfx::Rect expected_bounds =
618 wm::GetDefaultLeftSnappedWindowBoundsInParent(window.get());
619 gfx::Rect window_restore_bounds =
620 window_state->GetRestoreBoundsInScreen();
621 EXPECT_NE(expected_bounds.ToString(), window->bounds().ToString());
622 EXPECT_FALSE(window_state->IsSnapped());
623 EXPECT_FALSE(window_state->IsNormalOrSnapped());
624 EXPECT_TRUE(window_state->IsDocked());
625 window_state->Restore();
626 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT);
627 EXPECT_TRUE(window_state->IsDocked());
628 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT);
629 EXPECT_FALSE(window_state->IsDocked());
630 EXPECT_EQ(window_restore_bounds.ToString(),
631 window_restore_bounds2.ToString());
632 EXPECT_EQ(window_restore_bounds.ToString(), window->bounds().ToString());
635 TEST_F(AcceleratorControllerTest, CenterWindowAccelerator) {
636 scoped_ptr<aura::Window> window(
637 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
638 wm::WindowState* window_state = wm::GetWindowState(window.get());
639 window_state->Activate();
641 // Center the window using accelerator.
642 GetController()->PerformActionIfEnabled(WINDOW_POSITION_CENTER);
643 gfx::Rect work_area =
644 Shell::GetScreen()->GetDisplayNearestWindow(window.get()).work_area();
645 gfx::Rect bounds = window->GetBoundsInScreen();
646 EXPECT_NEAR(bounds.x() - work_area.x(),
647 work_area.right() - bounds.right(),
649 EXPECT_NEAR(bounds.y() - work_area.y(),
650 work_area.bottom() - bounds.bottom(),
653 // Add the window to docked container and try to center it.
654 window->SetBounds(gfx::Rect(0, 0, 20, 20));
655 const wm::WMEvent event(wm::WM_EVENT_DOCK);
656 wm::GetWindowState(window.get())->OnWMEvent(&event);
657 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
659 gfx::Rect docked_bounds = window->GetBoundsInScreen();
660 GetController()->PerformActionIfEnabled(WINDOW_POSITION_CENTER);
661 // It should not get centered and should remain docked.
662 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
663 EXPECT_EQ(docked_bounds.ToString(), window->GetBoundsInScreen().ToString());
666 TEST_F(AcceleratorControllerTest, AutoRepeat) {
667 ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_CONTROL_DOWN);
668 accelerator_a.set_type(ui::ET_KEY_PRESSED);
669 TestTarget target_a;
670 GetController()->Register(accelerator_a, &target_a);
671 ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_CONTROL_DOWN);
672 accelerator_b.set_type(ui::ET_KEY_PRESSED);
673 TestTarget target_b;
674 GetController()->Register(accelerator_b, &target_b);
676 ui::test::EventGenerator& generator = GetEventGenerator();
677 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
678 generator.ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
680 EXPECT_EQ(1, target_a.accelerator_pressed_count());
681 EXPECT_EQ(0, target_a.accelerator_repeat_count());
683 // Long press should generate one
684 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
685 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
686 EXPECT_EQ(2, target_a.accelerator_pressed_count());
687 EXPECT_EQ(1, target_a.accelerator_repeat_count());
688 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
689 EXPECT_EQ(2, target_a.accelerator_pressed_count());
690 EXPECT_EQ(2, target_a.accelerator_repeat_count());
691 generator.ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
692 EXPECT_EQ(2, target_a.accelerator_pressed_count());
693 EXPECT_EQ(2, target_a.accelerator_repeat_count());
695 // Long press was intercepted by another key press.
696 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
697 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
698 generator.PressKey(ui::VKEY_B, ui::EF_CONTROL_DOWN);
699 generator.ReleaseKey(ui::VKEY_B, ui::EF_CONTROL_DOWN);
700 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
701 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
702 generator.ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
704 EXPECT_EQ(1, target_b.accelerator_pressed_count());
705 EXPECT_EQ(0, target_b.accelerator_repeat_count());
706 EXPECT_EQ(4, target_a.accelerator_pressed_count());
707 EXPECT_EQ(4, target_a.accelerator_repeat_count());
710 TEST_F(AcceleratorControllerTest, Previous) {
711 ui::test::EventGenerator& generator = GetEventGenerator();
712 generator.PressKey(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
713 generator.ReleaseKey(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
715 EXPECT_EQ(ui::VKEY_VOLUME_MUTE,
716 GetPreviousAccelerator().key_code());
717 EXPECT_EQ(ui::EF_NONE,
718 GetPreviousAccelerator().modifiers());
720 generator.PressKey(ui::VKEY_TAB, ui::EF_CONTROL_DOWN);
721 generator.ReleaseKey(ui::VKEY_TAB, ui::EF_CONTROL_DOWN);
723 EXPECT_EQ(ui::VKEY_TAB,
724 GetPreviousAccelerator().key_code());
725 EXPECT_EQ(ui::EF_CONTROL_DOWN,
726 GetPreviousAccelerator().modifiers());
729 TEST_F(AcceleratorControllerTest, DontRepeatToggleFullscreen) {
730 const AcceleratorData accelerators[] = {
731 {true, ui::VKEY_J, ui::EF_ALT_DOWN, TOGGLE_FULLSCREEN},
732 {true, ui::VKEY_K, ui::EF_ALT_DOWN, TOGGLE_FULLSCREEN},
734 GetController()->RegisterAccelerators(accelerators, arraysize(accelerators));
736 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
737 params.context = CurrentContext();
738 params.bounds = gfx::Rect(5, 5, 20, 20);
739 views::Widget* widget = new views::Widget;
740 widget->Init(params);
741 widget->Show();
742 widget->Activate();
743 widget->GetNativeView()->SetProperty(aura::client::kCanMaximizeKey, true);
745 ui::test::EventGenerator& generator = GetEventGenerator();
746 wm::WindowState* window_state = wm::GetWindowState(widget->GetNativeView());
748 // Toggling not suppressed.
749 generator.PressKey(ui::VKEY_J, ui::EF_ALT_DOWN);
750 EXPECT_TRUE(window_state->IsFullscreen());
752 // The same accelerator - toggling suppressed.
753 generator.PressKey(ui::VKEY_J, ui::EF_ALT_DOWN | ui::EF_IS_REPEAT);
754 EXPECT_TRUE(window_state->IsFullscreen());
756 // Different accelerator.
757 generator.PressKey(ui::VKEY_K, ui::EF_ALT_DOWN);
758 EXPECT_FALSE(window_state->IsFullscreen());
761 // TODO(oshima): Fix this test to use EventGenerator.
762 #if defined(OS_WIN)
763 // crbug.com/317592
764 #define MAYBE_ProcessOnce DISABLED_ProcessOnce
765 #else
766 #define MAYBE_ProcessOnce ProcessOnce
767 #endif
769 #if defined(OS_WIN) || defined(USE_X11)
770 TEST_F(AcceleratorControllerTest, MAYBE_ProcessOnce) {
771 // The IME event filter interferes with the basic key event propagation we
772 // attempt to do here, so we disable it.
773 DisableIME();
774 ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
775 TestTarget target;
776 GetController()->Register(accelerator_a, &target);
778 // The accelerator is processed only once.
779 ui::EventProcessor* dispatcher =
780 Shell::GetPrimaryRootWindow()->GetHost()->event_processor();
781 #if defined(OS_WIN)
782 MSG msg1 = { NULL, WM_KEYDOWN, ui::VKEY_A, 0 };
783 ui::KeyEvent key_event1(msg1);
784 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&key_event1);
785 EXPECT_TRUE(key_event1.handled() || details.dispatcher_destroyed);
787 MSG msg2 = { NULL, WM_CHAR, L'A', 0 };
788 ui::KeyEvent key_event2(msg2);
789 details = dispatcher->OnEventFromSource(&key_event2);
790 EXPECT_FALSE(key_event2.handled() || details.dispatcher_destroyed);
792 MSG msg3 = { NULL, WM_KEYUP, ui::VKEY_A, 0 };
793 ui::KeyEvent key_event3(msg3);
794 details = dispatcher->OnEventFromSource(&key_event3);
795 EXPECT_FALSE(key_event3.handled() || details.dispatcher_destroyed);
796 #elif defined(USE_X11)
797 ui::ScopedXI2Event key_event;
798 key_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, 0);
799 ui::KeyEvent key_event1(key_event);
800 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&key_event1);
801 EXPECT_TRUE(key_event1.handled() || details.dispatcher_destroyed);
803 ui::KeyEvent key_event2('A', ui::VKEY_A, ui::EF_NONE);
804 details = dispatcher->OnEventFromSource(&key_event2);
805 EXPECT_FALSE(key_event2.handled() || details.dispatcher_destroyed);
807 key_event.InitKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, 0);
808 ui::KeyEvent key_event3(key_event);
809 details = dispatcher->OnEventFromSource(&key_event3);
810 EXPECT_FALSE(key_event3.handled() || details.dispatcher_destroyed);
811 #endif
812 EXPECT_EQ(1, target.accelerator_pressed_count());
814 #endif
816 TEST_F(AcceleratorControllerTest, GlobalAccelerators) {
817 // CycleBackward
818 EXPECT_TRUE(ProcessInController(
819 ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
820 // CycleForward
821 EXPECT_TRUE(
822 ProcessInController(ui::Accelerator(
823 ui::VKEY_TAB, ui::EF_ALT_DOWN)));
824 // CycleLinear
825 EXPECT_TRUE(ProcessInController(
826 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_NONE)));
828 #if defined(OS_CHROMEOS)
829 // The "Take Screenshot", "Take Partial Screenshot", volume, brightness, and
830 // keyboard brightness accelerators are only defined on ChromeOS.
832 test::TestScreenshotDelegate* delegate = GetScreenshotDelegate();
833 delegate->set_can_take_screenshot(false);
834 EXPECT_TRUE(ProcessInController(
835 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
836 EXPECT_TRUE(
837 ProcessInController(ui::Accelerator(
838 ui::VKEY_PRINT, ui::EF_NONE)));
839 EXPECT_TRUE(ProcessInController(ui::Accelerator(
840 ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
842 delegate->set_can_take_screenshot(true);
843 EXPECT_EQ(0, delegate->handle_take_screenshot_count());
844 EXPECT_TRUE(ProcessInController(
845 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
846 EXPECT_EQ(1, delegate->handle_take_screenshot_count());
847 EXPECT_TRUE(
848 ProcessInController(ui::Accelerator(
849 ui::VKEY_PRINT, ui::EF_NONE)));
850 EXPECT_EQ(2, delegate->handle_take_screenshot_count());
851 EXPECT_TRUE(ProcessInController(ui::Accelerator(
852 ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
853 EXPECT_EQ(2, delegate->handle_take_screenshot_count());
855 const ui::Accelerator volume_mute(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
856 const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
857 const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE);
859 TestVolumeControlDelegate* delegate = new TestVolumeControlDelegate;
860 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
861 scoped_ptr<VolumeControlDelegate>(delegate).Pass());
862 EXPECT_EQ(0, delegate->handle_volume_mute_count());
863 EXPECT_TRUE(ProcessInController(volume_mute));
864 EXPECT_EQ(1, delegate->handle_volume_mute_count());
865 EXPECT_EQ(volume_mute, delegate->last_accelerator());
866 EXPECT_EQ(0, delegate->handle_volume_down_count());
867 EXPECT_TRUE(ProcessInController(volume_down));
868 EXPECT_EQ(1, delegate->handle_volume_down_count());
869 EXPECT_EQ(volume_down, delegate->last_accelerator());
870 EXPECT_EQ(0, delegate->handle_volume_up_count());
871 EXPECT_TRUE(ProcessInController(volume_up));
872 EXPECT_EQ(1, delegate->handle_volume_up_count());
873 EXPECT_EQ(volume_up, delegate->last_accelerator());
875 // Brightness
876 // ui::VKEY_BRIGHTNESS_DOWN/UP are not defined on Windows.
877 const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
878 const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE);
880 DummyBrightnessControlDelegate* delegate =
881 new DummyBrightnessControlDelegate;
882 GetController()->SetBrightnessControlDelegate(
883 scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
884 EXPECT_EQ(0, delegate->handle_brightness_down_count());
885 EXPECT_TRUE(ProcessInController(brightness_down));
886 EXPECT_EQ(1, delegate->handle_brightness_down_count());
887 EXPECT_EQ(brightness_down, delegate->last_accelerator());
888 EXPECT_EQ(0, delegate->handle_brightness_up_count());
889 EXPECT_TRUE(ProcessInController(brightness_up));
890 EXPECT_EQ(1, delegate->handle_brightness_up_count());
891 EXPECT_EQ(brightness_up, delegate->last_accelerator());
894 // Keyboard brightness
895 const ui::Accelerator alt_brightness_down(ui::VKEY_BRIGHTNESS_DOWN,
896 ui::EF_ALT_DOWN);
897 const ui::Accelerator alt_brightness_up(ui::VKEY_BRIGHTNESS_UP,
898 ui::EF_ALT_DOWN);
900 EXPECT_TRUE(ProcessInController(alt_brightness_down));
901 EXPECT_TRUE(ProcessInController(alt_brightness_up));
902 DummyKeyboardBrightnessControlDelegate* delegate =
903 new DummyKeyboardBrightnessControlDelegate;
904 GetController()->SetKeyboardBrightnessControlDelegate(
905 scoped_ptr<KeyboardBrightnessControlDelegate>(delegate).Pass());
906 EXPECT_EQ(0, delegate->handle_keyboard_brightness_down_count());
907 EXPECT_TRUE(ProcessInController(alt_brightness_down));
908 EXPECT_EQ(1, delegate->handle_keyboard_brightness_down_count());
909 EXPECT_EQ(alt_brightness_down, delegate->last_accelerator());
910 EXPECT_EQ(0, delegate->handle_keyboard_brightness_up_count());
911 EXPECT_TRUE(ProcessInController(alt_brightness_up));
912 EXPECT_EQ(1, delegate->handle_keyboard_brightness_up_count());
913 EXPECT_EQ(alt_brightness_up, delegate->last_accelerator());
915 #endif
917 #if !defined(OS_WIN)
918 // Exit
919 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
920 ASSERT_TRUE(ewh);
921 StubForTest(ewh);
922 EXPECT_TRUE(is_idle(ewh));
923 EXPECT_FALSE(is_ui_shown(ewh));
924 EXPECT_TRUE(ProcessInController(
925 ui::Accelerator(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
926 EXPECT_FALSE(is_idle(ewh));
927 EXPECT_TRUE(is_ui_shown(ewh));
928 SimulateTimerExpired(ewh);
929 EXPECT_TRUE(is_idle(ewh));
930 EXPECT_FALSE(is_ui_shown(ewh));
931 Reset(ewh);
932 #endif
934 // New tab
935 EXPECT_TRUE(ProcessInController(
936 ui::Accelerator(ui::VKEY_T, ui::EF_CONTROL_DOWN)));
938 // New incognito window
939 EXPECT_TRUE(ProcessInController(
940 ui::Accelerator(ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
942 // New window
943 EXPECT_TRUE(ProcessInController(
944 ui::Accelerator(ui::VKEY_N, ui::EF_CONTROL_DOWN)));
946 // Restore tab
947 EXPECT_TRUE(ProcessInController(
948 ui::Accelerator(ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
950 // Show task manager
951 EXPECT_TRUE(ProcessInController(
952 ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN)));
954 #if defined(OS_CHROMEOS)
955 // Open file manager
956 EXPECT_TRUE(ProcessInController(
957 ui::Accelerator(ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
959 // Lock screen
960 // NOTE: Accelerators that do not work on the lock screen need to be
961 // tested before the sequence below is invoked because it causes a side
962 // effect of locking the screen.
963 EXPECT_TRUE(ProcessInController(
964 ui::Accelerator(ui::VKEY_L, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
965 #endif
968 TEST_F(AcceleratorControllerTest, GlobalAcceleratorsToggleAppList) {
969 AccessibilityDelegate* delegate =
970 ash::Shell::GetInstance()->accessibility_delegate();
971 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
973 // The press event should not open the AppList, the release should instead.
974 EXPECT_FALSE(
975 ProcessInController(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
976 EXPECT_EQ(ui::VKEY_LWIN,
977 GetCurrentAccelerator().key_code());
979 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
981 EXPECT_TRUE(
982 ProcessInController(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
983 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
985 EXPECT_EQ(ui::VKEY_LWIN,
986 GetPreviousAccelerator().key_code());
988 // When spoken feedback is on, the AppList should not toggle.
989 delegate->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE);
990 EXPECT_FALSE(
991 ProcessInController(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
992 EXPECT_FALSE(
993 ProcessInController(ReleaseAccelerator(
994 ui::VKEY_LWIN, ui::EF_NONE)));
995 delegate->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE);
996 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
998 EXPECT_FALSE(
999 ProcessInController(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
1000 EXPECT_TRUE(
1001 ProcessInController(ReleaseAccelerator(
1002 ui::VKEY_LWIN, ui::EF_NONE)));
1003 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1005 // When spoken feedback is on, the AppList should not toggle.
1006 delegate->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE);
1007 EXPECT_FALSE(
1008 ProcessInController(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
1009 EXPECT_FALSE(
1010 ProcessInController(ReleaseAccelerator(
1011 ui::VKEY_LWIN, ui::EF_NONE)));
1012 delegate->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE);
1013 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1015 #if defined(OS_CHROMEOS)
1016 // The press of VKEY_BROWSER_SEARCH should toggle the AppList
1017 EXPECT_TRUE(ProcessInController(ui::Accelerator(ui::VKEY_BROWSER_SEARCH,
1018 ui::EF_NONE)));
1019 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1020 EXPECT_FALSE(ProcessInController(ReleaseAccelerator(ui::VKEY_BROWSER_SEARCH,
1021 ui::EF_NONE)));
1022 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1023 #endif
1026 TEST_F(AcceleratorControllerTest, ImeGlobalAccelerators) {
1027 // Test IME shortcuts.
1029 ui::Accelerator control_space_down(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
1030 control_space_down.set_type(ui::ET_KEY_PRESSED);
1031 ui::Accelerator control_space_up(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
1032 control_space_up.set_type(ui::ET_KEY_RELEASED);
1033 const ui::Accelerator convert(ui::VKEY_CONVERT, ui::EF_NONE);
1034 const ui::Accelerator non_convert(ui::VKEY_NONCONVERT, ui::EF_NONE);
1035 const ui::Accelerator wide_half_1(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE);
1036 const ui::Accelerator wide_half_2(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE);
1037 const ui::Accelerator hangul(ui::VKEY_HANGUL, ui::EF_NONE);
1038 EXPECT_FALSE(ProcessInController(control_space_down));
1039 EXPECT_FALSE(ProcessInController(control_space_up));
1040 EXPECT_FALSE(ProcessInController(convert));
1041 EXPECT_FALSE(ProcessInController(non_convert));
1042 EXPECT_FALSE(ProcessInController(wide_half_1));
1043 EXPECT_FALSE(ProcessInController(wide_half_2));
1044 EXPECT_FALSE(ProcessInController(hangul));
1045 DummyImeControlDelegate* delegate = new DummyImeControlDelegate;
1046 GetController()->SetImeControlDelegate(
1047 scoped_ptr<ImeControlDelegate>(delegate).Pass());
1048 EXPECT_EQ(0, delegate->handle_previous_ime_count());
1049 EXPECT_TRUE(ProcessInController(control_space_down));
1050 EXPECT_EQ(1, delegate->handle_previous_ime_count());
1051 EXPECT_TRUE(ProcessInController(control_space_up));
1052 EXPECT_EQ(1, delegate->handle_previous_ime_count());
1053 EXPECT_EQ(0, delegate->handle_switch_ime_count());
1054 EXPECT_TRUE(ProcessInController(convert));
1055 EXPECT_EQ(1, delegate->handle_switch_ime_count());
1056 EXPECT_TRUE(ProcessInController(non_convert));
1057 EXPECT_EQ(2, delegate->handle_switch_ime_count());
1058 EXPECT_TRUE(ProcessInController(wide_half_1));
1059 EXPECT_EQ(3, delegate->handle_switch_ime_count());
1060 EXPECT_TRUE(ProcessInController(wide_half_2));
1061 EXPECT_EQ(4, delegate->handle_switch_ime_count());
1062 EXPECT_TRUE(ProcessInController(hangul));
1063 EXPECT_EQ(5, delegate->handle_switch_ime_count());
1066 // Test IME shortcuts that are triggered on key release.
1068 const ui::Accelerator shift_alt_press(ui::VKEY_MENU,
1069 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1070 const ReleaseAccelerator shift_alt(ui::VKEY_MENU, ui::EF_SHIFT_DOWN);
1071 const ui::Accelerator alt_shift_press(ui::VKEY_SHIFT,
1072 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1073 const ReleaseAccelerator alt_shift(ui::VKEY_SHIFT, ui::EF_ALT_DOWN);
1075 DummyImeControlDelegate* delegate = new DummyImeControlDelegate;
1076 GetController()->SetImeControlDelegate(
1077 scoped_ptr<ImeControlDelegate>(delegate).Pass());
1078 EXPECT_EQ(0, delegate->handle_next_ime_count());
1079 EXPECT_FALSE(ProcessInController(shift_alt_press));
1080 EXPECT_TRUE(ProcessInController(shift_alt));
1081 EXPECT_EQ(1, delegate->handle_next_ime_count());
1082 EXPECT_FALSE(ProcessInController(alt_shift_press));
1083 EXPECT_TRUE(ProcessInController(alt_shift));
1084 EXPECT_EQ(2, delegate->handle_next_ime_count());
1086 // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is
1087 // released.
1088 const ui::Accelerator shift_alt_x_press(
1089 ui::VKEY_X,
1090 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1091 const ReleaseAccelerator shift_alt_x(ui::VKEY_X,
1092 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1094 EXPECT_FALSE(ProcessInController(shift_alt_press));
1095 EXPECT_FALSE(ProcessInController(shift_alt_x_press));
1096 EXPECT_FALSE(ProcessInController(shift_alt_x));
1097 EXPECT_FALSE(ProcessInController(shift_alt));
1098 EXPECT_EQ(2, delegate->handle_next_ime_count());
1100 // But we _should_ if X is either VKEY_RETURN or VKEY_SPACE.
1101 // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
1102 const ui::Accelerator shift_alt_return_press(
1103 ui::VKEY_RETURN,
1104 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1105 const ReleaseAccelerator shift_alt_return(
1106 ui::VKEY_RETURN,
1107 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1109 EXPECT_FALSE(ProcessInController(shift_alt_press));
1110 EXPECT_FALSE(ProcessInController(shift_alt_return_press));
1111 EXPECT_FALSE(ProcessInController(shift_alt_return));
1112 EXPECT_TRUE(ProcessInController(shift_alt));
1113 EXPECT_EQ(3, delegate->handle_next_ime_count());
1115 const ui::Accelerator shift_alt_space_press(
1116 ui::VKEY_SPACE,
1117 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1118 const ReleaseAccelerator shift_alt_space(
1119 ui::VKEY_SPACE,
1120 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1122 EXPECT_FALSE(ProcessInController(shift_alt_press));
1123 EXPECT_FALSE(ProcessInController(shift_alt_space_press));
1124 EXPECT_FALSE(ProcessInController(shift_alt_space));
1125 EXPECT_TRUE(ProcessInController(shift_alt));
1126 EXPECT_EQ(4, delegate->handle_next_ime_count());
1129 #if defined(OS_CHROMEOS)
1130 // Test IME shortcuts again with unnormalized accelerators (Chrome OS only).
1132 const ui::Accelerator shift_alt_press(ui::VKEY_MENU, ui::EF_SHIFT_DOWN);
1133 const ReleaseAccelerator shift_alt(ui::VKEY_MENU, ui::EF_SHIFT_DOWN);
1134 const ui::Accelerator alt_shift_press(ui::VKEY_SHIFT, ui::EF_ALT_DOWN);
1135 const ReleaseAccelerator alt_shift(ui::VKEY_SHIFT, ui::EF_ALT_DOWN);
1137 DummyImeControlDelegate* delegate = new DummyImeControlDelegate;
1138 GetController()->SetImeControlDelegate(
1139 scoped_ptr<ImeControlDelegate>(delegate).Pass());
1140 EXPECT_EQ(0, delegate->handle_next_ime_count());
1141 EXPECT_FALSE(ProcessInController(shift_alt_press));
1142 EXPECT_TRUE(ProcessInController(shift_alt));
1143 EXPECT_EQ(1, delegate->handle_next_ime_count());
1144 EXPECT_FALSE(ProcessInController(alt_shift_press));
1145 EXPECT_TRUE(ProcessInController(alt_shift));
1146 EXPECT_EQ(2, delegate->handle_next_ime_count());
1148 // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is
1149 // released.
1150 const ui::Accelerator shift_alt_x_press(
1151 ui::VKEY_X,
1152 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1153 const ReleaseAccelerator shift_alt_x(ui::VKEY_X,
1154 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1156 EXPECT_FALSE(ProcessInController(shift_alt_press));
1157 EXPECT_FALSE(ProcessInController(shift_alt_x_press));
1158 EXPECT_FALSE(ProcessInController(shift_alt_x));
1159 EXPECT_FALSE(ProcessInController(shift_alt));
1160 EXPECT_EQ(2, delegate->handle_next_ime_count());
1162 #endif
1165 // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
1166 TEST_F(AcceleratorControllerTest, ImeGlobalAcceleratorsWorkaround139556) {
1167 // The workaround for crbug.com/139556 depends on the fact that we don't
1168 // use Shift+Alt+Enter/Space with ET_KEY_PRESSED as an accelerator. Test it.
1169 const ui::Accelerator shift_alt_return_press(
1170 ui::VKEY_RETURN,
1171 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1172 EXPECT_FALSE(ProcessInController(shift_alt_return_press));
1173 const ui::Accelerator shift_alt_space_press(
1174 ui::VKEY_SPACE,
1175 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1176 EXPECT_FALSE(ProcessInController(shift_alt_space_press));
1179 TEST_F(AcceleratorControllerTest, PreferredReservedAccelerators) {
1180 #if defined(OS_CHROMEOS)
1181 // Power key is reserved on chromeos.
1182 EXPECT_TRUE(GetController()->IsReserved(
1183 ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE)));
1184 EXPECT_FALSE(GetController()->IsPreferred(
1185 ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE)));
1186 #endif
1187 // ALT+Tab are not reserved but preferred.
1188 EXPECT_FALSE(GetController()->IsReserved(
1189 ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN)));
1190 EXPECT_FALSE(GetController()->IsReserved(
1191 ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
1192 EXPECT_TRUE(GetController()->IsPreferred(
1193 ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN)));
1194 EXPECT_TRUE(GetController()->IsPreferred(
1195 ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
1197 // Others are not reserved nor preferred
1198 EXPECT_FALSE(GetController()->IsReserved(
1199 ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
1200 EXPECT_FALSE(GetController()->IsPreferred(
1201 ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
1202 EXPECT_FALSE(GetController()->IsReserved(
1203 ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE)));
1204 EXPECT_FALSE(GetController()->IsPreferred(
1205 ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE)));
1206 EXPECT_FALSE(GetController()->IsReserved(
1207 ui::Accelerator(ui::VKEY_A, ui::EF_NONE)));
1208 EXPECT_FALSE(GetController()->IsPreferred(
1209 ui::Accelerator(ui::VKEY_A, ui::EF_NONE)));
1212 namespace {
1214 class PreferredReservedAcceleratorsTest : public test::AshTestBase {
1215 public:
1216 PreferredReservedAcceleratorsTest() {}
1217 ~PreferredReservedAcceleratorsTest() override {}
1219 // test::AshTestBase:
1220 void SetUp() override {
1221 AshTestBase::SetUp();
1222 Shell::GetInstance()->lock_state_controller()->
1223 set_animator_for_test(new test::TestSessionStateAnimator);
1226 private:
1227 DISALLOW_COPY_AND_ASSIGN(PreferredReservedAcceleratorsTest);
1230 } // namespace
1232 TEST_F(PreferredReservedAcceleratorsTest, AcceleratorsWithFullscreen) {
1233 aura::Window* w1 = CreateTestWindowInShellWithId(0);
1234 aura::Window* w2 = CreateTestWindowInShellWithId(1);
1235 wm::ActivateWindow(w1);
1237 wm::WMEvent fullscreen(wm::WM_EVENT_FULLSCREEN);
1238 wm::WindowState* w1_state = wm::GetWindowState(w1);
1239 w1_state->OnWMEvent(&fullscreen);
1240 ASSERT_TRUE(w1_state->IsFullscreen());
1242 ui::test::EventGenerator& generator = GetEventGenerator();
1243 #if defined(OS_CHROMEOS)
1244 // Power key (reserved) should always be handled.
1245 LockStateController::TestApi test_api(
1246 Shell::GetInstance()->lock_state_controller());
1247 EXPECT_FALSE(test_api.is_animating_lock());
1248 generator.PressKey(ui::VKEY_POWER, ui::EF_NONE);
1249 EXPECT_TRUE(test_api.is_animating_lock());
1250 #endif
1252 // A fullscreen window can consume ALT-TAB (preferred).
1253 ASSERT_EQ(w1, wm::GetActiveWindow());
1254 generator.PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
1255 ASSERT_EQ(w1, wm::GetActiveWindow());
1256 ASSERT_NE(w2, wm::GetActiveWindow());
1258 // ALT-TAB is non repeatable. Press A to cancel the
1259 // repeat record.
1260 generator.PressKey(ui::VKEY_A, ui::EF_NONE);
1261 generator.ReleaseKey(ui::VKEY_A, ui::EF_NONE);
1263 // A normal window shouldn't consume preferred accelerator.
1264 wm::WMEvent normal(wm::WM_EVENT_NORMAL);
1265 w1_state->OnWMEvent(&normal);
1266 ASSERT_FALSE(w1_state->IsFullscreen());
1268 EXPECT_EQ(w1, wm::GetActiveWindow());
1269 generator.PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
1270 ASSERT_NE(w1, wm::GetActiveWindow());
1271 ASSERT_EQ(w2, wm::GetActiveWindow());
1274 #if defined(OS_CHROMEOS)
1275 TEST_F(AcceleratorControllerTest, DisallowedAtModalWindow) {
1276 std::set<AcceleratorAction> all_actions;
1277 for (size_t i = 0 ; i < kAcceleratorDataLength; ++i)
1278 all_actions.insert(kAcceleratorData[i].action);
1279 std::set<AcceleratorAction> all_debug_actions;
1280 for (size_t i = 0 ; i < kDebugAcceleratorDataLength; ++i)
1281 all_debug_actions.insert(kDebugAcceleratorData[i].action);
1283 std::set<AcceleratorAction> actionsAllowedAtModalWindow;
1284 for (size_t k = 0 ; k < kActionsAllowedAtModalWindowLength; ++k)
1285 actionsAllowedAtModalWindow.insert(kActionsAllowedAtModalWindow[k]);
1286 for (std::set<AcceleratorAction>::const_iterator it =
1287 actionsAllowedAtModalWindow.begin();
1288 it != actionsAllowedAtModalWindow.end(); ++it) {
1289 EXPECT_TRUE(all_actions.find(*it) != all_actions.end() ||
1290 all_debug_actions.find(*it) != all_debug_actions.end())
1291 << " action from kActionsAllowedAtModalWindow"
1292 << " not found in kAcceleratorData or kDebugAcceleratorData. "
1293 << "action: " << *it;
1295 scoped_ptr<aura::Window> window(
1296 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1297 wm::ActivateWindow(window.get());
1298 Shell::GetInstance()->SimulateModalWindowOpenForTesting(true);
1299 for (std::set<AcceleratorAction>::const_iterator it = all_actions.begin();
1300 it != all_actions.end(); ++it) {
1301 if (actionsAllowedAtModalWindow.find(*it) ==
1302 actionsAllowedAtModalWindow.end()) {
1303 EXPECT_TRUE(GetController()->PerformActionIfEnabled(*it))
1304 << " for action (disallowed at modal window): " << *it;
1307 // Testing of top row (F5-F10) accelerators that should still work
1308 // when a modal window is open
1310 // Screenshot
1312 test::TestScreenshotDelegate* delegate = GetScreenshotDelegate();
1313 delegate->set_can_take_screenshot(false);
1314 EXPECT_TRUE(ProcessInController(
1315 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
1316 EXPECT_TRUE(
1317 ProcessInController(ui::Accelerator(
1318 ui::VKEY_PRINT, ui::EF_NONE)));
1319 EXPECT_TRUE(ProcessInController(ui::Accelerator(
1320 ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
1321 delegate->set_can_take_screenshot(true);
1322 EXPECT_EQ(0, delegate->handle_take_screenshot_count());
1323 EXPECT_TRUE(ProcessInController(
1324 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
1325 EXPECT_EQ(1, delegate->handle_take_screenshot_count());
1326 EXPECT_TRUE(
1327 ProcessInController(ui::Accelerator(
1328 ui::VKEY_PRINT, ui::EF_NONE)));
1329 EXPECT_EQ(2, delegate->handle_take_screenshot_count());
1330 EXPECT_TRUE(ProcessInController(ui::Accelerator(
1331 ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
1332 EXPECT_EQ(2, delegate->handle_take_screenshot_count());
1334 // Brightness
1335 const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
1336 const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE);
1338 DummyBrightnessControlDelegate* delegate =
1339 new DummyBrightnessControlDelegate;
1340 GetController()->SetBrightnessControlDelegate(
1341 scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
1342 EXPECT_EQ(0, delegate->handle_brightness_down_count());
1343 EXPECT_TRUE(ProcessInController(brightness_down));
1344 EXPECT_EQ(1, delegate->handle_brightness_down_count());
1345 EXPECT_EQ(brightness_down, delegate->last_accelerator());
1346 EXPECT_EQ(0, delegate->handle_brightness_up_count());
1347 EXPECT_TRUE(ProcessInController(brightness_up));
1348 EXPECT_EQ(1, delegate->handle_brightness_up_count());
1349 EXPECT_EQ(brightness_up, delegate->last_accelerator());
1351 // Volume
1352 const ui::Accelerator volume_mute(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
1353 const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
1354 const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE);
1356 EXPECT_TRUE(ProcessInController(volume_mute));
1357 EXPECT_TRUE(ProcessInController(volume_down));
1358 EXPECT_TRUE(ProcessInController(volume_up));
1359 TestVolumeControlDelegate* delegate = new TestVolumeControlDelegate;
1360 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
1361 scoped_ptr<VolumeControlDelegate>(delegate).Pass());
1362 EXPECT_EQ(0, delegate->handle_volume_mute_count());
1363 EXPECT_TRUE(ProcessInController(volume_mute));
1364 EXPECT_EQ(1, delegate->handle_volume_mute_count());
1365 EXPECT_EQ(volume_mute, delegate->last_accelerator());
1366 EXPECT_EQ(0, delegate->handle_volume_down_count());
1367 EXPECT_TRUE(ProcessInController(volume_down));
1368 EXPECT_EQ(1, delegate->handle_volume_down_count());
1369 EXPECT_EQ(volume_down, delegate->last_accelerator());
1370 EXPECT_EQ(0, delegate->handle_volume_up_count());
1371 EXPECT_TRUE(ProcessInController(volume_up));
1372 EXPECT_EQ(1, delegate->handle_volume_up_count());
1373 EXPECT_EQ(volume_up, delegate->last_accelerator());
1376 #endif
1378 TEST_F(AcceleratorControllerTest, DisallowedWithNoWindow) {
1379 AccessibilityDelegate* delegate =
1380 ash::Shell::GetInstance()->accessibility_delegate();
1382 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
1383 delegate->TriggerAccessibilityAlert(ui::A11Y_ALERT_NONE);
1384 EXPECT_TRUE(
1385 GetController()->PerformActionIfEnabled(kActionsNeedingWindow[i]));
1386 EXPECT_EQ(delegate->GetLastAccessibilityAlert(),
1387 ui::A11Y_ALERT_WINDOW_NEEDED);
1390 // Make sure we don't alert if we do have a window.
1391 scoped_ptr<aura::Window> window;
1392 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
1393 window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1394 wm::ActivateWindow(window.get());
1395 delegate->TriggerAccessibilityAlert(ui::A11Y_ALERT_NONE);
1396 GetController()->PerformActionIfEnabled(kActionsNeedingWindow[i]);
1397 EXPECT_NE(delegate->GetLastAccessibilityAlert(),
1398 ui::A11Y_ALERT_WINDOW_NEEDED);
1401 // Don't alert if we have a minimized window either.
1402 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
1403 window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1404 wm::ActivateWindow(window.get());
1405 GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE);
1406 delegate->TriggerAccessibilityAlert(ui::A11Y_ALERT_NONE);
1407 GetController()->PerformActionIfEnabled(kActionsNeedingWindow[i]);
1408 EXPECT_NE(delegate->GetLastAccessibilityAlert(),
1409 ui::A11Y_ALERT_WINDOW_NEEDED);
1413 } // namespace ash