Home | History | Annotate | Download | only in accelerators
      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