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"
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)
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() {
77 return CommandLine::ForCurrentProcess()->HasSwitch(
78 switches::kAshDebugShortcuts
);
84 bool HandleCycleWindowMRU(WindowCycleController::Direction direction
,
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.
92 void HandleCycleWindowLinear(CycleDirection direction
) {
93 Launcher::ForPrimaryDisplay()->CycleWindowLinear(direction
);
96 #if defined(OS_CHROMEOS)
98 Shell::GetInstance()->delegate()->LockScreen();
102 bool HandleFileManager() {
103 Shell::GetInstance()->delegate()->OpenFileManager();
108 Shell::GetInstance()->delegate()->OpenCrosh();
112 bool HandleToggleSpokenFeedback() {
113 Shell::GetInstance()->delegate()->
114 ToggleSpokenFeedback(A11Y_NOTIFICATION_SHOW
);
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();
126 shell
->focus_cycler()->RotateFocus(internal::FocusCycler::FORWARD
);
128 case Shell::BACKWARD
:
129 shell
->focus_cycler()->RotateFocus(internal::FocusCycler::BACKWARD
);
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());
157 // Rotates the screen.
158 bool HandleRotateScreen() {
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;
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());
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(
200 ash::Shell::GetInstance()->user_wallpaper_delegate()->
201 InitializeWallpaper();
206 bool HandleToggleRootWindowFullScreen() {
207 Shell::GetPrimaryRootWindow()->ToggleFullScreen();
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.
217 ash::Shell::GetInstance()->magnification_controller()->GetScale();
218 // Calculate rounded logarithm (base kMagnificationFactor) of scale.
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()->
236 bool HandleMediaNextTrack() {
237 Shell::GetInstance()->delegate()->HandleMediaNextTrack();
241 bool HandleMediaPlayPause() {
242 Shell::GetInstance()->delegate()->HandleMediaPlayPause();
246 bool HandleMediaPrevTrack() {
247 Shell::GetInstance()->delegate()->HandleMediaPrevTrack();
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());
261 bool HandlePrintViewHierarchy() {
262 aura::Window
* active_window
= ash::wm::GetActiveWindow();
265 views::Widget
* browser_widget
=
266 views::Widget::GetWidgetForNativeWindow(active_window
);
268 views::PrintViewHierarchy(browser_widget
->GetRootView());
272 void PrintWindowHierarchy(aura::Window
* window
, int indent
) {
273 std::string
indent_str(indent
, ' ');
274 std::string
name(window
->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);
298 #endif // !defined(NDEBUG)
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
) {
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());
354 void AcceleratorController::Register(const ui::Accelerator
& accelerator
,
355 ui::AcceleratorTarget
* target
) {
356 accelerator_manager_
->Register(accelerator
,
357 ui::AcceleratorManager::kNormalPriority
,
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();
403 if (at_login_screen
&&
404 actions_allowed_at_login_screen_
.find(action
) ==
405 actions_allowed_at_login_screen_
.end()) {
408 if (shell
->IsScreenLocked() &&
409 actions_allowed_at_lock_screen_
.find(action
) ==
410 actions_allowed_at_lock_screen_
.end()) {
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.
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
) {
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.
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
);
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
);
464 #if defined(OS_CHROMEOS)
465 case CYCLE_DISPLAY_MODE
:
466 Shell::GetInstance()->display_controller()->CycleDisplayMode();
470 case OPEN_FILE_MANAGER_DIALOG
:
471 return HandleFileManager();
473 return HandleCrosh();
474 case SWAP_PRIMARY_DISPLAY
:
475 Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
477 case TOGGLE_SPOKEN_FEEDBACK
:
478 return HandleToggleSpokenFeedback();
480 Shell::GetInstance()->system_tray_delegate()->ToggleWifi();
482 case TOUCH_HUD_MODE_CHANGE
:
483 if (Shell::GetInstance()->touch_observer_hud()) {
484 Shell::GetInstance()->touch_observer_hud()->ChangeToNextMode();
488 case DISABLE_GPU_WATCHDOG
:
489 content::GpuDataManager::GetInstance()->DisableGpuWatchdog();
492 case OPEN_FEEDBACK_PAGE
:
493 ash::Shell::GetInstance()->delegate()->OpenFeedbackPage();
496 Shell::GetInstance()->delegate()->Exit();
498 case NEW_INCOGNITO_WINDOW
:
499 Shell::GetInstance()->delegate()->NewWindow(true /* is_incognito */);
502 if (key_code
== ui::VKEY_T
)
503 shell
->delegate()->RecordUserMetricsAction(UMA_ACCEL_NEWTAB_T
);
504 Shell::GetInstance()->delegate()->NewTab();
507 Shell::GetInstance()->delegate()->NewWindow(false /* is_incognito */);
510 Shell::GetInstance()->delegate()->RestoreTab();
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.
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.
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
531 if (key_code
== ui::VKEY_LWIN
&&
532 (previous_event_type
== ui::ET_KEY_RELEASED
||
533 previous_key_code
!= ui::VKEY_LWIN
))
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())
543 ash::Shell::GetInstance()->ToggleAppList(NULL
);
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.
554 if (shell
->caps_lock_delegate()->IsCapsLockEnabled()) {
555 shell
->caps_lock_delegate()->SetCapsLockEnabled(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
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
)
569 shell
->caps_lock_delegate()->ToggleCapsLock();
571 case BRIGHTNESS_DOWN
:
572 if (brightness_control_delegate_
.get())
573 return brightness_control_delegate_
->HandleBrightnessDown(accelerator
);
576 if (brightness_control_delegate_
.get())
577 return brightness_control_delegate_
->HandleBrightnessUp(accelerator
);
579 case KEYBOARD_BRIGHTNESS_DOWN
:
580 if (keyboard_brightness_control_delegate_
.get())
581 return keyboard_brightness_control_delegate_
->
582 HandleKeyboardBrightnessDown(accelerator
);
584 case KEYBOARD_BRIGHTNESS_UP
:
585 if (keyboard_brightness_control_delegate_
.get())
586 return keyboard_brightness_control_delegate_
->
587 HandleKeyboardBrightnessUp(accelerator
);
590 return shell
->system_tray_delegate()->GetVolumeControlDelegate()->
591 HandleVolumeMute(accelerator
);
594 return shell
->system_tray_delegate()->GetVolumeControlDelegate()->
595 HandleVolumeDown(accelerator
);
598 return shell
->system_tray_delegate()->GetVolumeControlDelegate()->
599 HandleVolumeUp(accelerator
);
602 return shell
->focus_cycler()->FocusWidget(
603 Launcher::ForPrimaryDisplay()->widget());
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();
613 if (CommandLine::ForCurrentProcess()->HasSwitch(
614 switches::kAshEnableOak
)) {
615 oak::ShowOakWindowWithContext(Shell::GetPrimaryRootWindow());
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
);
628 case SHOW_TASK_MANAGER
:
629 Shell::GetInstance()->delegate()->ShowTaskManager();
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
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
649 if (ime_control_delegate_
.get())
650 return ime_control_delegate_
->HandleNextIme();
653 if (ime_control_delegate_
.get())
654 return ime_control_delegate_
->HandlePreviousIme();
657 if (ime_control_delegate_
.get())
658 return ime_control_delegate_
->HandleSwitchIme(accelerator
);
661 Launcher::ForPrimaryDisplay()->SwitchToWindow(0);
664 Launcher::ForPrimaryDisplay()->SwitchToWindow(1);
667 Launcher::ForPrimaryDisplay()->SwitchToWindow(2);
670 Launcher::ForPrimaryDisplay()->SwitchToWindow(3);
673 Launcher::ForPrimaryDisplay()->SwitchToWindow(4);
676 Launcher::ForPrimaryDisplay()->SwitchToWindow(5);
679 Launcher::ForPrimaryDisplay()->SwitchToWindow(6);
682 Launcher::ForPrimaryDisplay()->SwitchToWindow(7);
684 case SELECT_LAST_WIN
:
685 Launcher::ForPrimaryDisplay()->SwitchToWindow(-1);
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.
693 window
->type() != aura::client::WINDOW_TYPE_NORMAL
||
694 wm::IsWindowFullscreen(window
)) {
698 internal::SnapSizer::SnapWindow(window
,
699 action
== WINDOW_SNAP_LEFT
? internal::SnapSizer::LEFT_EDGE
:
700 internal::SnapSizer::RIGHT_EDGE
);
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.
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
);
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();
726 case WINDOW_POSITION_CENTER
: {
727 aura::Window
* window
= wm::GetActiveWindow();
729 wm::CenterWindow(window
);
735 return HandleRotateWindows();
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();
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
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());
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.
772 Shell::GetInstance()->power_button_controller()->
773 OnLockButtonEvent(action
== LOCK_PRESSED
, base::TimeTicks());
776 case PRINT_LAYER_HIERARCHY
:
777 return HandlePrintLayerHierarchy();
778 case PRINT_VIEW_HIERARCHY
:
779 return HandlePrintViewHierarchy();
780 case PRINT_WINDOW_HIERARCHY
:
781 return HandlePrintWindowHierarchy();
784 NOTREACHED() << "Unhandled action " << action
;
789 void AcceleratorController::SetBrightnessControlDelegate(
790 scoped_ptr
<BrightnessControlDelegate
> brightness_control_delegate
) {
791 // Install brightness control delegate only when internal
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 {