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