accelerator_controller.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt// Use of this source code is governed by a BSD-style license that can be
3df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt// found in the LICENSE file.
4df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
5df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/accelerators/accelerator_controller.h"
6df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
7df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include <algorithm>
8df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include <cmath>
9df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include <iostream>
10df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include <string>
11df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
12df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/accelerators/accelerator_commands.h"
13df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/accelerators/accelerator_table.h"
14df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/accelerators/debug_commands.h"
15df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/ash_switches.h"
16df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/caps_lock_delegate.h"
17df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/debug.h"
18df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/display/display_controller.h"
19df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/display/display_manager.h"
20df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/focus_cycler.h"
21df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/gpu_support.h"
22df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/ime_control_delegate.h"
23df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/magnifier/magnification_controller.h"
24df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/magnifier/partial_magnification_controller.h"
25df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/media_delegate.h"
26df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/multi_profile_uma.h"
27df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/new_window_delegate.h"
28df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/root_window_controller.h"
29df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/rotator/screen_rotation.h"
30df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/screenshot_delegate.h"
31df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/session_state_delegate.h"
32df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/shelf/shelf.h"
33df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/shelf/shelf_delegate.h"
34df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/shelf/shelf_model.h"
35df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/shelf/shelf_widget.h"
36df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/shell.h"
37df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/shell_delegate.h"
38df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/shell_window_ids.h"
39df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include "ash/system/brightness_control_delegate.h"
40#include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h"
41#include "ash/system/status_area_widget.h"
42#include "ash/system/tray/system_tray.h"
43#include "ash/system/tray/system_tray_delegate.h"
44#include "ash/system/tray/system_tray_notifier.h"
45#include "ash/system/web_notification/web_notification_tray.h"
46#include "ash/touch/touch_hud_debug.h"
47#include "ash/volume_control_delegate.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/workspace/snap_sizer.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/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
81namespace ash {
82namespace {
83
84using base::UserMetricsAction;
85using internal::DisplayInfo;
86
87bool DebugShortcutsEnabled() {
88#if defined(NDEBUG)
89  return CommandLine::ForCurrentProcess()->HasSwitch(
90          switches::kAshDebugShortcuts);
91#else
92  return true;
93#endif
94}
95
96bool HandleAccessibleFocusCycle(bool reverse) {
97  if (reverse) {
98    base::RecordAction(UserMetricsAction("Accel_Accessible_Focus_Previous"));
99  } else {
100    base::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
127bool HandleCycleBackwardMRU(const ui::Accelerator& accelerator) {
128  Shell* shell = Shell::GetInstance();
129
130  if (accelerator.key_code() == ui::VKEY_TAB)
131    base::RecordAction(base::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
143bool HandleCycleForwardMRU(const ui::Accelerator& accelerator) {
144  Shell* shell = Shell::GetInstance();
145
146  if (accelerator.key_code() == ui::VKEY_TAB)
147    base::RecordAction(base::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
159bool 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    base::RecordAction(base::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    base::RecordAction(base::UserMetricsAction("Accel_NextWindow_F5"));
171  shell->window_cycle_controller()->HandleLinearCycleWindow();
172  return true;
173}
174
175bool 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  base::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
196bool HandleFocusLauncher() {
197  Shell* shell = Shell::GetInstance();
198  base::RecordAction(base::UserMetricsAction("Accel_Focus_Launcher"));
199  return shell->focus_cycler()->FocusWidget(
200      Shelf::ForPrimaryDisplay()->shelf_widget());
201}
202
203bool HandleLaunchAppN(int n) {
204  base::RecordAction(UserMetricsAction("Accel_Launch_App"));
205  Shelf::ForPrimaryDisplay()->LaunchAppIndexAt(n);
206  return true;
207}
208
209bool HandleLaunchLastApp() {
210  base::RecordAction(UserMetricsAction("Accel_Launch_Last_App"));
211  Shelf::ForPrimaryDisplay()->LaunchAppIndexAt(-1);
212  return true;
213}
214
215// Magnify the screen
216bool 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
239bool HandleMediaNextTrack() {
240  Shell::GetInstance()->media_delegate()->HandleMediaNextTrack();
241  return true;
242}
243
244bool HandleMediaPlayPause() {
245  Shell::GetInstance()->media_delegate()->HandleMediaPlayPause();
246  return true;
247}
248
249bool HandleMediaPrevTrack() {
250  Shell::GetInstance()->media_delegate()->HandleMediaPrevTrack();
251  return true;
252}
253
254bool HandleNewIncognitoWindow() {
255  base::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
264bool HandleNewTab(ui::KeyboardCode key_code) {
265  if (key_code == ui::VKEY_T)
266    base::RecordAction(base::UserMetricsAction("Accel_NewTab_T"));
267  Shell::GetInstance()->new_window_delegate()->NewTab();
268  return true;
269}
270
271bool HandleNewWindow() {
272  base::RecordAction(base::UserMetricsAction("Accel_New_Window"));
273  Shell::GetInstance()->new_window_delegate()->NewWindow(
274      false /* is_incognito */);
275  return true;
276}
277
278bool 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  base::RecordAction(UserMetricsAction("Accel_Next_Ime"));
299  if (ime_control_delegate)
300    return ime_control_delegate->HandleNextIme();
301  return false;
302}
303
304bool HandleOpenFeedbackPage() {
305  base::RecordAction(UserMetricsAction("Accel_Open_Feedback_Page"));
306  ash::Shell::GetInstance()->new_window_delegate()->OpenFeedbackPage();
307  return true;
308}
309
310bool HandlePositionCenter() {
311  base::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
321bool HandlePreviousIme(ImeControlDelegate* ime_control_delegate,
322                       const ui::Accelerator& accelerator) {
323  base::RecordAction(UserMetricsAction("Accel_Previous_Ime"));
324  if (ime_control_delegate)
325    return ime_control_delegate->HandlePreviousIme(accelerator);
326  return false;
327}
328
329bool HandleRestoreTab() {
330  base::RecordAction(base::UserMetricsAction("Accel_Restore_Tab"));
331  Shell::GetInstance()->new_window_delegate()->RestoreTab();
332  return true;
333}
334
335bool 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      base::RecordAction(UserMetricsAction("Accel_Focus_Next_Pane"));
341      shell->focus_cycler()->RotateFocus(internal::FocusCycler::FORWARD);
342      break;
343    }
344    case Shell::BACKWARD: {
345      base::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.
354bool HandleRotateActiveWindow() {
355  base::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
371gfx::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.
387bool HandleRotateScreen() {
388  base::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
398bool 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  base::RecordAction(UserMetricsAction("Accel_Scale_Ui_Reset"));
406
407  display_manager->SetDisplayUIScale(display_id, 1.0f);
408  return true;
409}
410
411bool 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    base::RecordAction(UserMetricsAction("Accel_Scale_Ui_Up"));
420  } else {
421    base::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
431bool HandleSwapPrimaryDisplay() {
432  base::RecordAction(UserMetricsAction("Accel_Swap_Primary_Display"));
433  Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
434  return true;
435}
436
437bool HandleShowKeyboardOverlay() {
438  base::RecordAction(UserMetricsAction("Accel_Show_Keyboard_Overlay"));
439  ash::Shell::GetInstance()->new_window_delegate()->ShowKeyboardOverlay();
440
441  return true;
442}
443
444void HandleShowMessageCenterBubble() {
445  base::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
458bool HandleShowOak() {
459  if (CommandLine::ForCurrentProcess()->HasSwitch(
460        switches::kAshEnableOak)) {
461    oak::ShowOakWindowWithContext(Shell::GetPrimaryRootWindow());
462    return true;
463  }
464  return false;
465}
466
467bool HandleShowSystemTrayBubble() {
468  base::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
478bool HandleShowTaskManager() {
479  base::RecordAction(UserMetricsAction("Accel_Show_Task_Manager"));
480  Shell::GetInstance()->new_window_delegate()->ShowTaskManager();
481  return true;
482}
483
484void HandleSilenceSpokenFeedback() {
485  base::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
494bool HandleSwitchIme(ImeControlDelegate* ime_control_delegate,
495                     const ui::Accelerator& accelerator) {
496  base::RecordAction(UserMetricsAction("Accel_Switch_Ime"));
497  if (ime_control_delegate)
498    return ime_control_delegate->HandleSwitchIme(accelerator);
499  return false;
500}
501
502bool HandleTakePartialScreenshot(ScreenshotDelegate* screenshot_delegate) {
503  base::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
513bool HandleTakeScreenshot(ScreenshotDelegate* screenshot_delegate) {
514  base::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
523bool 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    base::RecordAction(base::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
547bool 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  base::RecordAction(UserMetricsAction("Accel_Toggle_Caps_Lock"));
561  shell->caps_lock_delegate()->ToggleCapsLock();
562  return true;
563}
564
565bool HandleToggleFullscreen(ui::KeyboardCode key_code) {
566  if (key_code == ui::VKEY_MEDIA_LAUNCH_APP2) {
567    base::RecordAction(UserMetricsAction("Accel_Fullscreen_F4"));
568  }
569  accelerators::ToggleFullscreen();
570  return true;
571}
572
573bool HandleToggleRootWindowFullScreen() {
574  Shell::GetPrimaryRootWindow()->GetDispatcher()->host()->ToggleFullScreen();
575  return true;
576}
577
578bool 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() != ui::wm::WINDOW_TYPE_NORMAL ||
584      window_state->IsFullscreen()) {
585    return false;
586  }
587
588  if (action == WINDOW_SNAP_LEFT) {
589    base::RecordAction(UserMetricsAction("Accel_Window_Snap_Left"));
590  } else {
591    base::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
600bool HandleWindowMinimize() {
601  base::RecordAction(
602      base::UserMetricsAction("Accel_Toggle_Minimized_Minus"));
603  return accelerators::ToggleMinimized();
604}
605
606#if defined(OS_CHROMEOS)
607bool HandleAddRemoveDisplay() {
608  base::RecordAction(UserMetricsAction("Accel_Add_Remove_Display"));
609  Shell::GetInstance()->display_manager()->AddRemoveDisplay();
610  return true;
611}
612
613bool HandleCrosh() {
614  base::RecordAction(UserMetricsAction("Accel_Open_Crosh"));
615
616  Shell::GetInstance()->new_window_delegate()->OpenCrosh();
617  return true;
618}
619
620bool HandleFileManager() {
621  base::RecordAction(UserMetricsAction("Accel_Open_File_Manager"));
622
623  Shell::GetInstance()->new_window_delegate()->OpenFileManager();
624  return true;
625}
626
627bool HandleLock(ui::KeyboardCode key_code) {
628  base::RecordAction(UserMetricsAction("Accel_LockScreen_L"));
629  Shell::GetInstance()->session_state_delegate()->LockScreen();
630  return true;
631}
632
633bool 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      base::RecordAction(UserMetricsAction("Accel_Switch_To_Next_User"));
645      break;
646    case SessionStateDelegate::CYCLE_TO_PREVIOUS_USER:
647      base::RecordAction(UserMetricsAction("Accel_Switch_To_Previous_User"));
648      break;
649  }
650  delegate->CycleActiveUser(cycle_user);
651  return true;
652}
653
654bool HandleToggleMirrorMode() {
655  base::RecordAction(UserMetricsAction("Accel_Toggle_Mirror_Mode"));
656  Shell::GetInstance()->display_controller()->ToggleMirrorMode();
657  return true;
658}
659
660bool HandleToggleSpokenFeedback() {
661  base::RecordAction(UserMetricsAction("Accel_Toggle_Spoken_Feedback"));
662
663  Shell::GetInstance()->accessibility_delegate()->
664      ToggleSpokenFeedback(A11Y_NOTIFICATION_SHOW);
665  return true;
666}
667
668bool 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
678bool 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
688bool HandleTouchHudProjectToggle() {
689  base::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
699bool 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
709bool 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
721void 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
739bool 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
752bool 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
767AcceleratorControllerContext::AcceleratorControllerContext() {
768  current_accelerator_.set_type(ui::ET_UNKNOWN);
769  previous_accelerator_.set_type(ui::ET_UNKNOWN);
770}
771
772void AcceleratorControllerContext::UpdateContext(
773    const ui::Accelerator& accelerator) {
774  previous_accelerator_ = current_accelerator_;
775  current_accelerator_ = accelerator;
776}
777
778////////////////////////////////////////////////////////////////////////////////
779// AcceleratorController, public:
780
781AcceleratorController::AcceleratorController()
782    : accelerator_manager_(new ui::AcceleratorManager) {
783  Init();
784}
785
786AcceleratorController::~AcceleratorController() {
787}
788
789void 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
827void AcceleratorController::Register(const ui::Accelerator& accelerator,
828                                     ui::AcceleratorTarget* target) {
829  accelerator_manager_->Register(accelerator,
830                                 ui::AcceleratorManager::kNormalPriority,
831                                 target);
832}
833
834void AcceleratorController::Unregister(const ui::Accelerator& accelerator,
835                                       ui::AcceleratorTarget* target) {
836  accelerator_manager_->Unregister(accelerator, target);
837}
838
839void AcceleratorController::UnregisterAll(ui::AcceleratorTarget* target) {
840  accelerator_manager_->UnregisterAll(target);
841}
842
843bool 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
851bool AcceleratorController::IsRegistered(
852    const ui::Accelerator& accelerator) const {
853  return accelerator_manager_->GetCurrentTarget(accelerator) != NULL;
854}
855
856bool 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
869bool 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      Shell::GetInstance()->gpu_support()->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
1158void 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
1169void AcceleratorController::SetImeControlDelegate(
1170    scoped_ptr<ImeControlDelegate> ime_control_delegate) {
1171  ime_control_delegate_ = ime_control_delegate.Pass();
1172}
1173
1174void AcceleratorController::SetScreenshotDelegate(
1175    scoped_ptr<ScreenshotDelegate> screenshot_delegate) {
1176  screenshot_delegate_ = screenshot_delegate.Pass();
1177}
1178
1179////////////////////////////////////////////////////////////////////////////////
1180// AcceleratorController, ui::AcceleratorTarget implementation:
1181
1182bool 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
1190void 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
1204void AcceleratorController::SetKeyboardBrightnessControlDelegate(
1205    scoped_ptr<KeyboardBrightnessControlDelegate>
1206    keyboard_brightness_control_delegate) {
1207  keyboard_brightness_control_delegate_ =
1208      keyboard_brightness_control_delegate.Pass();
1209}
1210
1211bool AcceleratorController::CanHandleAccelerators() const {
1212  return true;
1213}
1214
1215}  // namespace ash
1216