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