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 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
{
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
);
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
{
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_
;
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_
;
209 ++accelerator_pressed_count_
;
213 bool TestTarget::CanHandleAccelerators() const {
219 class AcceleratorControllerTest
: public test::AshTestBase
{
221 AcceleratorControllerTest() {}
222 ~AcceleratorControllerTest() override
{}
225 void EnableInternalDisplay() {
226 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()).
227 SetFirstDisplayAsInternalDisplay();
230 static AcceleratorController
* GetController();
232 static bool ProcessInController(const ui::Accelerator
& accelerator
) {
233 GetController()->accelerator_history()->
234 StoreCurrentAccelerator(accelerator
);
235 return GetController()->Process(accelerator
);
238 static const ui::Accelerator
& GetPreviousAccelerator() {
239 return GetController()->accelerator_history()->
240 previous_accelerator();
243 static const ui::Accelerator
& GetCurrentAccelerator() {
244 return GetController()->accelerator_history()->
245 current_accelerator();
248 // Several functions to access ExitWarningHandler (as friend).
249 static void StubForTest(ExitWarningHandler
* ewh
) {
250 ewh
->stub_timer_for_test_
= true;
252 static void Reset(ExitWarningHandler
* ewh
) {
253 ewh
->state_
= ExitWarningHandler::IDLE
;
255 static void SimulateTimerExpired(ExitWarningHandler
* ewh
) {
258 static bool is_ui_shown(ExitWarningHandler
* ewh
) {
259 return !!ewh
->widget_
;
261 static bool is_idle(ExitWarningHandler
* ewh
) {
262 return ewh
->state_
== ExitWarningHandler::IDLE
;
264 static bool is_exiting(ExitWarningHandler
* ewh
) {
265 return ewh
->state_
== ExitWarningHandler::EXITING
;
267 aura::Window
* CreatePanel() {
268 aura::Window
* window
=
269 CreateTestWindowInShellWithDelegateAndType(NULL
,
270 ui::wm::WINDOW_TYPE_PANEL
, 0, gfx::Rect(5, 5, 20, 20));
271 test::TestShelfDelegate
* shelf_delegate
=
272 test::TestShelfDelegate::instance();
273 shelf_delegate
->AddShelfItem(window
);
274 PanelLayoutManager
* manager
= static_cast<PanelLayoutManager
*>(
275 Shell::GetContainer(window
->GetRootWindow(),
276 kShellWindowId_PanelContainer
)->layout_manager());
282 DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest
);
285 AcceleratorController
* AcceleratorControllerTest::GetController() {
286 return Shell::GetInstance()->accelerator_controller();
290 // Double press of exit shortcut => exiting
291 TEST_F(AcceleratorControllerTest
, ExitWarningHandlerTestDoublePress
) {
292 ui::Accelerator
press(ui::VKEY_Q
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
);
293 ui::Accelerator
release(press
);
294 release
.set_type(ui::ET_KEY_RELEASED
);
295 ExitWarningHandler
* ewh
= GetController()->GetExitWarningHandlerForTest();
298 EXPECT_TRUE(is_idle(ewh
));
299 EXPECT_FALSE(is_ui_shown(ewh
));
300 EXPECT_TRUE(ProcessInController(press
));
301 EXPECT_FALSE(ProcessInController(release
));
302 EXPECT_FALSE(is_idle(ewh
));
303 EXPECT_TRUE(is_ui_shown(ewh
));
304 EXPECT_TRUE(ProcessInController(press
)); // second press before timer.
305 EXPECT_FALSE(ProcessInController(release
));
306 SimulateTimerExpired(ewh
);
307 EXPECT_TRUE(is_exiting(ewh
));
308 EXPECT_FALSE(is_ui_shown(ewh
));
312 // Single press of exit shortcut before timer => idle
313 TEST_F(AcceleratorControllerTest
, ExitWarningHandlerTestSinglePress
) {
314 ui::Accelerator
press(ui::VKEY_Q
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
);
315 ui::Accelerator
release(press
);
316 release
.set_type(ui::ET_KEY_RELEASED
);
317 ExitWarningHandler
* ewh
= GetController()->GetExitWarningHandlerForTest();
320 EXPECT_TRUE(is_idle(ewh
));
321 EXPECT_FALSE(is_ui_shown(ewh
));
322 EXPECT_TRUE(ProcessInController(press
));
323 EXPECT_FALSE(ProcessInController(release
));
324 EXPECT_FALSE(is_idle(ewh
));
325 EXPECT_TRUE(is_ui_shown(ewh
));
326 SimulateTimerExpired(ewh
);
327 EXPECT_TRUE(is_idle(ewh
));
328 EXPECT_FALSE(is_ui_shown(ewh
));
332 // Shutdown ash with exit warning bubble open should not crash.
333 TEST_F(AcceleratorControllerTest
, LingeringExitWarningBubble
) {
334 ExitWarningHandler
* ewh
= GetController()->GetExitWarningHandlerForTest();
338 // Trigger once to show the bubble.
339 ewh
->HandleAccelerator();
340 EXPECT_FALSE(is_idle(ewh
));
341 EXPECT_TRUE(is_ui_shown(ewh
));
343 // Exit ash and there should be no crash
345 #endif // !defined(OS_WIN)
347 TEST_F(AcceleratorControllerTest
, Register
) {
348 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
350 GetController()->Register(accelerator_a
, &target
);
352 // The registered accelerator is processed.
353 EXPECT_TRUE(ProcessInController(accelerator_a
));
354 EXPECT_EQ(1, target
.accelerator_pressed_count());
357 TEST_F(AcceleratorControllerTest
, RegisterMultipleTarget
) {
358 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
360 GetController()->Register(accelerator_a
, &target1
);
362 GetController()->Register(accelerator_a
, &target2
);
364 // If multiple targets are registered with the same accelerator, the target
365 // registered later processes the accelerator.
366 EXPECT_TRUE(ProcessInController(accelerator_a
));
367 EXPECT_EQ(0, target1
.accelerator_pressed_count());
368 EXPECT_EQ(1, target2
.accelerator_pressed_count());
371 TEST_F(AcceleratorControllerTest
, Unregister
) {
372 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
374 GetController()->Register(accelerator_a
, &target
);
375 const ui::Accelerator
accelerator_b(ui::VKEY_B
, ui::EF_NONE
);
376 GetController()->Register(accelerator_b
, &target
);
378 // Unregistering a different accelerator does not affect the other
380 GetController()->Unregister(accelerator_b
, &target
);
381 EXPECT_TRUE(ProcessInController(accelerator_a
));
382 EXPECT_EQ(1, target
.accelerator_pressed_count());
384 // The unregistered accelerator is no longer processed.
386 GetController()->Unregister(accelerator_a
, &target
);
387 EXPECT_FALSE(ProcessInController(accelerator_a
));
388 EXPECT_EQ(0, target
.accelerator_pressed_count());
391 TEST_F(AcceleratorControllerTest
, UnregisterAll
) {
392 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
394 GetController()->Register(accelerator_a
, &target1
);
395 const ui::Accelerator
accelerator_b(ui::VKEY_B
, ui::EF_NONE
);
396 GetController()->Register(accelerator_b
, &target1
);
397 const ui::Accelerator
accelerator_c(ui::VKEY_C
, ui::EF_NONE
);
399 GetController()->Register(accelerator_c
, &target2
);
400 GetController()->UnregisterAll(&target1
);
402 // All the accelerators registered for |target1| are no longer processed.
403 EXPECT_FALSE(ProcessInController(accelerator_a
));
404 EXPECT_FALSE(ProcessInController(accelerator_b
));
405 EXPECT_EQ(0, target1
.accelerator_pressed_count());
407 // UnregisterAll with a different target does not affect the other target.
408 EXPECT_TRUE(ProcessInController(accelerator_c
));
409 EXPECT_EQ(1, target2
.accelerator_pressed_count());
412 TEST_F(AcceleratorControllerTest
, Process
) {
413 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
415 GetController()->Register(accelerator_a
, &target1
);
417 // The registered accelerator is processed.
418 EXPECT_TRUE(ProcessInController(accelerator_a
));
419 EXPECT_EQ(1, target1
.accelerator_pressed_count());
421 // The non-registered accelerator is not processed.
422 const ui::Accelerator
accelerator_b(ui::VKEY_B
, ui::EF_NONE
);
423 EXPECT_FALSE(ProcessInController(accelerator_b
));
426 TEST_F(AcceleratorControllerTest
, IsRegistered
) {
427 const ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
428 const ui::Accelerator
accelerator_shift_a(ui::VKEY_A
, ui::EF_SHIFT_DOWN
);
430 GetController()->Register(accelerator_a
, &target
);
431 EXPECT_TRUE(GetController()->IsRegistered(accelerator_a
));
432 EXPECT_FALSE(GetController()->IsRegistered(accelerator_shift_a
));
433 GetController()->UnregisterAll(&target
);
434 EXPECT_FALSE(GetController()->IsRegistered(accelerator_a
));
437 TEST_F(AcceleratorControllerTest
, WindowSnap
) {
438 scoped_ptr
<aura::Window
> window(
439 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
440 wm::WindowState
* window_state
= wm::GetWindowState(window
.get());
442 window_state
->Activate();
445 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
446 gfx::Rect expected_bounds
= wm::GetDefaultLeftSnappedWindowBoundsInParent(
448 EXPECT_EQ(expected_bounds
.ToString(), window
->bounds().ToString());
451 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
452 gfx::Rect expected_bounds
= wm::GetDefaultRightSnappedWindowBoundsInParent(
454 EXPECT_EQ(expected_bounds
.ToString(), window
->bounds().ToString());
457 gfx::Rect normal_bounds
= window_state
->GetRestoreBoundsInParent();
459 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED
);
460 EXPECT_TRUE(window_state
->IsMaximized());
461 EXPECT_NE(normal_bounds
.ToString(), window
->bounds().ToString());
463 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED
);
464 EXPECT_FALSE(window_state
->IsMaximized());
465 // Window gets restored to its restore bounds since side-maximized state
466 // is treated as a "maximized" state.
467 EXPECT_EQ(normal_bounds
.ToString(), window
->bounds().ToString());
469 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED
);
470 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
471 EXPECT_FALSE(window_state
->IsMaximized());
473 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED
);
474 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
475 EXPECT_FALSE(window_state
->IsMaximized());
477 GetController()->PerformActionIfEnabled(TOGGLE_MAXIMIZED
);
478 EXPECT_TRUE(window_state
->IsMaximized());
479 GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE
);
480 EXPECT_FALSE(window_state
->IsMaximized());
481 EXPECT_TRUE(window_state
->IsMinimized());
482 window_state
->Restore();
483 window_state
->Activate();
486 GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE
);
487 EXPECT_TRUE(window_state
->IsMinimized());
491 TEST_F(AcceleratorControllerTest
, WindowSnapLeftDockLeftRestore
) {
492 scoped_ptr
<aura::Window
> window0(
493 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
494 scoped_ptr
<aura::Window
> window1(
495 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
496 wm::WindowState
* window1_state
= wm::GetWindowState(window1
.get());
497 window1_state
->Activate();
499 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
500 gfx::Rect normal_bounds
= window1_state
->GetRestoreBoundsInParent();
501 gfx::Rect expected_bounds
= wm::GetDefaultLeftSnappedWindowBoundsInParent(
503 EXPECT_EQ(expected_bounds
.ToString(), window1
->bounds().ToString());
504 EXPECT_TRUE(window1_state
->IsSnapped());
505 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
506 EXPECT_FALSE(window1_state
->IsNormalOrSnapped());
507 EXPECT_TRUE(window1_state
->IsDocked());
508 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
509 EXPECT_FALSE(window1_state
->IsDocked());
510 EXPECT_EQ(normal_bounds
.ToString(), window1
->bounds().ToString());
513 TEST_F(AcceleratorControllerTest
, WindowSnapRightDockRightRestore
) {
514 scoped_ptr
<aura::Window
> window0(
515 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
516 scoped_ptr
<aura::Window
> window1(
517 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
519 wm::WindowState
* window1_state
= wm::GetWindowState(window1
.get());
520 window1_state
->Activate();
522 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
523 gfx::Rect normal_bounds
= window1_state
->GetRestoreBoundsInParent();
524 gfx::Rect expected_bounds
=
525 wm::GetDefaultRightSnappedWindowBoundsInParent(window1
.get());
526 EXPECT_EQ(expected_bounds
.ToString(), window1
->bounds().ToString());
527 EXPECT_TRUE(window1_state
->IsSnapped());
528 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
529 EXPECT_FALSE(window1_state
->IsNormalOrSnapped());
530 EXPECT_TRUE(window1_state
->IsDocked());
531 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
532 EXPECT_FALSE(window1_state
->IsDocked());
533 EXPECT_EQ(normal_bounds
.ToString(), window1
->bounds().ToString());
536 TEST_F(AcceleratorControllerTest
, WindowSnapLeftDockLeftSnapRight
) {
537 scoped_ptr
<aura::Window
> window0(
538 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
539 scoped_ptr
<aura::Window
> window1(
540 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
542 wm::WindowState
* window1_state
= wm::GetWindowState(window1
.get());
543 window1_state
->Activate();
545 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
546 gfx::Rect expected_bounds
=
547 wm::GetDefaultLeftSnappedWindowBoundsInParent(window1
.get());
548 gfx::Rect expected_bounds2
=
549 wm::GetDefaultRightSnappedWindowBoundsInParent(window1
.get());
550 EXPECT_EQ(expected_bounds
.ToString(), window1
->bounds().ToString());
551 EXPECT_TRUE(window1_state
->IsSnapped());
552 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
553 EXPECT_FALSE(window1_state
->IsNormalOrSnapped());
554 EXPECT_TRUE(window1_state
->IsDocked());
555 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
556 EXPECT_FALSE(window1_state
->IsDocked());
557 EXPECT_TRUE(window1_state
->IsSnapped());
558 EXPECT_EQ(expected_bounds2
.ToString(), window1
->bounds().ToString());
561 TEST_F(AcceleratorControllerTest
, WindowDockLeftMinimizeWindowWithRestore
) {
562 scoped_ptr
<aura::Window
> window0(
563 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
564 scoped_ptr
<aura::Window
> window1(
565 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
567 wm::WindowState
* window1_state
= wm::GetWindowState(window1
.get());
568 window1_state
->Activate();
570 scoped_ptr
<aura::Window
> window2(
571 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
573 wm::WindowState
* window2_state
= wm::GetWindowState(window2
.get());
575 scoped_ptr
<aura::Window
> window3(
576 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
578 wm::WindowState
* window3_state
= wm::GetWindowState(window3
.get());
579 window3_state
->Activate();
581 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
582 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
583 gfx::Rect window3_docked_bounds
= window3
->bounds();
585 window2_state
->Activate();
586 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
587 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
588 window1_state
->Activate();
589 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
590 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
592 EXPECT_TRUE(window3_state
->IsDocked());
593 EXPECT_TRUE(window2_state
->IsDocked());
594 EXPECT_TRUE(window1_state
->IsDocked());
595 EXPECT_TRUE(window3_state
->IsMinimized());
597 window1_state
->Activate();
598 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
599 window2_state
->Activate();
600 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
601 window3_state
->Unminimize();
602 EXPECT_FALSE(window1_state
->IsDocked());
603 EXPECT_FALSE(window2_state
->IsDocked());
604 EXPECT_TRUE(window3_state
->IsDocked());
605 EXPECT_EQ(window3_docked_bounds
.ToString(), window3
->bounds().ToString());
608 TEST_F(AcceleratorControllerTest
, WindowPanelDockLeftDockRightRestore
) {
609 scoped_ptr
<aura::Window
> window0(
610 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
612 scoped_ptr
<aura::Window
> window(CreatePanel());
613 wm::WindowState
* window_state
= wm::GetWindowState(window
.get());
614 window_state
->Activate();
616 gfx::Rect window_restore_bounds2
= window
->bounds();
617 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_LEFT
);
618 gfx::Rect expected_bounds
=
619 wm::GetDefaultLeftSnappedWindowBoundsInParent(window
.get());
620 gfx::Rect window_restore_bounds
=
621 window_state
->GetRestoreBoundsInScreen();
622 EXPECT_NE(expected_bounds
.ToString(), window
->bounds().ToString());
623 EXPECT_FALSE(window_state
->IsSnapped());
624 EXPECT_FALSE(window_state
->IsNormalOrSnapped());
625 EXPECT_TRUE(window_state
->IsDocked());
626 window_state
->Restore();
627 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
628 EXPECT_TRUE(window_state
->IsDocked());
629 GetController()->PerformActionIfEnabled(WINDOW_CYCLE_SNAP_DOCK_RIGHT
);
630 EXPECT_FALSE(window_state
->IsDocked());
631 EXPECT_EQ(window_restore_bounds
.ToString(),
632 window_restore_bounds2
.ToString());
633 EXPECT_EQ(window_restore_bounds
.ToString(), window
->bounds().ToString());
636 TEST_F(AcceleratorControllerTest
, CenterWindowAccelerator
) {
637 scoped_ptr
<aura::Window
> window(
638 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
639 wm::WindowState
* window_state
= wm::GetWindowState(window
.get());
640 window_state
->Activate();
642 // Center the window using accelerator.
643 GetController()->PerformActionIfEnabled(WINDOW_POSITION_CENTER
);
644 gfx::Rect work_area
=
645 Shell::GetScreen()->GetDisplayNearestWindow(window
.get()).work_area();
646 gfx::Rect bounds
= window
->GetBoundsInScreen();
647 EXPECT_NEAR(bounds
.x() - work_area
.x(),
648 work_area
.right() - bounds
.right(),
650 EXPECT_NEAR(bounds
.y() - work_area
.y(),
651 work_area
.bottom() - bounds
.bottom(),
654 // Add the window to docked container and try to center it.
655 window
->SetBounds(gfx::Rect(0, 0, 20, 20));
656 aura::Window
* docked_container
= Shell::GetContainer(
657 window
->GetRootWindow(), kShellWindowId_DockedContainer
);
658 docked_container
->AddChild(window
.get());
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
);
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
);
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
);
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.
764 #define MAYBE_ProcessOnce DISABLED_ProcessOnce
766 #define MAYBE_ProcessOnce ProcessOnce
769 #if defined(OS_WIN) || defined(USE_X11)
770 TEST_F(AcceleratorControllerTest
, MAYBE_ProcessOnce
) {
771 ui::Accelerator
accelerator_a(ui::VKEY_A
, ui::EF_NONE
);
773 GetController()->Register(accelerator_a
, &target
);
775 // The accelerator is processed only once.
776 ui::EventProcessor
* dispatcher
=
777 Shell::GetPrimaryRootWindow()->GetHost()->event_processor();
779 MSG msg1
= { NULL
, WM_KEYDOWN
, ui::VKEY_A
, 0 };
780 ui::KeyEvent
key_event1(msg1
);
781 key_event1
.SetTranslated(true);
782 ui::EventDispatchDetails details
= dispatcher
->OnEventFromSource(&key_event1
);
783 EXPECT_TRUE(key_event1
.handled() || details
.dispatcher_destroyed
);
785 MSG msg2
= { NULL
, WM_CHAR
, L
'A', 0 };
786 ui::KeyEvent
key_event2(msg2
);
787 key_event2
.SetTranslated(true);
788 details
= dispatcher
->OnEventFromSource(&key_event2
);
789 EXPECT_FALSE(key_event2
.handled() || details
.dispatcher_destroyed
);
791 MSG msg3
= { NULL
, WM_KEYUP
, ui::VKEY_A
, 0 };
792 ui::KeyEvent
key_event3(msg3
);
793 key_event3
.SetTranslated(true);
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 key_event1
.SetTranslated(true);
801 ui::EventDispatchDetails details
= dispatcher
->OnEventFromSource(&key_event1
);
802 EXPECT_TRUE(key_event1
.handled() || details
.dispatcher_destroyed
);
804 ui::KeyEvent
key_event2('A', ui::VKEY_A
, ui::EF_NONE
);
805 key_event2
.SetTranslated(true);
806 details
= dispatcher
->OnEventFromSource(&key_event2
);
807 EXPECT_FALSE(key_event2
.handled() || details
.dispatcher_destroyed
);
809 key_event
.InitKeyEvent(ui::ET_KEY_RELEASED
, ui::VKEY_A
, 0);
810 ui::KeyEvent
key_event3(key_event
);
811 key_event3
.SetTranslated(true);
812 details
= dispatcher
->OnEventFromSource(&key_event3
);
813 EXPECT_FALSE(key_event3
.handled() || details
.dispatcher_destroyed
);
815 EXPECT_EQ(1, target
.accelerator_pressed_count());
819 TEST_F(AcceleratorControllerTest
, GlobalAccelerators
) {
821 EXPECT_TRUE(ProcessInController(
822 ui::Accelerator(ui::VKEY_TAB
, ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
)));
825 ProcessInController(ui::Accelerator(
826 ui::VKEY_TAB
, ui::EF_ALT_DOWN
)));
828 EXPECT_TRUE(ProcessInController(
829 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_NONE
)));
831 #if defined(OS_CHROMEOS)
832 // The "Take Screenshot", "Take Partial Screenshot", volume, brightness, and
833 // keyboard brightness accelerators are only defined on ChromeOS.
835 test::TestScreenshotDelegate
* delegate
= GetScreenshotDelegate();
836 delegate
->set_can_take_screenshot(false);
837 EXPECT_TRUE(ProcessInController(
838 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_CONTROL_DOWN
)));
840 ProcessInController(ui::Accelerator(
841 ui::VKEY_PRINT
, ui::EF_NONE
)));
842 EXPECT_TRUE(ProcessInController(ui::Accelerator(
843 ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
845 delegate
->set_can_take_screenshot(true);
846 EXPECT_EQ(0, delegate
->handle_take_screenshot_count());
847 EXPECT_TRUE(ProcessInController(
848 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_CONTROL_DOWN
)));
849 EXPECT_EQ(1, delegate
->handle_take_screenshot_count());
851 ProcessInController(ui::Accelerator(
852 ui::VKEY_PRINT
, ui::EF_NONE
)));
853 EXPECT_EQ(2, delegate
->handle_take_screenshot_count());
854 EXPECT_TRUE(ProcessInController(ui::Accelerator(
855 ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
856 EXPECT_EQ(2, delegate
->handle_take_screenshot_count());
858 const ui::Accelerator
volume_mute(ui::VKEY_VOLUME_MUTE
, ui::EF_NONE
);
859 const ui::Accelerator
volume_down(ui::VKEY_VOLUME_DOWN
, ui::EF_NONE
);
860 const ui::Accelerator
volume_up(ui::VKEY_VOLUME_UP
, ui::EF_NONE
);
862 TestVolumeControlDelegate
* delegate
= new TestVolumeControlDelegate
;
863 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
864 scoped_ptr
<VolumeControlDelegate
>(delegate
).Pass());
865 EXPECT_EQ(0, delegate
->handle_volume_mute_count());
866 EXPECT_TRUE(ProcessInController(volume_mute
));
867 EXPECT_EQ(1, delegate
->handle_volume_mute_count());
868 EXPECT_EQ(volume_mute
, delegate
->last_accelerator());
869 EXPECT_EQ(0, delegate
->handle_volume_down_count());
870 EXPECT_TRUE(ProcessInController(volume_down
));
871 EXPECT_EQ(1, delegate
->handle_volume_down_count());
872 EXPECT_EQ(volume_down
, delegate
->last_accelerator());
873 EXPECT_EQ(0, delegate
->handle_volume_up_count());
874 EXPECT_TRUE(ProcessInController(volume_up
));
875 EXPECT_EQ(1, delegate
->handle_volume_up_count());
876 EXPECT_EQ(volume_up
, delegate
->last_accelerator());
879 // ui::VKEY_BRIGHTNESS_DOWN/UP are not defined on Windows.
880 const ui::Accelerator
brightness_down(ui::VKEY_BRIGHTNESS_DOWN
, ui::EF_NONE
);
881 const ui::Accelerator
brightness_up(ui::VKEY_BRIGHTNESS_UP
, ui::EF_NONE
);
883 DummyBrightnessControlDelegate
* delegate
=
884 new DummyBrightnessControlDelegate
;
885 GetController()->SetBrightnessControlDelegate(
886 scoped_ptr
<BrightnessControlDelegate
>(delegate
).Pass());
887 EXPECT_EQ(0, delegate
->handle_brightness_down_count());
888 EXPECT_TRUE(ProcessInController(brightness_down
));
889 EXPECT_EQ(1, delegate
->handle_brightness_down_count());
890 EXPECT_EQ(brightness_down
, delegate
->last_accelerator());
891 EXPECT_EQ(0, delegate
->handle_brightness_up_count());
892 EXPECT_TRUE(ProcessInController(brightness_up
));
893 EXPECT_EQ(1, delegate
->handle_brightness_up_count());
894 EXPECT_EQ(brightness_up
, delegate
->last_accelerator());
897 // Keyboard brightness
898 const ui::Accelerator
alt_brightness_down(ui::VKEY_BRIGHTNESS_DOWN
,
900 const ui::Accelerator
alt_brightness_up(ui::VKEY_BRIGHTNESS_UP
,
903 EXPECT_TRUE(ProcessInController(alt_brightness_down
));
904 EXPECT_TRUE(ProcessInController(alt_brightness_up
));
905 DummyKeyboardBrightnessControlDelegate
* delegate
=
906 new DummyKeyboardBrightnessControlDelegate
;
907 GetController()->SetKeyboardBrightnessControlDelegate(
908 scoped_ptr
<KeyboardBrightnessControlDelegate
>(delegate
).Pass());
909 EXPECT_EQ(0, delegate
->handle_keyboard_brightness_down_count());
910 EXPECT_TRUE(ProcessInController(alt_brightness_down
));
911 EXPECT_EQ(1, delegate
->handle_keyboard_brightness_down_count());
912 EXPECT_EQ(alt_brightness_down
, delegate
->last_accelerator());
913 EXPECT_EQ(0, delegate
->handle_keyboard_brightness_up_count());
914 EXPECT_TRUE(ProcessInController(alt_brightness_up
));
915 EXPECT_EQ(1, delegate
->handle_keyboard_brightness_up_count());
916 EXPECT_EQ(alt_brightness_up
, delegate
->last_accelerator());
922 ExitWarningHandler
* ewh
= GetController()->GetExitWarningHandlerForTest();
925 EXPECT_TRUE(is_idle(ewh
));
926 EXPECT_FALSE(is_ui_shown(ewh
));
927 EXPECT_TRUE(ProcessInController(
928 ui::Accelerator(ui::VKEY_Q
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
929 EXPECT_FALSE(is_idle(ewh
));
930 EXPECT_TRUE(is_ui_shown(ewh
));
931 SimulateTimerExpired(ewh
);
932 EXPECT_TRUE(is_idle(ewh
));
933 EXPECT_FALSE(is_ui_shown(ewh
));
938 EXPECT_TRUE(ProcessInController(
939 ui::Accelerator(ui::VKEY_T
, ui::EF_CONTROL_DOWN
)));
941 // New incognito window
942 EXPECT_TRUE(ProcessInController(
943 ui::Accelerator(ui::VKEY_N
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
946 EXPECT_TRUE(ProcessInController(
947 ui::Accelerator(ui::VKEY_N
, ui::EF_CONTROL_DOWN
)));
950 EXPECT_TRUE(ProcessInController(
951 ui::Accelerator(ui::VKEY_T
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
954 EXPECT_TRUE(ProcessInController(
955 ui::Accelerator(ui::VKEY_ESCAPE
, ui::EF_SHIFT_DOWN
)));
957 #if defined(OS_CHROMEOS)
959 EXPECT_TRUE(ProcessInController(
960 ui::Accelerator(ui::VKEY_M
, ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
)));
963 // NOTE: Accelerators that do not work on the lock screen need to be
964 // tested before the sequence below is invoked because it causes a side
965 // effect of locking the screen.
966 EXPECT_TRUE(ProcessInController(
967 ui::Accelerator(ui::VKEY_L
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
971 TEST_F(AcceleratorControllerTest
, GlobalAcceleratorsToggleAppList
) {
972 AccessibilityDelegate
* delegate
=
973 ash::Shell::GetInstance()->accessibility_delegate();
974 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
976 // The press event should not open the AppList, the release should instead.
978 ProcessInController(ui::Accelerator(ui::VKEY_LWIN
, ui::EF_NONE
)));
979 EXPECT_EQ(ui::VKEY_LWIN
,
980 GetCurrentAccelerator().key_code());
982 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
985 ProcessInController(ReleaseAccelerator(ui::VKEY_LWIN
, ui::EF_NONE
)));
986 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
988 EXPECT_EQ(ui::VKEY_LWIN
,
989 GetPreviousAccelerator().key_code());
991 // When spoken feedback is on, the AppList should not toggle.
992 delegate
->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE
);
994 ProcessInController(ui::Accelerator(ui::VKEY_LWIN
, ui::EF_NONE
)));
996 ProcessInController(ReleaseAccelerator(
997 ui::VKEY_LWIN
, ui::EF_NONE
)));
998 delegate
->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE
);
999 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1002 ProcessInController(ui::Accelerator(ui::VKEY_LWIN
, ui::EF_NONE
)));
1004 ProcessInController(ReleaseAccelerator(
1005 ui::VKEY_LWIN
, ui::EF_NONE
)));
1006 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1008 // When spoken feedback is on, the AppList should not toggle.
1009 delegate
->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE
);
1011 ProcessInController(ui::Accelerator(ui::VKEY_LWIN
, ui::EF_NONE
)));
1013 ProcessInController(ReleaseAccelerator(
1014 ui::VKEY_LWIN
, ui::EF_NONE
)));
1015 delegate
->ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_NONE
);
1016 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1018 #if defined(OS_CHROMEOS)
1019 // The press of VKEY_BROWSER_SEARCH should toggle the AppList
1020 EXPECT_TRUE(ProcessInController(ui::Accelerator(ui::VKEY_BROWSER_SEARCH
,
1022 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1023 EXPECT_FALSE(ProcessInController(ReleaseAccelerator(ui::VKEY_BROWSER_SEARCH
,
1025 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
1029 TEST_F(AcceleratorControllerTest
, ImeGlobalAccelerators
) {
1030 // Test IME shortcuts.
1032 ui::Accelerator
control_space_down(ui::VKEY_SPACE
, ui::EF_CONTROL_DOWN
);
1033 control_space_down
.set_type(ui::ET_KEY_PRESSED
);
1034 ui::Accelerator
control_space_up(ui::VKEY_SPACE
, ui::EF_CONTROL_DOWN
);
1035 control_space_up
.set_type(ui::ET_KEY_RELEASED
);
1036 const ui::Accelerator
convert(ui::VKEY_CONVERT
, ui::EF_NONE
);
1037 const ui::Accelerator
non_convert(ui::VKEY_NONCONVERT
, ui::EF_NONE
);
1038 const ui::Accelerator
wide_half_1(ui::VKEY_DBE_SBCSCHAR
, ui::EF_NONE
);
1039 const ui::Accelerator
wide_half_2(ui::VKEY_DBE_DBCSCHAR
, ui::EF_NONE
);
1040 const ui::Accelerator
hangul(ui::VKEY_HANGUL
, ui::EF_NONE
);
1041 EXPECT_FALSE(ProcessInController(control_space_down
));
1042 EXPECT_FALSE(ProcessInController(control_space_up
));
1043 EXPECT_FALSE(ProcessInController(convert
));
1044 EXPECT_FALSE(ProcessInController(non_convert
));
1045 EXPECT_FALSE(ProcessInController(wide_half_1
));
1046 EXPECT_FALSE(ProcessInController(wide_half_2
));
1047 EXPECT_FALSE(ProcessInController(hangul
));
1048 DummyImeControlDelegate
* delegate
= new DummyImeControlDelegate
;
1049 GetController()->SetImeControlDelegate(
1050 scoped_ptr
<ImeControlDelegate
>(delegate
).Pass());
1051 EXPECT_EQ(0, delegate
->handle_previous_ime_count());
1052 EXPECT_TRUE(ProcessInController(control_space_down
));
1053 EXPECT_EQ(1, delegate
->handle_previous_ime_count());
1054 EXPECT_TRUE(ProcessInController(control_space_up
));
1055 EXPECT_EQ(1, delegate
->handle_previous_ime_count());
1056 EXPECT_EQ(0, delegate
->handle_switch_ime_count());
1057 EXPECT_TRUE(ProcessInController(convert
));
1058 EXPECT_EQ(1, delegate
->handle_switch_ime_count());
1059 EXPECT_TRUE(ProcessInController(non_convert
));
1060 EXPECT_EQ(2, delegate
->handle_switch_ime_count());
1061 EXPECT_TRUE(ProcessInController(wide_half_1
));
1062 EXPECT_EQ(3, delegate
->handle_switch_ime_count());
1063 EXPECT_TRUE(ProcessInController(wide_half_2
));
1064 EXPECT_EQ(4, delegate
->handle_switch_ime_count());
1065 EXPECT_TRUE(ProcessInController(hangul
));
1066 EXPECT_EQ(5, delegate
->handle_switch_ime_count());
1069 // Test IME shortcuts that are triggered on key release.
1071 const ui::Accelerator
shift_alt_press(ui::VKEY_MENU
,
1072 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1073 const ReleaseAccelerator
shift_alt(ui::VKEY_MENU
, ui::EF_SHIFT_DOWN
);
1074 const ui::Accelerator
alt_shift_press(ui::VKEY_SHIFT
,
1075 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1076 const ReleaseAccelerator
alt_shift(ui::VKEY_SHIFT
, ui::EF_ALT_DOWN
);
1078 DummyImeControlDelegate
* delegate
= new DummyImeControlDelegate
;
1079 GetController()->SetImeControlDelegate(
1080 scoped_ptr
<ImeControlDelegate
>(delegate
).Pass());
1081 EXPECT_EQ(0, delegate
->handle_next_ime_count());
1082 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1083 EXPECT_TRUE(ProcessInController(shift_alt
));
1084 EXPECT_EQ(1, delegate
->handle_next_ime_count());
1085 EXPECT_FALSE(ProcessInController(alt_shift_press
));
1086 EXPECT_TRUE(ProcessInController(alt_shift
));
1087 EXPECT_EQ(2, delegate
->handle_next_ime_count());
1089 // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is
1091 const ui::Accelerator
shift_alt_x_press(
1093 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1094 const ReleaseAccelerator
shift_alt_x(ui::VKEY_X
,
1095 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1097 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1098 EXPECT_FALSE(ProcessInController(shift_alt_x_press
));
1099 EXPECT_FALSE(ProcessInController(shift_alt_x
));
1100 EXPECT_FALSE(ProcessInController(shift_alt
));
1101 EXPECT_EQ(2, delegate
->handle_next_ime_count());
1103 // But we _should_ if X is either VKEY_RETURN or VKEY_SPACE.
1104 // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
1105 const ui::Accelerator
shift_alt_return_press(
1107 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1108 const ReleaseAccelerator
shift_alt_return(
1110 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1112 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1113 EXPECT_FALSE(ProcessInController(shift_alt_return_press
));
1114 EXPECT_FALSE(ProcessInController(shift_alt_return
));
1115 EXPECT_TRUE(ProcessInController(shift_alt
));
1116 EXPECT_EQ(3, delegate
->handle_next_ime_count());
1118 const ui::Accelerator
shift_alt_space_press(
1120 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1121 const ReleaseAccelerator
shift_alt_space(
1123 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1125 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1126 EXPECT_FALSE(ProcessInController(shift_alt_space_press
));
1127 EXPECT_FALSE(ProcessInController(shift_alt_space
));
1128 EXPECT_TRUE(ProcessInController(shift_alt
));
1129 EXPECT_EQ(4, delegate
->handle_next_ime_count());
1132 #if defined(OS_CHROMEOS)
1133 // Test IME shortcuts again with unnormalized accelerators (Chrome OS only).
1135 const ui::Accelerator
shift_alt_press(ui::VKEY_MENU
, ui::EF_SHIFT_DOWN
);
1136 const ReleaseAccelerator
shift_alt(ui::VKEY_MENU
, ui::EF_SHIFT_DOWN
);
1137 const ui::Accelerator
alt_shift_press(ui::VKEY_SHIFT
, ui::EF_ALT_DOWN
);
1138 const ReleaseAccelerator
alt_shift(ui::VKEY_SHIFT
, ui::EF_ALT_DOWN
);
1140 DummyImeControlDelegate
* delegate
= new DummyImeControlDelegate
;
1141 GetController()->SetImeControlDelegate(
1142 scoped_ptr
<ImeControlDelegate
>(delegate
).Pass());
1143 EXPECT_EQ(0, delegate
->handle_next_ime_count());
1144 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1145 EXPECT_TRUE(ProcessInController(shift_alt
));
1146 EXPECT_EQ(1, delegate
->handle_next_ime_count());
1147 EXPECT_FALSE(ProcessInController(alt_shift_press
));
1148 EXPECT_TRUE(ProcessInController(alt_shift
));
1149 EXPECT_EQ(2, delegate
->handle_next_ime_count());
1151 // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is
1153 const ui::Accelerator
shift_alt_x_press(
1155 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1156 const ReleaseAccelerator
shift_alt_x(ui::VKEY_X
,
1157 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1159 EXPECT_FALSE(ProcessInController(shift_alt_press
));
1160 EXPECT_FALSE(ProcessInController(shift_alt_x_press
));
1161 EXPECT_FALSE(ProcessInController(shift_alt_x
));
1162 EXPECT_FALSE(ProcessInController(shift_alt
));
1163 EXPECT_EQ(2, delegate
->handle_next_ime_count());
1168 // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
1169 TEST_F(AcceleratorControllerTest
, ImeGlobalAcceleratorsWorkaround139556
) {
1170 // The workaround for crbug.com/139556 depends on the fact that we don't
1171 // use Shift+Alt+Enter/Space with ET_KEY_PRESSED as an accelerator. Test it.
1172 const ui::Accelerator
shift_alt_return_press(
1174 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1175 EXPECT_FALSE(ProcessInController(shift_alt_return_press
));
1176 const ui::Accelerator
shift_alt_space_press(
1178 ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
);
1179 EXPECT_FALSE(ProcessInController(shift_alt_space_press
));
1182 TEST_F(AcceleratorControllerTest
, PreferredReservedAccelerators
) {
1183 #if defined(OS_CHROMEOS)
1184 // Power key is reserved on chromeos.
1185 EXPECT_TRUE(GetController()->IsReserved(
1186 ui::Accelerator(ui::VKEY_POWER
, ui::EF_NONE
)));
1187 EXPECT_FALSE(GetController()->IsPreferred(
1188 ui::Accelerator(ui::VKEY_POWER
, ui::EF_NONE
)));
1190 // ALT+Tab are not reserved but preferred.
1191 EXPECT_FALSE(GetController()->IsReserved(
1192 ui::Accelerator(ui::VKEY_TAB
, ui::EF_ALT_DOWN
)));
1193 EXPECT_FALSE(GetController()->IsReserved(
1194 ui::Accelerator(ui::VKEY_TAB
, ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
)));
1195 EXPECT_TRUE(GetController()->IsPreferred(
1196 ui::Accelerator(ui::VKEY_TAB
, ui::EF_ALT_DOWN
)));
1197 EXPECT_TRUE(GetController()->IsPreferred(
1198 ui::Accelerator(ui::VKEY_TAB
, ui::EF_SHIFT_DOWN
| ui::EF_ALT_DOWN
)));
1200 // Others are not reserved nor preferred
1201 EXPECT_FALSE(GetController()->IsReserved(
1202 ui::Accelerator(ui::VKEY_PRINT
, ui::EF_NONE
)));
1203 EXPECT_FALSE(GetController()->IsPreferred(
1204 ui::Accelerator(ui::VKEY_PRINT
, ui::EF_NONE
)));
1205 EXPECT_FALSE(GetController()->IsReserved(
1206 ui::Accelerator(ui::VKEY_TAB
, ui::EF_NONE
)));
1207 EXPECT_FALSE(GetController()->IsPreferred(
1208 ui::Accelerator(ui::VKEY_TAB
, ui::EF_NONE
)));
1209 EXPECT_FALSE(GetController()->IsReserved(
1210 ui::Accelerator(ui::VKEY_A
, ui::EF_NONE
)));
1211 EXPECT_FALSE(GetController()->IsPreferred(
1212 ui::Accelerator(ui::VKEY_A
, ui::EF_NONE
)));
1217 class PreferredReservedAcceleratorsTest
: public test::AshTestBase
{
1219 PreferredReservedAcceleratorsTest() {}
1220 ~PreferredReservedAcceleratorsTest() override
{}
1222 // test::AshTestBase:
1223 void SetUp() override
{
1224 AshTestBase::SetUp();
1225 Shell::GetInstance()->lock_state_controller()->
1226 set_animator_for_test(new test::TestSessionStateAnimator
);
1230 DISALLOW_COPY_AND_ASSIGN(PreferredReservedAcceleratorsTest
);
1235 TEST_F(PreferredReservedAcceleratorsTest
, AcceleratorsWithFullscreen
) {
1236 aura::Window
* w1
= CreateTestWindowInShellWithId(0);
1237 aura::Window
* w2
= CreateTestWindowInShellWithId(1);
1238 wm::ActivateWindow(w1
);
1240 wm::WMEvent
fullscreen(wm::WM_EVENT_FULLSCREEN
);
1241 wm::WindowState
* w1_state
= wm::GetWindowState(w1
);
1242 w1_state
->OnWMEvent(&fullscreen
);
1243 ASSERT_TRUE(w1_state
->IsFullscreen());
1245 ui::test::EventGenerator
& generator
= GetEventGenerator();
1246 #if defined(OS_CHROMEOS)
1247 // Power key (reserved) should always be handled.
1248 LockStateController::TestApi
test_api(
1249 Shell::GetInstance()->lock_state_controller());
1250 EXPECT_FALSE(test_api
.is_animating_lock());
1251 generator
.PressKey(ui::VKEY_POWER
, ui::EF_NONE
);
1252 EXPECT_TRUE(test_api
.is_animating_lock());
1255 // A fullscreen window can consume ALT-TAB (preferred).
1256 ASSERT_EQ(w1
, wm::GetActiveWindow());
1257 generator
.PressKey(ui::VKEY_TAB
, ui::EF_ALT_DOWN
);
1258 ASSERT_EQ(w1
, wm::GetActiveWindow());
1259 ASSERT_NE(w2
, wm::GetActiveWindow());
1261 // ALT-TAB is non repeatable. Press A to cancel the
1263 generator
.PressKey(ui::VKEY_A
, ui::EF_NONE
);
1264 generator
.ReleaseKey(ui::VKEY_A
, ui::EF_NONE
);
1266 // A normal window shouldn't consume preferred accelerator.
1267 wm::WMEvent
normal(wm::WM_EVENT_NORMAL
);
1268 w1_state
->OnWMEvent(&normal
);
1269 ASSERT_FALSE(w1_state
->IsFullscreen());
1271 EXPECT_EQ(w1
, wm::GetActiveWindow());
1272 generator
.PressKey(ui::VKEY_TAB
, ui::EF_ALT_DOWN
);
1273 ASSERT_NE(w1
, wm::GetActiveWindow());
1274 ASSERT_EQ(w2
, wm::GetActiveWindow());
1277 #if defined(OS_CHROMEOS)
1278 TEST_F(AcceleratorControllerTest
, DisallowedAtModalWindow
) {
1279 std::set
<AcceleratorAction
> all_actions
;
1280 for (size_t i
= 0 ; i
< kAcceleratorDataLength
; ++i
)
1281 all_actions
.insert(kAcceleratorData
[i
].action
);
1282 std::set
<AcceleratorAction
> all_debug_actions
;
1283 for (size_t i
= 0 ; i
< kDebugAcceleratorDataLength
; ++i
)
1284 all_debug_actions
.insert(kDebugAcceleratorData
[i
].action
);
1286 std::set
<AcceleratorAction
> actionsAllowedAtModalWindow
;
1287 for (size_t k
= 0 ; k
< kActionsAllowedAtModalWindowLength
; ++k
)
1288 actionsAllowedAtModalWindow
.insert(kActionsAllowedAtModalWindow
[k
]);
1289 for (std::set
<AcceleratorAction
>::const_iterator it
=
1290 actionsAllowedAtModalWindow
.begin();
1291 it
!= actionsAllowedAtModalWindow
.end(); ++it
) {
1292 EXPECT_TRUE(all_actions
.find(*it
) != all_actions
.end() ||
1293 all_debug_actions
.find(*it
) != all_debug_actions
.end())
1294 << " action from kActionsAllowedAtModalWindow"
1295 << " not found in kAcceleratorData or kDebugAcceleratorData. "
1296 << "action: " << *it
;
1298 scoped_ptr
<aura::Window
> window(
1299 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1300 wm::ActivateWindow(window
.get());
1301 Shell::GetInstance()->SimulateModalWindowOpenForTesting(true);
1302 for (std::set
<AcceleratorAction
>::const_iterator it
= all_actions
.begin();
1303 it
!= all_actions
.end(); ++it
) {
1304 if (actionsAllowedAtModalWindow
.find(*it
) ==
1305 actionsAllowedAtModalWindow
.end()) {
1306 EXPECT_TRUE(GetController()->PerformActionIfEnabled(*it
))
1307 << " for action (disallowed at modal window): " << *it
;
1310 // Testing of top row (F5-F10) accelerators that should still work
1311 // when a modal window is open
1315 test::TestScreenshotDelegate
* delegate
= GetScreenshotDelegate();
1316 delegate
->set_can_take_screenshot(false);
1317 EXPECT_TRUE(ProcessInController(
1318 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_CONTROL_DOWN
)));
1320 ProcessInController(ui::Accelerator(
1321 ui::VKEY_PRINT
, ui::EF_NONE
)));
1322 EXPECT_TRUE(ProcessInController(ui::Accelerator(
1323 ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
1324 delegate
->set_can_take_screenshot(true);
1325 EXPECT_EQ(0, delegate
->handle_take_screenshot_count());
1326 EXPECT_TRUE(ProcessInController(
1327 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_CONTROL_DOWN
)));
1328 EXPECT_EQ(1, delegate
->handle_take_screenshot_count());
1330 ProcessInController(ui::Accelerator(
1331 ui::VKEY_PRINT
, ui::EF_NONE
)));
1332 EXPECT_EQ(2, delegate
->handle_take_screenshot_count());
1333 EXPECT_TRUE(ProcessInController(ui::Accelerator(
1334 ui::VKEY_MEDIA_LAUNCH_APP1
, ui::EF_SHIFT_DOWN
| ui::EF_CONTROL_DOWN
)));
1335 EXPECT_EQ(2, delegate
->handle_take_screenshot_count());
1338 const ui::Accelerator
brightness_down(ui::VKEY_BRIGHTNESS_DOWN
, ui::EF_NONE
);
1339 const ui::Accelerator
brightness_up(ui::VKEY_BRIGHTNESS_UP
, ui::EF_NONE
);
1341 DummyBrightnessControlDelegate
* delegate
=
1342 new DummyBrightnessControlDelegate
;
1343 GetController()->SetBrightnessControlDelegate(
1344 scoped_ptr
<BrightnessControlDelegate
>(delegate
).Pass());
1345 EXPECT_EQ(0, delegate
->handle_brightness_down_count());
1346 EXPECT_TRUE(ProcessInController(brightness_down
));
1347 EXPECT_EQ(1, delegate
->handle_brightness_down_count());
1348 EXPECT_EQ(brightness_down
, delegate
->last_accelerator());
1349 EXPECT_EQ(0, delegate
->handle_brightness_up_count());
1350 EXPECT_TRUE(ProcessInController(brightness_up
));
1351 EXPECT_EQ(1, delegate
->handle_brightness_up_count());
1352 EXPECT_EQ(brightness_up
, delegate
->last_accelerator());
1355 const ui::Accelerator
volume_mute(ui::VKEY_VOLUME_MUTE
, ui::EF_NONE
);
1356 const ui::Accelerator
volume_down(ui::VKEY_VOLUME_DOWN
, ui::EF_NONE
);
1357 const ui::Accelerator
volume_up(ui::VKEY_VOLUME_UP
, ui::EF_NONE
);
1359 EXPECT_TRUE(ProcessInController(volume_mute
));
1360 EXPECT_TRUE(ProcessInController(volume_down
));
1361 EXPECT_TRUE(ProcessInController(volume_up
));
1362 TestVolumeControlDelegate
* delegate
= new TestVolumeControlDelegate
;
1363 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
1364 scoped_ptr
<VolumeControlDelegate
>(delegate
).Pass());
1365 EXPECT_EQ(0, delegate
->handle_volume_mute_count());
1366 EXPECT_TRUE(ProcessInController(volume_mute
));
1367 EXPECT_EQ(1, delegate
->handle_volume_mute_count());
1368 EXPECT_EQ(volume_mute
, delegate
->last_accelerator());
1369 EXPECT_EQ(0, delegate
->handle_volume_down_count());
1370 EXPECT_TRUE(ProcessInController(volume_down
));
1371 EXPECT_EQ(1, delegate
->handle_volume_down_count());
1372 EXPECT_EQ(volume_down
, delegate
->last_accelerator());
1373 EXPECT_EQ(0, delegate
->handle_volume_up_count());
1374 EXPECT_TRUE(ProcessInController(volume_up
));
1375 EXPECT_EQ(1, delegate
->handle_volume_up_count());
1376 EXPECT_EQ(volume_up
, delegate
->last_accelerator());
1381 TEST_F(AcceleratorControllerTest
, DisallowedWithNoWindow
) {
1382 AccessibilityDelegate
* delegate
=
1383 ash::Shell::GetInstance()->accessibility_delegate();
1385 for (size_t i
= 0; i
< kActionsNeedingWindowLength
; ++i
) {
1386 delegate
->TriggerAccessibilityAlert(ui::A11Y_ALERT_NONE
);
1388 GetController()->PerformActionIfEnabled(kActionsNeedingWindow
[i
]));
1389 EXPECT_EQ(delegate
->GetLastAccessibilityAlert(),
1390 ui::A11Y_ALERT_WINDOW_NEEDED
);
1393 // Make sure we don't alert if we do have a window.
1394 scoped_ptr
<aura::Window
> window
;
1395 for (size_t i
= 0; i
< kActionsNeedingWindowLength
; ++i
) {
1396 window
.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1397 wm::ActivateWindow(window
.get());
1398 delegate
->TriggerAccessibilityAlert(ui::A11Y_ALERT_NONE
);
1399 GetController()->PerformActionIfEnabled(kActionsNeedingWindow
[i
]);
1400 EXPECT_NE(delegate
->GetLastAccessibilityAlert(),
1401 ui::A11Y_ALERT_WINDOW_NEEDED
);
1404 // Don't alert if we have a minimized window either.
1405 for (size_t i
= 0; i
< kActionsNeedingWindowLength
; ++i
) {
1406 window
.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1407 wm::ActivateWindow(window
.get());
1408 GetController()->PerformActionIfEnabled(WINDOW_MINIMIZE
);
1409 delegate
->TriggerAccessibilityAlert(ui::A11Y_ALERT_NONE
);
1410 GetController()->PerformActionIfEnabled(kActionsNeedingWindow
[i
]);
1411 EXPECT_NE(delegate
->GetLastAccessibilityAlert(),
1412 ui::A11Y_ALERT_WINDOW_NEEDED
);