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