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