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 <algorithm> 8 #include <cmath> 9 #include <string> 10 11 #include "ash/accelerators/accelerator_commands.h" 12 #include "ash/accelerators/accelerator_table.h" 13 #include "ash/accelerators/debug_commands.h" 14 #include "ash/ash_switches.h" 15 #include "ash/debug.h" 16 #include "ash/display/display_controller.h" 17 #include "ash/display/display_manager.h" 18 #include "ash/focus_cycler.h" 19 #include "ash/gpu_support.h" 20 #include "ash/host/ash_window_tree_host.h" 21 #include "ash/ime_control_delegate.h" 22 #include "ash/magnifier/magnification_controller.h" 23 #include "ash/magnifier/partial_magnification_controller.h" 24 #include "ash/media_delegate.h" 25 #include "ash/multi_profile_uma.h" 26 #include "ash/new_window_delegate.h" 27 #include "ash/root_window_controller.h" 28 #include "ash/rotator/screen_rotation.h" 29 #include "ash/screenshot_delegate.h" 30 #include "ash/session/session_state_delegate.h" 31 #include "ash/shelf/shelf.h" 32 #include "ash/shelf/shelf_delegate.h" 33 #include "ash/shelf/shelf_model.h" 34 #include "ash/shelf/shelf_widget.h" 35 #include "ash/shell.h" 36 #include "ash/shell_delegate.h" 37 #include "ash/shell_window_ids.h" 38 #include "ash/system/brightness_control_delegate.h" 39 #include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h" 40 #include "ash/system/status_area_widget.h" 41 #include "ash/system/tray/system_tray.h" 42 #include "ash/system/tray/system_tray_delegate.h" 43 #include "ash/system/tray/system_tray_notifier.h" 44 #include "ash/system/web_notification/web_notification_tray.h" 45 #include "ash/touch/touch_hud_debug.h" 46 #include "ash/volume_control_delegate.h" 47 #include "ash/wm/maximize_mode/maximize_mode_controller.h" 48 #include "ash/wm/mru_window_tracker.h" 49 #include "ash/wm/overview/window_selector_controller.h" 50 #include "ash/wm/partial_screenshot_view.h" 51 #include "ash/wm/power_button_controller.h" 52 #include "ash/wm/window_cycle_controller.h" 53 #include "ash/wm/window_state.h" 54 #include "ash/wm/window_util.h" 55 #include "ash/wm/wm_event.h" 56 #include "base/bind.h" 57 #include "base/command_line.h" 58 #include "base/metrics/user_metrics.h" 59 #include "ui/aura/env.h" 60 #include "ui/aura/window_event_dispatcher.h" 61 #include "ui/base/accelerators/accelerator.h" 62 #include "ui/base/accelerators/accelerator_manager.h" 63 #include "ui/compositor/debug_utils.h" 64 #include "ui/compositor/layer.h" 65 #include "ui/compositor/layer_animation_sequence.h" 66 #include "ui/compositor/layer_animator.h" 67 #include "ui/events/event.h" 68 #include "ui/events/keycodes/keyboard_codes.h" 69 #include "ui/gfx/screen.h" 70 #include "ui/views/controls/webview/webview.h" 71 #include "ui/views/debug_utils.h" 72 #include "ui/views/widget/widget.h" 73 74 #if defined(OS_CHROMEOS) 75 #include "ash/system/chromeos/keyboard_brightness_controller.h" 76 #include "base/sys_info.h" 77 #include "chromeos/ime/ime_keyboard.h" 78 #include "chromeos/ime/input_method_manager.h" 79 #endif // defined(OS_CHROMEOS) 80 81 namespace ash { 82 namespace { 83 84 using base::UserMetricsAction; 85 86 bool DebugShortcutsEnabled() { 87 #if defined(NDEBUG) 88 return CommandLine::ForCurrentProcess()->HasSwitch( 89 switches::kAshDebugShortcuts); 90 #else 91 return true; 92 #endif 93 } 94 95 bool HandleAccessibleFocusCycle(bool reverse) { 96 if (reverse) { 97 base::RecordAction(UserMetricsAction("Accel_Accessible_Focus_Previous")); 98 } else { 99 base::RecordAction(UserMetricsAction("Accel_Accessible_Focus_Next")); 100 } 101 102 if (!Shell::GetInstance()->accessibility_delegate()-> 103 IsSpokenFeedbackEnabled()) { 104 return false; 105 } 106 aura::Window* active_window = ash::wm::GetActiveWindow(); 107 if (!active_window) 108 return false; 109 views::Widget* widget = 110 views::Widget::GetWidgetForNativeWindow(active_window); 111 if (!widget) 112 return false; 113 views::FocusManager* focus_manager = widget->GetFocusManager(); 114 if (!focus_manager) 115 return false; 116 views::View* view = focus_manager->GetFocusedView(); 117 if (!view) 118 return false; 119 if (!strcmp(view->GetClassName(), views::WebView::kViewClassName)) 120 return false; 121 122 focus_manager->AdvanceFocus(reverse); 123 return true; 124 } 125 126 bool HandleCycleBackwardMRU(const ui::Accelerator& accelerator) { 127 if (accelerator.key_code() == ui::VKEY_TAB) 128 base::RecordAction(base::UserMetricsAction("Accel_PrevWindow_Tab")); 129 130 Shell::GetInstance()->window_cycle_controller()->HandleCycleWindow( 131 WindowCycleController::BACKWARD); 132 return true; 133 } 134 135 bool HandleCycleForwardMRU(const ui::Accelerator& accelerator) { 136 if (accelerator.key_code() == ui::VKEY_TAB) 137 base::RecordAction(base::UserMetricsAction("Accel_NextWindow_Tab")); 138 139 Shell::GetInstance()->window_cycle_controller()->HandleCycleWindow( 140 WindowCycleController::FORWARD); 141 return true; 142 } 143 144 bool ToggleOverview(const ui::Accelerator& accelerator) { 145 base::RecordAction(base::UserMetricsAction("Accel_Overview_F5")); 146 Shell::GetInstance()->window_selector_controller()->ToggleOverview(); 147 return true; 148 } 149 150 bool HandleFocusShelf() { 151 Shell* shell = Shell::GetInstance(); 152 base::RecordAction(base::UserMetricsAction("Accel_Focus_Shelf")); 153 return shell->focus_cycler()->FocusWidget( 154 Shelf::ForPrimaryDisplay()->shelf_widget()); 155 } 156 157 bool HandleLaunchAppN(int n) { 158 base::RecordAction(UserMetricsAction("Accel_Launch_App")); 159 Shelf::ForPrimaryDisplay()->LaunchAppIndexAt(n); 160 return true; 161 } 162 163 bool HandleLaunchLastApp() { 164 base::RecordAction(UserMetricsAction("Accel_Launch_Last_App")); 165 Shelf::ForPrimaryDisplay()->LaunchAppIndexAt(-1); 166 return true; 167 } 168 169 // Magnify the screen 170 bool HandleMagnifyScreen(int delta_index) { 171 if (ash::Shell::GetInstance()->magnification_controller()->IsEnabled()) { 172 // TODO(yoshiki): Move the following logic to MagnificationController. 173 float scale = 174 ash::Shell::GetInstance()->magnification_controller()->GetScale(); 175 // Calculate rounded logarithm (base kMagnificationScaleFactor) of scale. 176 int scale_index = 177 std::floor(std::log(scale) / std::log(kMagnificationScaleFactor) + 0.5); 178 179 int new_scale_index = std::max(0, std::min(8, scale_index + delta_index)); 180 181 ash::Shell::GetInstance()->magnification_controller()-> 182 SetScale(std::pow(kMagnificationScaleFactor, new_scale_index), true); 183 } else if (ash::Shell::GetInstance()-> 184 partial_magnification_controller()->is_enabled()) { 185 float scale = delta_index > 0 ? kDefaultPartialMagnifiedScale : 1; 186 ash::Shell::GetInstance()->partial_magnification_controller()-> 187 SetScale(scale); 188 } 189 190 return true; 191 } 192 193 bool HandleMediaNextTrack() { 194 Shell::GetInstance()->media_delegate()->HandleMediaNextTrack(); 195 return true; 196 } 197 198 bool HandleMediaPlayPause() { 199 Shell::GetInstance()->media_delegate()->HandleMediaPlayPause(); 200 return true; 201 } 202 203 bool HandleMediaPrevTrack() { 204 Shell::GetInstance()->media_delegate()->HandleMediaPrevTrack(); 205 return true; 206 } 207 208 bool HandleNewIncognitoWindow() { 209 base::RecordAction(UserMetricsAction("Accel_New_Incognito_Window")); 210 bool incognito_allowed = 211 Shell::GetInstance()->delegate()->IsIncognitoAllowed(); 212 if (incognito_allowed) 213 Shell::GetInstance()->new_window_delegate()->NewWindow( 214 true /* is_incognito */); 215 return incognito_allowed; 216 } 217 218 bool HandleNewTab(ui::KeyboardCode key_code) { 219 if (key_code == ui::VKEY_T) 220 base::RecordAction(base::UserMetricsAction("Accel_NewTab_T")); 221 Shell::GetInstance()->new_window_delegate()->NewTab(); 222 return true; 223 } 224 225 bool HandleNewWindow() { 226 base::RecordAction(base::UserMetricsAction("Accel_New_Window")); 227 Shell::GetInstance()->new_window_delegate()->NewWindow( 228 false /* is_incognito */); 229 return true; 230 } 231 232 void HandleNextIme(ImeControlDelegate* ime_control_delegate, 233 ui::EventType previous_event_type, 234 ui::KeyboardCode previous_key_code) { 235 // This check is necessary e.g. not to process the Shift+Alt+ 236 // ET_KEY_RELEASED accelerator for Chrome OS (see ash/accelerators/ 237 // accelerator_controller.cc) when Shift+Alt+Tab is pressed and then Tab 238 // is released. 239 if (previous_event_type == ui::ET_KEY_RELEASED && 240 // Workaround for crbug.com/139556. CJK IME users tend to press 241 // Enter (or Space) and Shift+Alt almost at the same time to commit 242 // an IME string and then switch from the IME to the English layout. 243 // This workaround allows the user to trigger NEXT_IME even if the 244 // user presses Shift+Alt before releasing Enter. 245 // TODO(nona|mazda): Fix crbug.com/139556 in a cleaner way. 246 previous_key_code != ui::VKEY_RETURN && 247 previous_key_code != ui::VKEY_SPACE) { 248 // We totally ignore this accelerator. 249 // TODO(mazda): Fix crbug.com/158217 250 return; 251 } 252 base::RecordAction(UserMetricsAction("Accel_Next_Ime")); 253 if (ime_control_delegate) 254 ime_control_delegate->HandleNextIme(); 255 } 256 257 bool HandleOpenFeedbackPage() { 258 base::RecordAction(UserMetricsAction("Accel_Open_Feedback_Page")); 259 ash::Shell::GetInstance()->new_window_delegate()->OpenFeedbackPage(); 260 return true; 261 } 262 263 bool HandlePositionCenter() { 264 base::RecordAction(UserMetricsAction("Accel_Window_Position_Center")); 265 aura::Window* window = wm::GetActiveWindow(); 266 // Docked windows do not support centering and ignore accelerator. 267 if (window && !wm::GetWindowState(window)->IsDocked()) { 268 wm::CenterWindow(window); 269 return true; 270 } 271 return false; 272 } 273 274 bool HandlePreviousIme(ImeControlDelegate* ime_control_delegate, 275 const ui::Accelerator& accelerator) { 276 base::RecordAction(UserMetricsAction("Accel_Previous_Ime")); 277 if (ime_control_delegate) 278 return ime_control_delegate->HandlePreviousIme(accelerator); 279 return false; 280 } 281 282 bool HandleRestoreTab() { 283 base::RecordAction(base::UserMetricsAction("Accel_Restore_Tab")); 284 Shell::GetInstance()->new_window_delegate()->RestoreTab(); 285 return true; 286 } 287 288 bool HandleRotatePaneFocus(Shell::Direction direction) { 289 Shell* shell = Shell::GetInstance(); 290 switch (direction) { 291 // TODO(stevet): Not sure if this is the same as IDC_FOCUS_NEXT_PANE. 292 case Shell::FORWARD: { 293 base::RecordAction(UserMetricsAction("Accel_Focus_Next_Pane")); 294 shell->focus_cycler()->RotateFocus(FocusCycler::FORWARD); 295 break; 296 } 297 case Shell::BACKWARD: { 298 base::RecordAction(UserMetricsAction("Accel_Focus_Previous_Pane")); 299 shell->focus_cycler()->RotateFocus(FocusCycler::BACKWARD); 300 break; 301 } 302 } 303 return true; 304 } 305 306 // Rotate the active window. 307 bool HandleRotateActiveWindow() { 308 base::RecordAction(UserMetricsAction("Accel_Rotate_Window")); 309 aura::Window* active_window = wm::GetActiveWindow(); 310 if (active_window) { 311 // The rotation animation bases its target transform on the current 312 // rotation and position. Since there could be an animation in progress 313 // right now, queue this animation so when it starts it picks up a neutral 314 // rotation and position. Use replace so we only enqueue one at a time. 315 active_window->layer()->GetAnimator()-> 316 set_preemption_strategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); 317 active_window->layer()->GetAnimator()->StartAnimation( 318 new ui::LayerAnimationSequence( 319 new ash::ScreenRotation(360, active_window->layer()))); 320 } 321 return true; 322 } 323 324 gfx::Display::Rotation GetNextRotation(gfx::Display::Rotation current) { 325 switch (current) { 326 case gfx::Display::ROTATE_0: 327 return gfx::Display::ROTATE_90; 328 case gfx::Display::ROTATE_90: 329 return gfx::Display::ROTATE_180; 330 case gfx::Display::ROTATE_180: 331 return gfx::Display::ROTATE_270; 332 case gfx::Display::ROTATE_270: 333 return gfx::Display::ROTATE_0; 334 } 335 NOTREACHED() << "Unknown rotation:" << current; 336 return gfx::Display::ROTATE_0; 337 } 338 339 // Rotates the screen. 340 bool HandleRotateScreen() { 341 base::RecordAction(UserMetricsAction("Accel_Rotate_Window")); 342 gfx::Point point = Shell::GetScreen()->GetCursorScreenPoint(); 343 gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint(point); 344 const DisplayInfo& display_info = 345 Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id()); 346 Shell::GetInstance()->display_manager()->SetDisplayRotation( 347 display.id(), GetNextRotation(display_info.rotation())); 348 return true; 349 } 350 351 bool HandleScaleReset() { 352 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 353 int64 display_id = display_manager->GetDisplayIdForUIScaling(); 354 if (display_id == gfx::Display::kInvalidDisplayID) 355 return false; 356 357 base::RecordAction(UserMetricsAction("Accel_Scale_Ui_Reset")); 358 359 display_manager->SetDisplayUIScale(display_id, 1.0f); 360 return true; 361 } 362 363 bool HandleScaleUI(bool up) { 364 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 365 int64 display_id = display_manager->GetDisplayIdForUIScaling(); 366 if (display_id == gfx::Display::kInvalidDisplayID) 367 return false; 368 369 if (up) { 370 base::RecordAction(UserMetricsAction("Accel_Scale_Ui_Up")); 371 } else { 372 base::RecordAction(UserMetricsAction("Accel_Scale_Ui_Down")); 373 } 374 375 const DisplayInfo& display_info = display_manager->GetDisplayInfo(display_id); 376 float next_scale = DisplayManager::GetNextUIScale(display_info, up); 377 display_manager->SetDisplayUIScale(display_id, next_scale); 378 return true; 379 } 380 381 #if defined(OS_CHROMEOS) 382 bool HandleSwapPrimaryDisplay() { 383 base::RecordAction(UserMetricsAction("Accel_Swap_Primary_Display")); 384 Shell::GetInstance()->display_controller()->SwapPrimaryDisplay(); 385 return true; 386 } 387 #endif 388 389 bool HandleShowKeyboardOverlay() { 390 base::RecordAction(UserMetricsAction("Accel_Show_Keyboard_Overlay")); 391 ash::Shell::GetInstance()->new_window_delegate()->ShowKeyboardOverlay(); 392 393 return true; 394 } 395 396 void HandleShowMessageCenterBubble() { 397 base::RecordAction(UserMetricsAction("Accel_Show_Message_Center_Bubble")); 398 RootWindowController* controller = 399 RootWindowController::ForTargetRootWindow(); 400 StatusAreaWidget* status_area_widget = 401 controller->shelf()->status_area_widget(); 402 if (status_area_widget) { 403 WebNotificationTray* notification_tray = 404 status_area_widget->web_notification_tray(); 405 if (notification_tray->visible()) 406 notification_tray->ShowMessageCenterBubble(); 407 } 408 } 409 410 bool HandleShowSystemTrayBubble() { 411 base::RecordAction(UserMetricsAction("Accel_Show_System_Tray_Bubble")); 412 RootWindowController* controller = 413 RootWindowController::ForTargetRootWindow(); 414 if (!controller->GetSystemTray()->HasSystemBubble()) { 415 controller->GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW); 416 return true; 417 } 418 return false; 419 } 420 421 bool HandleShowTaskManager() { 422 base::RecordAction(UserMetricsAction("Accel_Show_Task_Manager")); 423 Shell::GetInstance()->new_window_delegate()->ShowTaskManager(); 424 return true; 425 } 426 427 #if defined(OS_CHROMEOS) 428 void HandleSilenceSpokenFeedback() { 429 base::RecordAction(UserMetricsAction("Accel_Silence_Spoken_Feedback")); 430 431 AccessibilityDelegate* delegate = 432 Shell::GetInstance()->accessibility_delegate(); 433 if (!delegate->IsSpokenFeedbackEnabled()) 434 return; 435 delegate->SilenceSpokenFeedback(); 436 } 437 #endif 438 439 bool HandleSwitchIme(ImeControlDelegate* ime_control_delegate, 440 const ui::Accelerator& accelerator) { 441 base::RecordAction(UserMetricsAction("Accel_Switch_Ime")); 442 if (ime_control_delegate) 443 return ime_control_delegate->HandleSwitchIme(accelerator); 444 return false; 445 } 446 447 bool HandleTakePartialScreenshot(ScreenshotDelegate* screenshot_delegate) { 448 base::RecordAction(UserMetricsAction("Accel_Take_Partial_Screenshot")); 449 if (screenshot_delegate) { 450 ash::PartialScreenshotView::StartPartialScreenshot( 451 screenshot_delegate); 452 } 453 // Return true to prevent propagation of the key event because 454 // this key combination is reserved for partial screenshot. 455 return true; 456 } 457 458 bool HandleTakeScreenshot(ScreenshotDelegate* screenshot_delegate) { 459 base::RecordAction(UserMetricsAction("Accel_Take_Screenshot")); 460 if (screenshot_delegate && 461 screenshot_delegate->CanTakeScreenshot()) { 462 screenshot_delegate->HandleTakeScreenshotForAllRootWindows(); 463 } 464 // Return true to prevent propagation of the key event. 465 return true; 466 } 467 468 bool HandleToggleAppList(ui::KeyboardCode key_code, 469 ui::EventType previous_event_type, 470 ui::KeyboardCode previous_key_code, 471 const ui::Accelerator& accelerator) { 472 // If something else was pressed between the Search key (LWIN) 473 // being pressed and released, then ignore the release of the 474 // Search key. 475 if (key_code == ui::VKEY_LWIN && 476 (previous_event_type == ui::ET_KEY_RELEASED || 477 previous_key_code != ui::VKEY_LWIN)) 478 return false; 479 if (key_code == ui::VKEY_LWIN) 480 base::RecordAction(base::UserMetricsAction("Accel_Search_LWin")); 481 // When spoken feedback is enabled, we should neither toggle the list nor 482 // consume the key since Search+Shift is one of the shortcuts the a11y 483 // feature uses. crbug.com/132296 484 DCHECK_EQ(ui::VKEY_LWIN, accelerator.key_code()); 485 if (Shell::GetInstance()->accessibility_delegate()-> 486 IsSpokenFeedbackEnabled()) 487 return false; 488 ash::Shell::GetInstance()->ToggleAppList(NULL); 489 return true; 490 } 491 492 bool HandleToggleFullscreen(ui::KeyboardCode key_code) { 493 if (key_code == ui::VKEY_MEDIA_LAUNCH_APP2) { 494 base::RecordAction(UserMetricsAction("Accel_Fullscreen_F4")); 495 } 496 accelerators::ToggleFullscreen(); 497 return true; 498 } 499 500 bool HandleToggleRootWindowFullScreen() { 501 Shell::GetPrimaryRootWindowController()->ash_host()->ToggleFullScreen(); 502 return true; 503 } 504 505 bool HandleWindowSnap(int action) { 506 wm::WindowState* window_state = wm::GetActiveWindowState(); 507 // Disable window snapping shortcut key for full screen window due to 508 // http://crbug.com/135487. 509 if (!window_state || 510 window_state->window()->type() != ui::wm::WINDOW_TYPE_NORMAL || 511 window_state->IsFullscreen() || 512 !window_state->CanSnap()) { 513 return false; 514 } 515 516 if (action == WINDOW_SNAP_LEFT) { 517 base::RecordAction(UserMetricsAction("Accel_Window_Snap_Left")); 518 } else { 519 base::RecordAction(UserMetricsAction("Accel_Window_Snap_Right")); 520 } 521 const wm::WMEvent event(action == WINDOW_SNAP_LEFT ? 522 wm::WM_EVENT_SNAP_LEFT : wm::WM_EVENT_SNAP_RIGHT); 523 window_state->OnWMEvent(&event); 524 return true; 525 } 526 527 bool HandleWindowMinimize() { 528 base::RecordAction( 529 base::UserMetricsAction("Accel_Toggle_Minimized_Minus")); 530 return accelerators::ToggleMinimized(); 531 } 532 533 #if defined(OS_CHROMEOS) 534 bool HandleAddRemoveDisplay() { 535 base::RecordAction(UserMetricsAction("Accel_Add_Remove_Display")); 536 Shell::GetInstance()->display_manager()->AddRemoveDisplay(); 537 return true; 538 } 539 540 bool HandleCrosh() { 541 base::RecordAction(UserMetricsAction("Accel_Open_Crosh")); 542 543 Shell::GetInstance()->new_window_delegate()->OpenCrosh(); 544 return true; 545 } 546 547 bool HandleFileManager() { 548 base::RecordAction(UserMetricsAction("Accel_Open_File_Manager")); 549 550 Shell::GetInstance()->new_window_delegate()->OpenFileManager(); 551 return true; 552 } 553 554 bool HandleLock(ui::KeyboardCode key_code) { 555 base::RecordAction(UserMetricsAction("Accel_LockScreen_L")); 556 Shell::GetInstance()->session_state_delegate()->LockScreen(); 557 return true; 558 } 559 560 bool HandleCycleUser(SessionStateDelegate::CycleUser cycle_user) { 561 if (!Shell::GetInstance()->delegate()->IsMultiProfilesEnabled()) 562 return false; 563 ash::SessionStateDelegate* delegate = 564 ash::Shell::GetInstance()->session_state_delegate(); 565 if (delegate->NumberOfLoggedInUsers() <= 1) 566 return false; 567 MultiProfileUMA::RecordSwitchActiveUser( 568 MultiProfileUMA::SWITCH_ACTIVE_USER_BY_ACCELERATOR); 569 switch (cycle_user) { 570 case SessionStateDelegate::CYCLE_TO_NEXT_USER: 571 base::RecordAction(UserMetricsAction("Accel_Switch_To_Next_User")); 572 break; 573 case SessionStateDelegate::CYCLE_TO_PREVIOUS_USER: 574 base::RecordAction(UserMetricsAction("Accel_Switch_To_Previous_User")); 575 break; 576 } 577 delegate->CycleActiveUser(cycle_user); 578 return true; 579 } 580 581 bool HandleToggleMirrorMode() { 582 base::RecordAction(UserMetricsAction("Accel_Toggle_Mirror_Mode")); 583 Shell::GetInstance()->display_controller()->ToggleMirrorMode(); 584 return true; 585 } 586 587 bool HandleToggleSpokenFeedback() { 588 base::RecordAction(UserMetricsAction("Accel_Toggle_Spoken_Feedback")); 589 590 Shell::GetInstance()->accessibility_delegate()-> 591 ToggleSpokenFeedback(A11Y_NOTIFICATION_SHOW); 592 return true; 593 } 594 595 bool HandleToggleTouchViewTesting() { 596 // TODO(skuhne): This is only temporary! Remove this! 597 if (CommandLine::ForCurrentProcess()->HasSwitch( 598 switches::kAshEnableTouchViewTesting)) { 599 MaximizeModeController* controller = Shell::GetInstance()-> 600 maximize_mode_controller(); 601 controller->EnableMaximizeModeWindowManager( 602 !controller->IsMaximizeModeWindowManagerEnabled()); 603 return true; 604 } 605 return false; 606 } 607 608 bool HandleTouchHudClear() { 609 RootWindowController* controller = 610 RootWindowController::ForTargetRootWindow(); 611 if (controller->touch_hud_debug()) { 612 controller->touch_hud_debug()->Clear(); 613 return true; 614 } 615 return false; 616 } 617 618 bool HandleTouchHudModeChange() { 619 RootWindowController* controller = 620 RootWindowController::ForTargetRootWindow(); 621 if (controller->touch_hud_debug()) { 622 controller->touch_hud_debug()->ChangeToNextMode(); 623 return true; 624 } 625 return false; 626 } 627 628 bool HandleTouchHudProjectToggle() { 629 base::RecordAction(UserMetricsAction("Accel_Touch_Hud_Clear")); 630 bool enabled = Shell::GetInstance()->is_touch_hud_projection_enabled(); 631 Shell::GetInstance()->SetTouchHudProjectionEnabled(!enabled); 632 return true; 633 } 634 635 bool HandleDisableCapsLock(ui::KeyboardCode key_code, 636 ui::EventType previous_event_type, 637 ui::KeyboardCode previous_key_code) { 638 if (previous_event_type == ui::ET_KEY_RELEASED || 639 (previous_key_code != ui::VKEY_LSHIFT && 640 previous_key_code != ui::VKEY_SHIFT && 641 previous_key_code != ui::VKEY_RSHIFT)) { 642 // If something else was pressed between the Shift key being pressed 643 // and released, then ignore the release of the Shift key. 644 return false; 645 } 646 base::RecordAction(UserMetricsAction("Accel_Disable_Caps_Lock")); 647 chromeos::input_method::InputMethodManager* ime = 648 chromeos::input_method::InputMethodManager::Get(); 649 chromeos::input_method::ImeKeyboard* keyboard = 650 ime ? ime->GetImeKeyboard() : NULL; 651 if (keyboard && keyboard->CapsLockIsEnabled()) { 652 keyboard->SetCapsLockEnabled(false); 653 return true; 654 } 655 return false; 656 } 657 658 bool HandleToggleCapsLock(ui::KeyboardCode key_code, 659 ui::EventType previous_event_type, 660 ui::KeyboardCode previous_key_code) { 661 if (key_code == ui::VKEY_LWIN) { 662 // If something else was pressed between the Search key (LWIN) 663 // being pressed and released, then ignore the release of the 664 // Search key. 665 // TODO(danakj): Releasing Alt first breaks this: crbug.com/166495 666 if (previous_event_type == ui::ET_KEY_RELEASED || 667 previous_key_code != ui::VKEY_LWIN) 668 return false; 669 } 670 base::RecordAction(UserMetricsAction("Accel_Toggle_Caps_Lock")); 671 chromeos::input_method::InputMethodManager* ime = 672 chromeos::input_method::InputMethodManager::Get(); 673 chromeos::input_method::ImeKeyboard* keyboard = 674 ime ? ime->GetImeKeyboard() : NULL; 675 if (keyboard) 676 keyboard->SetCapsLockEnabled(!keyboard->CapsLockIsEnabled()); 677 return true; 678 } 679 680 #endif // defined(OS_CHROMEOS) 681 682 // Debug print methods. 683 684 bool HandlePrintLayerHierarchy() { 685 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 686 for (size_t i = 0; i < root_windows.size(); ++i) { 687 ui::PrintLayerHierarchy( 688 root_windows[i]->layer(), 689 root_windows[i]->GetHost()->dispatcher()->GetLastMouseLocationInRoot()); 690 } 691 return true; 692 } 693 694 bool HandlePrintViewHierarchy() { 695 aura::Window* active_window = ash::wm::GetActiveWindow(); 696 if (!active_window) 697 return true; 698 views::Widget* browser_widget = 699 views::Widget::GetWidgetForNativeWindow(active_window); 700 if (!browser_widget) 701 return true; 702 views::PrintViewHierarchy(browser_widget->GetRootView()); 703 return true; 704 } 705 706 void PrintWindowHierarchy(aura::Window* window, 707 int indent, 708 std::ostringstream* out) { 709 std::string indent_str(indent, ' '); 710 std::string name(window->name()); 711 if (name.empty()) 712 name = "\"\""; 713 *out << indent_str << name << " (" << window << ")" 714 << " type=" << window->type() 715 << (wm::IsActiveWindow(window) ? " [active] " : " ") 716 << (window->IsVisible() ? " visible " : " ") 717 << window->bounds().ToString() 718 << '\n'; 719 720 for (size_t i = 0; i < window->children().size(); ++i) 721 PrintWindowHierarchy(window->children()[i], indent + 3, out); 722 } 723 724 bool HandlePrintWindowHierarchy() { 725 Shell::RootWindowControllerList controllers = 726 Shell::GetAllRootWindowControllers(); 727 for (size_t i = 0; i < controllers.size(); ++i) { 728 std::ostringstream out; 729 out << "RootWindow " << i << ":\n"; 730 PrintWindowHierarchy(controllers[i]->GetRootWindow(), 0, &out); 731 // Error so logs can be collected from end-users. 732 LOG(ERROR) << out.str(); 733 } 734 return true; 735 } 736 737 bool HandlePrintUIHierarchies() { 738 // This is a separate command so the user only has to hit one key to generate 739 // all the logs. Developers use the individual dumps repeatedly, so keep 740 // those as separate commands to avoid spamming their logs. 741 HandlePrintLayerHierarchy(); 742 HandlePrintWindowHierarchy(); 743 HandlePrintViewHierarchy(); 744 return true; 745 } 746 747 class AutoSet { 748 public: 749 AutoSet(ui::Accelerator* scoped, ui::Accelerator new_value) 750 : scoped_(scoped), new_value_(new_value) {} 751 ~AutoSet() { *scoped_ = new_value_; } 752 753 private: 754 ui::Accelerator* scoped_; 755 const ui::Accelerator new_value_; 756 757 DISALLOW_COPY_AND_ASSIGN(AutoSet); 758 }; 759 760 } // namespace 761 762 //////////////////////////////////////////////////////////////////////////////// 763 // AcceleratorController, public: 764 765 AcceleratorController::AcceleratorController() 766 : accelerator_manager_(new ui::AcceleratorManager) { 767 Init(); 768 } 769 770 AcceleratorController::~AcceleratorController() { 771 } 772 773 void AcceleratorController::Init() { 774 previous_accelerator_.set_type(ui::ET_UNKNOWN); 775 for (size_t i = 0; i < kActionsAllowedAtLoginOrLockScreenLength; ++i) { 776 actions_allowed_at_login_screen_.insert( 777 kActionsAllowedAtLoginOrLockScreen[i]); 778 actions_allowed_at_lock_screen_.insert( 779 kActionsAllowedAtLoginOrLockScreen[i]); 780 } 781 for (size_t i = 0; i < kActionsAllowedAtLockScreenLength; ++i) 782 actions_allowed_at_lock_screen_.insert(kActionsAllowedAtLockScreen[i]); 783 for (size_t i = 0; i < kActionsAllowedAtModalWindowLength; ++i) 784 actions_allowed_at_modal_window_.insert(kActionsAllowedAtModalWindow[i]); 785 for (size_t i = 0; i < kPreferredActionsLength; ++i) 786 preferred_actions_.insert(kPreferredActions[i]); 787 for (size_t i = 0; i < kReservedActionsLength; ++i) 788 reserved_actions_.insert(kReservedActions[i]); 789 for (size_t i = 0; i < kNonrepeatableActionsLength; ++i) 790 nonrepeatable_actions_.insert(kNonrepeatableActions[i]); 791 for (size_t i = 0; i < kActionsAllowedInAppModeLength; ++i) 792 actions_allowed_in_app_mode_.insert(kActionsAllowedInAppMode[i]); 793 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) 794 actions_needing_window_.insert(kActionsNeedingWindow[i]); 795 796 RegisterAccelerators(kAcceleratorData, kAcceleratorDataLength); 797 798 #if !defined(NDEBUG) 799 RegisterAccelerators(kDesktopAcceleratorData, kDesktopAcceleratorDataLength); 800 #endif 801 802 if (DebugShortcutsEnabled()) { 803 RegisterAccelerators(kDebugAcceleratorData, kDebugAcceleratorDataLength); 804 for (size_t i = 0; i < kReservedDebugActionsLength; ++i) 805 reserved_actions_.insert(kReservedDebugActions[i]); 806 } 807 808 #if defined(OS_CHROMEOS) 809 keyboard_brightness_control_delegate_.reset( 810 new KeyboardBrightnessController()); 811 #endif 812 } 813 814 void AcceleratorController::Register(const ui::Accelerator& accelerator, 815 ui::AcceleratorTarget* target) { 816 accelerator_manager_->Register(accelerator, 817 ui::AcceleratorManager::kNormalPriority, 818 target); 819 } 820 821 void AcceleratorController::Unregister(const ui::Accelerator& accelerator, 822 ui::AcceleratorTarget* target) { 823 accelerator_manager_->Unregister(accelerator, target); 824 } 825 826 void AcceleratorController::UnregisterAll(ui::AcceleratorTarget* target) { 827 accelerator_manager_->UnregisterAll(target); 828 } 829 830 bool AcceleratorController::Process(const ui::Accelerator& accelerator) { 831 AutoSet auto_set(&previous_accelerator_, accelerator); 832 833 if (ime_control_delegate_) { 834 return accelerator_manager_->Process( 835 ime_control_delegate_->RemapAccelerator(accelerator)); 836 } 837 return accelerator_manager_->Process(accelerator); 838 } 839 840 bool AcceleratorController::IsRegistered( 841 const ui::Accelerator& accelerator) const { 842 return accelerator_manager_->GetCurrentTarget(accelerator) != NULL; 843 } 844 845 bool AcceleratorController::IsPreferred( 846 const ui::Accelerator& accelerator) const { 847 const ui::Accelerator remapped_accelerator = ime_control_delegate_.get() ? 848 ime_control_delegate_->RemapAccelerator(accelerator) : accelerator; 849 850 std::map<ui::Accelerator, int>::const_iterator iter = 851 accelerators_.find(remapped_accelerator); 852 if (iter == accelerators_.end()) 853 return false; // not an accelerator. 854 855 return preferred_actions_.find(iter->second) != preferred_actions_.end(); 856 } 857 858 bool AcceleratorController::IsReserved( 859 const ui::Accelerator& accelerator) const { 860 const ui::Accelerator remapped_accelerator = ime_control_delegate_.get() ? 861 ime_control_delegate_->RemapAccelerator(accelerator) : accelerator; 862 863 std::map<ui::Accelerator, int>::const_iterator iter = 864 accelerators_.find(remapped_accelerator); 865 if (iter == accelerators_.end()) 866 return false; // not an accelerator. 867 868 return reserved_actions_.find(iter->second) != reserved_actions_.end(); 869 } 870 871 bool AcceleratorController::PerformAction(int action, 872 const ui::Accelerator& accelerator) { 873 ash::Shell* shell = ash::Shell::GetInstance(); 874 AcceleratorProcessingRestriction restriction = 875 GetAcceleratorProcessingRestriction(action); 876 if (restriction != RESTRICTION_NONE) 877 return restriction == RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION; 878 879 const ui::KeyboardCode key_code = accelerator.key_code(); 880 // PerformAction() is performed from gesture controllers and passes 881 // empty Accelerator() instance as the second argument. Such events 882 // should never be suspended. 883 const bool gesture_event = key_code == ui::VKEY_UNKNOWN; 884 // Ignore accelerators invoked as repeated (while holding a key for a long 885 // time, if their handling is nonrepeatable. 886 if (nonrepeatable_actions_.find(action) != nonrepeatable_actions_.end() && 887 accelerator.IsRepeat() && !gesture_event) { 888 return true; 889 } 890 // Type of the previous accelerator. Used by NEXT_IME and DISABLE_CAPS_LOCK. 891 const ui::EventType previous_event_type = previous_accelerator_.type(); 892 const ui::KeyboardCode previous_key_code = previous_accelerator_.key_code(); 893 894 // You *MUST* return true when some action is performed. Otherwise, this 895 // function might be called *twice*, via BrowserView::PreHandleKeyboardEvent 896 // and BrowserView::HandleKeyboardEvent, for a single accelerator press. 897 // 898 // If your accelerator invokes more than one line of code, please either 899 // implement it in your module's controller code (like TOGGLE_MIRROR_MODE 900 // below) or pull it into a HandleFoo() function above. 901 switch (action) { 902 case ACCESSIBLE_FOCUS_NEXT: 903 return HandleAccessibleFocusCycle(false); 904 case ACCESSIBLE_FOCUS_PREVIOUS: 905 return HandleAccessibleFocusCycle(true); 906 case CYCLE_BACKWARD_MRU: 907 return HandleCycleBackwardMRU(accelerator); 908 case CYCLE_FORWARD_MRU: 909 return HandleCycleForwardMRU(accelerator); 910 case TOGGLE_OVERVIEW: 911 return ToggleOverview(accelerator); 912 #if defined(OS_CHROMEOS) 913 case ADD_REMOVE_DISPLAY: 914 return HandleAddRemoveDisplay(); 915 case TOGGLE_MIRROR_MODE: 916 return HandleToggleMirrorMode(); 917 case LOCK_SCREEN: 918 return HandleLock(key_code); 919 case OPEN_FILE_MANAGER: 920 return HandleFileManager(); 921 case OPEN_CROSH: 922 return HandleCrosh(); 923 case SILENCE_SPOKEN_FEEDBACK: 924 HandleSilenceSpokenFeedback(); 925 break; 926 case SWAP_PRIMARY_DISPLAY: 927 return HandleSwapPrimaryDisplay(); 928 case SWITCH_TO_NEXT_USER: 929 return HandleCycleUser(SessionStateDelegate::CYCLE_TO_NEXT_USER); 930 case SWITCH_TO_PREVIOUS_USER: 931 return HandleCycleUser(SessionStateDelegate::CYCLE_TO_PREVIOUS_USER); 932 case TOGGLE_SPOKEN_FEEDBACK: 933 return HandleToggleSpokenFeedback(); 934 case TOGGLE_TOUCH_VIEW_TESTING: 935 return HandleToggleTouchViewTesting(); 936 case TOGGLE_WIFI: 937 Shell::GetInstance()->system_tray_notifier()->NotifyRequestToggleWifi(); 938 return true; 939 case TOUCH_HUD_CLEAR: 940 return HandleTouchHudClear(); 941 case TOUCH_HUD_MODE_CHANGE: 942 return HandleTouchHudModeChange(); 943 case TOUCH_HUD_PROJECTION_TOGGLE: 944 return HandleTouchHudProjectToggle(); 945 case DISABLE_GPU_WATCHDOG: 946 Shell::GetInstance()->gpu_support()->DisableGpuWatchdog(); 947 return true; 948 case DISABLE_CAPS_LOCK: 949 return HandleDisableCapsLock( 950 key_code, previous_event_type, previous_key_code); 951 case TOGGLE_CAPS_LOCK: 952 return HandleToggleCapsLock( 953 key_code, previous_event_type, previous_key_code); 954 #endif // OS_CHROMEOS 955 case OPEN_FEEDBACK_PAGE: 956 return HandleOpenFeedbackPage(); 957 case EXIT: 958 // UMA metrics are recorded in the handler. 959 exit_warning_handler_.HandleAccelerator(); 960 return true; 961 case NEW_INCOGNITO_WINDOW: 962 return HandleNewIncognitoWindow(); 963 case NEW_TAB: 964 return HandleNewTab(key_code); 965 case NEW_WINDOW: 966 return HandleNewWindow(); 967 case RESTORE_TAB: 968 return HandleRestoreTab(); 969 case TAKE_SCREENSHOT: 970 return HandleTakeScreenshot(screenshot_delegate_.get()); 971 case TAKE_PARTIAL_SCREENSHOT: 972 return HandleTakePartialScreenshot(screenshot_delegate_.get()); 973 case TOGGLE_APP_LIST: 974 return HandleToggleAppList( 975 key_code, previous_event_type, previous_key_code, accelerator); 976 case BRIGHTNESS_DOWN: 977 if (brightness_control_delegate_) 978 return brightness_control_delegate_->HandleBrightnessDown(accelerator); 979 break; 980 case BRIGHTNESS_UP: 981 if (brightness_control_delegate_) 982 return brightness_control_delegate_->HandleBrightnessUp(accelerator); 983 break; 984 case KEYBOARD_BRIGHTNESS_DOWN: 985 if (keyboard_brightness_control_delegate_) 986 return keyboard_brightness_control_delegate_-> 987 HandleKeyboardBrightnessDown(accelerator); 988 break; 989 case KEYBOARD_BRIGHTNESS_UP: 990 if (keyboard_brightness_control_delegate_) 991 return keyboard_brightness_control_delegate_-> 992 HandleKeyboardBrightnessUp(accelerator); 993 break; 994 case VOLUME_MUTE: { 995 ash::VolumeControlDelegate* volume_delegate = 996 shell->system_tray_delegate()->GetVolumeControlDelegate(); 997 return volume_delegate && volume_delegate->HandleVolumeMute(accelerator); 998 } 999 case VOLUME_DOWN: { 1000 ash::VolumeControlDelegate* volume_delegate = 1001 shell->system_tray_delegate()->GetVolumeControlDelegate(); 1002 return volume_delegate && volume_delegate->HandleVolumeDown(accelerator); 1003 } 1004 case VOLUME_UP: { 1005 ash::VolumeControlDelegate* volume_delegate = 1006 shell->system_tray_delegate()->GetVolumeControlDelegate(); 1007 return volume_delegate && volume_delegate->HandleVolumeUp(accelerator); 1008 } 1009 case FOCUS_SHELF: 1010 return HandleFocusShelf(); 1011 case FOCUS_NEXT_PANE: 1012 return HandleRotatePaneFocus(Shell::FORWARD); 1013 case FOCUS_PREVIOUS_PANE: 1014 return HandleRotatePaneFocus(Shell::BACKWARD); 1015 case SHOW_KEYBOARD_OVERLAY: 1016 return HandleShowKeyboardOverlay(); 1017 case SHOW_SYSTEM_TRAY_BUBBLE: 1018 return HandleShowSystemTrayBubble(); 1019 case SHOW_MESSAGE_CENTER_BUBBLE: 1020 HandleShowMessageCenterBubble(); 1021 break; 1022 case SHOW_TASK_MANAGER: 1023 return HandleShowTaskManager(); 1024 case NEXT_IME: 1025 HandleNextIme( 1026 ime_control_delegate_.get(), previous_event_type, previous_key_code); 1027 // NEXT_IME is bound to Alt-Shift key up event. To be consistent with 1028 // Windows behavior, do not consume the key event here. 1029 return false; 1030 case PREVIOUS_IME: 1031 return HandlePreviousIme(ime_control_delegate_.get(), accelerator); 1032 case PRINT_UI_HIERARCHIES: 1033 return HandlePrintUIHierarchies(); 1034 case SWITCH_IME: 1035 return HandleSwitchIme(ime_control_delegate_.get(), accelerator); 1036 case LAUNCH_APP_0: 1037 return HandleLaunchAppN(0); 1038 case LAUNCH_APP_1: 1039 return HandleLaunchAppN(1); 1040 case LAUNCH_APP_2: 1041 return HandleLaunchAppN(2); 1042 case LAUNCH_APP_3: 1043 return HandleLaunchAppN(3); 1044 case LAUNCH_APP_4: 1045 return HandleLaunchAppN(4); 1046 case LAUNCH_APP_5: 1047 return HandleLaunchAppN(5); 1048 case LAUNCH_APP_6: 1049 return HandleLaunchAppN(6); 1050 case LAUNCH_APP_7: 1051 return HandleLaunchAppN(7); 1052 case LAUNCH_LAST_APP: 1053 return HandleLaunchLastApp(); 1054 case WINDOW_SNAP_LEFT: 1055 case WINDOW_SNAP_RIGHT: 1056 return HandleWindowSnap(action); 1057 case WINDOW_MINIMIZE: 1058 return HandleWindowMinimize(); 1059 case TOGGLE_FULLSCREEN: 1060 return HandleToggleFullscreen(key_code); 1061 case TOGGLE_MAXIMIZED: 1062 accelerators::ToggleMaximized(); 1063 return true; 1064 case WINDOW_POSITION_CENTER: 1065 return HandlePositionCenter(); 1066 case SCALE_UI_UP: 1067 return HandleScaleUI(true /* up */); 1068 case SCALE_UI_DOWN: 1069 return HandleScaleUI(false /* down */); 1070 case SCALE_UI_RESET: 1071 return HandleScaleReset(); 1072 case ROTATE_WINDOW: 1073 return HandleRotateActiveWindow(); 1074 case ROTATE_SCREEN: 1075 return HandleRotateScreen(); 1076 case TOGGLE_DESKTOP_BACKGROUND_MODE: 1077 return debug::CycleDesktopBackgroundMode(); 1078 case TOGGLE_ROOT_WINDOW_FULL_SCREEN: 1079 return HandleToggleRootWindowFullScreen(); 1080 case DEBUG_TOGGLE_DEVICE_SCALE_FACTOR: 1081 Shell::GetInstance()->display_manager()->ToggleDisplayScaleFactor(); 1082 return true; 1083 case DEBUG_TOGGLE_SHOW_DEBUG_BORDERS: 1084 ash::debug::ToggleShowDebugBorders(); 1085 return true; 1086 case DEBUG_TOGGLE_SHOW_FPS_COUNTER: 1087 ash::debug::ToggleShowFpsCounter(); 1088 return true; 1089 case DEBUG_TOGGLE_SHOW_PAINT_RECTS: 1090 ash::debug::ToggleShowPaintRects(); 1091 return true; 1092 case MAGNIFY_SCREEN_ZOOM_IN: 1093 return HandleMagnifyScreen(1); 1094 case MAGNIFY_SCREEN_ZOOM_OUT: 1095 return HandleMagnifyScreen(-1); 1096 case MEDIA_NEXT_TRACK: 1097 return HandleMediaNextTrack(); 1098 case MEDIA_PLAY_PAUSE: 1099 return HandleMediaPlayPause(); 1100 case MEDIA_PREV_TRACK: 1101 return HandleMediaPrevTrack(); 1102 case POWER_PRESSED: // fallthrough 1103 case POWER_RELEASED: 1104 #if defined(OS_CHROMEOS) 1105 if (!base::SysInfo::IsRunningOnChromeOS()) { 1106 // There is no powerd in linux desktop, so call the 1107 // PowerButtonController here. 1108 Shell::GetInstance()->power_button_controller()-> 1109 OnPowerButtonEvent(action == POWER_PRESSED, base::TimeTicks()); 1110 } 1111 #endif 1112 // We don't do anything with these at present on the device, 1113 // (power button events are reported to us from powerm via 1114 // D-BUS), but we consume them to prevent them from getting 1115 // passed to apps -- see http://crbug.com/146609. 1116 return true; 1117 case LOCK_PRESSED: 1118 case LOCK_RELEASED: 1119 Shell::GetInstance()->power_button_controller()-> 1120 OnLockButtonEvent(action == LOCK_PRESSED, base::TimeTicks()); 1121 return true; 1122 case PRINT_LAYER_HIERARCHY: 1123 return HandlePrintLayerHierarchy(); 1124 case PRINT_VIEW_HIERARCHY: 1125 return HandlePrintViewHierarchy(); 1126 case PRINT_WINDOW_HIERARCHY: 1127 return HandlePrintWindowHierarchy(); 1128 default: 1129 NOTREACHED() << "Unhandled action " << action; 1130 } 1131 return false; 1132 } 1133 1134 AcceleratorController::AcceleratorProcessingRestriction 1135 AcceleratorController::GetCurrentAcceleratorRestriction() { 1136 return GetAcceleratorProcessingRestriction(-1); 1137 } 1138 1139 AcceleratorController::AcceleratorProcessingRestriction 1140 AcceleratorController::GetAcceleratorProcessingRestriction(int action) { 1141 ash::Shell* shell = ash::Shell::GetInstance(); 1142 if (!shell->session_state_delegate()->IsActiveUserSessionStarted() && 1143 actions_allowed_at_login_screen_.find(action) == 1144 actions_allowed_at_login_screen_.end()) { 1145 return RESTRICTION_PREVENT_PROCESSING; 1146 } 1147 if (shell->session_state_delegate()->IsScreenLocked() && 1148 actions_allowed_at_lock_screen_.find(action) == 1149 actions_allowed_at_lock_screen_.end()) { 1150 return RESTRICTION_PREVENT_PROCESSING; 1151 } 1152 if (shell->IsSystemModalWindowOpen() && 1153 actions_allowed_at_modal_window_.find(action) == 1154 actions_allowed_at_modal_window_.end()) { 1155 // Note we prevent the shortcut from propagating so it will not 1156 // be passed to the modal window. This is important for things like 1157 // Alt+Tab that would cause an undesired effect in the modal window by 1158 // cycling through its window elements. 1159 return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION; 1160 } 1161 if (shell->delegate()->IsRunningInForcedAppMode() && 1162 actions_allowed_in_app_mode_.find(action) == 1163 actions_allowed_in_app_mode_.end()) { 1164 return RESTRICTION_PREVENT_PROCESSING; 1165 } 1166 if (MruWindowTracker::BuildWindowList(false).empty() && 1167 actions_needing_window_.find(action) != actions_needing_window_.end()) { 1168 Shell::GetInstance()->accessibility_delegate()->TriggerAccessibilityAlert( 1169 A11Y_ALERT_WINDOW_NEEDED); 1170 return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION; 1171 } 1172 return RESTRICTION_NONE; 1173 } 1174 1175 void AcceleratorController::SetBrightnessControlDelegate( 1176 scoped_ptr<BrightnessControlDelegate> brightness_control_delegate) { 1177 brightness_control_delegate_ = brightness_control_delegate.Pass(); 1178 } 1179 1180 void AcceleratorController::SetImeControlDelegate( 1181 scoped_ptr<ImeControlDelegate> ime_control_delegate) { 1182 ime_control_delegate_ = ime_control_delegate.Pass(); 1183 } 1184 1185 void AcceleratorController::SetScreenshotDelegate( 1186 scoped_ptr<ScreenshotDelegate> screenshot_delegate) { 1187 screenshot_delegate_ = screenshot_delegate.Pass(); 1188 } 1189 1190 //////////////////////////////////////////////////////////////////////////////// 1191 // AcceleratorController, ui::AcceleratorTarget implementation: 1192 1193 bool AcceleratorController::AcceleratorPressed( 1194 const ui::Accelerator& accelerator) { 1195 std::map<ui::Accelerator, int>::const_iterator it = 1196 accelerators_.find(accelerator); 1197 DCHECK(it != accelerators_.end()); 1198 return PerformAction(static_cast<AcceleratorAction>(it->second), accelerator); 1199 } 1200 1201 void AcceleratorController::RegisterAccelerators( 1202 const AcceleratorData accelerators[], 1203 size_t accelerators_length) { 1204 for (size_t i = 0; i < accelerators_length; ++i) { 1205 ui::Accelerator accelerator(accelerators[i].keycode, 1206 accelerators[i].modifiers); 1207 accelerator.set_type(accelerators[i].trigger_on_press ? 1208 ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED); 1209 Register(accelerator, this); 1210 accelerators_.insert( 1211 std::make_pair(accelerator, accelerators[i].action)); 1212 } 1213 } 1214 1215 void AcceleratorController::SetKeyboardBrightnessControlDelegate( 1216 scoped_ptr<KeyboardBrightnessControlDelegate> 1217 keyboard_brightness_control_delegate) { 1218 keyboard_brightness_control_delegate_ = 1219 keyboard_brightness_control_delegate.Pass(); 1220 } 1221 1222 bool AcceleratorController::CanHandleAccelerators() const { 1223 return true; 1224 } 1225 1226 } // namespace ash 1227