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