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. 4 5 #include "ash/accelerators/accelerator_controller.h" 6 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_shell_delegate.h" 23 #include "ash/test/test_volume_control_delegate.h" 24 #include "ash/volume_control_delegate.h" 25 #include "ash/wm/lock_state_controller.h" 26 #include "ash/wm/window_state.h" 27 #include "ash/wm/window_util.h" 28 #include "ash/wm/wm_event.h" 29 #include "base/command_line.h" 30 #include "ui/aura/client/aura_constants.h" 31 #include "ui/aura/test/test_window_delegate.h" 32 #include "ui/aura/test/test_windows.h" 33 #include "ui/aura/window.h" 34 #include "ui/events/event.h" 35 #include "ui/events/event_processor.h" 36 #include "ui/events/test/event_generator.h" 37 #include "ui/gfx/screen.h" 38 #include "ui/views/widget/widget.h" 39 40 #if defined(USE_X11) 41 #include <X11/Xlib.h> 42 #include "ui/events/test/events_test_utils_x11.h" 43 #endif 44 45 namespace ash { 46 47 namespace { 48 49 class TestTarget : public ui::AcceleratorTarget { 50 public: 51 TestTarget() : accelerator_pressed_count_(0), accelerator_repeat_count_(0) {} 52 virtual ~TestTarget() {} 53 54 int accelerator_pressed_count() const { 55 return accelerator_pressed_count_; 56 } 57 58 int accelerator_repeat_count() const { return accelerator_repeat_count_; } 59 60 void reset() { 61 accelerator_pressed_count_ = 0; 62 accelerator_repeat_count_ = 0; 63 } 64 65 // Overridden from ui::AcceleratorTarget: 66 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; 67 virtual bool CanHandleAccelerators() const OVERRIDE; 68 69 private: 70 int accelerator_pressed_count_; 71 int accelerator_repeat_count_; 72 73 DISALLOW_COPY_AND_ASSIGN(TestTarget); 74 }; 75 76 class ReleaseAccelerator : public ui::Accelerator { 77 public: 78 ReleaseAccelerator(ui::KeyboardCode keycode, int modifiers) 79 : ui::Accelerator(keycode, modifiers) { 80 set_type(ui::ET_KEY_RELEASED); 81 } 82 }; 83 84 class DummyBrightnessControlDelegate : public BrightnessControlDelegate { 85 public: 86 explicit DummyBrightnessControlDelegate(bool consume) 87 : consume_(consume), 88 handle_brightness_down_count_(0), 89 handle_brightness_up_count_(0) { 90 } 91 virtual ~DummyBrightnessControlDelegate() {} 92 93 virtual bool HandleBrightnessDown( 94 const ui::Accelerator& accelerator) OVERRIDE { 95 ++handle_brightness_down_count_; 96 last_accelerator_ = accelerator; 97 return consume_; 98 } 99 virtual bool HandleBrightnessUp(const ui::Accelerator& accelerator) OVERRIDE { 100 ++handle_brightness_up_count_; 101 last_accelerator_ = accelerator; 102 return consume_; 103 } 104 virtual void SetBrightnessPercent(double percent, bool gradual) OVERRIDE {} 105 virtual void GetBrightnessPercent( 106 const base::Callback<void(double)>& callback) OVERRIDE { 107 callback.Run(100.0); 108 } 109 110 int handle_brightness_down_count() const { 111 return handle_brightness_down_count_; 112 } 113 int handle_brightness_up_count() const { 114 return handle_brightness_up_count_; 115 } 116 const ui::Accelerator& last_accelerator() const { 117 return last_accelerator_; 118 } 119 120 private: 121 const bool consume_; 122 int handle_brightness_down_count_; 123 int handle_brightness_up_count_; 124 ui::Accelerator last_accelerator_; 125 126 DISALLOW_COPY_AND_ASSIGN(DummyBrightnessControlDelegate); 127 }; 128 129 class DummyImeControlDelegate : public ImeControlDelegate { 130 public: 131 explicit DummyImeControlDelegate(bool consume) 132 : consume_(consume), 133 handle_next_ime_count_(0), 134 handle_previous_ime_count_(0), 135 handle_switch_ime_count_(0) { 136 } 137 virtual ~DummyImeControlDelegate() {} 138 139 virtual void HandleNextIme() OVERRIDE { 140 ++handle_next_ime_count_; 141 } 142 virtual bool HandlePreviousIme(const ui::Accelerator& accelerator) OVERRIDE { 143 ++handle_previous_ime_count_; 144 last_accelerator_ = accelerator; 145 return consume_; 146 } 147 virtual bool HandleSwitchIme(const ui::Accelerator& accelerator) OVERRIDE { 148 ++handle_switch_ime_count_; 149 last_accelerator_ = accelerator; 150 return consume_; 151 } 152 153 int handle_next_ime_count() const { 154 return handle_next_ime_count_; 155 } 156 int handle_previous_ime_count() const { 157 return handle_previous_ime_count_; 158 } 159 int handle_switch_ime_count() const { 160 return handle_switch_ime_count_; 161 } 162 const ui::Accelerator& last_accelerator() const { 163 return last_accelerator_; 164 } 165 virtual ui::Accelerator RemapAccelerator( 166 const ui::Accelerator& accelerator) OVERRIDE { 167 return ui::Accelerator(accelerator); 168 } 169 170 private: 171 const bool consume_; 172 int handle_next_ime_count_; 173 int handle_previous_ime_count_; 174 int handle_switch_ime_count_; 175 ui::Accelerator last_accelerator_; 176 177 DISALLOW_COPY_AND_ASSIGN(DummyImeControlDelegate); 178 }; 179 180 class DummyKeyboardBrightnessControlDelegate 181 : public KeyboardBrightnessControlDelegate { 182 public: 183 explicit DummyKeyboardBrightnessControlDelegate(bool consume) 184 : consume_(consume), 185 handle_keyboard_brightness_down_count_(0), 186 handle_keyboard_brightness_up_count_(0) { 187 } 188 virtual ~DummyKeyboardBrightnessControlDelegate() {} 189 190 virtual bool HandleKeyboardBrightnessDown( 191 const ui::Accelerator& accelerator) OVERRIDE { 192 ++handle_keyboard_brightness_down_count_; 193 last_accelerator_ = accelerator; 194 return consume_; 195 } 196 197 virtual bool HandleKeyboardBrightnessUp( 198 const ui::Accelerator& accelerator) OVERRIDE { 199 ++handle_keyboard_brightness_up_count_; 200 last_accelerator_ = accelerator; 201 return consume_; 202 } 203 204 int handle_keyboard_brightness_down_count() const { 205 return handle_keyboard_brightness_down_count_; 206 } 207 208 int handle_keyboard_brightness_up_count() const { 209 return handle_keyboard_brightness_up_count_; 210 } 211 212 const ui::Accelerator& last_accelerator() const { 213 return last_accelerator_; 214 } 215 216 private: 217 const bool consume_; 218 int handle_keyboard_brightness_down_count_; 219 int handle_keyboard_brightness_up_count_; 220 ui::Accelerator last_accelerator_; 221 222 DISALLOW_COPY_AND_ASSIGN(DummyKeyboardBrightnessControlDelegate); 223 }; 224 225 bool TestTarget::AcceleratorPressed(const ui::Accelerator& accelerator) { 226 if (accelerator.IsRepeat()) 227 ++accelerator_repeat_count_; 228 else 229 ++accelerator_pressed_count_; 230 return true; 231 } 232 233 bool TestTarget::CanHandleAccelerators() const { 234 return true; 235 } 236 237 } // namespace 238 239 class AcceleratorControllerTest : public test::AshTestBase { 240 public: 241 AcceleratorControllerTest() {} 242 virtual ~AcceleratorControllerTest() {} 243 244 protected: 245 void EnableInternalDisplay() { 246 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()). 247 SetFirstDisplayAsInternalDisplay(); 248 } 249 250 static AcceleratorController* GetController(); 251 252 // Several functions to access ExitWarningHandler (as friend). 253 static void StubForTest(ExitWarningHandler* ewh) { 254 ewh->stub_timer_for_test_ = true; 255 } 256 static void Reset(ExitWarningHandler* ewh) { 257 ewh->state_ = ExitWarningHandler::IDLE; 258 } 259 static void SimulateTimerExpired(ExitWarningHandler* ewh) { 260 ewh->TimerAction(); 261 } 262 static bool is_ui_shown(ExitWarningHandler* ewh) { 263 return !!ewh->widget_; 264 } 265 static bool is_idle(ExitWarningHandler* ewh) { 266 return ewh->state_ == ExitWarningHandler::IDLE; 267 } 268 static bool is_exiting(ExitWarningHandler* ewh) { 269 return ewh->state_ == ExitWarningHandler::EXITING; 270 } 271 272 private: 273 DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest); 274 }; 275 276 AcceleratorController* AcceleratorControllerTest::GetController() { 277 return Shell::GetInstance()->accelerator_controller(); 278 } 279 280 #if !defined(OS_WIN) 281 // Double press of exit shortcut => exiting 282 TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestDoublePress) { 283 ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); 284 ui::Accelerator release(press); 285 release.set_type(ui::ET_KEY_RELEASED); 286 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest(); 287 ASSERT_TRUE(!!ewh); 288 StubForTest(ewh); 289 EXPECT_TRUE(is_idle(ewh)); 290 EXPECT_FALSE(is_ui_shown(ewh)); 291 EXPECT_TRUE(GetController()->Process(press)); 292 EXPECT_FALSE(GetController()->Process(release)); 293 EXPECT_FALSE(is_idle(ewh)); 294 EXPECT_TRUE(is_ui_shown(ewh)); 295 EXPECT_TRUE(GetController()->Process(press)); // second press before timer. 296 EXPECT_FALSE(GetController()->Process(release)); 297 SimulateTimerExpired(ewh); 298 EXPECT_TRUE(is_exiting(ewh)); 299 EXPECT_FALSE(is_ui_shown(ewh)); 300 Reset(ewh); 301 } 302 303 // Single press of exit shortcut before timer => idle 304 TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestSinglePress) { 305 ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); 306 ui::Accelerator release(press); 307 release.set_type(ui::ET_KEY_RELEASED); 308 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest(); 309 ASSERT_TRUE(!!ewh); 310 StubForTest(ewh); 311 EXPECT_TRUE(is_idle(ewh)); 312 EXPECT_FALSE(is_ui_shown(ewh)); 313 EXPECT_TRUE(GetController()->Process(press)); 314 EXPECT_FALSE(GetController()->Process(release)); 315 EXPECT_FALSE(is_idle(ewh)); 316 EXPECT_TRUE(is_ui_shown(ewh)); 317 SimulateTimerExpired(ewh); 318 EXPECT_TRUE(is_idle(ewh)); 319 EXPECT_FALSE(is_ui_shown(ewh)); 320 Reset(ewh); 321 } 322 323 // Shutdown ash with exit warning bubble open should not crash. 324 TEST_F(AcceleratorControllerTest, LingeringExitWarningBubble) { 325 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest(); 326 ASSERT_TRUE(!!ewh); 327 StubForTest(ewh); 328 329 // Trigger once to show the bubble. 330 ewh->HandleAccelerator(); 331 EXPECT_FALSE(is_idle(ewh)); 332 EXPECT_TRUE(is_ui_shown(ewh)); 333 334 // Exit ash and there should be no crash 335 } 336 #endif // !defined(OS_WIN) 337 338 TEST_F(AcceleratorControllerTest, Register) { 339 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE); 340 TestTarget target; 341 GetController()->Register(accelerator_a, &target); 342 343 // The registered accelerator is processed. 344 EXPECT_TRUE(GetController()->Process(accelerator_a)); 345 EXPECT_EQ(1, target.accelerator_pressed_count()); 346 } 347 348 TEST_F(AcceleratorControllerTest, RegisterMultipleTarget) { 349 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE); 350 TestTarget target1; 351 GetController()->Register(accelerator_a, &target1); 352 TestTarget target2; 353 GetController()->Register(accelerator_a, &target2); 354 355 // If multiple targets are registered with the same accelerator, the target 356 // registered later processes the accelerator. 357 EXPECT_TRUE(GetController()->Process(accelerator_a)); 358 EXPECT_EQ(0, target1.accelerator_pressed_count()); 359 EXPECT_EQ(1, target2.accelerator_pressed_count()); 360 } 361 362 TEST_F(AcceleratorControllerTest, Unregister) { 363 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE); 364 TestTarget target; 365 GetController()->Register(accelerator_a, &target); 366 const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE); 367 GetController()->Register(accelerator_b, &target); 368 369 // Unregistering a different accelerator does not affect the other 370 // accelerator. 371 GetController()->Unregister(accelerator_b, &target); 372 EXPECT_TRUE(GetController()->Process(accelerator_a)); 373 EXPECT_EQ(1, target.accelerator_pressed_count()); 374 375 // The unregistered accelerator is no longer processed. 376 target.reset(); 377 GetController()->Unregister(accelerator_a, &target); 378 EXPECT_FALSE(GetController()->Process(accelerator_a)); 379 EXPECT_EQ(0, target.accelerator_pressed_count()); 380 } 381 382 TEST_F(AcceleratorControllerTest, UnregisterAll) { 383 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE); 384 TestTarget target1; 385 GetController()->Register(accelerator_a, &target1); 386 const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE); 387 GetController()->Register(accelerator_b, &target1); 388 const ui::Accelerator accelerator_c(ui::VKEY_C, ui::EF_NONE); 389 TestTarget target2; 390 GetController()->Register(accelerator_c, &target2); 391 GetController()->UnregisterAll(&target1); 392 393 // All the accelerators registered for |target1| are no longer processed. 394 EXPECT_FALSE(GetController()->Process(accelerator_a)); 395 EXPECT_FALSE(GetController()->Process(accelerator_b)); 396 EXPECT_EQ(0, target1.accelerator_pressed_count()); 397 398 // UnregisterAll with a different target does not affect the other target. 399 EXPECT_TRUE(GetController()->Process(accelerator_c)); 400 EXPECT_EQ(1, target2.accelerator_pressed_count()); 401 } 402 403 TEST_F(AcceleratorControllerTest, Process) { 404 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE); 405 TestTarget target1; 406 GetController()->Register(accelerator_a, &target1); 407 408 // The registered accelerator is processed. 409 EXPECT_TRUE(GetController()->Process(accelerator_a)); 410 EXPECT_EQ(1, target1.accelerator_pressed_count()); 411 412 // The non-registered accelerator is not processed. 413 const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE); 414 EXPECT_FALSE(GetController()->Process(accelerator_b)); 415 } 416 417 TEST_F(AcceleratorControllerTest, IsRegistered) { 418 const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE); 419 const ui::Accelerator accelerator_shift_a(ui::VKEY_A, ui::EF_SHIFT_DOWN); 420 TestTarget target; 421 GetController()->Register(accelerator_a, &target); 422 EXPECT_TRUE(GetController()->IsRegistered(accelerator_a)); 423 EXPECT_FALSE(GetController()->IsRegistered(accelerator_shift_a)); 424 GetController()->UnregisterAll(&target); 425 EXPECT_FALSE(GetController()->IsRegistered(accelerator_a)); 426 } 427 428 TEST_F(AcceleratorControllerTest, WindowSnap) { 429 scoped_ptr<aura::Window> window( 430 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20))); 431 const ui::Accelerator dummy; 432 433 wm::WindowState* window_state = wm::GetWindowState(window.get()); 434 435 window_state->Activate(); 436 437 { 438 GetController()->PerformAction(WINDOW_SNAP_LEFT, dummy); 439 gfx::Rect expected_bounds = wm::GetDefaultLeftSnappedWindowBoundsInParent( 440 window.get()); 441 EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString()); 442 } 443 { 444 GetController()->PerformAction(WINDOW_SNAP_RIGHT, dummy); 445 gfx::Rect expected_bounds = wm::GetDefaultRightSnappedWindowBoundsInParent( 446 window.get()); 447 EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString()); 448 } 449 { 450 gfx::Rect normal_bounds = window_state->GetRestoreBoundsInParent(); 451 452 GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy); 453 EXPECT_TRUE(window_state->IsMaximized()); 454 EXPECT_NE(normal_bounds.ToString(), window->bounds().ToString()); 455 456 GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy); 457 EXPECT_FALSE(window_state->IsMaximized()); 458 // Window gets restored to its restore bounds since side-maximized state 459 // is treated as a "maximized" state. 460 EXPECT_EQ(normal_bounds.ToString(), window->bounds().ToString()); 461 462 GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy); 463 GetController()->PerformAction(WINDOW_SNAP_LEFT, dummy); 464 EXPECT_FALSE(window_state->IsMaximized()); 465 466 GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy); 467 GetController()->PerformAction(WINDOW_SNAP_RIGHT, dummy); 468 EXPECT_FALSE(window_state->IsMaximized()); 469 470 GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy); 471 EXPECT_TRUE(window_state->IsMaximized()); 472 GetController()->PerformAction(WINDOW_MINIMIZE, dummy); 473 EXPECT_FALSE(window_state->IsMaximized()); 474 EXPECT_TRUE(window_state->IsMinimized()); 475 window_state->Restore(); 476 window_state->Activate(); 477 } 478 { 479 GetController()->PerformAction(WINDOW_MINIMIZE, dummy); 480 EXPECT_TRUE(window_state->IsMinimized()); 481 } 482 } 483 484 TEST_F(AcceleratorControllerTest, CenterWindowAccelerator) { 485 scoped_ptr<aura::Window> window( 486 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20))); 487 const ui::Accelerator dummy; 488 wm::WindowState* window_state = wm::GetWindowState(window.get()); 489 window_state->Activate(); 490 491 // Center the window using accelerator. 492 GetController()->PerformAction(WINDOW_POSITION_CENTER, dummy); 493 gfx::Rect work_area = 494 Shell::GetScreen()->GetDisplayNearestWindow(window.get()).work_area(); 495 gfx::Rect bounds = window->GetBoundsInScreen(); 496 EXPECT_NEAR(bounds.x() - work_area.x(), 497 work_area.right() - bounds.right(), 498 1); 499 EXPECT_NEAR(bounds.y() - work_area.y(), 500 work_area.bottom() - bounds.bottom(), 501 1); 502 503 // Add the window to docked container and try to center it. 504 window->SetBounds(gfx::Rect(0, 0, 20, 20)); 505 aura::Window* docked_container = Shell::GetContainer( 506 window->GetRootWindow(), kShellWindowId_DockedContainer); 507 docked_container->AddChild(window.get()); 508 gfx::Rect docked_bounds = window->GetBoundsInScreen(); 509 GetController()->PerformAction(WINDOW_POSITION_CENTER, dummy); 510 // It should not get centered and should remain docked. 511 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id()); 512 EXPECT_EQ(docked_bounds.ToString(), window->GetBoundsInScreen().ToString()); 513 } 514 515 TEST_F(AcceleratorControllerTest, AutoRepeat) { 516 ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_CONTROL_DOWN); 517 accelerator_a.set_type(ui::ET_KEY_PRESSED); 518 TestTarget target_a; 519 GetController()->Register(accelerator_a, &target_a); 520 ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_CONTROL_DOWN); 521 accelerator_b.set_type(ui::ET_KEY_PRESSED); 522 TestTarget target_b; 523 GetController()->Register(accelerator_b, &target_b); 524 525 ui::test::EventGenerator& generator = GetEventGenerator(); 526 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN); 527 generator.ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN); 528 529 EXPECT_EQ(1, target_a.accelerator_pressed_count()); 530 EXPECT_EQ(0, target_a.accelerator_repeat_count()); 531 532 // Long press should generate one 533 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN); 534 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT); 535 EXPECT_EQ(2, target_a.accelerator_pressed_count()); 536 EXPECT_EQ(1, target_a.accelerator_repeat_count()); 537 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT); 538 EXPECT_EQ(2, target_a.accelerator_pressed_count()); 539 EXPECT_EQ(2, target_a.accelerator_repeat_count()); 540 generator.ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN); 541 EXPECT_EQ(2, target_a.accelerator_pressed_count()); 542 EXPECT_EQ(2, target_a.accelerator_repeat_count()); 543 544 // Long press was intercepted by another key press. 545 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN); 546 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT); 547 generator.PressKey(ui::VKEY_B, ui::EF_CONTROL_DOWN); 548 generator.ReleaseKey(ui::VKEY_B, ui::EF_CONTROL_DOWN); 549 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN); 550 generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT); 551 generator.ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN); 552 553 EXPECT_EQ(1, target_b.accelerator_pressed_count()); 554 EXPECT_EQ(0, target_b.accelerator_repeat_count()); 555 EXPECT_EQ(4, target_a.accelerator_pressed_count()); 556 EXPECT_EQ(4, target_a.accelerator_repeat_count()); 557 } 558 559 TEST_F(AcceleratorControllerTest, Previous) { 560 ui::test::EventGenerator& generator = GetEventGenerator(); 561 generator.PressKey(ui::VKEY_VOLUME_MUTE, ui::EF_NONE); 562 generator.ReleaseKey(ui::VKEY_VOLUME_MUTE, ui::EF_NONE); 563 564 EXPECT_EQ(ui::VKEY_VOLUME_MUTE, 565 GetController()->previous_accelerator_for_test().key_code()); 566 EXPECT_EQ(ui::EF_NONE, 567 GetController()->previous_accelerator_for_test().modifiers()); 568 569 generator.PressKey(ui::VKEY_TAB, ui::EF_CONTROL_DOWN); 570 generator.ReleaseKey(ui::VKEY_TAB, ui::EF_CONTROL_DOWN); 571 572 EXPECT_EQ(ui::VKEY_TAB, 573 GetController()->previous_accelerator_for_test().key_code()); 574 EXPECT_EQ(ui::EF_CONTROL_DOWN, 575 GetController()->previous_accelerator_for_test().modifiers()); 576 } 577 578 TEST_F(AcceleratorControllerTest, DontRepeatToggleFullscreen) { 579 const AcceleratorData accelerators[] = { 580 {true, ui::VKEY_J, ui::EF_ALT_DOWN, TOGGLE_FULLSCREEN}, 581 {true, ui::VKEY_K, ui::EF_ALT_DOWN, TOGGLE_FULLSCREEN}, 582 }; 583 GetController()->RegisterAccelerators(accelerators, arraysize(accelerators)); 584 585 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); 586 params.context = CurrentContext(); 587 params.bounds = gfx::Rect(5, 5, 20, 20); 588 views::Widget* widget = new views::Widget; 589 widget->Init(params); 590 widget->Show(); 591 widget->Activate(); 592 widget->GetNativeView()->SetProperty(aura::client::kCanMaximizeKey, true); 593 594 ui::test::EventGenerator& generator = GetEventGenerator(); 595 wm::WindowState* window_state = wm::GetWindowState(widget->GetNativeView()); 596 597 // Toggling not suppressed. 598 generator.PressKey(ui::VKEY_J, ui::EF_ALT_DOWN); 599 EXPECT_TRUE(window_state->IsFullscreen()); 600 601 // The same accelerator - toggling suppressed. 602 generator.PressKey(ui::VKEY_J, ui::EF_ALT_DOWN | ui::EF_IS_REPEAT); 603 EXPECT_TRUE(window_state->IsFullscreen()); 604 605 // Different accelerator. 606 generator.PressKey(ui::VKEY_K, ui::EF_ALT_DOWN); 607 EXPECT_FALSE(window_state->IsFullscreen()); 608 } 609 610 // TODO(oshima): Fix this test to use EventGenerator. 611 #if defined(OS_WIN) 612 // crbug.com/317592 613 #define MAYBE_ProcessOnce DISABLED_ProcessOnce 614 #else 615 #define MAYBE_ProcessOnce ProcessOnce 616 #endif 617 618 #if defined(OS_WIN) || defined(USE_X11) 619 TEST_F(AcceleratorControllerTest, MAYBE_ProcessOnce) { 620 ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE); 621 TestTarget target; 622 GetController()->Register(accelerator_a, &target); 623 624 // The accelerator is processed only once. 625 ui::EventProcessor* dispatcher = 626 Shell::GetPrimaryRootWindow()->GetHost()->event_processor(); 627 #if defined(OS_WIN) 628 MSG msg1 = { NULL, WM_KEYDOWN, ui::VKEY_A, 0 }; 629 ui::KeyEvent key_event1(msg1); 630 key_event1.SetTranslated(true); 631 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&key_event1); 632 EXPECT_TRUE(key_event1.handled() || details.dispatcher_destroyed); 633 634 MSG msg2 = { NULL, WM_CHAR, L'A', 0 }; 635 ui::KeyEvent key_event2(msg2); 636 key_event2.SetTranslated(true); 637 details = dispatcher->OnEventFromSource(&key_event2); 638 EXPECT_FALSE(key_event2.handled() || details.dispatcher_destroyed); 639 640 MSG msg3 = { NULL, WM_KEYUP, ui::VKEY_A, 0 }; 641 ui::KeyEvent key_event3(msg3); 642 key_event3.SetTranslated(true); 643 details = dispatcher->OnEventFromSource(&key_event3); 644 EXPECT_FALSE(key_event3.handled() || details.dispatcher_destroyed); 645 #elif defined(USE_X11) 646 ui::ScopedXI2Event key_event; 647 key_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, 0); 648 ui::KeyEvent key_event1(key_event); 649 key_event1.SetTranslated(true); 650 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&key_event1); 651 EXPECT_TRUE(key_event1.handled() || details.dispatcher_destroyed); 652 653 ui::KeyEvent key_event2('A', ui::VKEY_A, ui::EF_NONE); 654 key_event2.SetTranslated(true); 655 details = dispatcher->OnEventFromSource(&key_event2); 656 EXPECT_FALSE(key_event2.handled() || details.dispatcher_destroyed); 657 658 key_event.InitKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, 0); 659 ui::KeyEvent key_event3(key_event); 660 key_event3.SetTranslated(true); 661 details = dispatcher->OnEventFromSource(&key_event3); 662 EXPECT_FALSE(key_event3.handled() || details.dispatcher_destroyed); 663 #endif 664 EXPECT_EQ(1, target.accelerator_pressed_count()); 665 } 666 #endif 667 668 TEST_F(AcceleratorControllerTest, GlobalAccelerators) { 669 // CycleBackward 670 EXPECT_TRUE(GetController()->Process( 671 ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN))); 672 // CycleForward 673 EXPECT_TRUE( 674 GetController()->Process(ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN))); 675 // CycleLinear 676 EXPECT_TRUE(GetController()->Process( 677 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_NONE))); 678 679 #if defined(OS_CHROMEOS) 680 // Take screenshot / partial screenshot 681 // True should always be returned regardless of the existence of the delegate. 682 { 683 test::TestScreenshotDelegate* delegate = GetScreenshotDelegate(); 684 delegate->set_can_take_screenshot(false); 685 EXPECT_TRUE(GetController()->Process( 686 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN))); 687 EXPECT_TRUE( 688 GetController()->Process(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); 689 EXPECT_TRUE(GetController()->Process(ui::Accelerator( 690 ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); 691 692 delegate->set_can_take_screenshot(true); 693 EXPECT_EQ(0, delegate->handle_take_screenshot_count()); 694 EXPECT_TRUE(GetController()->Process( 695 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN))); 696 EXPECT_EQ(1, delegate->handle_take_screenshot_count()); 697 EXPECT_TRUE( 698 GetController()->Process(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); 699 EXPECT_EQ(2, delegate->handle_take_screenshot_count()); 700 EXPECT_TRUE(GetController()->Process(ui::Accelerator( 701 ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); 702 EXPECT_EQ(2, delegate->handle_take_screenshot_count()); 703 } 704 #endif 705 const ui::Accelerator volume_mute(ui::VKEY_VOLUME_MUTE, ui::EF_NONE); 706 const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE); 707 const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE); 708 { 709 TestVolumeControlDelegate* delegate = 710 new TestVolumeControlDelegate(false); 711 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate( 712 scoped_ptr<VolumeControlDelegate>(delegate).Pass()); 713 EXPECT_EQ(0, delegate->handle_volume_mute_count()); 714 EXPECT_FALSE(GetController()->Process(volume_mute)); 715 EXPECT_EQ(1, delegate->handle_volume_mute_count()); 716 EXPECT_EQ(volume_mute, delegate->last_accelerator()); 717 EXPECT_EQ(0, delegate->handle_volume_down_count()); 718 EXPECT_FALSE(GetController()->Process(volume_down)); 719 EXPECT_EQ(1, delegate->handle_volume_down_count()); 720 EXPECT_EQ(volume_down, delegate->last_accelerator()); 721 EXPECT_EQ(0, delegate->handle_volume_up_count()); 722 EXPECT_FALSE(GetController()->Process(volume_up)); 723 EXPECT_EQ(1, delegate->handle_volume_up_count()); 724 EXPECT_EQ(volume_up, delegate->last_accelerator()); 725 } 726 { 727 TestVolumeControlDelegate* delegate = new TestVolumeControlDelegate(true); 728 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate( 729 scoped_ptr<VolumeControlDelegate>(delegate).Pass()); 730 EXPECT_EQ(0, delegate->handle_volume_mute_count()); 731 EXPECT_TRUE(GetController()->Process(volume_mute)); 732 EXPECT_EQ(1, delegate->handle_volume_mute_count()); 733 EXPECT_EQ(volume_mute, delegate->last_accelerator()); 734 EXPECT_EQ(0, delegate->handle_volume_down_count()); 735 EXPECT_TRUE(GetController()->Process(volume_down)); 736 EXPECT_EQ(1, delegate->handle_volume_down_count()); 737 EXPECT_EQ(volume_down, delegate->last_accelerator()); 738 EXPECT_EQ(0, delegate->handle_volume_up_count()); 739 EXPECT_TRUE(GetController()->Process(volume_up)); 740 EXPECT_EQ(1, delegate->handle_volume_up_count()); 741 EXPECT_EQ(volume_up, delegate->last_accelerator()); 742 } 743 #if defined(OS_CHROMEOS) 744 // Brightness 745 // ui::VKEY_BRIGHTNESS_DOWN/UP are not defined on Windows. 746 const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE); 747 const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE); 748 { 749 DummyBrightnessControlDelegate* delegate = 750 new DummyBrightnessControlDelegate(false); 751 GetController()->SetBrightnessControlDelegate( 752 scoped_ptr<BrightnessControlDelegate>(delegate).Pass()); 753 EXPECT_EQ(0, delegate->handle_brightness_down_count()); 754 EXPECT_FALSE(GetController()->Process(brightness_down)); 755 EXPECT_EQ(1, delegate->handle_brightness_down_count()); 756 EXPECT_EQ(brightness_down, delegate->last_accelerator()); 757 EXPECT_EQ(0, delegate->handle_brightness_up_count()); 758 EXPECT_FALSE(GetController()->Process(brightness_up)); 759 EXPECT_EQ(1, delegate->handle_brightness_up_count()); 760 EXPECT_EQ(brightness_up, delegate->last_accelerator()); 761 } 762 { 763 DummyBrightnessControlDelegate* delegate = 764 new DummyBrightnessControlDelegate(true); 765 GetController()->SetBrightnessControlDelegate( 766 scoped_ptr<BrightnessControlDelegate>(delegate).Pass()); 767 EXPECT_EQ(0, delegate->handle_brightness_down_count()); 768 EXPECT_TRUE(GetController()->Process(brightness_down)); 769 EXPECT_EQ(1, delegate->handle_brightness_down_count()); 770 EXPECT_EQ(brightness_down, delegate->last_accelerator()); 771 EXPECT_EQ(0, delegate->handle_brightness_up_count()); 772 EXPECT_TRUE(GetController()->Process(brightness_up)); 773 EXPECT_EQ(1, delegate->handle_brightness_up_count()); 774 EXPECT_EQ(brightness_up, delegate->last_accelerator()); 775 } 776 777 // Keyboard brightness 778 const ui::Accelerator alt_brightness_down(ui::VKEY_BRIGHTNESS_DOWN, 779 ui::EF_ALT_DOWN); 780 const ui::Accelerator alt_brightness_up(ui::VKEY_BRIGHTNESS_UP, 781 ui::EF_ALT_DOWN); 782 { 783 EXPECT_TRUE(GetController()->Process(alt_brightness_down)); 784 EXPECT_TRUE(GetController()->Process(alt_brightness_up)); 785 DummyKeyboardBrightnessControlDelegate* delegate = 786 new DummyKeyboardBrightnessControlDelegate(false); 787 GetController()->SetKeyboardBrightnessControlDelegate( 788 scoped_ptr<KeyboardBrightnessControlDelegate>(delegate).Pass()); 789 EXPECT_EQ(0, delegate->handle_keyboard_brightness_down_count()); 790 EXPECT_FALSE(GetController()->Process(alt_brightness_down)); 791 EXPECT_EQ(1, delegate->handle_keyboard_brightness_down_count()); 792 EXPECT_EQ(alt_brightness_down, delegate->last_accelerator()); 793 EXPECT_EQ(0, delegate->handle_keyboard_brightness_up_count()); 794 EXPECT_FALSE(GetController()->Process(alt_brightness_up)); 795 EXPECT_EQ(1, delegate->handle_keyboard_brightness_up_count()); 796 EXPECT_EQ(alt_brightness_up, delegate->last_accelerator()); 797 } 798 { 799 DummyKeyboardBrightnessControlDelegate* delegate = 800 new DummyKeyboardBrightnessControlDelegate(true); 801 GetController()->SetKeyboardBrightnessControlDelegate( 802 scoped_ptr<KeyboardBrightnessControlDelegate>(delegate).Pass()); 803 EXPECT_EQ(0, delegate->handle_keyboard_brightness_down_count()); 804 EXPECT_TRUE(GetController()->Process(alt_brightness_down)); 805 EXPECT_EQ(1, delegate->handle_keyboard_brightness_down_count()); 806 EXPECT_EQ(alt_brightness_down, delegate->last_accelerator()); 807 EXPECT_EQ(0, delegate->handle_keyboard_brightness_up_count()); 808 EXPECT_TRUE(GetController()->Process(alt_brightness_up)); 809 EXPECT_EQ(1, delegate->handle_keyboard_brightness_up_count()); 810 EXPECT_EQ(alt_brightness_up, delegate->last_accelerator()); 811 } 812 #endif 813 814 #if !defined(NDEBUG) 815 // ToggleDesktopBackgroundMode 816 EXPECT_TRUE(GetController()->Process( 817 ui::Accelerator(ui::VKEY_B, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN))); 818 #if !defined(OS_LINUX) 819 // ToggleDesktopFullScreen (not implemented yet on Linux) 820 EXPECT_TRUE(GetController()->Process( 821 ui::Accelerator(ui::VKEY_F11, ui::EF_CONTROL_DOWN))); 822 #endif // OS_LINUX 823 #endif // !NDEBUG 824 825 #if !defined(OS_WIN) 826 // Exit 827 ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest(); 828 ASSERT_TRUE(!!ewh); 829 StubForTest(ewh); 830 EXPECT_TRUE(is_idle(ewh)); 831 EXPECT_FALSE(is_ui_shown(ewh)); 832 EXPECT_TRUE(GetController()->Process( 833 ui::Accelerator(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); 834 EXPECT_FALSE(is_idle(ewh)); 835 EXPECT_TRUE(is_ui_shown(ewh)); 836 SimulateTimerExpired(ewh); 837 EXPECT_TRUE(is_idle(ewh)); 838 EXPECT_FALSE(is_ui_shown(ewh)); 839 Reset(ewh); 840 #endif 841 842 // New tab 843 EXPECT_TRUE(GetController()->Process( 844 ui::Accelerator(ui::VKEY_T, ui::EF_CONTROL_DOWN))); 845 846 // New incognito window 847 EXPECT_TRUE(GetController()->Process( 848 ui::Accelerator(ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); 849 850 // New window 851 EXPECT_TRUE(GetController()->Process( 852 ui::Accelerator(ui::VKEY_N, ui::EF_CONTROL_DOWN))); 853 854 // Restore tab 855 EXPECT_TRUE(GetController()->Process( 856 ui::Accelerator(ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); 857 858 // Show task manager 859 EXPECT_TRUE(GetController()->Process( 860 ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN))); 861 862 #if defined(OS_CHROMEOS) 863 // Open file manager 864 EXPECT_TRUE(GetController()->Process( 865 ui::Accelerator(ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN))); 866 867 // Lock screen 868 // NOTE: Accelerators that do not work on the lock screen need to be 869 // tested before the sequence below is invoked because it causes a side 870 // effect of locking the screen. 871 EXPECT_TRUE(GetController()->Process( 872 ui::Accelerator(ui::VKEY_L, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); 873 #endif 874 } 875 876 TEST_F(AcceleratorControllerTest, GlobalAcceleratorsToggleAppList) { 877 AccessibilityDelegate* delegate = 878 ash::Shell::GetInstance()->accessibility_delegate(); 879 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility()); 880 881 // The press event should not open the AppList, the release should instead. 882 EXPECT_FALSE( 883 GetController()->Process(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE))); 884 EXPECT_EQ(ui::VKEY_LWIN, 885 GetController()->previous_accelerator_for_test().key_code()); 886 887 EXPECT_TRUE( 888 GetController()->Process(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE))); 889 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility()); 890 891 // When spoken feedback is on, the AppList should not toggle. 892 delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE); 893 EXPECT_FALSE( 894 GetController()->Process(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE))); 895 EXPECT_FALSE( 896 GetController()->Process(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE))); 897 delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE); 898 EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility()); 899 900 EXPECT_FALSE( 901 GetController()->Process(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE))); 902 EXPECT_TRUE( 903 GetController()->Process(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE))); 904 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility()); 905 906 // When spoken feedback is on, the AppList should not toggle. 907 delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE); 908 EXPECT_FALSE( 909 GetController()->Process(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE))); 910 EXPECT_FALSE( 911 GetController()->Process(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE))); 912 delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE); 913 EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility()); 914 } 915 916 TEST_F(AcceleratorControllerTest, ImeGlobalAccelerators) { 917 // Test IME shortcuts. 918 { 919 const ui::Accelerator control_space(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN); 920 const ui::Accelerator convert(ui::VKEY_CONVERT, ui::EF_NONE); 921 const ui::Accelerator non_convert(ui::VKEY_NONCONVERT, ui::EF_NONE); 922 const ui::Accelerator wide_half_1(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE); 923 const ui::Accelerator wide_half_2(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE); 924 const ui::Accelerator hangul(ui::VKEY_HANGUL, ui::EF_NONE); 925 EXPECT_FALSE(GetController()->Process(control_space)); 926 EXPECT_FALSE(GetController()->Process(convert)); 927 EXPECT_FALSE(GetController()->Process(non_convert)); 928 EXPECT_FALSE(GetController()->Process(wide_half_1)); 929 EXPECT_FALSE(GetController()->Process(wide_half_2)); 930 EXPECT_FALSE(GetController()->Process(hangul)); 931 DummyImeControlDelegate* delegate = new DummyImeControlDelegate(true); 932 GetController()->SetImeControlDelegate( 933 scoped_ptr<ImeControlDelegate>(delegate).Pass()); 934 EXPECT_EQ(0, delegate->handle_previous_ime_count()); 935 EXPECT_TRUE(GetController()->Process(control_space)); 936 EXPECT_EQ(1, delegate->handle_previous_ime_count()); 937 EXPECT_EQ(0, delegate->handle_switch_ime_count()); 938 EXPECT_TRUE(GetController()->Process(convert)); 939 EXPECT_EQ(1, delegate->handle_switch_ime_count()); 940 EXPECT_TRUE(GetController()->Process(non_convert)); 941 EXPECT_EQ(2, delegate->handle_switch_ime_count()); 942 EXPECT_TRUE(GetController()->Process(wide_half_1)); 943 EXPECT_EQ(3, delegate->handle_switch_ime_count()); 944 EXPECT_TRUE(GetController()->Process(wide_half_2)); 945 EXPECT_EQ(4, delegate->handle_switch_ime_count()); 946 EXPECT_TRUE(GetController()->Process(hangul)); 947 EXPECT_EQ(5, delegate->handle_switch_ime_count()); 948 } 949 950 // Test IME shortcuts that are triggered on key release. 951 { 952 const ui::Accelerator shift_alt_press(ui::VKEY_MENU, 953 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 954 const ReleaseAccelerator shift_alt(ui::VKEY_MENU, ui::EF_SHIFT_DOWN); 955 const ui::Accelerator alt_shift_press(ui::VKEY_SHIFT, 956 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 957 const ReleaseAccelerator alt_shift(ui::VKEY_SHIFT, ui::EF_ALT_DOWN); 958 959 DummyImeControlDelegate* delegate = new DummyImeControlDelegate(true); 960 GetController()->SetImeControlDelegate( 961 scoped_ptr<ImeControlDelegate>(delegate).Pass()); 962 EXPECT_EQ(0, delegate->handle_next_ime_count()); 963 EXPECT_FALSE(GetController()->Process(shift_alt_press)); 964 EXPECT_FALSE(GetController()->Process(shift_alt)); 965 EXPECT_EQ(1, delegate->handle_next_ime_count()); 966 EXPECT_FALSE(GetController()->Process(alt_shift_press)); 967 EXPECT_FALSE(GetController()->Process(alt_shift)); 968 EXPECT_EQ(2, delegate->handle_next_ime_count()); 969 970 // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is 971 // released. 972 const ui::Accelerator shift_alt_x_press( 973 ui::VKEY_X, 974 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 975 const ReleaseAccelerator shift_alt_x(ui::VKEY_X, 976 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 977 978 EXPECT_FALSE(GetController()->Process(shift_alt_press)); 979 EXPECT_FALSE(GetController()->Process(shift_alt_x_press)); 980 EXPECT_FALSE(GetController()->Process(shift_alt_x)); 981 EXPECT_FALSE(GetController()->Process(shift_alt)); 982 EXPECT_EQ(2, delegate->handle_next_ime_count()); 983 984 // But we _should_ if X is either VKEY_RETURN or VKEY_SPACE. 985 // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way. 986 const ui::Accelerator shift_alt_return_press( 987 ui::VKEY_RETURN, 988 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 989 const ReleaseAccelerator shift_alt_return( 990 ui::VKEY_RETURN, 991 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 992 993 EXPECT_FALSE(GetController()->Process(shift_alt_press)); 994 EXPECT_FALSE(GetController()->Process(shift_alt_return_press)); 995 EXPECT_FALSE(GetController()->Process(shift_alt_return)); 996 EXPECT_FALSE(GetController()->Process(shift_alt)); 997 EXPECT_EQ(3, delegate->handle_next_ime_count()); 998 999 const ui::Accelerator shift_alt_space_press( 1000 ui::VKEY_SPACE, 1001 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 1002 const ReleaseAccelerator shift_alt_space( 1003 ui::VKEY_SPACE, 1004 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 1005 1006 EXPECT_FALSE(GetController()->Process(shift_alt_press)); 1007 EXPECT_FALSE(GetController()->Process(shift_alt_space_press)); 1008 EXPECT_FALSE(GetController()->Process(shift_alt_space)); 1009 EXPECT_FALSE(GetController()->Process(shift_alt)); 1010 EXPECT_EQ(4, delegate->handle_next_ime_count()); 1011 } 1012 1013 #if defined(OS_CHROMEOS) 1014 // Test IME shortcuts again with unnormalized accelerators (Chrome OS only). 1015 { 1016 const ui::Accelerator shift_alt_press(ui::VKEY_MENU, ui::EF_SHIFT_DOWN); 1017 const ReleaseAccelerator shift_alt(ui::VKEY_MENU, ui::EF_SHIFT_DOWN); 1018 const ui::Accelerator alt_shift_press(ui::VKEY_SHIFT, ui::EF_ALT_DOWN); 1019 const ReleaseAccelerator alt_shift(ui::VKEY_SHIFT, ui::EF_ALT_DOWN); 1020 1021 DummyImeControlDelegate* delegate = new DummyImeControlDelegate(true); 1022 GetController()->SetImeControlDelegate( 1023 scoped_ptr<ImeControlDelegate>(delegate).Pass()); 1024 EXPECT_EQ(0, delegate->handle_next_ime_count()); 1025 EXPECT_FALSE(GetController()->Process(shift_alt_press)); 1026 EXPECT_FALSE(GetController()->Process(shift_alt)); 1027 EXPECT_EQ(1, delegate->handle_next_ime_count()); 1028 EXPECT_FALSE(GetController()->Process(alt_shift_press)); 1029 EXPECT_FALSE(GetController()->Process(alt_shift)); 1030 EXPECT_EQ(2, delegate->handle_next_ime_count()); 1031 1032 // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is 1033 // released. 1034 const ui::Accelerator shift_alt_x_press( 1035 ui::VKEY_X, 1036 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 1037 const ReleaseAccelerator shift_alt_x(ui::VKEY_X, 1038 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 1039 1040 EXPECT_FALSE(GetController()->Process(shift_alt_press)); 1041 EXPECT_FALSE(GetController()->Process(shift_alt_x_press)); 1042 EXPECT_FALSE(GetController()->Process(shift_alt_x)); 1043 EXPECT_FALSE(GetController()->Process(shift_alt)); 1044 EXPECT_EQ(2, delegate->handle_next_ime_count()); 1045 } 1046 #endif 1047 } 1048 1049 // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way. 1050 TEST_F(AcceleratorControllerTest, ImeGlobalAcceleratorsWorkaround139556) { 1051 // The workaround for crbug.com/139556 depends on the fact that we don't 1052 // use Shift+Alt+Enter/Space with ET_KEY_PRESSED as an accelerator. Test it. 1053 const ui::Accelerator shift_alt_return_press( 1054 ui::VKEY_RETURN, 1055 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 1056 EXPECT_FALSE(GetController()->Process(shift_alt_return_press)); 1057 const ui::Accelerator shift_alt_space_press( 1058 ui::VKEY_SPACE, 1059 ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); 1060 EXPECT_FALSE(GetController()->Process(shift_alt_space_press)); 1061 } 1062 1063 TEST_F(AcceleratorControllerTest, PreferredReservedAccelerators) { 1064 #if defined(OS_CHROMEOS) 1065 // Power key is reserved on chromeos. 1066 EXPECT_TRUE(GetController()->IsReserved( 1067 ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE))); 1068 EXPECT_FALSE(GetController()->IsPreferred( 1069 ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE))); 1070 #endif 1071 // ALT+Tab are not reserved but preferred. 1072 EXPECT_FALSE(GetController()->IsReserved( 1073 ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN))); 1074 EXPECT_FALSE(GetController()->IsReserved( 1075 ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN))); 1076 EXPECT_TRUE(GetController()->IsPreferred( 1077 ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN))); 1078 EXPECT_TRUE(GetController()->IsPreferred( 1079 ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN))); 1080 1081 // Others are not reserved nor preferred 1082 EXPECT_FALSE(GetController()->IsReserved( 1083 ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); 1084 EXPECT_FALSE(GetController()->IsPreferred( 1085 ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); 1086 EXPECT_FALSE(GetController()->IsReserved( 1087 ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE))); 1088 EXPECT_FALSE(GetController()->IsPreferred( 1089 ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE))); 1090 EXPECT_FALSE(GetController()->IsReserved( 1091 ui::Accelerator(ui::VKEY_A, ui::EF_NONE))); 1092 EXPECT_FALSE(GetController()->IsPreferred( 1093 ui::Accelerator(ui::VKEY_A, ui::EF_NONE))); 1094 } 1095 1096 namespace { 1097 1098 class PreferredReservedAcceleratorsTest : public test::AshTestBase { 1099 public: 1100 PreferredReservedAcceleratorsTest() {} 1101 virtual ~PreferredReservedAcceleratorsTest() {} 1102 1103 // test::AshTestBase: 1104 virtual void SetUp() OVERRIDE { 1105 AshTestBase::SetUp(); 1106 Shell::GetInstance()->lock_state_controller()-> 1107 set_animator_for_test(new test::TestSessionStateAnimator); 1108 } 1109 1110 private: 1111 DISALLOW_COPY_AND_ASSIGN(PreferredReservedAcceleratorsTest); 1112 }; 1113 1114 } // namespace 1115 1116 TEST_F(PreferredReservedAcceleratorsTest, AcceleratorsWithFullscreen) { 1117 aura::Window* w1 = CreateTestWindowInShellWithId(0); 1118 aura::Window* w2 = CreateTestWindowInShellWithId(1); 1119 wm::ActivateWindow(w1); 1120 1121 wm::WMEvent fullscreen(wm::WM_EVENT_FULLSCREEN); 1122 wm::WindowState* w1_state = wm::GetWindowState(w1); 1123 w1_state->OnWMEvent(&fullscreen); 1124 ASSERT_TRUE(w1_state->IsFullscreen()); 1125 1126 ui::test::EventGenerator& generator = GetEventGenerator(); 1127 #if defined(OS_CHROMEOS) 1128 // Power key (reserved) should always be handled. 1129 LockStateController::TestApi test_api( 1130 Shell::GetInstance()->lock_state_controller()); 1131 EXPECT_FALSE(test_api.is_animating_lock()); 1132 generator.PressKey(ui::VKEY_POWER, ui::EF_NONE); 1133 EXPECT_TRUE(test_api.is_animating_lock()); 1134 #endif 1135 1136 // A fullscreen window can consume ALT-TAB (preferred). 1137 ASSERT_EQ(w1, wm::GetActiveWindow()); 1138 generator.PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN); 1139 ASSERT_EQ(w1, wm::GetActiveWindow()); 1140 ASSERT_NE(w2, wm::GetActiveWindow()); 1141 1142 // ALT-TAB is non repeatable. Press A to cancel the 1143 // repeat record. 1144 generator.PressKey(ui::VKEY_A, ui::EF_NONE); 1145 generator.ReleaseKey(ui::VKEY_A, ui::EF_NONE); 1146 1147 // A normal window shouldn't consume preferred accelerator. 1148 wm::WMEvent normal(wm::WM_EVENT_NORMAL); 1149 w1_state->OnWMEvent(&normal); 1150 ASSERT_FALSE(w1_state->IsFullscreen()); 1151 1152 EXPECT_EQ(w1, wm::GetActiveWindow()); 1153 generator.PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN); 1154 ASSERT_NE(w1, wm::GetActiveWindow()); 1155 ASSERT_EQ(w2, wm::GetActiveWindow()); 1156 } 1157 1158 #if defined(OS_CHROMEOS) 1159 TEST_F(AcceleratorControllerTest, DisallowedAtModalWindow) { 1160 std::set<AcceleratorAction> all_actions; 1161 for (size_t i = 0 ; i < kAcceleratorDataLength; ++i) 1162 all_actions.insert(kAcceleratorData[i].action); 1163 #if !defined(NDEBUG) 1164 std::set<AcceleratorAction> all_desktop_actions; 1165 for (size_t i = 0 ; i < kDesktopAcceleratorDataLength; ++i) 1166 all_desktop_actions.insert(kDesktopAcceleratorData[i].action); 1167 #endif 1168 1169 std::set<AcceleratorAction> actionsAllowedAtModalWindow; 1170 for (size_t k = 0 ; k < kActionsAllowedAtModalWindowLength; ++k) 1171 actionsAllowedAtModalWindow.insert(kActionsAllowedAtModalWindow[k]); 1172 for (std::set<AcceleratorAction>::const_iterator it = 1173 actionsAllowedAtModalWindow.begin(); 1174 it != actionsAllowedAtModalWindow.end(); ++it) { 1175 EXPECT_TRUE(all_actions.find(*it) != all_actions.end() 1176 1177 #if !defined(NDEBUG) 1178 || all_desktop_actions.find(*it) != all_desktop_actions.end() 1179 #endif 1180 ) 1181 << " action from kActionsAllowedAtModalWindow" 1182 << " not found in kAcceleratorData or kDesktopAcceleratorData. " 1183 << "action: " << *it; 1184 } 1185 scoped_ptr<aura::Window> window( 1186 CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20))); 1187 const ui::Accelerator dummy; 1188 wm::ActivateWindow(window.get()); 1189 Shell::GetInstance()->SimulateModalWindowOpenForTesting(true); 1190 for (std::set<AcceleratorAction>::const_iterator it = all_actions.begin(); 1191 it != all_actions.end(); ++it) { 1192 if (actionsAllowedAtModalWindow.find(*it) == 1193 actionsAllowedAtModalWindow.end()) { 1194 EXPECT_TRUE(GetController()->PerformAction(*it, dummy)) 1195 << " for action (disallowed at modal window): " << *it; 1196 } 1197 } 1198 // Testing of top row (F5-F10) accelerators that should still work 1199 // when a modal window is open 1200 // 1201 // Screenshot 1202 { 1203 test::TestScreenshotDelegate* delegate = GetScreenshotDelegate(); 1204 delegate->set_can_take_screenshot(false); 1205 EXPECT_TRUE(GetController()->Process( 1206 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN))); 1207 EXPECT_TRUE( 1208 GetController()->Process(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); 1209 EXPECT_TRUE(GetController()->Process(ui::Accelerator( 1210 ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); 1211 delegate->set_can_take_screenshot(true); 1212 EXPECT_EQ(0, delegate->handle_take_screenshot_count()); 1213 EXPECT_TRUE(GetController()->Process( 1214 ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN))); 1215 EXPECT_EQ(1, delegate->handle_take_screenshot_count()); 1216 EXPECT_TRUE( 1217 GetController()->Process(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); 1218 EXPECT_EQ(2, delegate->handle_take_screenshot_count()); 1219 EXPECT_TRUE(GetController()->Process(ui::Accelerator( 1220 ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); 1221 EXPECT_EQ(2, delegate->handle_take_screenshot_count()); 1222 } 1223 // Brightness 1224 const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE); 1225 const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE); 1226 { 1227 DummyBrightnessControlDelegate* delegate = 1228 new DummyBrightnessControlDelegate(false); 1229 GetController()->SetBrightnessControlDelegate( 1230 scoped_ptr<BrightnessControlDelegate>(delegate).Pass()); 1231 EXPECT_EQ(0, delegate->handle_brightness_down_count()); 1232 EXPECT_FALSE(GetController()->Process(brightness_down)); 1233 EXPECT_EQ(1, delegate->handle_brightness_down_count()); 1234 EXPECT_EQ(brightness_down, delegate->last_accelerator()); 1235 EXPECT_EQ(0, delegate->handle_brightness_up_count()); 1236 EXPECT_FALSE(GetController()->Process(brightness_up)); 1237 EXPECT_EQ(1, delegate->handle_brightness_up_count()); 1238 EXPECT_EQ(brightness_up, delegate->last_accelerator()); 1239 } 1240 { 1241 DummyBrightnessControlDelegate* delegate = 1242 new DummyBrightnessControlDelegate(true); 1243 GetController()->SetBrightnessControlDelegate( 1244 scoped_ptr<BrightnessControlDelegate>(delegate).Pass()); 1245 EXPECT_EQ(0, delegate->handle_brightness_down_count()); 1246 EXPECT_TRUE(GetController()->Process(brightness_down)); 1247 EXPECT_EQ(1, delegate->handle_brightness_down_count()); 1248 EXPECT_EQ(brightness_down, delegate->last_accelerator()); 1249 EXPECT_EQ(0, delegate->handle_brightness_up_count()); 1250 EXPECT_TRUE(GetController()->Process(brightness_up)); 1251 EXPECT_EQ(1, delegate->handle_brightness_up_count()); 1252 EXPECT_EQ(brightness_up, delegate->last_accelerator()); 1253 } 1254 // Volume 1255 const ui::Accelerator volume_mute(ui::VKEY_VOLUME_MUTE, ui::EF_NONE); 1256 const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE); 1257 const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE); 1258 { 1259 EXPECT_TRUE(GetController()->Process(volume_mute)); 1260 EXPECT_TRUE(GetController()->Process(volume_down)); 1261 EXPECT_TRUE(GetController()->Process(volume_up)); 1262 TestVolumeControlDelegate* delegate = 1263 new TestVolumeControlDelegate(false); 1264 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate( 1265 scoped_ptr<VolumeControlDelegate>(delegate).Pass()); 1266 EXPECT_EQ(0, delegate->handle_volume_mute_count()); 1267 EXPECT_FALSE(GetController()->Process(volume_mute)); 1268 EXPECT_EQ(1, delegate->handle_volume_mute_count()); 1269 EXPECT_EQ(volume_mute, delegate->last_accelerator()); 1270 EXPECT_EQ(0, delegate->handle_volume_down_count()); 1271 EXPECT_FALSE(GetController()->Process(volume_down)); 1272 EXPECT_EQ(1, delegate->handle_volume_down_count()); 1273 EXPECT_EQ(volume_down, delegate->last_accelerator()); 1274 EXPECT_EQ(0, delegate->handle_volume_up_count()); 1275 EXPECT_FALSE(GetController()->Process(volume_up)); 1276 EXPECT_EQ(1, delegate->handle_volume_up_count()); 1277 EXPECT_EQ(volume_up, delegate->last_accelerator()); 1278 } 1279 { 1280 TestVolumeControlDelegate* delegate = new TestVolumeControlDelegate(true); 1281 ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate( 1282 scoped_ptr<VolumeControlDelegate>(delegate).Pass()); 1283 EXPECT_EQ(0, delegate->handle_volume_mute_count()); 1284 EXPECT_TRUE(GetController()->Process(volume_mute)); 1285 EXPECT_EQ(1, delegate->handle_volume_mute_count()); 1286 EXPECT_EQ(volume_mute, delegate->last_accelerator()); 1287 EXPECT_EQ(0, delegate->handle_volume_down_count()); 1288 EXPECT_TRUE(GetController()->Process(volume_down)); 1289 EXPECT_EQ(1, delegate->handle_volume_down_count()); 1290 EXPECT_EQ(volume_down, delegate->last_accelerator()); 1291 EXPECT_EQ(0, delegate->handle_volume_up_count()); 1292 EXPECT_TRUE(GetController()->Process(volume_up)); 1293 EXPECT_EQ(1, delegate->handle_volume_up_count()); 1294 EXPECT_EQ(volume_up, delegate->last_accelerator()); 1295 } 1296 } 1297 #endif 1298 1299 TEST_F(AcceleratorControllerTest, DisallowedWithNoWindow) { 1300 const ui::Accelerator dummy; 1301 AccessibilityDelegate* delegate = 1302 ash::Shell::GetInstance()->accessibility_delegate(); 1303 1304 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) { 1305 delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE); 1306 EXPECT_TRUE( 1307 GetController()->PerformAction(kActionsNeedingWindow[i], dummy)); 1308 EXPECT_EQ(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_WINDOW_NEEDED); 1309 } 1310 1311 // Make sure we don't alert if we do have a window. 1312 scoped_ptr<aura::Window> window; 1313 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) { 1314 window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20))); 1315 wm::ActivateWindow(window.get()); 1316 delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE); 1317 GetController()->PerformAction(kActionsNeedingWindow[i], dummy); 1318 EXPECT_NE(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_WINDOW_NEEDED); 1319 } 1320 1321 // Don't alert if we have a minimized window either. 1322 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) { 1323 window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20))); 1324 wm::ActivateWindow(window.get()); 1325 GetController()->PerformAction(WINDOW_MINIMIZE, dummy); 1326 delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE); 1327 GetController()->PerformAction(kActionsNeedingWindow[i], dummy); 1328 EXPECT_NE(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_WINDOW_NEEDED); 1329 } 1330 } 1331 1332 } // namespace ash 1333