blob: 8f1d9477b775d5e515cc4969996b7b603e89d145 [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_commands.h"
#include "ash/accelerators/debug_commands.h"
#include "ash/ash_switches.h"
#include "ash/debug.h"
#include "ash/display/display_controller.h"
#include "ash/display/display_manager.h"
#include "ash/display/display_util.h"
#include "ash/focus_cycler.h"
#include "ash/gpu_support.h"
#include "ash/ime_control_delegate.h"
#include "ash/magnifier/magnification_controller.h"
#include "ash/magnifier/partial_magnification_controller.h"
#include "ash/media_delegate.h"
#include "ash/multi_profile_uma.h"
#include "ash/new_window_delegate.h"
#include "ash/root_window_controller.h"
#include "ash/rotator/screen_rotation_animator.h"
#include "ash/rotator/window_rotation.h"
#include "ash/screenshot_delegate.h"
#include "ash/session/session_state_delegate.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_delegate.h"
#include "ash/shelf/shelf_model.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/shell_window_ids.h"
#include "ash/system/brightness_control_delegate.h"
#include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/tray/system_tray.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "ash/system/web_notification/web_notification_tray.h"
#include "ash/touch/touch_hud_debug.h"
#include "ash/utility/partial_screenshot_controller.h"
#include "ash/volume_control_delegate.h"
#include "ash/wm/maximize_mode/maximize_mode_controller.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/power_button_controller.h"
#include "ash/wm/window_cycle_controller.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/metrics/user_metrics.h"
#include "ui/aura/env.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/accelerators/accelerator_manager.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/screen.h"
#include "ui/views/controls/webview/webview.h"
#if defined(OS_CHROMEOS)
#include "ash/system/chromeos/keyboard_brightness_controller.h"
#include "base/sys_info.h"
#include "ui/base/ime/chromeos/ime_keyboard.h"
#include "ui/base/ime/chromeos/input_method_manager.h"
#endif // defined(OS_CHROMEOS)
namespace ash {
namespace {
using base::UserMetricsAction;
void HandleCycleBackwardMRU(const ui::Accelerator& accelerator) {
if (accelerator.key_code() == ui::VKEY_TAB)
base::RecordAction(base::UserMetricsAction("Accel_PrevWindow_Tab"));
Shell::GetInstance()->window_cycle_controller()->HandleCycleWindow(
WindowCycleController::BACKWARD);
}
void HandleCycleForwardMRU(const ui::Accelerator& accelerator) {
if (accelerator.key_code() == ui::VKEY_TAB)
base::RecordAction(base::UserMetricsAction("Accel_NextWindow_Tab"));
Shell::GetInstance()->window_cycle_controller()->HandleCycleWindow(
WindowCycleController::FORWARD);
}
void HandleRotatePaneFocus(Shell::Direction direction) {
Shell* shell = Shell::GetInstance();
switch (direction) {
// TODO(stevet): Not sure if this is the same as IDC_FOCUS_NEXT_PANE.
case Shell::FORWARD: {
base::RecordAction(UserMetricsAction("Accel_Focus_Next_Pane"));
shell->focus_cycler()->RotateFocus(FocusCycler::FORWARD);
break;
}
case Shell::BACKWARD: {
base::RecordAction(UserMetricsAction("Accel_Focus_Previous_Pane"));
shell->focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
break;
}
}
}
void HandleFocusShelf() {
Shell* shell = Shell::GetInstance();
base::RecordAction(base::UserMetricsAction("Accel_Focus_Shelf"));
shell->focus_cycler()->FocusWidget(
Shelf::ForPrimaryDisplay()->shelf_widget());
}
void HandleLaunchAppN(int n) {
base::RecordAction(UserMetricsAction("Accel_Launch_App"));
Shelf::ForPrimaryDisplay()->LaunchAppIndexAt(n);
}
void HandleLaunchLastApp() {
base::RecordAction(UserMetricsAction("Accel_Launch_Last_App"));
Shelf::ForPrimaryDisplay()->LaunchAppIndexAt(-1);
}
bool CanHandleMagnifyScreen() {
Shell* shell = Shell::GetInstance();
return shell->magnification_controller()->IsEnabled() ||
shell->partial_magnification_controller()->is_enabled();
}
// Magnify the screen
void HandleMagnifyScreen(int delta_index) {
if (ash::Shell::GetInstance()->magnification_controller()->IsEnabled()) {
// TODO(yoshiki): Move the following logic to MagnificationController.
float scale =
ash::Shell::GetInstance()->magnification_controller()->GetScale();
// Calculate rounded logarithm (base kMagnificationScaleFactor) of scale.
int scale_index = std::floor(
std::log(scale) / std::log(ui::kMagnificationScaleFactor) + 0.5);
int new_scale_index = std::max(0, std::min(8, scale_index + delta_index));
ash::Shell::GetInstance()->magnification_controller()->SetScale(
std::pow(ui::kMagnificationScaleFactor, new_scale_index), true);
} else if (ash::Shell::GetInstance()->
partial_magnification_controller()->is_enabled()) {
float scale = delta_index > 0 ? kDefaultPartialMagnifiedScale : 1;
ash::Shell::GetInstance()->partial_magnification_controller()->
SetScale(scale);
}
}
void HandleMediaNextTrack() {
Shell::GetInstance()->media_delegate()->HandleMediaNextTrack();
}
void HandleMediaPlayPause() {
Shell::GetInstance()->media_delegate()->HandleMediaPlayPause();
}
void HandleMediaPrevTrack() {
Shell::GetInstance()->media_delegate()->HandleMediaPrevTrack();
}
bool CanHandleNewIncognitoWindow() {
return Shell::GetInstance()->delegate()->IsIncognitoAllowed();
}
void HandleNewIncognitoWindow() {
base::RecordAction(UserMetricsAction("Accel_New_Incognito_Window"));
Shell::GetInstance()->new_window_delegate()->NewWindow(
true /* is_incognito */);
}
void HandleNewTab(const ui::Accelerator& accelerator) {
if (accelerator.key_code() == ui::VKEY_T)
base::RecordAction(base::UserMetricsAction("Accel_NewTab_T"));
Shell::GetInstance()->new_window_delegate()->NewTab();
}
void HandleNewWindow() {
base::RecordAction(base::UserMetricsAction("Accel_New_Window"));
Shell::GetInstance()->new_window_delegate()->NewWindow(
false /* is_incognito */);
}
bool CanHandleNextIme(ImeControlDelegate* ime_control_delegate,
const ui::Accelerator& previous_accelerator) {
// This check is necessary e.g. not to process the Shift+Alt+
// ET_KEY_RELEASED accelerator for Chrome OS (see ash/accelerators/
// accelerator_controller.cc) when Shift+Alt+Tab is pressed and then Tab
// is released.
ui::KeyboardCode previous_key_code = previous_accelerator.key_code();
if (previous_accelerator.type() == ui::ET_KEY_RELEASED &&
// Workaround for crbug.com/139556. CJK IME users tend to press
// Enter (or Space) and Shift+Alt almost at the same time to commit
// an IME string and then switch from the IME to the English layout.
// This workaround allows the user to trigger NEXT_IME even if the
// user presses Shift+Alt before releasing Enter.
// TODO(nona|mazda): Fix crbug.com/139556 in a cleaner way.
previous_key_code != ui::VKEY_RETURN &&
previous_key_code != ui::VKEY_SPACE) {
// We totally ignore this accelerator.
// TODO(mazda): Fix crbug.com/158217
return false;
}
return ime_control_delegate && ime_control_delegate->CanCycleIme();
}
void HandleNextIme(ImeControlDelegate* ime_control_delegate) {
base::RecordAction(UserMetricsAction("Accel_Next_Ime"));
ime_control_delegate->HandleNextIme();
}
void HandleOpenFeedbackPage() {
base::RecordAction(UserMetricsAction("Accel_Open_Feedback_Page"));
ash::Shell::GetInstance()->new_window_delegate()->OpenFeedbackPage();
}
bool CanHandlePreviousIme(ImeControlDelegate* ime_control_delegate) {
return ime_control_delegate && ime_control_delegate->CanCycleIme();
}
void HandlePreviousIme(ImeControlDelegate* ime_control_delegate,
const ui::Accelerator& accelerator) {
base::RecordAction(UserMetricsAction("Accel_Previous_Ime"));
if (accelerator.type() == ui::ET_KEY_PRESSED)
ime_control_delegate->HandlePreviousIme();
// Else: consume the Ctrl+Space ET_KEY_RELEASED event but do not do anything.
}
void HandleRestoreTab() {
base::RecordAction(base::UserMetricsAction("Accel_Restore_Tab"));
Shell::GetInstance()->new_window_delegate()->RestoreTab();
}
gfx::Display::Rotation GetNextRotation(gfx::Display::Rotation current) {
switch (current) {
case gfx::Display::ROTATE_0:
return gfx::Display::ROTATE_90;
case gfx::Display::ROTATE_90:
return gfx::Display::ROTATE_180;
case gfx::Display::ROTATE_180:
return gfx::Display::ROTATE_270;
case gfx::Display::ROTATE_270:
return gfx::Display::ROTATE_0;
}
NOTREACHED() << "Unknown rotation:" << current;
return gfx::Display::ROTATE_0;
}
// Rotates the screen.
void HandleRotateScreen() {
base::RecordAction(UserMetricsAction("Accel_Rotate_Window"));
gfx::Point point = Shell::GetScreen()->GetCursorScreenPoint();
gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint(point);
const DisplayInfo& display_info =
Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id());
ash::ScreenRotationAnimator(display.id())
.Rotate(GetNextRotation(display_info.GetActiveRotation()),
gfx::Display::ROTATION_SOURCE_USER);
}
// Rotate the active window.
void HandleRotateActiveWindow() {
base::RecordAction(UserMetricsAction("Accel_Rotate_Window"));
aura::Window* active_window = wm::GetActiveWindow();
if (active_window) {
// The rotation animation bases its target transform on the current
// rotation and position. Since there could be an animation in progress
// right now, queue this animation so when it starts it picks up a neutral
// rotation and position. Use replace so we only enqueue one at a time.
active_window->layer()->GetAnimator()->
set_preemption_strategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
active_window->layer()->GetAnimator()->StartAnimation(
new ui::LayerAnimationSequence(
new ash::WindowRotation(360, active_window->layer())));
}
}
bool CanHandleScaleReset() {
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
int64 display_id = display_manager->GetDisplayIdForUIScaling();
return (display_id != gfx::Display::kInvalidDisplayID &&
display_manager->GetDisplayInfo(display_id).configured_ui_scale() !=
1.0f);
}
void HandleScaleReset() {
base::RecordAction(UserMetricsAction("Accel_Scale_Ui_Reset"));
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
int64 display_id = display_manager->GetDisplayIdForUIScaling();
display_manager->SetDisplayUIScale(display_id, 1.0f);
}
bool CanHandleScaleUI() {
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
int64 display_id = display_manager->GetDisplayIdForUIScaling();
return display_id != gfx::Display::kInvalidDisplayID;
}
void HandleScaleUI(bool up) {
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
int64 display_id = display_manager->GetDisplayIdForUIScaling();
if (up) {
base::RecordAction(UserMetricsAction("Accel_Scale_Ui_Up"));
} else {
base::RecordAction(UserMetricsAction("Accel_Scale_Ui_Down"));
}
const DisplayInfo& display_info = display_manager->GetDisplayInfo(display_id);
float next_scale = GetNextUIScale(display_info, up);
display_manager->SetDisplayUIScale(display_id, next_scale);
}
void HandleShowKeyboardOverlay() {
base::RecordAction(UserMetricsAction("Accel_Show_Keyboard_Overlay"));
ash::Shell::GetInstance()->new_window_delegate()->ShowKeyboardOverlay();
}
bool CanHandleShowMessageCenterBubble() {
RootWindowController* controller =
RootWindowController::ForTargetRootWindow();
StatusAreaWidget* status_area_widget =
controller->shelf()->status_area_widget();
return status_area_widget &&
status_area_widget->web_notification_tray()->visible();
}
void HandleShowMessageCenterBubble() {
base::RecordAction(UserMetricsAction("Accel_Show_Message_Center_Bubble"));
RootWindowController* controller =
RootWindowController::ForTargetRootWindow();
StatusAreaWidget* status_area_widget =
controller->shelf()->status_area_widget();
if (status_area_widget) {
WebNotificationTray* notification_tray =
status_area_widget->web_notification_tray();
if (notification_tray->visible())
notification_tray->ShowMessageCenterBubble();
}
}
void HandleShowSystemTrayBubble() {
base::RecordAction(UserMetricsAction("Accel_Show_System_Tray_Bubble"));
RootWindowController* controller =
RootWindowController::ForTargetRootWindow();
if (!controller->GetSystemTray()->HasSystemBubble())
controller->GetSystemTray()->ShowDefaultView(BUBBLE_CREATE_NEW);
}
void HandleShowTaskManager() {
base::RecordAction(UserMetricsAction("Accel_Show_Task_Manager"));
Shell::GetInstance()->new_window_delegate()->ShowTaskManager();
}
bool CanHandleSwitchIme(ImeControlDelegate* ime_control_delegate,
const ui::Accelerator& accelerator) {
return ime_control_delegate &&
ime_control_delegate->CanSwitchIme(accelerator);
}
void HandleSwitchIme(ImeControlDelegate* ime_control_delegate,
const ui::Accelerator& accelerator) {
base::RecordAction(UserMetricsAction("Accel_Switch_Ime"));
ime_control_delegate->HandleSwitchIme(accelerator);
}
void HandleTakePartialScreenshot(ScreenshotDelegate* screenshot_delegate) {
base::RecordAction(UserMetricsAction("Accel_Take_Partial_Screenshot"));
DCHECK(screenshot_delegate);
Shell::GetInstance()
->partial_screenshot_controller()
->StartPartialScreenshotSession(screenshot_delegate);
}
void HandleTakeScreenshot(ScreenshotDelegate* screenshot_delegate) {
base::RecordAction(UserMetricsAction("Accel_Take_Screenshot"));
DCHECK(screenshot_delegate);
if (screenshot_delegate->CanTakeScreenshot())
screenshot_delegate->HandleTakeScreenshotForAllRootWindows();
}
bool CanHandleToggleAppList(const ui::Accelerator& accelerator,
const ui::Accelerator& previous_accelerator) {
if (accelerator.key_code() == ui::VKEY_LWIN) {
// If something else was pressed between the Search key (LWIN)
// being pressed and released, then ignore the release of the
// Search key.
if (previous_accelerator.type() != ui::ET_KEY_PRESSED ||
previous_accelerator.key_code() != ui::VKEY_LWIN) {
return false;
}
// 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
if (Shell::GetInstance()
->accessibility_delegate()
->IsSpokenFeedbackEnabled()) {
return false;
}
}
return true;
}
void HandleToggleAppList(const ui::Accelerator& accelerator) {
if (accelerator.key_code() == ui::VKEY_LWIN)
base::RecordAction(base::UserMetricsAction("Accel_Search_LWin"));
ash::Shell::GetInstance()->ToggleAppList(NULL);
}
void HandleToggleFullscreen(const ui::Accelerator& accelerator) {
if (accelerator.key_code() == ui::VKEY_MEDIA_LAUNCH_APP2)
base::RecordAction(UserMetricsAction("Accel_Fullscreen_F4"));
accelerators::ToggleFullscreen();
}
void HandleToggleOverview() {
base::RecordAction(base::UserMetricsAction("Accel_Overview_F5"));
Shell::GetInstance()->window_selector_controller()->ToggleOverview();
}
bool CanHandleWindowSnapOrDock() {
wm::WindowState* window_state = wm::GetActiveWindowState();
// Disable window snapping shortcut key for full screen window due to
// http://crbug.com/135487.
return (window_state && window_state->IsUserPositionable() &&
!window_state->IsFullscreen());
}
void HandleWindowSnapOrDock(AcceleratorAction action) {
if (action == WINDOW_CYCLE_SNAP_DOCK_LEFT)
base::RecordAction(UserMetricsAction("Accel_Window_Snap_Left"));
else
base::RecordAction(UserMetricsAction("Accel_Window_Snap_Right"));
const wm::WMEvent event(action == WINDOW_CYCLE_SNAP_DOCK_LEFT ?
wm::WM_EVENT_CYCLE_SNAP_DOCK_LEFT :
wm::WM_EVENT_CYCLE_SNAP_DOCK_RIGHT);
wm::GetActiveWindowState()->OnWMEvent(&event);
}
void HandleWindowMinimize() {
base::RecordAction(
base::UserMetricsAction("Accel_Toggle_Minimized_Minus"));
accelerators::ToggleMinimized();
}
bool CanHandlePositionCenter() {
// Docked windows do not support centering.
wm::WindowState* window_state = wm::GetActiveWindowState();
return (window_state && !window_state->IsDocked());
}
void HandlePositionCenter() {
base::RecordAction(UserMetricsAction("Accel_Window_Position_Center"));
wm::CenterWindow(wm::GetActiveWindow());
}
#if defined(OS_CHROMEOS)
void HandleBrightnessDown(BrightnessControlDelegate* delegate,
const ui::Accelerator& accelerator) {
if (delegate)
delegate->HandleBrightnessDown(accelerator);
}
void HandleBrightnessUp(BrightnessControlDelegate* delegate,
const ui::Accelerator& accelerator) {
if (delegate)
delegate->HandleBrightnessUp(accelerator);
}
bool CanHandleDisableCapsLock(const ui::Accelerator& previous_accelerator) {
ui::KeyboardCode previous_key_code = previous_accelerator.key_code();
if (previous_accelerator.type() == ui::ET_KEY_RELEASED ||
(previous_key_code != ui::VKEY_LSHIFT &&
previous_key_code != ui::VKEY_SHIFT &&
previous_key_code != ui::VKEY_RSHIFT)) {
// If something else was pressed between the Shift key being pressed
// and released, then ignore the release of the Shift key.
return false;
}
chromeos::input_method::InputMethodManager* ime =
chromeos::input_method::InputMethodManager::Get();
chromeos::input_method::ImeKeyboard* keyboard =
ime ? ime->GetImeKeyboard() : NULL;
return (keyboard && keyboard->CapsLockIsEnabled());
}
void HandleDisableCapsLock() {
base::RecordAction(UserMetricsAction("Accel_Disable_Caps_Lock"));
chromeos::input_method::InputMethodManager* ime =
chromeos::input_method::InputMethodManager::Get();
ime->GetImeKeyboard()->SetCapsLockEnabled(false);
}
void HandleKeyboardBrightnessDown(KeyboardBrightnessControlDelegate* delegate,
const ui::Accelerator& accelerator) {
if (delegate)
delegate->HandleKeyboardBrightnessDown(accelerator);
}
void HandleKeyboardBrightnessUp(KeyboardBrightnessControlDelegate* delegate,
const ui::Accelerator& accelerator) {
if (delegate)
delegate->HandleKeyboardBrightnessUp(accelerator);
}
void HandleLock() {
base::RecordAction(UserMetricsAction("Accel_LockScreen_L"));
Shell::GetInstance()->session_state_delegate()->LockScreen();
}
void HandleCrosh() {
base::RecordAction(UserMetricsAction("Accel_Open_Crosh"));
Shell::GetInstance()->new_window_delegate()->OpenCrosh();
}
void HandleFileManager() {
base::RecordAction(UserMetricsAction("Accel_Open_File_Manager"));
Shell::GetInstance()->new_window_delegate()->OpenFileManager();
}
void HandleGetHelp() {
Shell::GetInstance()->new_window_delegate()->OpenGetHelp();
}
bool CanHandleSilenceSpokenFeedback() {
AccessibilityDelegate* delegate =
Shell::GetInstance()->accessibility_delegate();
return delegate->IsSpokenFeedbackEnabled();
}
void HandleSilenceSpokenFeedback() {
base::RecordAction(UserMetricsAction("Accel_Silence_Spoken_Feedback"));
Shell::GetInstance()->accessibility_delegate()->SilenceSpokenFeedback();
}
void HandleSwapPrimaryDisplay() {
base::RecordAction(UserMetricsAction("Accel_Swap_Primary_Display"));
Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
}
bool CanHandleCycleUser() {
Shell* shell = Shell::GetInstance();
return shell->delegate()->IsMultiProfilesEnabled() &&
shell->session_state_delegate()->NumberOfLoggedInUsers() > 1;
}
void HandleCycleUser(SessionStateDelegate::CycleUser cycle_user) {
MultiProfileUMA::RecordSwitchActiveUser(
MultiProfileUMA::SWITCH_ACTIVE_USER_BY_ACCELERATOR);
switch (cycle_user) {
case SessionStateDelegate::CYCLE_TO_NEXT_USER:
base::RecordAction(UserMetricsAction("Accel_Switch_To_Next_User"));
break;
case SessionStateDelegate::CYCLE_TO_PREVIOUS_USER:
base::RecordAction(UserMetricsAction("Accel_Switch_To_Previous_User"));
break;
}
Shell::GetInstance()->session_state_delegate()->CycleActiveUser(cycle_user);
}
bool CanHandleToggleCapsLock(const ui::Accelerator& accelerator,
const ui::Accelerator& previous_accelerator) {
if (accelerator.key_code() == ui::VKEY_LWIN) {
// If something else was pressed between the Search key (LWIN)
// being pressed and released, then ignore the release of the
// Search key.
// TODO(danakj): Releasing Alt first breaks this: crbug.com/166495
if (previous_accelerator.type() == ui::ET_KEY_RELEASED ||
previous_accelerator.key_code() != ui::VKEY_LWIN)
return false;
}
chromeos::input_method::InputMethodManager* ime =
chromeos::input_method::InputMethodManager::Get();
return ime && ime->GetImeKeyboard();
}
void HandleToggleCapsLock() {
base::RecordAction(UserMetricsAction("Accel_Toggle_Caps_Lock"));
chromeos::input_method::InputMethodManager* ime =
chromeos::input_method::InputMethodManager::Get();
chromeos::input_method::ImeKeyboard* keyboard = ime->GetImeKeyboard();
keyboard->SetCapsLockEnabled(!keyboard->CapsLockIsEnabled());
}
void HandleToggleMirrorMode() {
base::RecordAction(UserMetricsAction("Accel_Toggle_Mirror_Mode"));
Shell::GetInstance()->display_controller()->ToggleMirrorMode();
}
void HandleToggleSpokenFeedback() {
base::RecordAction(UserMetricsAction("Accel_Toggle_Spoken_Feedback"));
Shell::GetInstance()->accessibility_delegate()->
ToggleSpokenFeedback(ui::A11Y_NOTIFICATION_SHOW);
}
bool CanHandleToggleTouchViewTesting() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAshEnableTouchViewTesting);
}
void HandleToggleTouchViewTesting() {
// TODO(skuhne): This is only temporary! Remove this!
MaximizeModeController* controller = Shell::GetInstance()->
maximize_mode_controller();
controller->EnableMaximizeModeWindowManager(
!controller->IsMaximizeModeWindowManagerEnabled());
}
bool CanHandleTouchHud() {
return RootWindowController::ForTargetRootWindow()->touch_hud_debug();
}
void HandleTouchHudClear() {
RootWindowController::ForTargetRootWindow()->touch_hud_debug()->Clear();
}
void HandleTouchHudModeChange() {
RootWindowController* controller =
RootWindowController::ForTargetRootWindow();
controller->touch_hud_debug()->ChangeToNextMode();
}
void HandleVolumeDown(const ui::Accelerator& accelerator) {
VolumeControlDelegate* volume_delegate =
Shell::GetInstance()->system_tray_delegate()->GetVolumeControlDelegate();
if (volume_delegate)
volume_delegate->HandleVolumeDown(accelerator);
}
void HandleVolumeMute(const ui::Accelerator& accelerator) {
VolumeControlDelegate* volume_delegate =
Shell::GetInstance()->system_tray_delegate()->GetVolumeControlDelegate();
if (volume_delegate)
volume_delegate->HandleVolumeMute(accelerator);
}
void HandleVolumeUp(const ui::Accelerator& accelerator) {
VolumeControlDelegate* volume_delegate =
Shell::GetInstance()->system_tray_delegate()->GetVolumeControlDelegate();
if (volume_delegate)
volume_delegate->HandleVolumeUp(accelerator);
}
#endif // defined(OS_CHROMEOS)
} // namespace
////////////////////////////////////////////////////////////////////////////////
// AcceleratorController, public:
AcceleratorController::AcceleratorController()
: accelerator_manager_(new ui::AcceleratorManager),
accelerator_history_(new ui::AcceleratorHistory) {
Init();
}
AcceleratorController::~AcceleratorController() {
}
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_) {
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::IsPreferred(
const ui::Accelerator& accelerator) const {
const ui::Accelerator remapped_accelerator = ime_control_delegate_.get() ?
ime_control_delegate_->RemapAccelerator(accelerator) : accelerator;
std::map<ui::Accelerator, AcceleratorAction>::const_iterator iter =
accelerators_.find(remapped_accelerator);
if (iter == accelerators_.end())
return false; // not an accelerator.
return preferred_actions_.find(iter->second) != preferred_actions_.end();
}
bool AcceleratorController::IsReserved(
const ui::Accelerator& accelerator) const {
const ui::Accelerator remapped_accelerator = ime_control_delegate_.get() ?
ime_control_delegate_->RemapAccelerator(accelerator) : accelerator;
std::map<ui::Accelerator, AcceleratorAction>::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::PerformActionIfEnabled(AcceleratorAction action) {
if (CanPerformAction(action, ui::Accelerator())) {
PerformAction(action, ui::Accelerator());
return true;
}
return false;
}
AcceleratorController::AcceleratorProcessingRestriction
AcceleratorController::GetCurrentAcceleratorRestriction() {
return GetAcceleratorProcessingRestriction(-1);
}
void AcceleratorController::SetBrightnessControlDelegate(
scoped_ptr<BrightnessControlDelegate> brightness_control_delegate) {
brightness_control_delegate_ = brightness_control_delegate.Pass();
}
void AcceleratorController::SetImeControlDelegate(
scoped_ptr<ImeControlDelegate> ime_control_delegate) {
ime_control_delegate_ = ime_control_delegate.Pass();
}
void AcceleratorController::SetScreenshotDelegate(
scoped_ptr<ScreenshotDelegate> screenshot_delegate) {
screenshot_delegate_ = screenshot_delegate.Pass();
}
////////////////////////////////////////////////////////////////////////////////
// AcceleratorController, ui::AcceleratorTarget implementation:
bool AcceleratorController::AcceleratorPressed(
const ui::Accelerator& accelerator) {
std::map<ui::Accelerator, AcceleratorAction>::const_iterator it =
accelerators_.find(accelerator);
DCHECK(it != accelerators_.end());
AcceleratorAction action = it->second;
if (CanPerformAction(action, accelerator)) {
PerformAction(action, accelerator);
return ShouldActionConsumeKeyEvent(action);
}
return false;
}
bool AcceleratorController::CanHandleAccelerators() const {
return true;
}
///////////////////////////////////////////////////////////////////////////////
// AcceleratorController, private:
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 < kActionsAllowedAtModalWindowLength; ++i)
actions_allowed_at_modal_window_.insert(kActionsAllowedAtModalWindow[i]);
for (size_t i = 0; i < kPreferredActionsLength; ++i)
preferred_actions_.insert(kPreferredActions[i]);
for (size_t i = 0; i < kReservedActionsLength; ++i)
reserved_actions_.insert(kReservedActions[i]);
for (size_t i = 0; i < kNonrepeatableActionsLength; ++i)
nonrepeatable_actions_.insert(kNonrepeatableActions[i]);
for (size_t i = 0; i < kActionsAllowedInAppModeLength; ++i)
actions_allowed_in_app_mode_.insert(kActionsAllowedInAppMode[i]);
for (size_t i = 0; i < kActionsNeedingWindowLength; ++i)
actions_needing_window_.insert(kActionsNeedingWindow[i]);
RegisterAccelerators(kAcceleratorData, kAcceleratorDataLength);
if (debug::DebugAcceleratorsEnabled()) {
RegisterAccelerators(kDebugAcceleratorData, kDebugAcceleratorDataLength);
// All debug accelerators are reserved.
for (size_t i = 0; i < kDebugAcceleratorDataLength; ++i)
reserved_actions_.insert(kDebugAcceleratorData[i].action);
}
#if defined(OS_CHROMEOS)
keyboard_brightness_control_delegate_.reset(
new KeyboardBrightnessController());
#endif
}
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::CanPerformAction(
AcceleratorAction action,
const ui::Accelerator& accelerator) {
if (nonrepeatable_actions_.find(action) != nonrepeatable_actions_.end() &&
accelerator.IsRepeat()) {
return false;
}
AcceleratorProcessingRestriction restriction =
GetAcceleratorProcessingRestriction(action);
if (restriction != RESTRICTION_NONE)
return restriction == RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION;
const ui::Accelerator& previous_accelerator =
accelerator_history_->previous_accelerator();
// True should be returned if running |action| does something. Otherwise,
// false should be returned to give the web contents a chance at handling the
// accelerator.
switch (action) {
case DEBUG_PRINT_LAYER_HIERARCHY:
case DEBUG_PRINT_VIEW_HIERARCHY:
case DEBUG_PRINT_WINDOW_HIERARCHY:
case DEBUG_TOGGLE_DESKTOP_BACKGROUND_MODE:
case DEBUG_TOGGLE_DEVICE_SCALE_FACTOR:
case DEBUG_TOGGLE_ROOT_WINDOW_FULL_SCREEN:
case DEBUG_TOGGLE_SHOW_DEBUG_BORDERS:
case DEBUG_TOGGLE_SHOW_FPS_COUNTER:
case DEBUG_TOGGLE_SHOW_PAINT_RECTS:
return debug::DebugAcceleratorsEnabled();
case MAGNIFY_SCREEN_ZOOM_IN:
case MAGNIFY_SCREEN_ZOOM_OUT:
return CanHandleMagnifyScreen();
case NEW_INCOGNITO_WINDOW:
return CanHandleNewIncognitoWindow();
case NEXT_IME:
return CanHandleNextIme(ime_control_delegate_.get(),
previous_accelerator);
case PREVIOUS_IME:
return CanHandlePreviousIme(ime_control_delegate_.get());
case SCALE_UI_RESET:
return CanHandleScaleReset();
case SCALE_UI_UP:
case SCALE_UI_DOWN:
return CanHandleScaleUI();
case SHOW_MESSAGE_CENTER_BUBBLE:
return CanHandleShowMessageCenterBubble();
case SWITCH_IME:
return CanHandleSwitchIme(ime_control_delegate_.get(), accelerator);
case TOGGLE_APP_LIST:
return CanHandleToggleAppList(accelerator, previous_accelerator);
case WINDOW_CYCLE_SNAP_DOCK_LEFT:
case WINDOW_CYCLE_SNAP_DOCK_RIGHT:
return CanHandleWindowSnapOrDock();
case WINDOW_POSITION_CENTER:
return CanHandlePositionCenter();
#if defined(OS_CHROMEOS)
case DEBUG_ADD_REMOVE_DISPLAY:
return debug::DebugAcceleratorsEnabled();
case DISABLE_CAPS_LOCK:
return CanHandleDisableCapsLock(previous_accelerator);
case SILENCE_SPOKEN_FEEDBACK:
return CanHandleSilenceSpokenFeedback();
case SWITCH_TO_PREVIOUS_USER:
case SWITCH_TO_NEXT_USER:
return CanHandleCycleUser();
case TOGGLE_CAPS_LOCK:
return CanHandleToggleCapsLock(accelerator, previous_accelerator);
case TOGGLE_TOUCH_VIEW_TESTING:
return CanHandleToggleTouchViewTesting();
case TOUCH_HUD_CLEAR:
case TOUCH_HUD_MODE_CHANGE:
return CanHandleTouchHud();
#endif
case CYCLE_BACKWARD_MRU:
case CYCLE_FORWARD_MRU:
case EXIT:
case FOCUS_NEXT_PANE:
case FOCUS_PREVIOUS_PANE:
case FOCUS_SHELF:
case LAUNCH_APP_0:
case LAUNCH_APP_1:
case LAUNCH_APP_2:
case LAUNCH_APP_3:
case LAUNCH_APP_4:
case LAUNCH_APP_5:
case LAUNCH_APP_6:
case LAUNCH_APP_7:
case LAUNCH_LAST_APP:
case MEDIA_NEXT_TRACK:
case MEDIA_PLAY_PAUSE:
case MEDIA_PREV_TRACK:
case NEW_TAB:
case NEW_WINDOW:
case OPEN_FEEDBACK_PAGE:
case PRINT_UI_HIERARCHIES:
case RESTORE_TAB:
case ROTATE_SCREEN:
case ROTATE_WINDOW:
case SHOW_KEYBOARD_OVERLAY:
case SHOW_SYSTEM_TRAY_BUBBLE:
case SHOW_TASK_MANAGER:
case TAKE_PARTIAL_SCREENSHOT:
case TAKE_SCREENSHOT:
case TOGGLE_FULLSCREEN:
case TOGGLE_MAXIMIZED:
case TOGGLE_OVERVIEW:
case WINDOW_MINIMIZE:
#if defined(OS_CHROMEOS)
case BRIGHTNESS_DOWN:
case BRIGHTNESS_UP:
case DISABLE_GPU_WATCHDOG:
case KEYBOARD_BRIGHTNESS_DOWN:
case KEYBOARD_BRIGHTNESS_UP:
case LOCK_PRESSED:
case LOCK_RELEASED:
case LOCK_SCREEN:
case OPEN_CROSH:
case OPEN_FILE_MANAGER:
case OPEN_GET_HELP:
case POWER_PRESSED:
case POWER_RELEASED:
case SWAP_PRIMARY_DISPLAY:
case TOGGLE_MIRROR_MODE:
case TOGGLE_SPOKEN_FEEDBACK:
case TOGGLE_WIFI:
case TOUCH_HUD_PROJECTION_TOGGLE:
case VOLUME_DOWN:
case VOLUME_MUTE:
case VOLUME_UP:
#else
case DUMMY_FOR_RESERVED:
#endif
return true;
}
return false;
}
void AcceleratorController::PerformAction(AcceleratorAction action,
const ui::Accelerator& accelerator) {
AcceleratorProcessingRestriction restriction =
GetAcceleratorProcessingRestriction(action);
if (restriction != RESTRICTION_NONE)
return;
// If your accelerator invokes more than one line of code, please either
// implement it in your module's controller code (like TOGGLE_MIRROR_MODE
// below) or pull it into a HandleFoo() function above.
switch (action) {
case CYCLE_BACKWARD_MRU:
HandleCycleBackwardMRU(accelerator);
break;
case CYCLE_FORWARD_MRU:
HandleCycleForwardMRU(accelerator);
break;
case DEBUG_PRINT_LAYER_HIERARCHY:
case DEBUG_PRINT_VIEW_HIERARCHY:
case DEBUG_PRINT_WINDOW_HIERARCHY:
case DEBUG_TOGGLE_DESKTOP_BACKGROUND_MODE:
case DEBUG_TOGGLE_DEVICE_SCALE_FACTOR:
case DEBUG_TOGGLE_ROOT_WINDOW_FULL_SCREEN:
case DEBUG_TOGGLE_SHOW_DEBUG_BORDERS:
case DEBUG_TOGGLE_SHOW_FPS_COUNTER:
case DEBUG_TOGGLE_SHOW_PAINT_RECTS:
debug::PerformDebugActionIfEnabled(action);
break;
case EXIT:
// UMA metrics are recorded in the handler.
exit_warning_handler_.HandleAccelerator();
break;
case FOCUS_NEXT_PANE:
HandleRotatePaneFocus(Shell::FORWARD);
break;
case FOCUS_PREVIOUS_PANE:
HandleRotatePaneFocus(Shell::BACKWARD);
break;
case FOCUS_SHELF:
HandleFocusShelf();
break;
case LAUNCH_APP_0:
HandleLaunchAppN(0);
break;
case LAUNCH_APP_1:
HandleLaunchAppN(1);
break;
case LAUNCH_APP_2:
HandleLaunchAppN(2);
break;
case LAUNCH_APP_3:
HandleLaunchAppN(3);
break;
case LAUNCH_APP_4:
HandleLaunchAppN(4);
break;
case LAUNCH_APP_5:
HandleLaunchAppN(5);
break;
case LAUNCH_APP_6:
HandleLaunchAppN(6);
break;
case LAUNCH_APP_7:
HandleLaunchAppN(7);
break;
case LAUNCH_LAST_APP:
HandleLaunchLastApp();
break;
case MAGNIFY_SCREEN_ZOOM_IN:
HandleMagnifyScreen(1);
break;
case MAGNIFY_SCREEN_ZOOM_OUT:
HandleMagnifyScreen(-1);
break;
case MEDIA_NEXT_TRACK:
HandleMediaNextTrack();
break;
case MEDIA_PLAY_PAUSE:
HandleMediaPlayPause();
break;
case MEDIA_PREV_TRACK:
HandleMediaPrevTrack();
break;
case NEW_INCOGNITO_WINDOW:
HandleNewIncognitoWindow();
break;
case NEW_TAB:
HandleNewTab(accelerator);
break;
case NEW_WINDOW:
HandleNewWindow();
break;
case NEXT_IME:
HandleNextIme(ime_control_delegate_.get());
break;
case OPEN_FEEDBACK_PAGE:
HandleOpenFeedbackPage();
break;
case PREVIOUS_IME:
HandlePreviousIme(ime_control_delegate_.get(), accelerator);
break;
case PRINT_UI_HIERARCHIES:
debug::PrintUIHierarchies();
break;
case RESTORE_TAB:
HandleRestoreTab();
break;
case ROTATE_SCREEN:
HandleRotateScreen();
break;
case ROTATE_WINDOW:
HandleRotateActiveWindow();
break;
case SCALE_UI_DOWN:
HandleScaleUI(false /* down */);
break;
case SCALE_UI_RESET:
HandleScaleReset();
break;
case SCALE_UI_UP:
HandleScaleUI(true /* up */);
break;
case SHOW_KEYBOARD_OVERLAY:
HandleShowKeyboardOverlay();
break;
case SHOW_MESSAGE_CENTER_BUBBLE:
HandleShowMessageCenterBubble();
break;
case SHOW_SYSTEM_TRAY_BUBBLE:
HandleShowSystemTrayBubble();
break;
case SHOW_TASK_MANAGER:
HandleShowTaskManager();
break;
case SWITCH_IME:
HandleSwitchIme(ime_control_delegate_.get(), accelerator);
break;
case TAKE_PARTIAL_SCREENSHOT:
HandleTakePartialScreenshot(screenshot_delegate_.get());
break;
case TAKE_SCREENSHOT:
HandleTakeScreenshot(screenshot_delegate_.get());
break;
case TOGGLE_APP_LIST:
HandleToggleAppList(accelerator);
break;
case TOGGLE_FULLSCREEN:
HandleToggleFullscreen(accelerator);
break;
case TOGGLE_MAXIMIZED:
accelerators::ToggleMaximized();
break;
case TOGGLE_OVERVIEW:
HandleToggleOverview();
break;
case WINDOW_CYCLE_SNAP_DOCK_LEFT:
case WINDOW_CYCLE_SNAP_DOCK_RIGHT:
HandleWindowSnapOrDock(action);
break;
case WINDOW_MINIMIZE:
HandleWindowMinimize();
break;
case WINDOW_POSITION_CENTER:
HandlePositionCenter();
break;
#if defined(OS_CHROMEOS)
case BRIGHTNESS_DOWN:
HandleBrightnessDown(brightness_control_delegate_.get(), accelerator);
break;
case BRIGHTNESS_UP:
HandleBrightnessUp(brightness_control_delegate_.get(), accelerator);
break;
case DEBUG_ADD_REMOVE_DISPLAY:
debug::PerformDebugActionIfEnabled(action);
break;
case DISABLE_CAPS_LOCK:
HandleDisableCapsLock();
break;
case DISABLE_GPU_WATCHDOG:
Shell::GetInstance()->gpu_support()->DisableGpuWatchdog();
break;
case KEYBOARD_BRIGHTNESS_DOWN:
HandleKeyboardBrightnessDown(keyboard_brightness_control_delegate_.get(),
accelerator);
break;
case KEYBOARD_BRIGHTNESS_UP:
HandleKeyboardBrightnessUp(keyboard_brightness_control_delegate_.get(),
accelerator);
break;
case LOCK_PRESSED:
case LOCK_RELEASED:
Shell::GetInstance()->power_button_controller()->
OnLockButtonEvent(action == LOCK_PRESSED, base::TimeTicks());
break;
case LOCK_SCREEN:
HandleLock();
break;
case OPEN_CROSH:
HandleCrosh();
break;
case OPEN_FILE_MANAGER:
HandleFileManager();
break;
case OPEN_GET_HELP:
HandleGetHelp();
break;
case POWER_PRESSED: // fallthrough
case POWER_RELEASED:
if (!base::SysInfo::IsRunningOnChromeOS()) {
// There is no powerd, the Chrome OS power manager, in linux desktop,
// so call the PowerButtonController here.
Shell::GetInstance()->power_button_controller()->
OnPowerButtonEvent(action == POWER_PRESSED, base::TimeTicks());
}
// We don't do anything with these at present on the device,
// (power button events are reported to us from powerm via
// D-BUS), but we consume them to prevent them from getting
// passed to apps -- see http://crbug.com/146609.
break;
case SILENCE_SPOKEN_FEEDBACK:
HandleSilenceSpokenFeedback();
break;
case SWAP_PRIMARY_DISPLAY:
HandleSwapPrimaryDisplay();
break;
case SWITCH_TO_NEXT_USER:
HandleCycleUser(SessionStateDelegate::CYCLE_TO_NEXT_USER);
break;
case SWITCH_TO_PREVIOUS_USER:
HandleCycleUser(SessionStateDelegate::CYCLE_TO_PREVIOUS_USER);
break;
case TOGGLE_CAPS_LOCK:
HandleToggleCapsLock();
break;
case TOGGLE_MIRROR_MODE:
HandleToggleMirrorMode();
break;
case TOGGLE_SPOKEN_FEEDBACK:
HandleToggleSpokenFeedback();
break;
case TOGGLE_TOUCH_VIEW_TESTING:
HandleToggleTouchViewTesting();
break;
case TOGGLE_WIFI:
Shell::GetInstance()->system_tray_notifier()->NotifyRequestToggleWifi();
break;
case TOUCH_HUD_CLEAR:
HandleTouchHudClear();
break;
case TOUCH_HUD_MODE_CHANGE:
HandleTouchHudModeChange();
break;
case TOUCH_HUD_PROJECTION_TOGGLE:
accelerators::ToggleTouchHudProjection();
break;
case VOLUME_DOWN:
HandleVolumeDown(accelerator);
break;
case VOLUME_MUTE:
HandleVolumeMute(accelerator);
break;
case VOLUME_UP:
HandleVolumeUp(accelerator);
break;
#else
case DUMMY_FOR_RESERVED:
NOTREACHED();
break;
#endif
}
}
bool AcceleratorController::ShouldActionConsumeKeyEvent(
AcceleratorAction action) {
#if defined(OS_CHROMEOS)
if (action == SILENCE_SPOKEN_FEEDBACK)
return false;
#endif
// Adding new exceptions is *STRONGLY* discouraged.
return true;
}
AcceleratorController::AcceleratorProcessingRestriction
AcceleratorController::GetAcceleratorProcessingRestriction(int action) {
ash::Shell* shell = ash::Shell::GetInstance();
if (!shell->session_state_delegate()->IsActiveUserSessionStarted() &&
actions_allowed_at_login_screen_.find(action) ==
actions_allowed_at_login_screen_.end()) {
return RESTRICTION_PREVENT_PROCESSING;
}
if (shell->session_state_delegate()->IsScreenLocked() &&
actions_allowed_at_lock_screen_.find(action) ==
actions_allowed_at_lock_screen_.end()) {
return RESTRICTION_PREVENT_PROCESSING;
}
if (shell->delegate()->IsRunningInForcedAppMode() &&
actions_allowed_in_app_mode_.find(action) ==
actions_allowed_in_app_mode_.end()) {
return RESTRICTION_PREVENT_PROCESSING;
}
if (shell->IsSystemModalWindowOpen() &&
actions_allowed_at_modal_window_.find(action) ==
actions_allowed_at_modal_window_.end()) {
// Note we prevent the shortcut from propagating so it will not
// be passed to the modal window. This is important for things like
// Alt+Tab that would cause an undesired effect in the modal window by
// cycling through its window elements.
return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION;
}
if (shell->mru_window_tracker()->BuildMruWindowList().empty() &&
actions_needing_window_.find(action) != actions_needing_window_.end()) {
Shell::GetInstance()->accessibility_delegate()->TriggerAccessibilityAlert(
ui::A11Y_ALERT_WINDOW_NEEDED);
return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION;
}
return RESTRICTION_NONE;
}
void AcceleratorController::SetKeyboardBrightnessControlDelegate(
scoped_ptr<KeyboardBrightnessControlDelegate>
keyboard_brightness_control_delegate) {
keyboard_brightness_control_delegate_ =
keyboard_brightness_control_delegate.Pass();
}
} // namespace ash