blob: 74cce7be5917088d2bbd1a8bb535883e4f82d758 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/accelerators/accelerator_controller.h"
#include <algorithm>
#include <cmath>
#include <string>
#include "ash/accelerators/accelerator_table.h"
#include "ash/ash_switches.h"
#include "ash/caps_lock_delegate.h"
#include "ash/desktop_background/desktop_background_controller.h"
#include "ash/display/display_controller.h"
#include "ash/display/multi_display_manager.h"
#include "ash/focus_cycler.h"
#include "ash/ime_control_delegate.h"
#include "ash/launcher/launcher.h"
#include "ash/launcher/launcher_delegate.h"
#include "ash/launcher/launcher_model.h"
#include "ash/magnifier/magnification_controller.h"
#include "ash/root_window_controller.h"
#include "ash/rotator/screen_rotation.h"
#include "ash/screen_ash.h"
#include "ash/screenshot_delegate.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/shell_window_ids.h"
#include "ash/system/brightness/brightness_control_delegate.h"
#include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h"
#include "ash/system/tray/system_tray.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/volume_control_delegate.h"
#include "ash/wm/partial_screenshot_view.h"
#include "ash/wm/property_util.h"
#include "ash/wm/window_cycle_controller.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/snap_sizer.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/accelerators/accelerator_manager.h"
#include "ui/base/events/event.h"
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/compositor/debug_utils.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/gfx/screen.h"
#include "ui/oak/oak.h"
#include "ui/views/debug_utils.h"
#include "ui/views/widget/widget.h"
#if defined(OS_CHROMEOS)
#include "ash/display/output_configurator_animation.h"
#include "base/chromeos/chromeos_version.h"
#include "chromeos/display/output_configurator.h"
#endif // defined(OS_CHROMEOS)
namespace ash {
namespace {
// Factor of magnification scale. For example, when this value is 1.189, scale
// value will be changed x1.000, x1.189, x1.414, x1.681, x2.000, ...
// Note: this value is 2.0 ^ (1 / 4).
const float kMagnificationFactor = 1.18920712f;
bool DebugShortcutsEnabled() {
#if defined(NDEBUG)
return CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAshDebugShortcuts);
#else
return true;
#endif
}
bool HandleCycleWindowMRU(WindowCycleController::Direction direction,
bool is_alt_down) {
Shell::GetInstance()->
window_cycle_controller()->HandleCycleWindow(direction, is_alt_down);
// Always report we handled the key, even if the window didn't change.
return true;
}
void HandleCycleWindowLinear(CycleDirection direction) {
Shell::GetInstance()->launcher()->CycleWindowLinear(direction);
}
#if defined(OS_CHROMEOS)
bool HandleLock() {
Shell::GetInstance()->delegate()->LockScreen();
return true;
}
bool HandleFileManager(bool as_dialog) {
Shell::GetInstance()->delegate()->OpenFileManager(as_dialog);
return true;
}
bool HandleCrosh() {
Shell::GetInstance()->delegate()->OpenCrosh();
return true;
}
bool HandleToggleSpokenFeedback() {
Shell::GetInstance()->delegate()->ToggleSpokenFeedback();
return true;
}
void HandleCycleDisplayMode() {
Shell* shell = Shell::GetInstance();
if (!base::chromeos::IsRunningOnChromeOS()) {
internal::MultiDisplayManager::CycleDisplay();
} else if (shell->output_configurator()->connected_output_count() > 1) {
internal::OutputConfiguratorAnimation* animation =
shell->output_configurator_animation();
animation->StartFadeOutAnimation(base::Bind(
base::IgnoreResult(&chromeos::OutputConfigurator::CycleDisplayMode),
base::Unretained(shell->output_configurator())));
}
}
void HandleSwapPrimaryDisplay() {
if (gfx::Screen::GetNumDisplays() > 1) {
Shell::GetInstance()->display_controller()->SetPrimaryDisplay(
ScreenAsh::GetSecondaryDisplay());
}
}
#endif // defined(OS_CHROMEOS)
bool HandleExit() {
ShellDelegate* delegate = Shell::GetInstance()->delegate();
if (!delegate)
return false;
delegate->Exit();
return true;
}
bool HandleNewTab() {
Shell::GetInstance()->delegate()->NewTab();
return true;
}
bool HandleNewWindow(bool is_incognito) {
ShellDelegate* delegate = Shell::GetInstance()->delegate();
if (!delegate)
return false;
delegate->NewWindow(is_incognito);
return true;
}
bool HandleRestoreTab() {
Shell::GetInstance()->delegate()->RestoreTab();
return true;
}
bool HandleShowTaskManager() {
Shell::GetInstance()->delegate()->ShowTaskManager();
return true;
}
bool HandleRotatePaneFocus(Shell::Direction direction) {
if (!Shell::GetInstance()->delegate()->RotatePaneFocus(direction)) {
// No browser window is available. Focus the launcher.
Shell* shell = Shell::GetInstance();
switch (direction) {
case Shell::FORWARD:
shell->focus_cycler()->RotateFocus(internal::FocusCycler::FORWARD);
break;
case Shell::BACKWARD:
shell->focus_cycler()->RotateFocus(internal::FocusCycler::BACKWARD);
break;
}
}
return true;
}
// Rotates the default window container.
bool HandleRotateWindows() {
Shell::RootWindowControllerList controllers =
Shell::GetAllRootWindowControllers();
for (size_t i = 0; i < controllers.size(); ++i) {
aura::Window* target = controllers[i]->GetContainer(
internal::kShellWindowId_DefaultContainer);
scoped_ptr<ui::LayerAnimationSequence> screen_rotation(
new ui::LayerAnimationSequence(new ash::ScreenRotation(360)));
target->layer()->GetAnimator()->StartAnimation(
screen_rotation.release());
}
return true;
}
// Rotates the screen.
bool HandleRotateScreen() {
static int i = 0;
int delta = 0;
switch (i) {
case 0: delta = 90; break;
case 1: delta = 90; break;
case 2: delta = 90; break;
case 3: delta = 90; break;
case 4: delta = -90; break;
case 5: delta = -90; break;
case 6: delta = -90; break;
case 7: delta = -90; break;
case 8: delta = -90; break;
case 9: delta = 180; break;
case 10: delta = 180; break;
case 11: delta = 90; break;
case 12: delta = 180; break;
case 13: delta = 180; break;
}
i = (i + 1) % 14;
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
for (size_t i = 0; i < root_windows.size(); ++i) {
aura::RootWindow* root_window = root_windows[i];
root_window->layer()->GetAnimator()->
set_preemption_strategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
scoped_ptr<ui::LayerAnimationSequence> screen_rotation(
new ui::LayerAnimationSequence(new ash::ScreenRotation(delta)));
screen_rotation->AddObserver(root_window);
root_window->layer()->GetAnimator()->
StartAnimation(screen_rotation.release());
}
return true;
}
bool HandleToggleDesktopBackgroundMode() {
DesktopBackgroundController* desktop_background_controller =
Shell::GetInstance()->desktop_background_controller();
if (desktop_background_controller->desktop_background_mode() ==
DesktopBackgroundController::BACKGROUND_IMAGE) {
desktop_background_controller->SetDesktopBackgroundSolidColorMode(
SK_ColorBLACK);
} else {
ash::Shell::GetInstance()->user_wallpaper_delegate()->
InitializeWallpaper();
}
return true;
}
bool HandleToggleRootWindowFullScreen() {
Shell::GetPrimaryRootWindow()->ToggleFullScreen();
return true;
}
// Magnify the screen
bool HandleMagnifyScreen(int delta_index) {
// TODO(yoshiki): Create the class like MagnifierStepScaleController, and
// move the following scale control to it.
float scale =
ash::Shell::GetInstance()->magnification_controller()->GetScale();
// Calculate rounded logarithm (base kMagnificationFactor) of scale.
int scale_index =
std::floor(std::log(scale) / std::log(kMagnificationFactor) + 0.5);
int new_scale_index = std::max(0, std::min(8, scale_index + delta_index));
ash::Shell::GetInstance()->magnification_controller()->
SetScale(std::pow(kMagnificationFactor, new_scale_index), true);
return true;
}
bool HandleMediaNextTrack() {
Shell::GetInstance()->delegate()->HandleMediaNextTrack();
return true;
}
bool HandleMediaPlayPause() {
Shell::GetInstance()->delegate()->HandleMediaPlayPause();
return true;
}
bool HandleMediaPrevTrack() {
Shell::GetInstance()->delegate()->HandleMediaPrevTrack();
return true;
}
#if !defined(NDEBUG)
bool HandlePrintLayerHierarchy() {
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
for (size_t i = 0; i < root_windows.size(); ++i) {
ui::PrintLayerHierarchy(root_windows[i]->layer(),
root_windows[i]->GetLastMouseLocationInRoot());
}
return true;
}
bool HandlePrintViewHierarchy() {
aura::Window* default_container =
Shell::GetPrimaryRootWindowController()->GetContainer(
internal::kShellWindowId_DefaultContainer);
if (default_container->children().empty())
return true;
aura::Window* browser_frame = default_container->children()[0];
views::Widget* browser_widget =
views::Widget::GetWidgetForNativeWindow(browser_frame);
views::PrintViewHierarchy(browser_widget->GetRootView());
return true;
}
void PrintWindowHierarchy(aura::Window* window, int indent) {
std::string indent_str(indent, ' ');
DLOG(INFO) << indent_str << window->name() << " type " << window->type()
<< (wm::IsActiveWindow(window) ? "active" : "");
for (size_t i = 0; i < window->children().size(); ++i)
PrintWindowHierarchy(window->children()[i], indent + 3);
}
bool HandlePrintWindowHierarchy() {
DLOG(INFO) << "Window hierarchy:";
Shell::RootWindowControllerList controllers =
Shell::GetAllRootWindowControllers();
for (size_t i = 0; i < controllers.size(); ++i) {
DLOG(INFO) << "RootWindow " << i << ":";
aura::Window* container = controllers[i]->GetContainer(
internal::kShellWindowId_DefaultContainer);
PrintWindowHierarchy(container, 0);
}
return true;
}
#endif // !defined(NDEBUG)
} // namespace
////////////////////////////////////////////////////////////////////////////////
// AcceleratorController, public:
AcceleratorController::AcceleratorController()
: accelerator_manager_(new ui::AcceleratorManager) {
Init();
}
AcceleratorController::~AcceleratorController() {
}
void AcceleratorController::Init() {
for (size_t i = 0; i < kActionsAllowedAtLoginOrLockScreenLength; ++i) {
actions_allowed_at_login_screen_.insert(
kActionsAllowedAtLoginOrLockScreen[i]);
actions_allowed_at_lock_screen_.insert(
kActionsAllowedAtLoginOrLockScreen[i]);
}
for (size_t i = 0; i < kActionsAllowedAtLockScreenLength; ++i) {
actions_allowed_at_lock_screen_.insert(kActionsAllowedAtLockScreen[i]);
}
for (size_t i = 0; i < kReservedActionsLength; ++i) {
reserved_actions_.insert(kReservedActions[i]);
}
RegisterAccelerators(kAcceleratorData, kAcceleratorDataLength);
if (DebugShortcutsEnabled())
RegisterAccelerators(kDebugAcceleratorData, kDebugAcceleratorDataLength);
}
void AcceleratorController::Register(const ui::Accelerator& accelerator,
ui::AcceleratorTarget* target) {
accelerator_manager_->Register(accelerator,
ui::AcceleratorManager::kNormalPriority,
target);
}
void AcceleratorController::Unregister(const ui::Accelerator& accelerator,
ui::AcceleratorTarget* target) {
accelerator_manager_->Unregister(accelerator, target);
}
void AcceleratorController::UnregisterAll(ui::AcceleratorTarget* target) {
accelerator_manager_->UnregisterAll(target);
}
bool AcceleratorController::Process(const ui::Accelerator& accelerator) {
if (ime_control_delegate_.get()) {
return accelerator_manager_->Process(
ime_control_delegate_->RemapAccelerator(accelerator));
}
return accelerator_manager_->Process(accelerator);
}
bool AcceleratorController::IsRegistered(
const ui::Accelerator& accelerator) const {
return accelerator_manager_->GetCurrentTarget(accelerator) != NULL;
}
bool AcceleratorController::IsReservedAccelerator(
const ui::Accelerator& accelerator) const {
const ui::Accelerator remapped_accelerator = ime_control_delegate_.get() ?
ime_control_delegate_->RemapAccelerator(accelerator) : accelerator;
if (!accelerator_manager_->ShouldHandle(remapped_accelerator))
return false;
std::map<ui::Accelerator, int>::const_iterator iter =
accelerators_.find(remapped_accelerator);
if (iter == accelerators_.end())
return false; // not an accelerator.
return reserved_actions_.find(iter->second) != reserved_actions_.end();
}
bool AcceleratorController::PerformAction(int action,
const ui::Accelerator& accelerator) {
ash::Shell* shell = ash::Shell::GetInstance();
bool at_login_screen = false;
#if defined(OS_CHROMEOS)
at_login_screen = shell->delegate() && !shell->delegate()->IsSessionStarted();
#endif
bool at_lock_screen = shell->IsScreenLocked();
if (at_login_screen &&
actions_allowed_at_login_screen_.find(action) ==
actions_allowed_at_login_screen_.end()) {
return false;
}
if (at_lock_screen &&
actions_allowed_at_lock_screen_.find(action) ==
actions_allowed_at_lock_screen_.end()) {
return false;
}
const ui::KeyboardCode key_code = accelerator.key_code();
// You *MUST* return true when some action is performed. Otherwise, this
// function might be called *twice*, via BrowserView::PreHandleKeyboardEvent
// and BrowserView::HandleKeyboardEvent, for a single accelerator press.
switch (action) {
case CYCLE_BACKWARD_MRU:
if (key_code == ui::VKEY_TAB && shell->delegate())
shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_PREVWINDOW_TAB);
return HandleCycleWindowMRU(WindowCycleController::BACKWARD,
accelerator.IsAltDown());
case CYCLE_FORWARD_MRU:
if (key_code == ui::VKEY_TAB && shell->delegate())
shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_NEXTWINDOW_TAB);
return HandleCycleWindowMRU(WindowCycleController::FORWARD,
accelerator.IsAltDown());
case CYCLE_BACKWARD_LINEAR:
if (key_code == ui::VKEY_F5 && shell->delegate())
shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_PREVWINDOW_F5);
HandleCycleWindowLinear(CYCLE_BACKWARD);
return true;
case CYCLE_FORWARD_LINEAR:
if (key_code == ui::VKEY_F5 && shell->delegate())
shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_NEXTWINDOW_F5);
HandleCycleWindowLinear(CYCLE_FORWARD);
return true;
#if defined(OS_CHROMEOS)
case CYCLE_DISPLAY_MODE:
HandleCycleDisplayMode();
return true;
case LOCK_SCREEN:
return HandleLock();
case OPEN_FILE_MANAGER_DIALOG:
return HandleFileManager(true /* as_dialog */);
case OPEN_FILE_MANAGER_TAB:
return HandleFileManager(false /* as_dialog */);
case OPEN_CROSH:
return HandleCrosh();
case SWAP_PRIMARY_DISPLAY:
HandleSwapPrimaryDisplay();
return true;
case TOGGLE_SPOKEN_FEEDBACK:
return HandleToggleSpokenFeedback();
case TOGGLE_WIFI:
if (Shell::GetInstance()->tray_delegate())
Shell::GetInstance()->tray_delegate()->ToggleWifi();
return true;
#endif
case OPEN_FEEDBACK_PAGE:
ash::Shell::GetInstance()->delegate()->OpenFeedbackPage();
return true;
case EXIT:
return HandleExit();
case NEW_INCOGNITO_WINDOW:
return HandleNewWindow(true /* is_incognito */);
case NEW_TAB:
if (key_code == ui::VKEY_T && shell->delegate())
shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_NEWTAB_T);
return HandleNewTab();
case NEW_WINDOW:
return HandleNewWindow(false /* is_incognito */);
case RESTORE_TAB:
return HandleRestoreTab();
case TAKE_SCREENSHOT:
if (screenshot_delegate_.get() &&
screenshot_delegate_->CanTakeScreenshot()) {
screenshot_delegate_->HandleTakeScreenshotForAllRootWindows();
}
// Return true to prevent propagation of the key event.
return true;
case TAKE_PARTIAL_SCREENSHOT:
if (screenshot_delegate_.get()) {
ash::PartialScreenshotView::StartPartialScreenshot(
screenshot_delegate_.get());
}
// Return true to prevent propagation of the key event because
// this key combination is reserved for partial screenshot.
return true;
case TOGGLE_APP_LIST:
if (key_code == ui::VKEY_LWIN && shell->delegate())
shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_SEARCH_LWIN);
// When spoken feedback is enabled, we should neither toggle the list nor
// consume the key since Search+Shift is one of the shortcuts the a11y
// feature uses. crbug.com/132296
DCHECK_EQ(ui::VKEY_LWIN, accelerator.key_code());
if (Shell::GetInstance()->delegate()->IsSpokenFeedbackEnabled())
return false;
ash::Shell::GetInstance()->ToggleAppList();
return true;
case DISABLE_CAPS_LOCK:
if (shell->caps_lock_delegate()->IsCapsLockEnabled())
shell->caps_lock_delegate()->SetCapsLockEnabled(false);
return true;
case TOGGLE_CAPS_LOCK:
shell->caps_lock_delegate()->ToggleCapsLock();
return true;
case BRIGHTNESS_DOWN:
if (brightness_control_delegate_.get())
return brightness_control_delegate_->HandleBrightnessDown(accelerator);
break;
case BRIGHTNESS_UP:
if (brightness_control_delegate_.get())
return brightness_control_delegate_->HandleBrightnessUp(accelerator);
break;
case KEYBOARD_BRIGHTNESS_DOWN:
if (keyboard_brightness_control_delegate_.get())
return keyboard_brightness_control_delegate_->
HandleKeyboardBrightnessDown(accelerator);
break;
case KEYBOARD_BRIGHTNESS_UP:
if (keyboard_brightness_control_delegate_.get())
return keyboard_brightness_control_delegate_->
HandleKeyboardBrightnessUp(accelerator);
break;
case VOLUME_MUTE:
return shell->tray_delegate()->GetVolumeControlDelegate()->
HandleVolumeMute(accelerator);
break;
case VOLUME_DOWN:
return shell->tray_delegate()->GetVolumeControlDelegate()->
HandleVolumeDown(accelerator);
break;
case VOLUME_UP:
return shell->tray_delegate()->GetVolumeControlDelegate()->
HandleVolumeUp(accelerator);
break;
case FOCUS_LAUNCHER:
if (shell->launcher())
return shell->focus_cycler()->FocusWidget(shell->launcher()->widget());
break;
case FOCUS_NEXT_PANE:
return HandleRotatePaneFocus(Shell::FORWARD);
case FOCUS_PREVIOUS_PANE:
return HandleRotatePaneFocus(Shell::BACKWARD);
case FOCUS_SYSTEM_TRAY:
if (shell->system_tray())
return shell->focus_cycler()->FocusWidget(
shell->system_tray()->GetWidget());
break;
case SHOW_KEYBOARD_OVERLAY:
ash::Shell::GetInstance()->delegate()->ShowKeyboardOverlay();
return true;
case SHOW_OAK:
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAshEnableOak)) {
oak::ShowOakWindow();
return true;
}
break;
case SHOW_TASK_MANAGER:
return HandleShowTaskManager();
case NEXT_IME:
if (ime_control_delegate_.get())
return ime_control_delegate_->HandleNextIme();
break;
case PREVIOUS_IME:
if (ime_control_delegate_.get())
return ime_control_delegate_->HandlePreviousIme();
break;
case SWITCH_IME:
if (ime_control_delegate_.get())
return ime_control_delegate_->HandleSwitchIme(accelerator);
break;
case SELECT_WIN_0:
SwitchToWindow(0);
return true;
case SELECT_WIN_1:
SwitchToWindow(1);
return true;
case SELECT_WIN_2:
SwitchToWindow(2);
return true;
case SELECT_WIN_3:
SwitchToWindow(3);
return true;
case SELECT_WIN_4:
SwitchToWindow(4);
return true;
case SELECT_WIN_5:
SwitchToWindow(5);
return true;
case SELECT_WIN_6:
SwitchToWindow(6);
return true;
case SELECT_WIN_7:
SwitchToWindow(7);
return true;
case SELECT_LAST_WIN:
SwitchToWindow(-1);
return true;
case WINDOW_SNAP_LEFT:
case WINDOW_SNAP_RIGHT: {
aura::Window* window = wm::GetActiveWindow();
// Disable window docking shortcut key for full screen window due to
// http://crbug.com/135487.
if (!window ||
window->type() != aura::client::WINDOW_TYPE_NORMAL ||
wm::IsWindowFullscreen(window)) {
break;
}
internal::SnapSizer sizer(window,
gfx::Point(),
action == WINDOW_SNAP_LEFT ? internal::SnapSizer::LEFT_EDGE :
internal::SnapSizer::RIGHT_EDGE);
if (wm::IsWindowFullscreen(window) ||
wm::IsWindowMaximized(window)) {
// Before we can set the bounds we need to restore the window.
// Restoring the window will set the window to its restored bounds.
// To avoid an unnecessary bounds changes (which may have side effects)
// we set the restore bounds to the bounds we want, restore the window,
// then reset the restore bounds. This way no unnecessary bounds
// changes occurs and the original restore bounds is remembered.
gfx::Rect restore = *GetRestoreBoundsInScreen(window);
SetRestoreBoundsInParent(window, sizer.GetSnapBounds(window->bounds()));
wm::RestoreWindow(window);
SetRestoreBoundsInScreen(window, restore);
} else {
window->SetBounds(sizer.GetSnapBounds(window->bounds()));
}
return true;
}
case WINDOW_MINIMIZE: {
aura::Window* window = wm::GetActiveWindow();
// Attempt to restore the window that would be cycled through next from
// the launcher when there is no active window.
if (!window)
return HandleCycleWindowMRU(WindowCycleController::FORWARD, false);
// Disable the shortcut for minimizing full screen window due to
// crbug.com/131709, which is a crashing issue related to minimizing
// full screen pepper window.
if (!wm::IsWindowFullscreen(window)) {
wm::MinimizeWindow(window);
return true;
}
break;
}
case TOGGLE_MAXIMIZED: {
if (key_code == ui::VKEY_F4 && shell->delegate()) {
shell->delegate()->RecordUserMetricsAction(
UMA_ACCEL_MAXIMIZE_RESTORE_F4);
}
aura::Window* window = wm::GetActiveWindow();
if (!window)
return true;
if (wm::IsWindowFullscreen(window)) {
// Chrome also uses VKEY_F4 as a shortcut. Its action is to toggle
// fullscreen. We return false below so Chrome will process the
// shortcut again and, in case of VKEY_F4, exit fullscreen.
return false;
}
if (wm::IsWindowMaximized(window))
wm::RestoreWindow(window);
else if (wm::CanMaximizeWindow(window))
wm::MaximizeWindow(window);
return true;
}
case WINDOW_POSITION_CENTER: {
aura::Window* window = wm::GetActiveWindow();
if (window) {
wm::CenterWindow(window);
return true;
}
break;
}
case ROTATE_WINDOWS:
return HandleRotateWindows();
case ROTATE_SCREEN:
return HandleRotateScreen();
case TOGGLE_DESKTOP_BACKGROUND_MODE:
return HandleToggleDesktopBackgroundMode();
case TOGGLE_ROOT_WINDOW_FULL_SCREEN:
return HandleToggleRootWindowFullScreen();
case DISPLAY_TOGGLE_SCALE:
internal::MultiDisplayManager::ToggleDisplayScale();
return true;
case MAGNIFY_SCREEN_ZOOM_IN:
return HandleMagnifyScreen(1);
case MAGNIFY_SCREEN_ZOOM_OUT:
return HandleMagnifyScreen(-1);
case MEDIA_NEXT_TRACK:
return HandleMediaNextTrack();
case MEDIA_PLAY_PAUSE:
return HandleMediaPlayPause();
case MEDIA_PREV_TRACK:
return HandleMediaPrevTrack();
case POWER_PRESSED: // fallthrough
case POWER_RELEASED:
// We don't do anything with these at present, but we consume them to
// prevent them from getting passed to apps -- see
// http://crbug.com/146609.
return true;
#if !defined(NDEBUG)
case PRINT_LAYER_HIERARCHY:
return HandlePrintLayerHierarchy();
case PRINT_VIEW_HIERARCHY:
return HandlePrintViewHierarchy();
case PRINT_WINDOW_HIERARCHY:
return HandlePrintWindowHierarchy();
#endif
default:
NOTREACHED() << "Unhandled action " << action;
}
return false;
}
void AcceleratorController::SetBrightnessControlDelegate(
scoped_ptr<BrightnessControlDelegate> brightness_control_delegate) {
// TODO(oshima): Show brightness control regardless of display type
// temporarily. crbug.com/152003.
brightness_control_delegate_.swap(brightness_control_delegate);
}
void AcceleratorController::SetImeControlDelegate(
scoped_ptr<ImeControlDelegate> ime_control_delegate) {
ime_control_delegate_.swap(ime_control_delegate);
}
void AcceleratorController::SetKeyboardBrightnessControlDelegate(
scoped_ptr<KeyboardBrightnessControlDelegate>
keyboard_brightness_control_delegate) {
keyboard_brightness_control_delegate_.swap(
keyboard_brightness_control_delegate);
}
void AcceleratorController::SetScreenshotDelegate(
scoped_ptr<ScreenshotDelegate> screenshot_delegate) {
screenshot_delegate_.swap(screenshot_delegate);
}
////////////////////////////////////////////////////////////////////////////////
// AcceleratorController, ui::AcceleratorTarget implementation:
bool AcceleratorController::AcceleratorPressed(
const ui::Accelerator& accelerator) {
std::map<ui::Accelerator, int>::const_iterator it =
accelerators_.find(accelerator);
DCHECK(it != accelerators_.end());
return PerformAction(static_cast<AcceleratorAction>(it->second), accelerator);
}
void AcceleratorController::SwitchToWindow(int window) {
const LauncherItems& items =
Shell::GetInstance()->launcher()->model()->items();
int item_count =
Shell::GetInstance()->launcher()->model()->item_count();
int indexes_left = window >= 0 ? window : item_count;
int found_index = -1;
// Iterating until we have hit the index we are interested in which
// is true once indexes_left becomes negative.
for (int i = 0; i < item_count && indexes_left >= 0; i++) {
if (items[i].type != TYPE_APP_LIST &&
items[i].type != TYPE_BROWSER_SHORTCUT) {
found_index = i;
indexes_left--;
}
}
// There are two ways how found_index can be valid: a.) the nth item was
// found (which is true when indexes_left is -1) or b.) the last item was
// requested (which is true when index was passed in as a negative number).
if (found_index >= 0 && (indexes_left == -1 || window < 0) &&
(items[found_index].status == ash::STATUS_RUNNING ||
items[found_index].status == ash::STATUS_CLOSED)) {
// Then set this one as active.
Shell::GetInstance()->launcher()->ActivateLauncherItem(found_index);
}
}
void AcceleratorController::RegisterAccelerators(
const AcceleratorData accelerators[],
size_t accelerators_length) {
for (size_t i = 0; i < accelerators_length; ++i) {
ui::Accelerator accelerator(accelerators[i].keycode,
accelerators[i].modifiers);
accelerator.set_type(accelerators[i].trigger_on_press ?
ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED);
Register(accelerator, this);
accelerators_.insert(
std::make_pair(accelerator, accelerators[i].action));
}
}
bool AcceleratorController::CanHandleAccelerators() const {
return true;
}
} // namespace ash