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"
44 #include "ui/events/test/events_test_utils_x11.h"
51 class TestTarget
: public ui::AcceleratorTarget
{
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_
; }
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
;
72 int accelerator_pressed_count_
;
73 int accelerator_repeat_count_
;
75 DISALLOW_COPY_AND_ASSIGN(TestTarget
);
78 class ReleaseAccelerator
: public ui::Accelerator
{
80 ReleaseAccelerator(ui::KeyboardCode keycode
, int modifiers
)
81 : ui::Accelerator(keycode
, modifiers
) {
82 set_type(ui::ET_KEY_RELEASED
);
86 class DummyBrightnessControlDelegate
: public BrightnessControlDelegate
{
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
{
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_
;
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
{
126 DummyImeControlDelegate()
127 : handle_next_ime_count_(0),
128 handle_previous_ime_count_(0),
129 handle_switch_ime_count_(0) {}
130 ~DummyImeControlDelegate() override
{}
132 void HandleNextIme() override
{ ++handle_next_ime_count_
; }
133 bool HandlePreviousIme(const ui::Accelerator
& accelerator
) override
{
134 ++handle_previous_ime_count_
;
137 bool HandleSwitchIme(const ui::Accelerator
& accelerator
) override
{
138 ++handle_switch_ime_count_
;
142 int handle_next_ime_count() const {
143 return handle_next_ime_count_
;
145 int handle_previous_ime_count() const {
146 return handle_previous_ime_count_
;
148 int handle_switch_ime_count() const {
149 return handle_switch_ime_count_
;
151 ui::Accelerator
RemapAccelerator(
152 const ui::Accelerator
& accelerator
) override
{
153 return ui::Accelerator(accelerator
);
157 int handle_next_ime_count_
;
158 int handle_previous_ime_count_
;
159 int handle_switch_ime_count_
;
161 DISALLOW_COPY_AND_ASSIGN(DummyImeControlDelegate
);
164 class DummyKeyboardBrightnessControlDelegate
165 : public KeyboardBrightnessControlDelegate
{
167 DummyKeyboardBrightnessControlDelegate()
168 : handle_keyboard_brightness_down_count_(0),
169 handle_keyboard_brightness_up_count_(0) {}
170 ~DummyKeyboardBrightnessControlDelegate() override
{}
172 void HandleKeyboardBrightnessDown(
173 const ui::Accelerator
& accelerator
) override
{
174 ++handle_keyboard_brightness_down_count_
;
175 last_accelerator_
= accelerator
;
178 void HandleKeyboardBrightnessUp(const ui::Accelerator
& accelerator
) override
{
179 ++handle_keyboard_brightness_up_count_
;
180 last_accelerator_
= accelerator
;
183 int handle_keyboard_brightness_down_count() const {
184 return handle_keyboard_brightness_down_count_
;
187 int handle_keyboard_brightness_up_count() const {
188 return handle_keyboard_brightness_up_count_
;
191 const ui::Accelerator
& last_accelerator() const {
192 return last_accelerator_
;
196 int handle_keyboard_brightness_down_count_
;
197 int handle_keyboard_brightness_up_count_
;
198 ui::Accelerator last_accelerator_
;
200 DISALLOW_COPY_AND_ASSIGN(DummyKeyboardBrightnessControlDelegate
);
203 bool TestTarget::AcceleratorPressed(const ui::Accelerator
& accelerator
) {
204 if (accelerator
.IsRepeat())
205 ++accelerator_repeat_count_
;
207 ++accelerator_pressed_count_
;
211 bool TestTarget::CanHandleAccelerators() const {
217 class AcceleratorControllerTest
: public test::AshTestBase
{
219 AcceleratorControllerTest() {}
220 ~AcceleratorControllerTest() override
{}
223 void EnableInternalDisplay() {
224 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()).
225 SetFirstDisplayAsInternalDisplay();
228 static AcceleratorController
* GetController();
230 static bool ProcessInController(const ui::Accelerator
& accelerator
) {
231 GetController()->accelerator_history()->
232 StoreCurrentAccelerator(accelerator
);
233 return GetController()->Process(accelerator
);
236 static const ui::Accelerator
& GetPreviousAccelerator() {
237 return GetController()->accelerator_history()->
238 previous_accelerator();
241 static const ui::Accelerator
& GetCurrentAccelerator() {
242 return GetController()->accelerator_history()->
243 current_accelerator();
246 // Several functions to access ExitWarningHandler (as friend).
247 static void StubForTest(ExitWarningHandler
* ewh
) {
248 ewh
->stub_timer_for_test_
= true;
250 static void Reset(ExitWarningHandler
* ewh
) {
251 ewh
->state_
= ExitWarningHandler::IDLE
;
253 static void SimulateTimerExpired(ExitWarningHandler
* ewh
) {
256 static bool is_ui_shown(ExitWarningHandler
* ewh
) {
257 return !!ewh
->widget_
;
259 static bool is_idle(ExitWarningHandler
* ewh
) {
260 return ewh
->state_
== ExitWarningHandler::IDLE
;
262 static bool is_exiting(ExitWarningHandler
* ewh
) {
263 return ewh
->state_
== ExitWarningHandler::EXITING
;
265 aura::Window
* CreatePanel() {
266 aura::Window
* window
=
267 CreateTestWindowInShellWithDelegateAndType(NULL
,
268 ui::wm::WINDOW_TYPE_PANEL
, 0, gfx::Rect(5, 5, 20, 20));
269 test::TestShelfDelegate
* shelf_delegate
=
270 test::TestShelfDelegate::instance();
271 shelf_delegate
->AddShelfItem(window
);
272 PanelLayoutManager
* manager
= static_cast<PanelLayoutManager
*>(
273 Shell::GetContainer(window
->GetRootWindow(),
274 kShellWindowId_PanelContainer
)->layout_manager());
280 DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest
);
283 AcceleratorController
* AcceleratorControllerTest::GetController() {
284 return Shell::GetInstance()->accelerator_controller();
288 // Double press of exit shortcut => exiting
289 TEST_F(AcceleratorControllerTest
, ExitWarningHandlerTestDoublePress
) {
290 ui::Accelerator
press(ui::VKEY_Q
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
);
291 ui::Accelerator
release(press
);
292 release
.set_type(ui::ET_KEY_RELEASED
);
293 ExitWarningHandler
* ewh
= GetController()->GetExitWarningHandlerForTest();
296 EXPECT_TRUE(is_idle(ewh
));
297 EXPECT_FALSE(is_ui_shown(ewh
));
298 EXPECT_TRUE(ProcessInController(press
));
299 EXPECT_FALSE(ProcessInController(release
));
300 EXPECT_FALSE(is_idle(ewh
));
301 EXPECT_TRUE(is_ui_shown(ewh
));
302 EXPECT_TRUE(ProcessInController(press
)); // second press before timer.
303 EXPECT_FALSE(ProcessInController(release
));
304 SimulateTimerExpired(ewh
);
305 EXPECT_TRUE(is_exiting(ewh
));
306 EXPECT_FALSE(is_ui_shown(ewh
));
310 // Single press of exit shortcut before timer => idle
311 TEST_F(AcceleratorControllerTest
, ExitWarningHandlerTestSinglePress
) {
312 ui::Accelerator
press(ui::VKEY_Q
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
);
313 ui::Accelerator
release(press
);
314 release
.set_type(ui::ET_KEY_RELEASED
);
315 ExitWarningHandler
* ewh
= GetController()->GetExitWarningHandlerForTest();
318 EXPECT_TRUE(is_idle(ewh
));
319 EXPECT_FALSE(is_ui_shown(ewh
));
320 EXPECT_TRUE(ProcessInController(press
));
321 EXPECT_FALSE(ProcessInController(release
));
322 EXPECT_FALSE(is_idle(ewh
));
323 EXPECT_TRUE(is_ui_shown(ewh
));
324 SimulateTimerExpired(ewh
);
325 EXPECT_TRUE(is_idle(ewh
));
326 EXPECT_FALSE(is_ui_shown(ewh
));
330 // Shutdown ash with exit warning bubble open should not crash.
331 TEST_F(AcceleratorControllerTest
, LingeringExitWarningBubble
) {
332 ExitWarningHandler
* ewh
= GetController()->GetExitWarningHandlerForTest();
336 // Trigger once to show the bubble.
337 ewh
->HandleAccelerator();
338 EXPECT_FALSE(is_idle(ewh
));
339 EXPECT_TRUE(is_ui_shown(ewh
));
341 // Exit ash and there should be no crash
343 #endif // !defined(OS_WIN)
345 TEST_F(AcceleratorControllerTest
, Register
) {
346 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
348 GetController()->Register(accelerator_a
, &target
);
350 // The registered accelerator is processed.
351 EXPECT_TRUE(ProcessInController(accelerator_a
));
352 EXPECT_EQ(1, target
.accelerator_pressed_count());
355 TEST_F(AcceleratorControllerTest
, RegisterMultipleTarget
) {
356 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
358 GetController()->Register(accelerator_a
, &target1
);
360 GetController()->Register(accelerator_a
, &target2
);
362 // If multiple targets are registered with the same accelerator, the target
363 // registered later processes the accelerator.
364 EXPECT_TRUE(ProcessInController(accelerator_a
));
365 EXPECT_EQ(0, target1
.accelerator_pressed_count());
366 EXPECT_EQ(1, target2
.accelerator_pressed_count());
369 TEST_F(AcceleratorControllerTest
, Unregister
) {
370 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
372 GetController()->Register(accelerator_a
, &target
);
373 const ui::Accelerator
accelerator_b(ui::VKEY_B
, ui::EF_NONE
);
374 GetController()->Register(accelerator_b
, &target
);
376 // Unregistering a different accelerator does not affect the other
378 GetController()->Unregister(accelerator_b
, &target
);
379 EXPECT_TRUE(ProcessInController(accelerator_a
));
380 EXPECT_EQ(1, target
.accelerator_pressed_count());
382 // The unregistered accelerator is no longer processed.
384 GetController()->Unregister(accelerator_a
, &target
);
385 EXPECT_FALSE(ProcessInController(accelerator_a
));
386 EXPECT_EQ(0, target
.accelerator_pressed_count());
389 TEST_F(AcceleratorControllerTest
, UnregisterAll
) {
390 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
392 GetController()->Register(accelerator_a
, &target1
);
393 const ui::Accelerator
accelerator_b(ui::VKEY_B
, ui::EF_NONE
);
394 GetController()->Register(accelerator_b
, &target1
);
395 const ui::Accelerator
accelerator_c(ui::VKEY_C
, ui::EF_NONE
);
397 GetController()->Register(accelerator_c
, &target2
);
398 GetController()->UnregisterAll(&target1
);
400 // All the accelerators registered for |target1| are no longer processed.
401 EXPECT_FALSE(ProcessInController(accelerator_a
));
402 EXPECT_FALSE(ProcessInController(accelerator_b
));
403 EXPECT_EQ(0, target1
.accelerator_pressed_count());
405 // UnregisterAll with a different target does not affect the other target.
406 EXPECT_TRUE(ProcessInController(accelerator_c
));
407 EXPECT_EQ(1, target2
.accelerator_pressed_count());
410 TEST_F(AcceleratorControllerTest
, Process
) {
411 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
413 GetController()->Register(accelerator_a
, &target1
);
415 // The registered accelerator is processed.
416 EXPECT_TRUE(ProcessInController(accelerator_a
));
417 EXPECT_EQ(1, target1
.accelerator_pressed_count());
419 // The non-registered accelerator is not processed.
420 const ui::Accelerator
accelerator_b(ui::VKEY_B
, ui::EF_NONE
);
421 EXPECT_FALSE(ProcessInController(accelerator_b
));
424 TEST_F(AcceleratorControllerTest
, IsRegistered
) {
425 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
426 const ui::Accelerator
accelerator_shift_a(ui::VKEY_A
, ui::EF_SHIFT_DOWN
);
428 GetController()->Register(accelerator_a
, &target
);
429 EXPECT_TRUE(GetController()->IsRegistered(accelerator_a
));
430 EXPECT_FALSE(GetController()->IsRegistered(accelerator_shift_a
));
431 GetController()->UnregisterAll(&target
);
432 EXPECT_FALSE(GetController()->IsRegistered(accelerator_a
));
435 TEST_F(AcceleratorControllerTest
, WindowSnap
) {
436 scoped_ptr
<aura::Window
> window(
437 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
438 wm::WindowState
* window_state
= wm::GetWindowState(window
.get());
440 window_state
->Activate();
443 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
444 gfx::Rect expected_bounds
= wm::GetDefaultLeftSnappedWindowBoundsInParent(
446 EXPECT_EQ(expected_bounds
.ToString(), window
->bounds().ToString());
449 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
450 gfx::Rect expected_bounds
= wm::GetDefaultRightSnappedWindowBoundsInParent(
452 EXPECT_EQ(expected_bounds
.ToString(), window
->bounds().ToString());
455 gfx::Rect normal_bounds
= window_state
->GetRestoreBoundsInParent();
457 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED
);
458 EXPECT_TRUE(window_state
->IsMaximized());
459 EXPECT_NE(normal_bounds
.ToString(), window
->bounds().ToString());
461 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED
);
462 EXPECT_FALSE(window_state
->IsMaximized());
463 // Window gets restored to its restore bounds since side-maximized state
464 // is treated as a "maximized" state.
465 EXPECT_EQ(normal_bounds
.ToString(), window
->bounds().ToString());
467 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED
);
468 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
469 EXPECT_FALSE(window_state
->IsMaximized());
471 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED
);
472 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
473 EXPECT_FALSE(window_state
->IsMaximized());
475 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED
);
476 EXPECT_TRUE(window_state
->IsMaximized());
477 GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE
);
478 EXPECT_FALSE(window_state
->IsMaximized());
479 EXPECT_TRUE(window_state
->IsMinimized());
480 window_state
->Restore();
481 window_state
->Activate();
484 GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE
);
485 EXPECT_TRUE(window_state
->IsMinimized());
489 TEST_F(AcceleratorControllerTest
, WindowSnapLeftDockLeftRestore
) {
490 scoped_ptr
<aura::Window
> window0(
491 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
492 scoped_ptr
<aura::Window
> window1(
493 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
494 wm::WindowState
* window1_state
= wm::GetWindowState(window1
.get());
495 window1_state
->Activate();
497 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
498 gfx::Rect normal_bounds
= window1_state
->GetRestoreBoundsInParent();
499 gfx::Rect expected_bounds
= wm::GetDefaultLeftSnappedWindowBoundsInParent(
501 EXPECT_EQ(expected_bounds
.ToString(), window1
->bounds().ToString());
502 EXPECT_TRUE(window1_state
->IsSnapped());
503 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
504 EXPECT_FALSE(window1_state
->IsNormalOrSnapped());
505 EXPECT_TRUE(window1_state
->IsDocked());
506 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
507 EXPECT_FALSE(window1_state
->IsDocked());
508 EXPECT_EQ(normal_bounds
.ToString(), window1
->bounds().ToString());
511 TEST_F(AcceleratorControllerTest
, WindowSnapRightDockRightRestore
) {
512 scoped_ptr
<aura::Window
> window0(
513 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
514 scoped_ptr
<aura::Window
> window1(
515 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
517 wm::WindowState
* window1_state
= wm::GetWindowState(window1
.get());
518 window1_state
->Activate();
520 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
521 gfx::Rect normal_bounds
= window1_state
->GetRestoreBoundsInParent();
522 gfx::Rect expected_bounds
=
523 wm::GetDefaultRightSnappedWindowBoundsInParent(window1
.get());
524 EXPECT_EQ(expected_bounds
.ToString(), window1
->bounds().ToString());
525 EXPECT_TRUE(window1_state
->IsSnapped());
526 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
527 EXPECT_FALSE(window1_state
->IsNormalOrSnapped());
528 EXPECT_TRUE(window1_state
->IsDocked());
529 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
530 EXPECT_FALSE(window1_state
->IsDocked());
531 EXPECT_EQ(normal_bounds
.ToString(), window1
->bounds().ToString());
534 TEST_F(AcceleratorControllerTest
, WindowSnapLeftDockLeftSnapRight
) {
535 scoped_ptr
<aura::Window
> window0(
536 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
537 scoped_ptr
<aura::Window
> window1(
538 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
540 wm::WindowState
* window1_state
= wm::GetWindowState(window1
.get());
541 window1_state
->Activate();
543 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
544 gfx::Rect expected_bounds
=
545 wm::GetDefaultLeftSnappedWindowBoundsInParent(window1
.get());
546 gfx::Rect expected_bounds2
=
547 wm::GetDefaultRightSnappedWindowBoundsInParent(window1
.get());
548 EXPECT_EQ(expected_bounds
.ToString(), window1
->bounds().ToString());
549 EXPECT_TRUE(window1_state
->IsSnapped());
550 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
551 EXPECT_FALSE(window1_state
->IsNormalOrSnapped());
552 EXPECT_TRUE(window1_state
->IsDocked());
553 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
554 EXPECT_FALSE(window1_state
->IsDocked());
555 EXPECT_TRUE(window1_state
->IsSnapped());
556 EXPECT_EQ(expected_bounds2
.ToString(), window1
->bounds().ToString());
559 TEST_F(AcceleratorControllerTest
, WindowDockLeftMinimizeWindowWithRestore
) {
560 scoped_ptr
<aura::Window
> window0(
561 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
562 scoped_ptr
<aura::Window
> window1(
563 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
565 wm::WindowState
* window1_state
= wm::GetWindowState(window1
.get());
566 window1_state
->Activate();
568 scoped_ptr
<aura::Window
> window2(
569 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
571 wm::WindowState
* window2_state
= wm::GetWindowState(window2
.get());
573 scoped_ptr
<aura::Window
> window3(
574 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
576 wm::WindowState
* window3_state
= wm::GetWindowState(window3
.get());
577 window3_state
->Activate();
579 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
580 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
581 gfx::Rect window3_docked_bounds
= window3
->bounds();
583 window2_state
->Activate();
584 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
585 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
586 window1_state
->Activate();
587 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
588 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
590 EXPECT_TRUE(window3_state
->IsDocked());
591 EXPECT_TRUE(window2_state
->IsDocked());
592 EXPECT_TRUE(window1_state
->IsDocked());
593 EXPECT_TRUE(window3_state
->IsMinimized());
595 window1_state
->Activate();
596 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
597 window2_state
->Activate();
598 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
599 window3_state
->Unminimize();
600 EXPECT_FALSE(window1_state
->IsDocked());
601 EXPECT_FALSE(window2_state
->IsDocked());
602 EXPECT_TRUE(window3_state
->IsDocked());
603 EXPECT_EQ(window3_docked_bounds
.ToString(), window3
->bounds().ToString());
606 TEST_F(AcceleratorControllerTest
, WindowPanelDockLeftDockRightRestore
) {
607 scoped_ptr
<aura::Window
> window0(
608 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
610 scoped_ptr
<aura::Window
> window(CreatePanel());
611 wm::WindowState
* window_state
= wm::GetWindowState(window
.get());
612 window_state
->Activate();
614 gfx::Rect window_restore_bounds2
= window
->bounds();
615 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
616 gfx::Rect expected_bounds
=
617 wm::GetDefaultLeftSnappedWindowBoundsInParent(window
.get());
618 gfx::Rect window_restore_bounds
=
619 window_state
->GetRestoreBoundsInScreen();
620 EXPECT_NE(expected_bounds
.ToString(), window
->bounds().ToString());
621 EXPECT_FALSE(window_state
->IsSnapped());
622 EXPECT_FALSE(window_state
->IsNormalOrSnapped());
623 EXPECT_TRUE(window_state
->IsDocked());
624 window_state
->Restore();
625 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
626 EXPECT_TRUE(window_state
->IsDocked());
627 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
628 EXPECT_FALSE(window_state
->IsDocked());
629 EXPECT_EQ(window_restore_bounds
.ToString(),
630 window_restore_bounds2
.ToString());
631 EXPECT_EQ(window_restore_bounds
.ToString(), window
->bounds().ToString());
634 TEST_F(AcceleratorControllerTest
, CenterWindowAccelerator
) {
635 scoped_ptr
<aura::Window
> window(
636 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
637 wm::WindowState
* window_state
= wm::GetWindowState(window
.get());
638 window_state
->Activate();
640 // Center the window using accelerator.
641 GetController()->PerformActionIfEnabled(WINDOW_POSITION_CENTER
);
642 gfx::Rect work_area
=
643 Shell::GetScreen()->GetDisplayNearestWindow(window
.get()).work_area();
644 gfx::Rect bounds
= window
->GetBoundsInScreen();
645 EXPECT_NEAR(bounds
.x() - work_area
.x(),
646 work_area
.right() - bounds
.right(),
648 EXPECT_NEAR(bounds
.y() - work_area
.y(),
649 work_area
.bottom() - bounds
.bottom(),
652 // Add the window to docked container and try to center it.
653 window
->SetBounds(gfx::Rect(0, 0, 20, 20));
654 aura::Window
* docked_container
= Shell::GetContainer(
655 window
->GetRootWindow(), kShellWindowId_DockedContainer
);
656 docked_container
->AddChild(window
.get());
657 gfx::Rect docked_bounds
= window
->GetBoundsInScreen();
658 GetController()->PerformActionIfEnabled(WINDOW_POSITION_CENTER
);
659 // It should not get centered and should remain docked.
660 EXPECT_EQ(kShellWindowId_DockedContainer
, window
->parent()->id());
661 EXPECT_EQ(docked_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
664 TEST_F(AcceleratorControllerTest
, AutoRepeat
) {
665 ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_CONTROL_DOWN
);
666 accelerator_a
.set_type(ui::ET_KEY_PRESSED
);
668 GetController()->Register(accelerator_a
, &target_a
);
669 ui::Accelerator
accelerator_b(ui::VKEY_B
, ui::EF_CONTROL_DOWN
);
670 accelerator_b
.set_type(ui::ET_KEY_PRESSED
);
672 GetController()->Register(accelerator_b
, &target_b
);
674 ui::test::EventGenerator
& generator
= GetEventGenerator();
675 generator
.PressKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
);
676 generator
.ReleaseKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
);
678 EXPECT_EQ(1, target_a
.accelerator_pressed_count());
679 EXPECT_EQ(0, target_a
.accelerator_repeat_count());
681 // Long press should generate one
682 generator
.PressKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
);
683 generator
.PressKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
| ui::EF_IS_REPEAT
);
684 EXPECT_EQ(2, target_a
.accelerator_pressed_count());
685 EXPECT_EQ(1, target_a
.accelerator_repeat_count());
686 generator
.PressKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
| ui::EF_IS_REPEAT
);
687 EXPECT_EQ(2, target_a
.accelerator_pressed_count());
688 EXPECT_EQ(2, target_a
.accelerator_repeat_count());
689 generator
.ReleaseKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
);
690 EXPECT_EQ(2, target_a
.accelerator_pressed_count());
691 EXPECT_EQ(2, target_a
.accelerator_repeat_count());
693 // Long press was intercepted by another key press.
694 generator
.PressKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
);
695 generator
.PressKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
| ui::EF_IS_REPEAT
);
696 generator
.PressKey(ui::VKEY_B
, ui::EF_CONTROL_DOWN
);
697 generator
.ReleaseKey(ui::VKEY_B
, ui::EF_CONTROL_DOWN
);
698 generator
.PressKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
);
699 generator
.PressKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
| ui::EF_IS_REPEAT
);
700 generator
.ReleaseKey(ui::VKEY_A
, ui::EF_CONTROL_DOWN
);
702 EXPECT_EQ(1, target_b
.accelerator_pressed_count());
703 EXPECT_EQ(0, target_b
.accelerator_repeat_count());
704 EXPECT_EQ(4, target_a
.accelerator_pressed_count());
705 EXPECT_EQ(4, target_a
.accelerator_repeat_count());
708 TEST_F(AcceleratorControllerTest
, Previous
) {
709 ui::test::EventGenerator
& generator
= GetEventGenerator();
710 generator
.PressKey(ui::VKEY_VOLUME_MUTE
, ui::EF_NONE
);
711 generator
.ReleaseKey(ui::VKEY_VOLUME_MUTE
, ui::EF_NONE
);
713 EXPECT_EQ(ui::VKEY_VOLUME_MUTE
,
714 GetPreviousAccelerator().key_code());
715 EXPECT_EQ(ui::EF_NONE
,
716 GetPreviousAccelerator().modifiers());
718 generator
.PressKey(ui::VKEY_TAB
, ui::EF_CONTROL_DOWN
);
719 generator
.ReleaseKey(ui::VKEY_TAB
, ui::EF_CONTROL_DOWN
);
721 EXPECT_EQ(ui::VKEY_TAB
,
722 GetPreviousAccelerator().key_code());
723 EXPECT_EQ(ui::EF_CONTROL_DOWN
,
724 GetPreviousAccelerator().modifiers());
727 TEST_F(AcceleratorControllerTest
, DontRepeatToggleFullscreen
) {
728 const AcceleratorData accelerators
[] = {
729 {true, ui::VKEY_J
, ui::EF_ALT_DOWN
, TOGGLE_FULLSCREEN
},
730 {true, ui::VKEY_K
, ui::EF_ALT_DOWN
, TOGGLE_FULLSCREEN
},
732 GetController()->RegisterAccelerators(accelerators
, arraysize(accelerators
));
734 views::Widget::InitParams
params(views::Widget::InitParams::TYPE_WINDOW
);
735 params
.context
= CurrentContext();
736 params
.bounds
= gfx::Rect(5, 5, 20, 20);
737 views::Widget
* widget
= new views::Widget
;
738 widget
->Init(params
);
741 widget
->GetNativeView()->SetProperty(aura::client::kCanMaximizeKey
, true);
743 ui::test::EventGenerator
& generator
= GetEventGenerator();
744 wm::WindowState
* window_state
= wm::GetWindowState(widget
->GetNativeView());
746 // Toggling not suppressed.
747 generator
.PressKey(ui::VKEY_J
, ui::EF_ALT_DOWN
);
748 EXPECT_TRUE(window_state
->IsFullscreen());
750 // The same accelerator - toggling suppressed.
751 generator
.PressKey(ui::VKEY_J
, ui::EF_ALT_DOWN
| ui::EF_IS_REPEAT
);
752 EXPECT_TRUE(window_state
->IsFullscreen());
754 // Different accelerator.
755 generator
.PressKey(ui::VKEY_K
, ui::EF_ALT_DOWN
);
756 EXPECT_FALSE(window_state
->IsFullscreen());
759 // TODO(oshima): Fix this test to use EventGenerator.
762 #define MAYBE_ProcessOnce DISABLED_ProcessOnce
764 #define MAYBE_ProcessOnce ProcessOnce
767 #if defined(OS_WIN) || defined(USE_X11)
768 TEST_F(AcceleratorControllerTest
, MAYBE_ProcessOnce
) {
769 ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
771 GetController()->Register(accelerator_a
, &target
);
773 // The accelerator is processed only once.
774 ui::EventProcessor
* dispatcher
=
775 Shell::GetPrimaryRootWindow()->GetHost()->event_processor();
777 MSG msg1
= { NULL
, WM_KEYDOWN
, ui::VKEY_A
, 0 };
778 ui::KeyEvent
key_event1(msg1
);
779 key_event1
.SetTranslated(true);
780 ui::EventDispatchDetails details
= dispatcher
->OnEventFromSource(&key_event1
);
781 EXPECT_TRUE(key_event1
.handled() || details
.dispatcher_destroyed
);
783 MSG msg2
= { NULL
, WM_CHAR
, L
'A', 0 };
784 ui::KeyEvent
key_event2(msg2
);
785 key_event2
.SetTranslated(true);
786 details
= dispatcher
->OnEventFromSource(&key_event2
);
787 EXPECT_FALSE(key_event2
.handled() || details
.dispatcher_destroyed
);
789 MSG msg3
= { NULL
, WM_KEYUP
, ui::VKEY_A
, 0 };
790 ui::KeyEvent
key_event3(msg3
);
791 key_event3
.SetTranslated(true);
792 details
= dispatcher
->OnEventFromSource(&key_event3
);
793 EXPECT_FALSE(key_event3
.handled() || details
.dispatcher_destroyed
);
794 #elif defined(USE_X11)
795 ui::ScopedXI2Event key_event
;
796 key_event
.InitKeyEvent(ui::ET_KEY_PRESSED
, ui::VKEY_A
, 0);
797 ui::KeyEvent
key_event1(key_event
);
798 key_event1
.SetTranslated(true);
799 ui::EventDispatchDetails details
= dispatcher
->OnEventFromSource(&key_event1
);
800 EXPECT_TRUE(key_event1
.handled() || details
.dispatcher_destroyed
);
802 ui::KeyEvent
key_event2('A', ui::VKEY_A
, ui::EF_NONE
);
803 key_event2
.SetTranslated(true);
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 key_event3
.SetTranslated(true);
810 details
= dispatcher
->OnEventFromSource(&key_event3
);
811 EXPECT_FALSE(key_event3
.handled() || details
.dispatcher_destroyed
);
813 EXPECT_EQ(1, target
.accelerator_pressed_count());
817 TEST_F(AcceleratorControllerTest
, GlobalAccelerators
) {
819 EXPECT_TRUE(ProcessInController(
820 ui::Accelerator(ui::VKEY_TAB
, ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
)));
823 ProcessInController(ui::Accelerator(
824 ui::VKEY_TAB
, ui::EF_ALT_DOWN
)));
826 EXPECT_TRUE(ProcessInController(
827 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_NONE
)));
829 #if defined(OS_CHROMEOS)
830 // The "Take Screenshot", "Take Partial Screenshot", volume, brightness, and
831 // keyboard brightness accelerators are only defined on ChromeOS.
833 test::TestScreenshotDelegate
* delegate
= GetScreenshotDelegate();
834 delegate
->set_can_take_screenshot(false);
835 EXPECT_TRUE(ProcessInController(
836 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_CONTROL_DOWN
)));
838 ProcessInController(ui::Accelerator(
839 ui::VKEY_PRINT
, ui::EF_NONE
)));
840 EXPECT_TRUE(ProcessInController(ui::Accelerator(
841 ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
843 delegate
->set_can_take_screenshot(true);
844 EXPECT_EQ(0, delegate
->handle_take_screenshot_count());
845 EXPECT_TRUE(ProcessInController(
846 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_CONTROL_DOWN
)));
847 EXPECT_EQ(1, delegate
->handle_take_screenshot_count());
849 ProcessInController(ui::Accelerator(
850 ui::VKEY_PRINT
, ui::EF_NONE
)));
851 EXPECT_EQ(2, delegate
->handle_take_screenshot_count());
852 EXPECT_TRUE(ProcessInController(ui::Accelerator(
853 ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
854 EXPECT_EQ(2, delegate
->handle_take_screenshot_count());
856 const ui::Accelerator
volume_mute(ui::VKEY_VOLUME_MUTE
, ui::EF_NONE
);
857 const ui::Accelerator
volume_down(ui::VKEY_VOLUME_DOWN
, ui::EF_NONE
);
858 const ui::Accelerator
volume_up(ui::VKEY_VOLUME_UP
, ui::EF_NONE
);
860 TestVolumeControlDelegate
* delegate
= new TestVolumeControlDelegate
;
861 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
862 scoped_ptr
<VolumeControlDelegate
>(delegate
).Pass());
863 EXPECT_EQ(0, delegate
->handle_volume_mute_count());
864 EXPECT_TRUE(ProcessInController(volume_mute
));
865 EXPECT_EQ(1, delegate
->handle_volume_mute_count());
866 EXPECT_EQ(volume_mute
, delegate
->last_accelerator());
867 EXPECT_EQ(0, delegate
->handle_volume_down_count());
868 EXPECT_TRUE(ProcessInController(volume_down
));
869 EXPECT_EQ(1, delegate
->handle_volume_down_count());
870 EXPECT_EQ(volume_down
, delegate
->last_accelerator());
871 EXPECT_EQ(0, delegate
->handle_volume_up_count());
872 EXPECT_TRUE(ProcessInController(volume_up
));
873 EXPECT_EQ(1, delegate
->handle_volume_up_count());
874 EXPECT_EQ(volume_up
, delegate
->last_accelerator());
877 // ui::VKEY_BRIGHTNESS_DOWN/UP are not defined on Windows.
878 const ui::Accelerator
brightness_down(ui::VKEY_BRIGHTNESS_DOWN
, ui::EF_NONE
);
879 const ui::Accelerator
brightness_up(ui::VKEY_BRIGHTNESS_UP
, ui::EF_NONE
);
881 DummyBrightnessControlDelegate
* delegate
=
882 new DummyBrightnessControlDelegate
;
883 GetController()->SetBrightnessControlDelegate(
884 scoped_ptr
<BrightnessControlDelegate
>(delegate
).Pass());
885 EXPECT_EQ(0, delegate
->handle_brightness_down_count());
886 EXPECT_TRUE(ProcessInController(brightness_down
));
887 EXPECT_EQ(1, delegate
->handle_brightness_down_count());
888 EXPECT_EQ(brightness_down
, delegate
->last_accelerator());
889 EXPECT_EQ(0, delegate
->handle_brightness_up_count());
890 EXPECT_TRUE(ProcessInController(brightness_up
));
891 EXPECT_EQ(1, delegate
->handle_brightness_up_count());
892 EXPECT_EQ(brightness_up
, delegate
->last_accelerator());
895 // Keyboard brightness
896 const ui::Accelerator
alt_brightness_down(ui::VKEY_BRIGHTNESS_DOWN
,
898 const ui::Accelerator
alt_brightness_up(ui::VKEY_BRIGHTNESS_UP
,
901 EXPECT_TRUE(ProcessInController(alt_brightness_down
));
902 EXPECT_TRUE(ProcessInController(alt_brightness_up
));
903 DummyKeyboardBrightnessControlDelegate
* delegate
=
904 new DummyKeyboardBrightnessControlDelegate
;
905 GetController()->SetKeyboardBrightnessControlDelegate(
906 scoped_ptr
<KeyboardBrightnessControlDelegate
>(delegate
).Pass());
907 EXPECT_EQ(0, delegate
->handle_keyboard_brightness_down_count());
908 EXPECT_TRUE(ProcessInController(alt_brightness_down
));
909 EXPECT_EQ(1, delegate
->handle_keyboard_brightness_down_count());
910 EXPECT_EQ(alt_brightness_down
, delegate
->last_accelerator());
911 EXPECT_EQ(0, delegate
->handle_keyboard_brightness_up_count());
912 EXPECT_TRUE(ProcessInController(alt_brightness_up
));
913 EXPECT_EQ(1, delegate
->handle_keyboard_brightness_up_count());
914 EXPECT_EQ(alt_brightness_up
, delegate
->last_accelerator());
920 ExitWarningHandler
* ewh
= GetController()->GetExitWarningHandlerForTest();
923 EXPECT_TRUE(is_idle(ewh
));
924 EXPECT_FALSE(is_ui_shown(ewh
));
925 EXPECT_TRUE(ProcessInController(
926 ui::Accelerator(ui::VKEY_Q
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
927 EXPECT_FALSE(is_idle(ewh
));
928 EXPECT_TRUE(is_ui_shown(ewh
));
929 SimulateTimerExpired(ewh
);
930 EXPECT_TRUE(is_idle(ewh
));
931 EXPECT_FALSE(is_ui_shown(ewh
));
936 EXPECT_TRUE(ProcessInController(
937 ui::Accelerator(ui::VKEY_T
, ui::EF_CONTROL_DOWN
)));
939 // New incognito window
940 EXPECT_TRUE(ProcessInController(
941 ui::Accelerator(ui::VKEY_N
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
944 EXPECT_TRUE(ProcessInController(
945 ui::Accelerator(ui::VKEY_N
, ui::EF_CONTROL_DOWN
)));
948 EXPECT_TRUE(ProcessInController(
949 ui::Accelerator(ui::VKEY_T
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
952 EXPECT_TRUE(ProcessInController(
953 ui::Accelerator(ui::VKEY_ESCAPE
, ui::EF_SHIFT_DOWN
)));
955 #if defined(OS_CHROMEOS)
957 EXPECT_TRUE(ProcessInController(
958 ui::Accelerator(ui::VKEY_M
, ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
)));
961 // NOTE: Accelerators that do not work on the lock screen need to be
962 // tested before the sequence below is invoked because it causes a side
963 // effect of locking the screen.
964 EXPECT_TRUE(ProcessInController(
965 ui::Accelerator(ui::VKEY_L
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
969 TEST_F(AcceleratorControllerTest
, GlobalAcceleratorsToggleAppList
) {
970 AccessibilityDelegate
* delegate
=
971 ash::Shell::GetInstance()->accessibility_delegate();
972 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
974 // The press event should not open the AppList, the release should instead.
976 ProcessInController(ui::Accelerator(ui::VKEY_LWIN
, ui::EF_NONE
)));
977 EXPECT_EQ(ui::VKEY_LWIN
,
978 GetCurrentAccelerator().key_code());
980 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
983 ProcessInController(ReleaseAccelerator(ui::VKEY_LWIN
, ui::EF_NONE
)));
984 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
986 EXPECT_EQ(ui::VKEY_LWIN
,
987 GetPreviousAccelerator().key_code());
989 // When spoken feedback is on, the AppList should not toggle.
990 delegate
->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE
);
992 ProcessInController(ui::Accelerator(ui::VKEY_LWIN
, ui::EF_NONE
)));
994 ProcessInController(ReleaseAccelerator(
995 ui::VKEY_LWIN
, ui::EF_NONE
)));
996 delegate
->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE
);
997 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1000 ProcessInController(ui::Accelerator(ui::VKEY_LWIN
, ui::EF_NONE
)));
1002 ProcessInController(ReleaseAccelerator(
1003 ui::VKEY_LWIN
, ui::EF_NONE
)));
1004 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1006 // When spoken feedback is on, the AppList should not toggle.
1007 delegate
->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE
);
1009 ProcessInController(ui::Accelerator(ui::VKEY_LWIN
, ui::EF_NONE
)));
1011 ProcessInController(ReleaseAccelerator(
1012 ui::VKEY_LWIN
, ui::EF_NONE
)));
1013 delegate
->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE
);
1014 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1016 #if defined(OS_CHROMEOS)
1017 // The press of VKEY_BROWSER_SEARCH should toggle the AppList
1018 EXPECT_TRUE(ProcessInController(ui::Accelerator(ui::VKEY_BROWSER_SEARCH
,
1020 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1021 EXPECT_FALSE(ProcessInController(ReleaseAccelerator(ui::VKEY_BROWSER_SEARCH
,
1023 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1027 TEST_F(AcceleratorControllerTest
, ImeGlobalAccelerators
) {
1028 // Test IME shortcuts.
1030 const ui::Accelerator
control_space(ui::VKEY_SPACE
, ui::EF_CONTROL_DOWN
);
1031 const ui::Accelerator
convert(ui::VKEY_CONVERT
, ui::EF_NONE
);
1032 const ui::Accelerator
non_convert(ui::VKEY_NONCONVERT
, ui::EF_NONE
);
1033 const ui::Accelerator
wide_half_1(ui::VKEY_DBE_SBCSCHAR
, ui::EF_NONE
);
1034 const ui::Accelerator
wide_half_2(ui::VKEY_DBE_DBCSCHAR
, ui::EF_NONE
);
1035 const ui::Accelerator
hangul(ui::VKEY_HANGUL
, ui::EF_NONE
);
1036 EXPECT_FALSE(ProcessInController(control_space
));
1037 EXPECT_FALSE(ProcessInController(convert
));
1038 EXPECT_FALSE(ProcessInController(non_convert
));
1039 EXPECT_FALSE(ProcessInController(wide_half_1
));
1040 EXPECT_FALSE(ProcessInController(wide_half_2
));
1041 EXPECT_FALSE(ProcessInController(hangul
));
1042 DummyImeControlDelegate
* delegate
= new DummyImeControlDelegate
;
1043 GetController()->SetImeControlDelegate(
1044 scoped_ptr
<ImeControlDelegate
>(delegate
).Pass());
1045 EXPECT_EQ(0, delegate
->handle_previous_ime_count());
1046 EXPECT_TRUE(ProcessInController(control_space
));
1047 EXPECT_EQ(1, delegate
->handle_previous_ime_count());
1048 EXPECT_EQ(0, delegate
->handle_switch_ime_count());
1049 EXPECT_TRUE(ProcessInController(convert
));
1050 EXPECT_EQ(1, delegate
->handle_switch_ime_count());
1051 EXPECT_TRUE(ProcessInController(non_convert
));
1052 EXPECT_EQ(2, delegate
->handle_switch_ime_count());
1053 EXPECT_TRUE(ProcessInController(wide_half_1
));
1054 EXPECT_EQ(3, delegate
->handle_switch_ime_count());
1055 EXPECT_TRUE(ProcessInController(wide_half_2
));
1056 EXPECT_EQ(4, delegate
->handle_switch_ime_count());
1057 EXPECT_TRUE(ProcessInController(hangul
));
1058 EXPECT_EQ(5, delegate
->handle_switch_ime_count());
1061 // Test IME shortcuts that are triggered on key release.
1063 const ui::Accelerator
shift_alt_press(ui::VKEY_MENU
,
1064 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1065 const ReleaseAccelerator
shift_alt(ui::VKEY_MENU
, ui::EF_SHIFT_DOWN
);
1066 const ui::Accelerator
alt_shift_press(ui::VKEY_SHIFT
,
1067 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1068 const ReleaseAccelerator
alt_shift(ui::VKEY_SHIFT
, ui::EF_ALT_DOWN
);
1070 DummyImeControlDelegate
* delegate
= new DummyImeControlDelegate
;
1071 GetController()->SetImeControlDelegate(
1072 scoped_ptr
<ImeControlDelegate
>(delegate
).Pass());
1073 EXPECT_EQ(0, delegate
->handle_next_ime_count());
1074 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1075 EXPECT_FALSE(ProcessInController(shift_alt
));
1076 EXPECT_EQ(1, delegate
->handle_next_ime_count());
1077 EXPECT_FALSE(ProcessInController(alt_shift_press
));
1078 EXPECT_FALSE(ProcessInController(alt_shift
));
1079 EXPECT_EQ(2, delegate
->handle_next_ime_count());
1081 // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is
1083 const ui::Accelerator
shift_alt_x_press(
1085 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1086 const ReleaseAccelerator
shift_alt_x(ui::VKEY_X
,
1087 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1089 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1090 EXPECT_FALSE(ProcessInController(shift_alt_x_press
));
1091 EXPECT_FALSE(ProcessInController(shift_alt_x
));
1092 EXPECT_FALSE(ProcessInController(shift_alt
));
1093 EXPECT_EQ(2, delegate
->handle_next_ime_count());
1095 // But we _should_ if X is either VKEY_RETURN or VKEY_SPACE.
1096 // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
1097 const ui::Accelerator
shift_alt_return_press(
1099 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1100 const ReleaseAccelerator
shift_alt_return(
1102 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1104 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1105 EXPECT_FALSE(ProcessInController(shift_alt_return_press
));
1106 EXPECT_FALSE(ProcessInController(shift_alt_return
));
1107 EXPECT_FALSE(ProcessInController(shift_alt
));
1108 EXPECT_EQ(3, delegate
->handle_next_ime_count());
1110 const ui::Accelerator
shift_alt_space_press(
1112 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1113 const ReleaseAccelerator
shift_alt_space(
1115 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1117 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1118 EXPECT_FALSE(ProcessInController(shift_alt_space_press
));
1119 EXPECT_FALSE(ProcessInController(shift_alt_space
));
1120 EXPECT_FALSE(ProcessInController(shift_alt
));
1121 EXPECT_EQ(4, delegate
->handle_next_ime_count());
1124 #if defined(OS_CHROMEOS)
1125 // Test IME shortcuts again with unnormalized accelerators (Chrome OS only).
1127 const ui::Accelerator
shift_alt_press(ui::VKEY_MENU
, ui::EF_SHIFT_DOWN
);
1128 const ReleaseAccelerator
shift_alt(ui::VKEY_MENU
, ui::EF_SHIFT_DOWN
);
1129 const ui::Accelerator
alt_shift_press(ui::VKEY_SHIFT
, ui::EF_ALT_DOWN
);
1130 const ReleaseAccelerator
alt_shift(ui::VKEY_SHIFT
, ui::EF_ALT_DOWN
);
1132 DummyImeControlDelegate
* delegate
= new DummyImeControlDelegate
;
1133 GetController()->SetImeControlDelegate(
1134 scoped_ptr
<ImeControlDelegate
>(delegate
).Pass());
1135 EXPECT_EQ(0, delegate
->handle_next_ime_count());
1136 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1137 EXPECT_FALSE(ProcessInController(shift_alt
));
1138 EXPECT_EQ(1, delegate
->handle_next_ime_count());
1139 EXPECT_FALSE(ProcessInController(alt_shift_press
));
1140 EXPECT_FALSE(ProcessInController(alt_shift
));
1141 EXPECT_EQ(2, delegate
->handle_next_ime_count());
1143 // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is
1145 const ui::Accelerator
shift_alt_x_press(
1147 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1148 const ReleaseAccelerator
shift_alt_x(ui::VKEY_X
,
1149 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1151 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1152 EXPECT_FALSE(ProcessInController(shift_alt_x_press
));
1153 EXPECT_FALSE(ProcessInController(shift_alt_x
));
1154 EXPECT_FALSE(ProcessInController(shift_alt
));
1155 EXPECT_EQ(2, delegate
->handle_next_ime_count());
1160 // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
1161 TEST_F(AcceleratorControllerTest
, ImeGlobalAcceleratorsWorkaround139556
) {
1162 // The workaround for crbug.com/139556 depends on the fact that we don't
1163 // use Shift+Alt+Enter/Space with ET_KEY_PRESSED as an accelerator. Test it.
1164 const ui::Accelerator
shift_alt_return_press(
1166 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1167 EXPECT_FALSE(ProcessInController(shift_alt_return_press
));
1168 const ui::Accelerator
shift_alt_space_press(
1170 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1171 EXPECT_FALSE(ProcessInController(shift_alt_space_press
));
1174 TEST_F(AcceleratorControllerTest
, PreferredReservedAccelerators
) {
1175 #if defined(OS_CHROMEOS)
1176 // Power key is reserved on chromeos.
1177 EXPECT_TRUE(GetController()->IsReserved(
1178 ui::Accelerator(ui::VKEY_POWER
, ui::EF_NONE
)));
1179 EXPECT_FALSE(GetController()->IsPreferred(
1180 ui::Accelerator(ui::VKEY_POWER
, ui::EF_NONE
)));
1182 // ALT+Tab are not reserved but preferred.
1183 EXPECT_FALSE(GetController()->IsReserved(
1184 ui::Accelerator(ui::VKEY_TAB
, ui::EF_ALT_DOWN
)));
1185 EXPECT_FALSE(GetController()->IsReserved(
1186 ui::Accelerator(ui::VKEY_TAB
, ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
)));
1187 EXPECT_TRUE(GetController()->IsPreferred(
1188 ui::Accelerator(ui::VKEY_TAB
, ui::EF_ALT_DOWN
)));
1189 EXPECT_TRUE(GetController()->IsPreferred(
1190 ui::Accelerator(ui::VKEY_TAB
, ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
)));
1192 // Others are not reserved nor preferred
1193 EXPECT_FALSE(GetController()->IsReserved(
1194 ui::Accelerator(ui::VKEY_PRINT
, ui::EF_NONE
)));
1195 EXPECT_FALSE(GetController()->IsPreferred(
1196 ui::Accelerator(ui::VKEY_PRINT
, ui::EF_NONE
)));
1197 EXPECT_FALSE(GetController()->IsReserved(
1198 ui::Accelerator(ui::VKEY_TAB
, ui::EF_NONE
)));
1199 EXPECT_FALSE(GetController()->IsPreferred(
1200 ui::Accelerator(ui::VKEY_TAB
, ui::EF_NONE
)));
1201 EXPECT_FALSE(GetController()->IsReserved(
1202 ui::Accelerator(ui::VKEY_A
, ui::EF_NONE
)));
1203 EXPECT_FALSE(GetController()->IsPreferred(
1204 ui::Accelerator(ui::VKEY_A
, ui::EF_NONE
)));
1209 class PreferredReservedAcceleratorsTest
: public test::AshTestBase
{
1211 PreferredReservedAcceleratorsTest() {}
1212 ~PreferredReservedAcceleratorsTest() override
{}
1214 // test::AshTestBase:
1215 void SetUp() override
{
1216 AshTestBase::SetUp();
1217 Shell::GetInstance()->lock_state_controller()->
1218 set_animator_for_test(new test::TestSessionStateAnimator
);
1222 DISALLOW_COPY_AND_ASSIGN(PreferredReservedAcceleratorsTest
);
1227 TEST_F(PreferredReservedAcceleratorsTest
, AcceleratorsWithFullscreen
) {
1228 aura::Window
* w1
= CreateTestWindowInShellWithId(0);
1229 aura::Window
* w2
= CreateTestWindowInShellWithId(1);
1230 wm::ActivateWindow(w1
);
1232 wm::WMEvent
fullscreen(wm::WM_EVENT_FULLSCREEN
);
1233 wm::WindowState
* w1_state
= wm::GetWindowState(w1
);
1234 w1_state
->OnWMEvent(&fullscreen
);
1235 ASSERT_TRUE(w1_state
->IsFullscreen());
1237 ui::test::EventGenerator
& generator
= GetEventGenerator();
1238 #if defined(OS_CHROMEOS)
1239 // Power key (reserved) should always be handled.
1240 LockStateController::TestApi
test_api(
1241 Shell::GetInstance()->lock_state_controller());
1242 EXPECT_FALSE(test_api
.is_animating_lock());
1243 generator
.PressKey(ui::VKEY_POWER
, ui::EF_NONE
);
1244 EXPECT_TRUE(test_api
.is_animating_lock());
1247 // A fullscreen window can consume ALT-TAB (preferred).
1248 ASSERT_EQ(w1
, wm::GetActiveWindow());
1249 generator
.PressKey(ui::VKEY_TAB
, ui::EF_ALT_DOWN
);
1250 ASSERT_EQ(w1
, wm::GetActiveWindow());
1251 ASSERT_NE(w2
, wm::GetActiveWindow());
1253 // ALT-TAB is non repeatable. Press A to cancel the
1255 generator
.PressKey(ui::VKEY_A
, ui::EF_NONE
);
1256 generator
.ReleaseKey(ui::VKEY_A
, ui::EF_NONE
);
1258 // A normal window shouldn't consume preferred accelerator.
1259 wm::WMEvent
normal(wm::WM_EVENT_NORMAL
);
1260 w1_state
->OnWMEvent(&normal
);
1261 ASSERT_FALSE(w1_state
->IsFullscreen());
1263 EXPECT_EQ(w1
, wm::GetActiveWindow());
1264 generator
.PressKey(ui::VKEY_TAB
, ui::EF_ALT_DOWN
);
1265 ASSERT_NE(w1
, wm::GetActiveWindow());
1266 ASSERT_EQ(w2
, wm::GetActiveWindow());
1269 #if defined(OS_CHROMEOS)
1270 TEST_F(AcceleratorControllerTest
, DisallowedAtModalWindow
) {
1271 std::set
<AcceleratorAction
> all_actions
;
1272 for (size_t i
= 0 ; i
< kAcceleratorDataLength
; ++i
)
1273 all_actions
.insert(kAcceleratorData
[i
].action
);
1274 std::set
<AcceleratorAction
> all_debug_actions
;
1275 for (size_t i
= 0 ; i
< kDebugAcceleratorDataLength
; ++i
)
1276 all_debug_actions
.insert(kDebugAcceleratorData
[i
].action
);
1278 std::set
<AcceleratorAction
> actionsAllowedAtModalWindow
;
1279 for (size_t k
= 0 ; k
< kActionsAllowedAtModalWindowLength
; ++k
)
1280 actionsAllowedAtModalWindow
.insert(kActionsAllowedAtModalWindow
[k
]);
1281 for (std::set
<AcceleratorAction
>::const_iterator it
=
1282 actionsAllowedAtModalWindow
.begin();
1283 it
!= actionsAllowedAtModalWindow
.end(); ++it
) {
1284 EXPECT_TRUE(all_actions
.find(*it
) != all_actions
.end() ||
1285 all_debug_actions
.find(*it
) != all_debug_actions
.end())
1286 << " action from kActionsAllowedAtModalWindow"
1287 << " not found in kAcceleratorData or kDebugAcceleratorData. "
1288 << "action: " << *it
;
1290 scoped_ptr
<aura::Window
> window(
1291 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1292 wm::ActivateWindow(window
.get());
1293 Shell::GetInstance()->SimulateModalWindowOpenForTesting(true);
1294 for (std::set
<AcceleratorAction
>::const_iterator it
= all_actions
.begin();
1295 it
!= all_actions
.end(); ++it
) {
1296 if (actionsAllowedAtModalWindow
.find(*it
) ==
1297 actionsAllowedAtModalWindow
.end()) {
1298 EXPECT_TRUE(GetController()->PerformActionIfEnabled(*it
))
1299 << " for action (disallowed at modal window): " << *it
;
1302 // Testing of top row (F5-F10) accelerators that should still work
1303 // when a modal window is open
1307 test::TestScreenshotDelegate
* delegate
= GetScreenshotDelegate();
1308 delegate
->set_can_take_screenshot(false);
1309 EXPECT_TRUE(ProcessInController(
1310 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_CONTROL_DOWN
)));
1312 ProcessInController(ui::Accelerator(
1313 ui::VKEY_PRINT
, ui::EF_NONE
)));
1314 EXPECT_TRUE(ProcessInController(ui::Accelerator(
1315 ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
1316 delegate
->set_can_take_screenshot(true);
1317 EXPECT_EQ(0, delegate
->handle_take_screenshot_count());
1318 EXPECT_TRUE(ProcessInController(
1319 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_CONTROL_DOWN
)));
1320 EXPECT_EQ(1, delegate
->handle_take_screenshot_count());
1322 ProcessInController(ui::Accelerator(
1323 ui::VKEY_PRINT
, ui::EF_NONE
)));
1324 EXPECT_EQ(2, delegate
->handle_take_screenshot_count());
1325 EXPECT_TRUE(ProcessInController(ui::Accelerator(
1326 ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
1327 EXPECT_EQ(2, delegate
->handle_take_screenshot_count());
1330 const ui::Accelerator
brightness_down(ui::VKEY_BRIGHTNESS_DOWN
, ui::EF_NONE
);
1331 const ui::Accelerator
brightness_up(ui::VKEY_BRIGHTNESS_UP
, ui::EF_NONE
);
1333 DummyBrightnessControlDelegate
* delegate
=
1334 new DummyBrightnessControlDelegate
;
1335 GetController()->SetBrightnessControlDelegate(
1336 scoped_ptr
<BrightnessControlDelegate
>(delegate
).Pass());
1337 EXPECT_EQ(0, delegate
->handle_brightness_down_count());
1338 EXPECT_TRUE(ProcessInController(brightness_down
));
1339 EXPECT_EQ(1, delegate
->handle_brightness_down_count());
1340 EXPECT_EQ(brightness_down
, delegate
->last_accelerator());
1341 EXPECT_EQ(0, delegate
->handle_brightness_up_count());
1342 EXPECT_TRUE(ProcessInController(brightness_up
));
1343 EXPECT_EQ(1, delegate
->handle_brightness_up_count());
1344 EXPECT_EQ(brightness_up
, delegate
->last_accelerator());
1347 const ui::Accelerator
volume_mute(ui::VKEY_VOLUME_MUTE
, ui::EF_NONE
);
1348 const ui::Accelerator
volume_down(ui::VKEY_VOLUME_DOWN
, ui::EF_NONE
);
1349 const ui::Accelerator
volume_up(ui::VKEY_VOLUME_UP
, ui::EF_NONE
);
1351 EXPECT_TRUE(ProcessInController(volume_mute
));
1352 EXPECT_TRUE(ProcessInController(volume_down
));
1353 EXPECT_TRUE(ProcessInController(volume_up
));
1354 TestVolumeControlDelegate
* delegate
= new TestVolumeControlDelegate
;
1355 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
1356 scoped_ptr
<VolumeControlDelegate
>(delegate
).Pass());
1357 EXPECT_EQ(0, delegate
->handle_volume_mute_count());
1358 EXPECT_TRUE(ProcessInController(volume_mute
));
1359 EXPECT_EQ(1, delegate
->handle_volume_mute_count());
1360 EXPECT_EQ(volume_mute
, delegate
->last_accelerator());
1361 EXPECT_EQ(0, delegate
->handle_volume_down_count());
1362 EXPECT_TRUE(ProcessInController(volume_down
));
1363 EXPECT_EQ(1, delegate
->handle_volume_down_count());
1364 EXPECT_EQ(volume_down
, delegate
->last_accelerator());
1365 EXPECT_EQ(0, delegate
->handle_volume_up_count());
1366 EXPECT_TRUE(ProcessInController(volume_up
));
1367 EXPECT_EQ(1, delegate
->handle_volume_up_count());
1368 EXPECT_EQ(volume_up
, delegate
->last_accelerator());
1373 TEST_F(AcceleratorControllerTest
, DisallowedWithNoWindow
) {
1374 AccessibilityDelegate
* delegate
=
1375 ash::Shell::GetInstance()->accessibility_delegate();
1377 for (size_t i
= 0; i
< kActionsNeedingWindowLength
; ++i
) {
1378 delegate
->TriggerAccessibilityAlert(ui::A11Y_ALERT_NONE
);
1380 GetController()->PerformActionIfEnabled(kActionsNeedingWindow
[i
]));
1381 EXPECT_EQ(delegate
->GetLastAccessibilityAlert(),
1382 ui::A11Y_ALERT_WINDOW_NEEDED
);
1385 // Make sure we don't alert if we do have a window.
1386 scoped_ptr
<aura::Window
> window
;
1387 for (size_t i
= 0; i
< kActionsNeedingWindowLength
; ++i
) {
1388 window
.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1389 wm::ActivateWindow(window
.get());
1390 delegate
->TriggerAccessibilityAlert(ui::A11Y_ALERT_NONE
);
1391 GetController()->PerformActionIfEnabled(kActionsNeedingWindow
[i
]);
1392 EXPECT_NE(delegate
->GetLastAccessibilityAlert(),
1393 ui::A11Y_ALERT_WINDOW_NEEDED
);
1396 // Don't alert if we have a minimized window either.
1397 for (size_t i
= 0; i
< kActionsNeedingWindowLength
; ++i
) {
1398 window
.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1399 wm::ActivateWindow(window
.get());
1400 GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE
);
1401 delegate
->TriggerAccessibilityAlert(ui::A11Y_ALERT_NONE
);
1402 GetController()->PerformActionIfEnabled(kActionsNeedingWindow
[i
]);
1403 EXPECT_NE(delegate
->GetLastAccessibilityAlert(),
1404 ui::A11Y_ALERT_WINDOW_NEEDED
);