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