By moving the call to Load() up in SearchProvider::Start(), we are giving a chance...
[chromium-blink-merge.git] / ash / accelerators / accelerator_controller.cc
blob0d2d0a4049e6e76257e4d29548d8225cd9fb81b7
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.
5 #include "ash/accelerators/accelerator_controller.h"
7 #include <algorithm>
8 #include <cmath>
9 #include <string>
11 #include "ash/accelerators/accelerator_table.h"
12 #include "ash/ash_switches.h"
13 #include "ash/caps_lock_delegate.h"
14 #include "ash/desktop_background/desktop_background_controller.h"
15 #include "ash/desktop_background/user_wallpaper_delegate.h"
16 #include "ash/display/display_controller.h"
17 #include "ash/display/display_manager.h"
18 #include "ash/focus_cycler.h"
19 #include "ash/ime_control_delegate.h"
20 #include "ash/launcher/launcher.h"
21 #include "ash/launcher/launcher_delegate.h"
22 #include "ash/launcher/launcher_model.h"
23 #include "ash/magnifier/magnification_controller.h"
24 #include "ash/magnifier/partial_magnification_controller.h"
25 #include "ash/root_window_controller.h"
26 #include "ash/rotator/screen_rotation.h"
27 #include "ash/screenshot_delegate.h"
28 #include "ash/shell.h"
29 #include "ash/shell_delegate.h"
30 #include "ash/shell_window_ids.h"
31 #include "ash/system/brightness/brightness_control_delegate.h"
32 #include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h"
33 #include "ash/system/status_area_widget.h"
34 #include "ash/system/tray/system_tray.h"
35 #include "ash/system/tray/system_tray_delegate.h"
36 #include "ash/touch/touch_observer_hud.h"
37 #include "ash/volume_control_delegate.h"
38 #include "ash/wm/partial_screenshot_view.h"
39 #include "ash/wm/power_button_controller.h"
40 #include "ash/wm/property_util.h"
41 #include "ash/wm/window_cycle_controller.h"
42 #include "ash/wm/window_util.h"
43 #include "ash/wm/workspace/snap_sizer.h"
44 #include "base/bind.h"
45 #include "base/command_line.h"
46 #include "content/public/browser/gpu_data_manager.h"
47 #include "ui/aura/env.h"
48 #include "ui/aura/root_window.h"
49 #include "ui/base/accelerators/accelerator.h"
50 #include "ui/base/accelerators/accelerator_manager.h"
51 #include "ui/base/events/event.h"
52 #include "ui/base/keycodes/keyboard_codes.h"
53 #include "ui/compositor/debug_utils.h"
54 #include "ui/compositor/layer.h"
55 #include "ui/compositor/layer_animation_sequence.h"
56 #include "ui/compositor/layer_animator.h"
57 #include "ui/gfx/screen.h"
58 #include "ui/oak/oak.h"
59 #include "ui/views/debug_utils.h"
60 #include "ui/views/widget/widget.h"
62 #if defined(OS_CHROMEOS)
63 #include "ash/system/chromeos/keyboard_brightness_controller.h"
64 #include "base/chromeos/chromeos_version.h"
65 #endif // defined(OS_CHROMEOS)
67 namespace ash {
68 namespace {
70 // Factor of magnification scale. For example, when this value is 1.189, scale
71 // value will be changed x1.000, x1.189, x1.414, x1.681, x2.000, ...
72 // Note: this value is 2.0 ^ (1 / 4).
73 const float kMagnificationFactor = 1.18920712f;
75 bool DebugShortcutsEnabled() {
76 #if defined(NDEBUG)
77 return CommandLine::ForCurrentProcess()->HasSwitch(
78 switches::kAshDebugShortcuts);
79 #else
80 return true;
81 #endif
84 bool HandleCycleWindowMRU(WindowCycleController::Direction direction,
85 bool is_alt_down) {
86 Shell::GetInstance()->
87 window_cycle_controller()->HandleCycleWindow(direction, is_alt_down);
88 // Always report we handled the key, even if the window didn't change.
89 return true;
92 void HandleCycleWindowLinear(CycleDirection direction) {
93 Launcher::ForPrimaryDisplay()->CycleWindowLinear(direction);
96 #if defined(OS_CHROMEOS)
97 bool HandleLock() {
98 Shell::GetInstance()->delegate()->LockScreen();
99 return true;
102 bool HandleFileManager() {
103 Shell::GetInstance()->delegate()->OpenFileManager();
104 return true;
107 bool HandleCrosh() {
108 Shell::GetInstance()->delegate()->OpenCrosh();
109 return true;
112 bool HandleToggleSpokenFeedback() {
113 Shell::GetInstance()->delegate()->
114 ToggleSpokenFeedback(A11Y_NOTIFICATION_SHOW);
115 return true;
118 #endif // defined(OS_CHROMEOS)
120 bool HandleRotatePaneFocus(Shell::Direction direction) {
121 if (!Shell::GetInstance()->delegate()->RotatePaneFocus(direction)) {
122 // No browser window is available. Focus the launcher.
123 Shell* shell = Shell::GetInstance();
124 switch (direction) {
125 case Shell::FORWARD:
126 shell->focus_cycler()->RotateFocus(internal::FocusCycler::FORWARD);
127 break;
128 case Shell::BACKWARD:
129 shell->focus_cycler()->RotateFocus(internal::FocusCycler::BACKWARD);
130 break;
133 return true;
136 // Rotates the default window container.
137 bool HandleRotateWindows() {
138 Shell::RootWindowControllerList controllers =
139 Shell::GetAllRootWindowControllers();
140 for (size_t i = 0; i < controllers.size(); ++i) {
141 aura::Window* target = controllers[i]->GetContainer(
142 internal::kShellWindowId_DefaultContainer);
143 // The rotation animation bases its target transform on the current
144 // rotation and position. Since there could be an animation in progress
145 // right now, queue this animation so when it starts it picks up a neutral
146 // rotation and position. Use replace so we only enqueue one at a time.
147 target->layer()->GetAnimator()->
148 set_preemption_strategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
149 scoped_ptr<ui::LayerAnimationSequence> screen_rotation(
150 new ui::LayerAnimationSequence(new ash::ScreenRotation(360)));
151 target->layer()->GetAnimator()->StartAnimation(
152 screen_rotation.release());
154 return true;
157 // Rotates the screen.
158 bool HandleRotateScreen() {
159 static int i = 0;
160 int delta = 0;
161 switch (i) {
162 case 0: delta = 90; break;
163 case 1: delta = 90; break;
164 case 2: delta = 90; break;
165 case 3: delta = 90; break;
166 case 4: delta = -90; break;
167 case 5: delta = -90; break;
168 case 6: delta = -90; break;
169 case 7: delta = -90; break;
170 case 8: delta = -90; break;
171 case 9: delta = 180; break;
172 case 10: delta = 180; break;
173 case 11: delta = 90; break;
174 case 12: delta = 180; break;
175 case 13: delta = 180; break;
177 i = (i + 1) % 14;
178 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
179 for (size_t i = 0; i < root_windows.size(); ++i) {
180 aura::RootWindow* root_window = root_windows[i];
181 root_window->layer()->GetAnimator()->
182 set_preemption_strategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
183 scoped_ptr<ui::LayerAnimationSequence> screen_rotation(
184 new ui::LayerAnimationSequence(new ash::ScreenRotation(delta)));
185 screen_rotation->AddObserver(root_window);
186 root_window->layer()->GetAnimator()->
187 StartAnimation(screen_rotation.release());
189 return true;
192 bool HandleToggleDesktopBackgroundMode() {
193 DesktopBackgroundController* desktop_background_controller =
194 Shell::GetInstance()->desktop_background_controller();
195 if (desktop_background_controller->desktop_background_mode() ==
196 DesktopBackgroundController::BACKGROUND_IMAGE) {
197 desktop_background_controller->SetDesktopBackgroundSolidColorMode(
198 SK_ColorBLACK);
199 } else {
200 ash::Shell::GetInstance()->user_wallpaper_delegate()->
201 InitializeWallpaper();
203 return true;
206 bool HandleToggleRootWindowFullScreen() {
207 Shell::GetPrimaryRootWindow()->ToggleFullScreen();
208 return true;
211 // Magnify the screen
212 bool HandleMagnifyScreen(int delta_index) {
213 if (ash::Shell::GetInstance()->magnification_controller()->IsEnabled()) {
214 // TODO(yoshiki): Create the class like MagnifierStepScaleController, and
215 // move the following scale control to it.
216 float scale =
217 ash::Shell::GetInstance()->magnification_controller()->GetScale();
218 // Calculate rounded logarithm (base kMagnificationFactor) of scale.
219 int scale_index =
220 std::floor(std::log(scale) / std::log(kMagnificationFactor) + 0.5);
222 int new_scale_index = std::max(0, std::min(8, scale_index + delta_index));
224 ash::Shell::GetInstance()->magnification_controller()->
225 SetScale(std::pow(kMagnificationFactor, new_scale_index), true);
226 } else if (ash::Shell::GetInstance()->
227 partial_magnification_controller()->is_enabled()) {
228 float scale = delta_index > 0 ? kDefaultPartialMagnifiedScale : 1;
229 ash::Shell::GetInstance()->partial_magnification_controller()->
230 SetScale(scale);
233 return true;
236 bool HandleMediaNextTrack() {
237 Shell::GetInstance()->delegate()->HandleMediaNextTrack();
238 return true;
241 bool HandleMediaPlayPause() {
242 Shell::GetInstance()->delegate()->HandleMediaPlayPause();
243 return true;
246 bool HandleMediaPrevTrack() {
247 Shell::GetInstance()->delegate()->HandleMediaPrevTrack();
248 return true;
251 #if !defined(NDEBUG)
252 bool HandlePrintLayerHierarchy() {
253 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
254 for (size_t i = 0; i < root_windows.size(); ++i) {
255 ui::PrintLayerHierarchy(root_windows[i]->layer(),
256 root_windows[i]->GetLastMouseLocationInRoot());
258 return true;
261 bool HandlePrintViewHierarchy() {
262 aura::Window* active_window = ash::wm::GetActiveWindow();
263 if (!active_window)
264 return true;
265 views::Widget* browser_widget =
266 views::Widget::GetWidgetForNativeWindow(active_window);
267 if (browser_widget)
268 views::PrintViewHierarchy(browser_widget->GetRootView());
269 return true;
272 void PrintWindowHierarchy(aura::Window* window, int indent) {
273 std::string indent_str(indent, ' ');
274 std::string name(window->name());
275 if (name.empty())
276 name = "\"\"";
277 DLOG(INFO) << indent_str << name << " (" << window << ")"
278 << " type=" << window->type()
279 << (wm::IsActiveWindow(window) ? " [active] " : " ")
280 << (window->IsVisible() ? " visible " : " ")
281 << window->bounds().ToString();
283 for (size_t i = 0; i < window->children().size(); ++i)
284 PrintWindowHierarchy(window->children()[i], indent + 3);
287 bool HandlePrintWindowHierarchy() {
288 DLOG(INFO) << "Window hierarchy:";
289 Shell::RootWindowControllerList controllers =
290 Shell::GetAllRootWindowControllers();
291 for (size_t i = 0; i < controllers.size(); ++i) {
292 DLOG(INFO) << "RootWindow " << i << ":";
293 PrintWindowHierarchy(controllers[i]->root_window(), 0);
295 return true;
298 #endif // !defined(NDEBUG)
300 } // namespace
302 ////////////////////////////////////////////////////////////////////////////////
303 // AcceleratorControllerContext, public:
305 AcceleratorControllerContext::AcceleratorControllerContext() {
306 current_accelerator_.set_type(ui::ET_UNKNOWN);
307 previous_accelerator_.set_type(ui::ET_UNKNOWN);
310 void AcceleratorControllerContext::UpdateContext(
311 const ui::Accelerator& accelerator) {
312 previous_accelerator_ = current_accelerator_;
313 current_accelerator_ = accelerator;
316 ////////////////////////////////////////////////////////////////////////////////
317 // AcceleratorController, public:
319 AcceleratorController::AcceleratorController()
320 : accelerator_manager_(new ui::AcceleratorManager) {
321 Init();
324 AcceleratorController::~AcceleratorController() {
327 void AcceleratorController::Init() {
328 for (size_t i = 0; i < kActionsAllowedAtLoginOrLockScreenLength; ++i) {
329 actions_allowed_at_login_screen_.insert(
330 kActionsAllowedAtLoginOrLockScreen[i]);
331 actions_allowed_at_lock_screen_.insert(
332 kActionsAllowedAtLoginOrLockScreen[i]);
334 for (size_t i = 0; i < kActionsAllowedAtLockScreenLength; ++i)
335 actions_allowed_at_lock_screen_.insert(kActionsAllowedAtLockScreen[i]);
336 for (size_t i = 0; i < kActionsAllowedAtModalWindowLength; ++i)
337 actions_allowed_at_modal_window_.insert(kActionsAllowedAtModalWindow[i]);
338 for (size_t i = 0; i < kReservedActionsLength; ++i)
339 reserved_actions_.insert(kReservedActions[i]);
340 for (size_t i = 0; i < kNonrepeatableActionsLength; ++i)
341 nonrepeatable_actions_.insert(kNonrepeatableActions[i]);
343 RegisterAccelerators(kAcceleratorData, kAcceleratorDataLength);
345 if (DebugShortcutsEnabled())
346 RegisterAccelerators(kDebugAcceleratorData, kDebugAcceleratorDataLength);
348 #if defined(OS_CHROMEOS)
349 keyboard_brightness_control_delegate_.reset(
350 new KeyboardBrightnessController());
351 #endif
354 void AcceleratorController::Register(const ui::Accelerator& accelerator,
355 ui::AcceleratorTarget* target) {
356 accelerator_manager_->Register(accelerator,
357 ui::AcceleratorManager::kNormalPriority,
358 target);
361 void AcceleratorController::Unregister(const ui::Accelerator& accelerator,
362 ui::AcceleratorTarget* target) {
363 accelerator_manager_->Unregister(accelerator, target);
366 void AcceleratorController::UnregisterAll(ui::AcceleratorTarget* target) {
367 accelerator_manager_->UnregisterAll(target);
370 bool AcceleratorController::Process(const ui::Accelerator& accelerator) {
371 if (ime_control_delegate_.get()) {
372 return accelerator_manager_->Process(
373 ime_control_delegate_->RemapAccelerator(accelerator));
375 return accelerator_manager_->Process(accelerator);
378 bool AcceleratorController::IsRegistered(
379 const ui::Accelerator& accelerator) const {
380 return accelerator_manager_->GetCurrentTarget(accelerator) != NULL;
383 bool AcceleratorController::IsReservedAccelerator(
384 const ui::Accelerator& accelerator) const {
385 const ui::Accelerator remapped_accelerator = ime_control_delegate_.get() ?
386 ime_control_delegate_->RemapAccelerator(accelerator) : accelerator;
388 std::map<ui::Accelerator, int>::const_iterator iter =
389 accelerators_.find(remapped_accelerator);
390 if (iter == accelerators_.end())
391 return false; // not an accelerator.
393 return reserved_actions_.find(iter->second) != reserved_actions_.end();
396 bool AcceleratorController::PerformAction(int action,
397 const ui::Accelerator& accelerator) {
398 ash::Shell* shell = ash::Shell::GetInstance();
399 bool at_login_screen = false;
400 #if defined(OS_CHROMEOS)
401 at_login_screen = !shell->delegate()->IsSessionStarted();
402 #endif
403 if (at_login_screen &&
404 actions_allowed_at_login_screen_.find(action) ==
405 actions_allowed_at_login_screen_.end()) {
406 return false;
408 if (shell->IsScreenLocked() &&
409 actions_allowed_at_lock_screen_.find(action) ==
410 actions_allowed_at_lock_screen_.end()) {
411 return false;
413 if (shell->IsSystemModalWindowOpen() &&
414 actions_allowed_at_modal_window_.find(action) ==
415 actions_allowed_at_modal_window_.end()) {
416 // Note: we return true. This indicates the shortcut is handled
417 // and will not be passed to the modal window. This is important
418 // for things like Alt+Tab that would cause an undesired effect
419 // in the modal window by cycling through its window elements.
420 return true;
422 const ui::KeyboardCode key_code = accelerator.key_code();
423 // PerformAction() is performed from gesture controllers and passes
424 // empty Accelerator() instance as the second argument. Such events
425 // should never be suspended.
426 const bool gesture_event = key_code == ui::VKEY_UNKNOWN;
428 // Ignore accelerators invoked as repeated (while holding a key for a long
429 // time, if their handling is nonrepeatable.
430 if (nonrepeatable_actions_.find(action) != nonrepeatable_actions_.end() &&
431 context_.repeated() && !gesture_event) {
432 return true;
434 // Type of the previous accelerator. Used by NEXT_IME and DISABLE_CAPS_LOCK.
435 const ui::EventType previous_event_type =
436 context_.previous_accelerator().type();
437 const ui::KeyboardCode previous_key_code =
438 context_.previous_accelerator().key_code();
440 // You *MUST* return true when some action is performed. Otherwise, this
441 // function might be called *twice*, via BrowserView::PreHandleKeyboardEvent
442 // and BrowserView::HandleKeyboardEvent, for a single accelerator press.
443 switch (action) {
444 case CYCLE_BACKWARD_MRU:
445 if (key_code == ui::VKEY_TAB)
446 shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_PREVWINDOW_TAB);
447 return HandleCycleWindowMRU(WindowCycleController::BACKWARD,
448 accelerator.IsAltDown());
449 case CYCLE_FORWARD_MRU:
450 if (key_code == ui::VKEY_TAB)
451 shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_NEXTWINDOW_TAB);
452 return HandleCycleWindowMRU(WindowCycleController::FORWARD,
453 accelerator.IsAltDown());
454 case CYCLE_BACKWARD_LINEAR:
455 if (key_code == ui::VKEY_MEDIA_LAUNCH_APP1)
456 shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_PREVWINDOW_F5);
457 HandleCycleWindowLinear(CYCLE_BACKWARD);
458 return true;
459 case CYCLE_FORWARD_LINEAR:
460 if (key_code == ui::VKEY_MEDIA_LAUNCH_APP1)
461 shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_NEXTWINDOW_F5);
462 HandleCycleWindowLinear(CYCLE_FORWARD);
463 return true;
464 #if defined(OS_CHROMEOS)
465 case CYCLE_DISPLAY_MODE:
466 Shell::GetInstance()->display_controller()->CycleDisplayMode();
467 return true;
468 case LOCK_SCREEN:
469 return HandleLock();
470 case OPEN_FILE_MANAGER_DIALOG:
471 return HandleFileManager();
472 case OPEN_CROSH:
473 return HandleCrosh();
474 case SWAP_PRIMARY_DISPLAY:
475 Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
476 return true;
477 case TOGGLE_SPOKEN_FEEDBACK:
478 return HandleToggleSpokenFeedback();
479 case TOGGLE_WIFI:
480 Shell::GetInstance()->system_tray_delegate()->ToggleWifi();
481 return true;
482 case TOUCH_HUD_MODE_CHANGE:
483 if (Shell::GetInstance()->touch_observer_hud()) {
484 Shell::GetInstance()->touch_observer_hud()->ChangeToNextMode();
485 return true;
487 return false;
488 case DISABLE_GPU_WATCHDOG:
489 content::GpuDataManager::GetInstance()->DisableGpuWatchdog();
490 return true;
491 #endif
492 case OPEN_FEEDBACK_PAGE:
493 ash::Shell::GetInstance()->delegate()->OpenFeedbackPage();
494 return true;
495 case EXIT:
496 Shell::GetInstance()->delegate()->Exit();
497 return true;
498 case NEW_INCOGNITO_WINDOW:
499 Shell::GetInstance()->delegate()->NewWindow(true /* is_incognito */);
500 return true;
501 case NEW_TAB:
502 if (key_code == ui::VKEY_T)
503 shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_NEWTAB_T);
504 Shell::GetInstance()->delegate()->NewTab();
505 return true;
506 case NEW_WINDOW:
507 Shell::GetInstance()->delegate()->NewWindow(false /* is_incognito */);
508 return true;
509 case RESTORE_TAB:
510 Shell::GetInstance()->delegate()->RestoreTab();
511 return true;
512 case TAKE_SCREENSHOT:
513 if (screenshot_delegate_.get() &&
514 screenshot_delegate_->CanTakeScreenshot()) {
515 screenshot_delegate_->HandleTakeScreenshotForAllRootWindows();
517 // Return true to prevent propagation of the key event.
518 return true;
519 case TAKE_PARTIAL_SCREENSHOT:
520 if (screenshot_delegate_.get()) {
521 ash::PartialScreenshotView::StartPartialScreenshot(
522 screenshot_delegate_.get());
524 // Return true to prevent propagation of the key event because
525 // this key combination is reserved for partial screenshot.
526 return true;
527 case TOGGLE_APP_LIST:
528 // If something else was pressed between the Search key (LWIN)
529 // being pressed and released, then ignore the release of the
530 // Search key.
531 if (key_code == ui::VKEY_LWIN &&
532 (previous_event_type == ui::ET_KEY_RELEASED ||
533 previous_key_code != ui::VKEY_LWIN))
534 return false;
535 if (key_code == ui::VKEY_LWIN)
536 shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_SEARCH_LWIN);
537 // When spoken feedback is enabled, we should neither toggle the list nor
538 // consume the key since Search+Shift is one of the shortcuts the a11y
539 // feature uses. crbug.com/132296
540 DCHECK_EQ(ui::VKEY_LWIN, accelerator.key_code());
541 if (Shell::GetInstance()->delegate()->IsSpokenFeedbackEnabled())
542 return false;
543 ash::Shell::GetInstance()->ToggleAppList(NULL);
544 return true;
545 case DISABLE_CAPS_LOCK:
546 if (previous_event_type == ui::ET_KEY_RELEASED ||
547 (previous_key_code != ui::VKEY_LSHIFT &&
548 previous_key_code != ui::VKEY_SHIFT &&
549 previous_key_code != ui::VKEY_RSHIFT)) {
550 // If something else was pressed between the Shift key being pressed
551 // and released, then ignore the release of the Shift key.
552 return false;
554 if (shell->caps_lock_delegate()->IsCapsLockEnabled()) {
555 shell->caps_lock_delegate()->SetCapsLockEnabled(false);
556 return true;
558 return false;
559 case TOGGLE_CAPS_LOCK:
560 if (key_code == ui::VKEY_LWIN) {
561 // If something else was pressed between the Search key (LWIN)
562 // being pressed and released, then ignore the release of the
563 // Search key.
564 // TODO(danakj): Releasing Alt first breaks this: crbug.com/166495
565 if (previous_event_type == ui::ET_KEY_RELEASED ||
566 previous_key_code != ui::VKEY_LWIN)
567 return false;
569 shell->caps_lock_delegate()->ToggleCapsLock();
570 return true;
571 case BRIGHTNESS_DOWN:
572 if (brightness_control_delegate_.get())
573 return brightness_control_delegate_->HandleBrightnessDown(accelerator);
574 break;
575 case BRIGHTNESS_UP:
576 if (brightness_control_delegate_.get())
577 return brightness_control_delegate_->HandleBrightnessUp(accelerator);
578 break;
579 case KEYBOARD_BRIGHTNESS_DOWN:
580 if (keyboard_brightness_control_delegate_.get())
581 return keyboard_brightness_control_delegate_->
582 HandleKeyboardBrightnessDown(accelerator);
583 break;
584 case KEYBOARD_BRIGHTNESS_UP:
585 if (keyboard_brightness_control_delegate_.get())
586 return keyboard_brightness_control_delegate_->
587 HandleKeyboardBrightnessUp(accelerator);
588 break;
589 case VOLUME_MUTE:
590 return shell->system_tray_delegate()->GetVolumeControlDelegate()->
591 HandleVolumeMute(accelerator);
592 break;
593 case VOLUME_DOWN:
594 return shell->system_tray_delegate()->GetVolumeControlDelegate()->
595 HandleVolumeDown(accelerator);
596 break;
597 case VOLUME_UP:
598 return shell->system_tray_delegate()->GetVolumeControlDelegate()->
599 HandleVolumeUp(accelerator);
600 break;
601 case FOCUS_LAUNCHER:
602 return shell->focus_cycler()->FocusWidget(
603 Launcher::ForPrimaryDisplay()->widget());
604 break;
605 case FOCUS_NEXT_PANE:
606 return HandleRotatePaneFocus(Shell::FORWARD);
607 case FOCUS_PREVIOUS_PANE:
608 return HandleRotatePaneFocus(Shell::BACKWARD);
609 case SHOW_KEYBOARD_OVERLAY:
610 ash::Shell::GetInstance()->delegate()->ShowKeyboardOverlay();
611 return true;
612 case SHOW_OAK:
613 if (CommandLine::ForCurrentProcess()->HasSwitch(
614 switches::kAshEnableOak)) {
615 oak::ShowOakWindowWithContext(Shell::GetPrimaryRootWindow());
616 return true;
618 break;
619 case SHOW_SYSTEM_TRAY_BUBBLE: {
620 internal::RootWindowController* controller =
621 Shell::IsLauncherPerDisplayEnabled() ?
622 internal::RootWindowController::ForActiveRootWindow() :
623 Shell::GetPrimaryRootWindowController();
624 if (!controller->GetSystemTray()->HasSystemBubble())
625 controller->GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW);
626 break;
628 case SHOW_TASK_MANAGER:
629 Shell::GetInstance()->delegate()->ShowTaskManager();
630 return true;
631 case NEXT_IME:
632 // This check is necessary e.g. not to process the Shift+Alt+
633 // ET_KEY_RELEASED accelerator for Chrome OS (see ash/accelerators/
634 // accelerator_controller.cc) when Shift+Alt+Tab is pressed and then Tab
635 // is released.
636 if (previous_event_type == ui::ET_KEY_RELEASED &&
637 // Workaround for crbug.com/139556. CJK IME users tend to press
638 // Enter (or Space) and Shift+Alt almost at the same time to commit
639 // an IME string and then switch from the IME to the English layout.
640 // This workaround allows the user to trigger NEXT_IME even if the
641 // user presses Shift+Alt before releasing Enter.
642 // TODO(nona|mazda): Fix crbug.com/139556 in a cleaner way.
643 previous_key_code != ui::VKEY_RETURN &&
644 previous_key_code != ui::VKEY_SPACE) {
645 // We totally ignore this accelerator.
646 // TODO(mazda): Fix crbug.com/158217
647 return false;
649 if (ime_control_delegate_.get())
650 return ime_control_delegate_->HandleNextIme();
651 break;
652 case PREVIOUS_IME:
653 if (ime_control_delegate_.get())
654 return ime_control_delegate_->HandlePreviousIme();
655 break;
656 case SWITCH_IME:
657 if (ime_control_delegate_.get())
658 return ime_control_delegate_->HandleSwitchIme(accelerator);
659 break;
660 case SELECT_WIN_0:
661 Launcher::ForPrimaryDisplay()->SwitchToWindow(0);
662 return true;
663 case SELECT_WIN_1:
664 Launcher::ForPrimaryDisplay()->SwitchToWindow(1);
665 return true;
666 case SELECT_WIN_2:
667 Launcher::ForPrimaryDisplay()->SwitchToWindow(2);
668 return true;
669 case SELECT_WIN_3:
670 Launcher::ForPrimaryDisplay()->SwitchToWindow(3);
671 return true;
672 case SELECT_WIN_4:
673 Launcher::ForPrimaryDisplay()->SwitchToWindow(4);
674 return true;
675 case SELECT_WIN_5:
676 Launcher::ForPrimaryDisplay()->SwitchToWindow(5);
677 return true;
678 case SELECT_WIN_6:
679 Launcher::ForPrimaryDisplay()->SwitchToWindow(6);
680 return true;
681 case SELECT_WIN_7:
682 Launcher::ForPrimaryDisplay()->SwitchToWindow(7);
683 return true;
684 case SELECT_LAST_WIN:
685 Launcher::ForPrimaryDisplay()->SwitchToWindow(-1);
686 return true;
687 case WINDOW_SNAP_LEFT:
688 case WINDOW_SNAP_RIGHT: {
689 aura::Window* window = wm::GetActiveWindow();
690 // Disable window docking shortcut key for full screen window due to
691 // http://crbug.com/135487.
692 if (!window ||
693 window->type() != aura::client::WINDOW_TYPE_NORMAL ||
694 wm::IsWindowFullscreen(window)) {
695 break;
698 internal::SnapSizer::SnapWindow(window,
699 action == WINDOW_SNAP_LEFT ? internal::SnapSizer::LEFT_EDGE :
700 internal::SnapSizer::RIGHT_EDGE);
701 return true;
703 case WINDOW_MINIMIZE: {
704 aura::Window* window = wm::GetActiveWindow();
705 // Attempt to restore the window that would be cycled through next from
706 // the launcher when there is no active window.
707 if (!window)
708 return HandleCycleWindowMRU(WindowCycleController::FORWARD, false);
709 // Disable the shortcut for minimizing full screen window due to
710 // crbug.com/131709, which is a crashing issue related to minimizing
711 // full screen pepper window.
712 if (!wm::IsWindowFullscreen(window)) {
713 wm::MinimizeWindow(window);
714 return true;
716 break;
718 case TOGGLE_MAXIMIZED: {
719 if (key_code == ui::VKEY_MEDIA_LAUNCH_APP2) {
720 shell->delegate()->RecordUserMetricsAction(
721 UMA_ACCEL_MAXIMIZE_RESTORE_F4);
723 shell->delegate()->ToggleMaximized();
724 return true;
726 case WINDOW_POSITION_CENTER: {
727 aura::Window* window = wm::GetActiveWindow();
728 if (window) {
729 wm::CenterWindow(window);
730 return true;
732 break;
734 case ROTATE_WINDOWS:
735 return HandleRotateWindows();
736 case ROTATE_SCREEN:
737 return HandleRotateScreen();
738 case TOGGLE_DESKTOP_BACKGROUND_MODE:
739 return HandleToggleDesktopBackgroundMode();
740 case TOGGLE_ROOT_WINDOW_FULL_SCREEN:
741 return HandleToggleRootWindowFullScreen();
742 case DISPLAY_TOGGLE_SCALE:
743 internal::DisplayManager::ToggleDisplayScale();
744 return true;
745 case MAGNIFY_SCREEN_ZOOM_IN:
746 return HandleMagnifyScreen(1);
747 case MAGNIFY_SCREEN_ZOOM_OUT:
748 return HandleMagnifyScreen(-1);
749 case MEDIA_NEXT_TRACK:
750 return HandleMediaNextTrack();
751 case MEDIA_PLAY_PAUSE:
752 return HandleMediaPlayPause();
753 case MEDIA_PREV_TRACK:
754 return HandleMediaPrevTrack();
755 case POWER_PRESSED: // fallthrough
756 case POWER_RELEASED:
757 #if defined(OS_CHROMEOS)
758 if (!base::chromeos::IsRunningOnChromeOS()) {
759 // There is no powerd in linux desktop, so call the
760 // PowerButtonController here.
761 Shell::GetInstance()->power_button_controller()->
762 OnPowerButtonEvent(action == POWER_PRESSED, base::TimeTicks());
764 #endif
765 // We don't do anything with these at present on the device,
766 // (power button events are reported to us from powerm via
767 // D-BUS), but we consume them to prevent them from getting
768 // passed to apps -- see http://crbug.com/146609.
769 return true;
770 case LOCK_PRESSED:
771 case LOCK_RELEASED:
772 Shell::GetInstance()->power_button_controller()->
773 OnLockButtonEvent(action == LOCK_PRESSED, base::TimeTicks());
774 return true;
775 #if !defined(NDEBUG)
776 case PRINT_LAYER_HIERARCHY:
777 return HandlePrintLayerHierarchy();
778 case PRINT_VIEW_HIERARCHY:
779 return HandlePrintViewHierarchy();
780 case PRINT_WINDOW_HIERARCHY:
781 return HandlePrintWindowHierarchy();
782 #endif
783 default:
784 NOTREACHED() << "Unhandled action " << action;
786 return false;
789 void AcceleratorController::SetBrightnessControlDelegate(
790 scoped_ptr<BrightnessControlDelegate> brightness_control_delegate) {
791 // Install brightness control delegate only when internal
792 // display exists.
793 if (Shell::GetInstance()->display_manager()->HasInternalDisplay() ||
794 CommandLine::ForCurrentProcess()->HasSwitch(
795 switches::kAshEnableBrightnessControl)) {
796 brightness_control_delegate_.swap(brightness_control_delegate);
800 void AcceleratorController::SetImeControlDelegate(
801 scoped_ptr<ImeControlDelegate> ime_control_delegate) {
802 ime_control_delegate_.swap(ime_control_delegate);
805 void AcceleratorController::SetScreenshotDelegate(
806 scoped_ptr<ScreenshotDelegate> screenshot_delegate) {
807 screenshot_delegate_.swap(screenshot_delegate);
810 ////////////////////////////////////////////////////////////////////////////////
811 // AcceleratorController, ui::AcceleratorTarget implementation:
813 bool AcceleratorController::AcceleratorPressed(
814 const ui::Accelerator& accelerator) {
815 std::map<ui::Accelerator, int>::const_iterator it =
816 accelerators_.find(accelerator);
817 DCHECK(it != accelerators_.end());
818 return PerformAction(static_cast<AcceleratorAction>(it->second), accelerator);
821 void AcceleratorController::RegisterAccelerators(
822 const AcceleratorData accelerators[],
823 size_t accelerators_length) {
824 for (size_t i = 0; i < accelerators_length; ++i) {
825 ui::Accelerator accelerator(accelerators[i].keycode,
826 accelerators[i].modifiers);
827 accelerator.set_type(accelerators[i].trigger_on_press ?
828 ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED);
829 Register(accelerator, this);
830 accelerators_.insert(
831 std::make_pair(accelerator, accelerators[i].action));
835 void AcceleratorController::SetKeyboardBrightnessControlDelegate(
836 scoped_ptr<KeyboardBrightnessControlDelegate>
837 keyboard_brightness_control_delegate) {
838 keyboard_brightness_control_delegate_ =
839 keyboard_brightness_control_delegate.Pass();
842 bool AcceleratorController::CanHandleAccelerators() const {
843 return true;
846 } // namespace ash