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