OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ash/common/accelerators/accelerator_controller.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "ash/common/accelerators/accelerator_commands.h" | |
10 #include "ash/common/accelerators/accelerator_controller_delegate.h" | |
11 #include "ash/common/accelerators/debug_commands.h" | |
12 #include "ash/common/accessibility_delegate.h" | |
13 #include "ash/common/accessibility_types.h" | |
14 #include "ash/common/focus_cycler.h" | |
15 #include "ash/common/ime_control_delegate.h" | |
16 #include "ash/common/media_controller.h" | |
17 #include "ash/common/multi_profile_uma.h" | |
18 #include "ash/common/new_window_controller.h" | |
19 #include "ash/common/palette_delegate.h" | |
20 #include "ash/common/session/session_state_delegate.h" | |
21 #include "ash/common/shelf/shelf_widget.h" | |
22 #include "ash/common/shelf/wm_shelf.h" | |
23 #include "ash/common/shell_delegate.h" | |
24 #include "ash/common/wm/mru_window_tracker.h" | |
25 #include "ash/common/wm/overview/window_selector_controller.h" | |
26 #include "ash/common/wm/window_cycle_controller.h" | |
27 #include "ash/common/wm/window_positioning_utils.h" | |
28 #include "ash/common/wm/window_state.h" | |
29 #include "ash/common/wm/wm_event.h" | |
30 #include "ash/common/wm_shell.h" | |
31 #include "ash/common/wm_window.h" | |
32 #include "ash/resources/vector_icons/vector_icons.h" | |
33 #include "ash/root_window_controller.h" | |
34 #include "ash/strings/grit/ash_strings.h" | |
35 #include "ash/system/brightness_control_delegate.h" | |
36 #include "ash/system/ime_menu/ime_menu_tray.h" | |
37 #include "ash/system/keyboard_brightness_control_delegate.h" | |
38 #include "ash/system/palette/palette_tray.h" | |
39 #include "ash/system/palette/palette_utils.h" | |
40 #include "ash/system/status_area_widget.h" | |
41 #include "ash/system/system_notifier.h" | |
42 #include "ash/system/tray/system_tray_delegate.h" | |
43 #include "ash/system/tray/system_tray_notifier.h" | |
44 #include "ash/system/web_notification/web_notification_tray.h" | |
45 #include "base/metrics/histogram_macros.h" | |
46 #include "base/metrics/user_metrics.h" | |
47 #include "chromeos/dbus/dbus_thread_manager.h" | |
48 #include "chromeos/dbus/power_manager_client.h" | |
49 #include "ui/base/accelerators/accelerator.h" | |
50 #include "ui/base/accelerators/accelerator_manager.h" | |
51 #include "ui/base/ime/chromeos/ime_keyboard.h" | |
52 #include "ui/base/ime/chromeos/input_method_manager.h" | |
53 #include "ui/base/l10n/l10n_util.h" | |
54 #include "ui/gfx/paint_vector_icon.h" | |
55 #include "ui/keyboard/keyboard_controller.h" | |
56 #include "ui/message_center/message_center.h" | |
57 | |
58 namespace ash { | |
59 namespace { | |
60 | |
61 using base::UserMetricsAction; | |
62 using message_center::Notification; | |
63 | |
64 // Identifier for the high contrast toggle accelerator notification. | |
65 const char kHighContrastToggleAccelNotificationId[] = | |
66 "chrome://settings/accessibility/highcontrast"; | |
67 | |
68 ui::Accelerator CreateAccelerator(ui::KeyboardCode keycode, | |
69 int modifiers, | |
70 bool trigger_on_press) { | |
71 ui::Accelerator accelerator(keycode, modifiers); | |
72 accelerator.set_type(trigger_on_press ? ui::ET_KEY_PRESSED | |
73 : ui::ET_KEY_RELEASED); | |
74 return accelerator; | |
75 } | |
76 | |
77 void RecordUmaHistogram(const char* histogram_name, | |
78 DeprecatedAcceleratorUsage sample) { | |
79 auto* histogram = base::LinearHistogram::FactoryGet( | |
80 histogram_name, 1, DEPRECATED_USAGE_COUNT, DEPRECATED_USAGE_COUNT + 1, | |
81 base::HistogramBase::kUmaTargetedHistogramFlag); | |
82 histogram->Add(sample); | |
83 } | |
84 | |
85 void HandleCycleBackwardMRU(const ui::Accelerator& accelerator) { | |
86 if (accelerator.key_code() == ui::VKEY_TAB) | |
87 base::RecordAction(base::UserMetricsAction("Accel_PrevWindow_Tab")); | |
88 | |
89 WmShell::Get()->window_cycle_controller()->HandleCycleWindow( | |
90 WindowCycleController::BACKWARD); | |
91 } | |
92 | |
93 void HandleCycleForwardMRU(const ui::Accelerator& accelerator) { | |
94 if (accelerator.key_code() == ui::VKEY_TAB) | |
95 base::RecordAction(base::UserMetricsAction("Accel_NextWindow_Tab")); | |
96 | |
97 WmShell::Get()->window_cycle_controller()->HandleCycleWindow( | |
98 WindowCycleController::FORWARD); | |
99 } | |
100 | |
101 void HandleRotatePaneFocus(FocusCycler::Direction direction) { | |
102 switch (direction) { | |
103 // TODO(stevet): Not sure if this is the same as IDC_FOCUS_NEXT_PANE. | |
104 case FocusCycler::FORWARD: { | |
105 base::RecordAction(UserMetricsAction("Accel_Focus_Next_Pane")); | |
106 break; | |
107 } | |
108 case FocusCycler::BACKWARD: { | |
109 base::RecordAction(UserMetricsAction("Accel_Focus_Previous_Pane")); | |
110 break; | |
111 } | |
112 } | |
113 WmShell::Get()->focus_cycler()->RotateFocus(direction); | |
114 } | |
115 | |
116 void HandleFocusShelf() { | |
117 base::RecordAction(UserMetricsAction("Accel_Focus_Shelf")); | |
118 // TODO(jamescook): Should this be GetRootWindowForNewWindows()? | |
119 WmShelf* shelf = WmShelf::ForWindow(WmShell::Get()->GetPrimaryRootWindow()); | |
120 WmShell::Get()->focus_cycler()->FocusWidget(shelf->shelf_widget()); | |
121 } | |
122 | |
123 void HandleLaunchAppN(int n) { | |
124 base::RecordAction(UserMetricsAction("Accel_Launch_App")); | |
125 WmShelf::LaunchShelfItem(n); | |
126 } | |
127 | |
128 void HandleLaunchLastApp() { | |
129 base::RecordAction(UserMetricsAction("Accel_Launch_Last_App")); | |
130 WmShelf::LaunchShelfItem(-1); | |
131 } | |
132 | |
133 void HandleMediaNextTrack() { | |
134 WmShell::Get()->media_controller()->HandleMediaNextTrack(); | |
135 } | |
136 | |
137 void HandleMediaPlayPause() { | |
138 WmShell::Get()->media_controller()->HandleMediaPlayPause(); | |
139 } | |
140 | |
141 void HandleMediaPrevTrack() { | |
142 WmShell::Get()->media_controller()->HandleMediaPrevTrack(); | |
143 } | |
144 | |
145 bool CanHandleNewIncognitoWindow() { | |
146 return WmShell::Get()->delegate()->IsIncognitoAllowed(); | |
147 } | |
148 | |
149 void HandleNewIncognitoWindow() { | |
150 base::RecordAction(UserMetricsAction("Accel_New_Incognito_Window")); | |
151 WmShell::Get()->new_window_controller()->NewWindow(true /* is_incognito */); | |
152 } | |
153 | |
154 void HandleNewTab(const ui::Accelerator& accelerator) { | |
155 if (accelerator.key_code() == ui::VKEY_T) | |
156 base::RecordAction(UserMetricsAction("Accel_NewTab_T")); | |
157 WmShell::Get()->new_window_controller()->NewTab(); | |
158 } | |
159 | |
160 void HandleNewWindow() { | |
161 base::RecordAction(UserMetricsAction("Accel_New_Window")); | |
162 WmShell::Get()->new_window_controller()->NewWindow(false /* is_incognito */); | |
163 } | |
164 | |
165 bool CanHandleNextIme(ImeControlDelegate* ime_control_delegate) { | |
166 return ime_control_delegate && ime_control_delegate->CanCycleIme(); | |
167 } | |
168 | |
169 bool CanHandleCycleMru(const ui::Accelerator& accelerator) { | |
170 // Don't do anything when Alt+Tab is hit while a virtual keyboard is showing. | |
171 // Touchscreen users have better window switching options. It would be | |
172 // preferable if we could tell whether this event actually came from a virtual | |
173 // keyboard, but there's no easy way to do so, thus we block Alt+Tab when the | |
174 // virtual keyboard is showing, even if it came from a real keyboard. See | |
175 // http://crbug.com/638269 | |
176 keyboard::KeyboardController* keyboard_controller = | |
177 keyboard::KeyboardController::GetInstance(); | |
178 return !(keyboard_controller && keyboard_controller->keyboard_visible()); | |
179 } | |
180 | |
181 void HandleNextIme(ImeControlDelegate* ime_control_delegate) { | |
182 base::RecordAction(UserMetricsAction("Accel_Next_Ime")); | |
183 ime_control_delegate->HandleNextIme(); | |
184 } | |
185 | |
186 void HandleOpenFeedbackPage() { | |
187 base::RecordAction(UserMetricsAction("Accel_Open_Feedback_Page")); | |
188 WmShell::Get()->new_window_controller()->OpenFeedbackPage(); | |
189 } | |
190 | |
191 bool CanHandlePreviousIme(ImeControlDelegate* ime_control_delegate) { | |
192 return ime_control_delegate && ime_control_delegate->CanCycleIme(); | |
193 } | |
194 | |
195 void HandlePreviousIme(ImeControlDelegate* ime_control_delegate, | |
196 const ui::Accelerator& accelerator) { | |
197 base::RecordAction(UserMetricsAction("Accel_Previous_Ime")); | |
198 if (accelerator.type() == ui::ET_KEY_PRESSED) | |
199 ime_control_delegate->HandlePreviousIme(); | |
200 // Else: consume the Ctrl+Space ET_KEY_RELEASED event but do not do anything. | |
201 } | |
202 | |
203 void HandleRestoreTab() { | |
204 base::RecordAction(UserMetricsAction("Accel_Restore_Tab")); | |
205 WmShell::Get()->new_window_controller()->RestoreTab(); | |
206 } | |
207 | |
208 void HandleShowKeyboardOverlay() { | |
209 base::RecordAction(UserMetricsAction("Accel_Show_Keyboard_Overlay")); | |
210 WmShell::Get()->new_window_controller()->ShowKeyboardOverlay(); | |
211 } | |
212 | |
213 bool CanHandleShowMessageCenterBubble() { | |
214 WmWindow* target_root = WmShell::Get()->GetRootWindowForNewWindows(); | |
215 StatusAreaWidget* status_area_widget = | |
216 WmShelf::ForWindow(target_root)->shelf_widget()->status_area_widget(); | |
217 return status_area_widget && | |
218 status_area_widget->web_notification_tray()->visible(); | |
219 } | |
220 | |
221 void HandleShowMessageCenterBubble() { | |
222 base::RecordAction(UserMetricsAction("Accel_Show_Message_Center_Bubble")); | |
223 WmWindow* target_root = WmShell::Get()->GetRootWindowForNewWindows(); | |
224 StatusAreaWidget* status_area_widget = | |
225 WmShelf::ForWindow(target_root)->shelf_widget()->status_area_widget(); | |
226 if (status_area_widget) { | |
227 WebNotificationTray* notification_tray = | |
228 status_area_widget->web_notification_tray(); | |
229 if (notification_tray->visible()) | |
230 notification_tray->ShowMessageCenterBubble(); | |
231 } | |
232 } | |
233 | |
234 void HandleShowTaskManager() { | |
235 base::RecordAction(UserMetricsAction("Accel_Show_Task_Manager")); | |
236 WmShell::Get()->new_window_controller()->ShowTaskManager(); | |
237 } | |
238 | |
239 bool CanHandleSwitchIme(ImeControlDelegate* ime_control_delegate, | |
240 const ui::Accelerator& accelerator) { | |
241 return ime_control_delegate && | |
242 ime_control_delegate->CanSwitchIme(accelerator); | |
243 } | |
244 | |
245 void HandleSwitchIme(ImeControlDelegate* ime_control_delegate, | |
246 const ui::Accelerator& accelerator) { | |
247 base::RecordAction(UserMetricsAction("Accel_Switch_Ime")); | |
248 ime_control_delegate->HandleSwitchIme(accelerator); | |
249 } | |
250 | |
251 bool CanHandleToggleAppList(const ui::Accelerator& accelerator, | |
252 const ui::Accelerator& previous_accelerator) { | |
253 if (accelerator.key_code() == ui::VKEY_LWIN) { | |
254 // If something else was pressed between the Search key (LWIN) | |
255 // being pressed and released, then ignore the release of the | |
256 // Search key. | |
257 if (previous_accelerator.type() != ui::ET_KEY_PRESSED || | |
258 previous_accelerator.key_code() != ui::VKEY_LWIN) { | |
259 return false; | |
260 } | |
261 | |
262 // When spoken feedback is enabled, we should neither toggle the list nor | |
263 // consume the key since Search+Shift is one of the shortcuts the a11y | |
264 // feature uses. crbug.com/132296 | |
265 if (WmShell::Get()->accessibility_delegate()->IsSpokenFeedbackEnabled()) | |
266 return false; | |
267 } | |
268 return true; | |
269 } | |
270 | |
271 void HandleToggleAppList(const ui::Accelerator& accelerator) { | |
272 if (accelerator.key_code() == ui::VKEY_LWIN) | |
273 base::RecordAction(UserMetricsAction("Accel_Search_LWin")); | |
274 WmShell::Get()->ToggleAppList(); | |
275 } | |
276 | |
277 void HandleToggleFullscreen(const ui::Accelerator& accelerator) { | |
278 if (accelerator.key_code() == ui::VKEY_MEDIA_LAUNCH_APP2) | |
279 base::RecordAction(UserMetricsAction("Accel_Fullscreen_F4")); | |
280 accelerators::ToggleFullscreen(); | |
281 } | |
282 | |
283 void HandleToggleOverview() { | |
284 base::RecordAction(base::UserMetricsAction("Accel_Overview_F5")); | |
285 WmShell::Get()->window_selector_controller()->ToggleOverview(); | |
286 } | |
287 | |
288 bool CanHandleWindowSnapOrDock() { | |
289 WmWindow* active_window = WmShell::Get()->GetActiveWindow(); | |
290 if (!active_window) | |
291 return false; | |
292 wm::WindowState* window_state = active_window->GetWindowState(); | |
293 // Disable window snapping shortcut key for full screen window due to | |
294 // http://crbug.com/135487. | |
295 return (window_state && window_state->IsUserPositionable() && | |
296 !window_state->IsFullscreen()); | |
297 } | |
298 | |
299 void HandleWindowSnapOrDock(AcceleratorAction action) { | |
300 if (action == WINDOW_CYCLE_SNAP_DOCK_LEFT) | |
301 base::RecordAction(UserMetricsAction("Accel_Window_Snap_Left")); | |
302 else | |
303 base::RecordAction(UserMetricsAction("Accel_Window_Snap_Right")); | |
304 | |
305 const wm::WMEvent event(action == WINDOW_CYCLE_SNAP_DOCK_LEFT | |
306 ? wm::WM_EVENT_CYCLE_SNAP_DOCK_LEFT | |
307 : wm::WM_EVENT_CYCLE_SNAP_DOCK_RIGHT); | |
308 WmWindow* active_window = WmShell::Get()->GetActiveWindow(); | |
309 DCHECK(active_window); | |
310 active_window->GetWindowState()->OnWMEvent(&event); | |
311 } | |
312 | |
313 void HandleWindowMinimize() { | |
314 base::RecordAction(base::UserMetricsAction("Accel_Toggle_Minimized_Minus")); | |
315 accelerators::ToggleMinimized(); | |
316 } | |
317 | |
318 bool CanHandlePositionCenter() { | |
319 // Docked windows do not support centering. | |
320 WmWindow* active_window = WmShell::Get()->GetActiveWindow(); | |
321 return (active_window && !active_window->GetWindowState()->IsDocked()); | |
322 } | |
323 | |
324 void HandlePositionCenter() { | |
325 base::RecordAction(UserMetricsAction("Accel_Window_Position_Center")); | |
326 wm::CenterWindow(WmShell::Get()->GetActiveWindow()); | |
327 } | |
328 | |
329 void HandleShowImeMenuBubble() { | |
330 base::RecordAction(UserMetricsAction("Accel_Show_Ime_Menu_Bubble")); | |
331 | |
332 StatusAreaWidget* status_area_widget = | |
333 WmShelf::ForWindow(WmShell::Get()->GetPrimaryRootWindow()) | |
334 ->GetStatusAreaWidget(); | |
335 if (status_area_widget) { | |
336 ImeMenuTray* ime_menu_tray = status_area_widget->ime_menu_tray(); | |
337 if (ime_menu_tray && ime_menu_tray->visible() && | |
338 !ime_menu_tray->IsImeMenuBubbleShown()) { | |
339 ime_menu_tray->ShowImeMenuBubble(); | |
340 } | |
341 } | |
342 } | |
343 | |
344 void HandleCrosh() { | |
345 base::RecordAction(UserMetricsAction("Accel_Open_Crosh")); | |
346 | |
347 WmShell::Get()->new_window_controller()->OpenCrosh(); | |
348 } | |
349 | |
350 bool CanHandleDisableCapsLock(const ui::Accelerator& previous_accelerator) { | |
351 ui::KeyboardCode previous_key_code = previous_accelerator.key_code(); | |
352 if (previous_accelerator.type() == ui::ET_KEY_RELEASED || | |
353 (previous_key_code != ui::VKEY_LSHIFT && | |
354 previous_key_code != ui::VKEY_SHIFT && | |
355 previous_key_code != ui::VKEY_RSHIFT)) { | |
356 // If something else was pressed between the Shift key being pressed | |
357 // and released, then ignore the release of the Shift key. | |
358 return false; | |
359 } | |
360 chromeos::input_method::InputMethodManager* ime = | |
361 chromeos::input_method::InputMethodManager::Get(); | |
362 chromeos::input_method::ImeKeyboard* keyboard = | |
363 ime ? ime->GetImeKeyboard() : NULL; | |
364 return (keyboard && keyboard->CapsLockIsEnabled()); | |
365 } | |
366 | |
367 void HandleDisableCapsLock() { | |
368 base::RecordAction(UserMetricsAction("Accel_Disable_Caps_Lock")); | |
369 chromeos::input_method::InputMethodManager* ime = | |
370 chromeos::input_method::InputMethodManager::Get(); | |
371 ime->GetImeKeyboard()->SetCapsLockEnabled(false); | |
372 } | |
373 | |
374 void HandleFileManager() { | |
375 base::RecordAction(UserMetricsAction("Accel_Open_File_Manager")); | |
376 | |
377 WmShell::Get()->new_window_controller()->OpenFileManager(); | |
378 } | |
379 | |
380 void HandleGetHelp() { | |
381 WmShell::Get()->new_window_controller()->OpenGetHelp(); | |
382 } | |
383 | |
384 bool CanHandleLock() { | |
385 return WmShell::Get()->GetSessionStateDelegate()->CanLockScreen(); | |
386 } | |
387 | |
388 void HandleLock() { | |
389 base::RecordAction(UserMetricsAction("Accel_LockScreen_L")); | |
390 WmShell::Get()->GetSessionStateDelegate()->LockScreen(); | |
391 } | |
392 | |
393 void HandleShowStylusTools() { | |
394 base::RecordAction(UserMetricsAction("Accel_Show_Stylus_Tools")); | |
395 | |
396 RootWindowController* root_window_controller = | |
397 WmShell::Get()->GetRootWindowForNewWindows()->GetRootWindowController(); | |
398 PaletteTray* palette_tray = | |
399 root_window_controller->GetShelf()->GetStatusAreaWidget()->palette_tray(); | |
400 palette_tray->ShowPalette(); | |
401 } | |
402 | |
403 bool CanHandleShowStylusTools() { | |
404 return WmShell::Get()->palette_delegate() && | |
405 WmShell::Get()->palette_delegate()->ShouldShowPalette(); | |
406 } | |
407 | |
408 void HandleSuspend() { | |
409 base::RecordAction(UserMetricsAction("Accel_Suspend")); | |
410 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestSuspend(); | |
411 } | |
412 | |
413 bool CanHandleCycleUser() { | |
414 return WmShell::Get()->delegate()->IsMultiProfilesEnabled() && | |
415 WmShell::Get()->GetSessionStateDelegate()->NumberOfLoggedInUsers() > 1; | |
416 } | |
417 | |
418 void HandleCycleUser(CycleUserDirection direction) { | |
419 MultiProfileUMA::RecordSwitchActiveUser( | |
420 MultiProfileUMA::SWITCH_ACTIVE_USER_BY_ACCELERATOR); | |
421 switch (direction) { | |
422 case CycleUserDirection::NEXT: | |
423 base::RecordAction(UserMetricsAction("Accel_Switch_To_Next_User")); | |
424 break; | |
425 case CycleUserDirection::PREVIOUS: | |
426 base::RecordAction(UserMetricsAction("Accel_Switch_To_Previous_User")); | |
427 break; | |
428 } | |
429 WmShell::Get()->GetSessionStateDelegate()->CycleActiveUser(direction); | |
430 } | |
431 | |
432 bool CanHandleToggleCapsLock(const ui::Accelerator& accelerator, | |
433 const ui::Accelerator& previous_accelerator) { | |
434 chromeos::input_method::InputMethodManager* ime = | |
435 chromeos::input_method::InputMethodManager::Get(); | |
436 | |
437 // This shortcust is set to be trigger on release. Either the current | |
438 // accelerator is a Search release or Alt release. | |
439 if (accelerator.key_code() == ui::VKEY_LWIN && | |
440 accelerator.type() == ui::ET_KEY_RELEASED) { | |
441 // The previous must be either an Alt press or Search press: | |
442 // 1. Press Alt, Press Search, Release Search, Release Alt. | |
443 // 2. Press Search, Press Alt, Release Search, Release Alt. | |
444 if (previous_accelerator.type() == ui::ET_KEY_PRESSED && | |
445 (previous_accelerator.key_code() == ui::VKEY_LWIN || | |
446 previous_accelerator.key_code() == ui::VKEY_MENU)) { | |
447 return ime && ime->GetImeKeyboard(); | |
448 } | |
449 } | |
450 | |
451 // Alt release. | |
452 if (accelerator.key_code() == ui::VKEY_MENU && | |
453 accelerator.type() == ui::ET_KEY_RELEASED) { | |
454 // The previous must be either an Alt press or Search press: | |
455 // 3. Press Alt, Press Search, Release Alt, Release Search. | |
456 // 4. Press Search, Press Alt, Release Alt, Release Search. | |
457 if (previous_accelerator.type() == ui::ET_KEY_PRESSED && | |
458 (previous_accelerator.key_code() == ui::VKEY_LWIN || | |
459 previous_accelerator.key_code() == ui::VKEY_MENU)) { | |
460 return ime && ime->GetImeKeyboard(); | |
461 } | |
462 } | |
463 | |
464 return false; | |
465 } | |
466 | |
467 void HandleToggleCapsLock() { | |
468 base::RecordAction(UserMetricsAction("Accel_Toggle_Caps_Lock")); | |
469 chromeos::input_method::InputMethodManager* ime = | |
470 chromeos::input_method::InputMethodManager::Get(); | |
471 chromeos::input_method::ImeKeyboard* keyboard = ime->GetImeKeyboard(); | |
472 keyboard->SetCapsLockEnabled(!keyboard->CapsLockIsEnabled()); | |
473 } | |
474 | |
475 void HandleToggleHighContrast() { | |
476 base::RecordAction(UserMetricsAction("Accel_Toggle_High_Contrast")); | |
477 | |
478 // Show a notification so the user knows that this accelerator toggled | |
479 // high contrast mode, and that they can press it again to toggle back. | |
480 // The message center automatically only shows this once per session. | |
481 std::unique_ptr<Notification> notification(new Notification( | |
482 message_center::NOTIFICATION_TYPE_SIMPLE, | |
483 kHighContrastToggleAccelNotificationId, base::string16() /* title */, | |
484 l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_ACCEL_MSG), | |
485 gfx::Image(CreateVectorIcon(kSystemMenuAccessibilityIcon, SK_ColorBLACK)), | |
486 base::string16() /* display source */, GURL(), | |
487 message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, | |
488 system_notifier::kNotifierAccessibility), | |
489 message_center::RichNotificationData(), nullptr)); | |
490 message_center::MessageCenter::Get()->AddNotification( | |
491 std::move(notification)); | |
492 | |
493 WmShell::Get()->accessibility_delegate()->ToggleHighContrast(); | |
494 } | |
495 | |
496 void HandleToggleSpokenFeedback() { | |
497 base::RecordAction(UserMetricsAction("Accel_Toggle_Spoken_Feedback")); | |
498 | |
499 WmShell::Get()->accessibility_delegate()->ToggleSpokenFeedback( | |
500 A11Y_NOTIFICATION_SHOW); | |
501 } | |
502 | |
503 void HandleVolumeDown(mojom::VolumeController* volume_controller, | |
504 const ui::Accelerator& accelerator) { | |
505 if (accelerator.key_code() == ui::VKEY_VOLUME_DOWN) | |
506 base::RecordAction(UserMetricsAction("Accel_VolumeDown_F9")); | |
507 | |
508 if (volume_controller) | |
509 volume_controller->VolumeDown(); | |
510 } | |
511 | |
512 void HandleVolumeMute(mojom::VolumeController* volume_controller, | |
513 const ui::Accelerator& accelerator) { | |
514 if (accelerator.key_code() == ui::VKEY_VOLUME_MUTE) | |
515 base::RecordAction(UserMetricsAction("Accel_VolumeMute_F8")); | |
516 | |
517 if (volume_controller) | |
518 volume_controller->VolumeMute(); | |
519 } | |
520 | |
521 void HandleVolumeUp(mojom::VolumeController* volume_controller, | |
522 const ui::Accelerator& accelerator) { | |
523 if (accelerator.key_code() == ui::VKEY_VOLUME_UP) | |
524 base::RecordAction(UserMetricsAction("Accel_VolumeUp_F10")); | |
525 | |
526 if (volume_controller) | |
527 volume_controller->VolumeUp(); | |
528 } | |
529 | |
530 } // namespace | |
531 | |
532 //////////////////////////////////////////////////////////////////////////////// | |
533 // AcceleratorController, public: | |
534 | |
535 AcceleratorController::AcceleratorController( | |
536 AcceleratorControllerDelegate* delegate, | |
537 ui::AcceleratorManagerDelegate* manager_delegate) | |
538 : delegate_(delegate), | |
539 accelerator_manager_(new ui::AcceleratorManager(manager_delegate)), | |
540 accelerator_history_(new ui::AcceleratorHistory) { | |
541 Init(); | |
542 } | |
543 | |
544 AcceleratorController::~AcceleratorController() {} | |
545 | |
546 void AcceleratorController::Register( | |
547 const std::vector<ui::Accelerator>& accelerators, | |
548 ui::AcceleratorTarget* target) { | |
549 accelerator_manager_->Register( | |
550 accelerators, ui::AcceleratorManager::kNormalPriority, target); | |
551 } | |
552 | |
553 void AcceleratorController::Unregister(const ui::Accelerator& accelerator, | |
554 ui::AcceleratorTarget* target) { | |
555 accelerator_manager_->Unregister(accelerator, target); | |
556 } | |
557 | |
558 void AcceleratorController::UnregisterAll(ui::AcceleratorTarget* target) { | |
559 accelerator_manager_->UnregisterAll(target); | |
560 } | |
561 | |
562 bool AcceleratorController::Process(const ui::Accelerator& accelerator) { | |
563 return accelerator_manager_->Process(accelerator); | |
564 } | |
565 | |
566 bool AcceleratorController::IsRegistered( | |
567 const ui::Accelerator& accelerator) const { | |
568 return accelerator_manager_->IsRegistered(accelerator); | |
569 } | |
570 | |
571 bool AcceleratorController::IsPreferred( | |
572 const ui::Accelerator& accelerator) const { | |
573 std::map<ui::Accelerator, AcceleratorAction>::const_iterator iter = | |
574 accelerators_.find(accelerator); | |
575 if (iter == accelerators_.end()) | |
576 return false; // not an accelerator. | |
577 | |
578 return preferred_actions_.find(iter->second) != preferred_actions_.end(); | |
579 } | |
580 | |
581 bool AcceleratorController::IsReserved( | |
582 const ui::Accelerator& accelerator) const { | |
583 std::map<ui::Accelerator, AcceleratorAction>::const_iterator iter = | |
584 accelerators_.find(accelerator); | |
585 if (iter == accelerators_.end()) | |
586 return false; // not an accelerator. | |
587 | |
588 return reserved_actions_.find(iter->second) != reserved_actions_.end(); | |
589 } | |
590 | |
591 bool AcceleratorController::IsDeprecated( | |
592 const ui::Accelerator& accelerator) const { | |
593 return deprecated_accelerators_.count(accelerator) != 0; | |
594 } | |
595 | |
596 bool AcceleratorController::PerformActionIfEnabled(AcceleratorAction action) { | |
597 if (CanPerformAction(action, ui::Accelerator())) { | |
598 PerformAction(action, ui::Accelerator()); | |
599 return true; | |
600 } | |
601 return false; | |
602 } | |
603 | |
604 AcceleratorController::AcceleratorProcessingRestriction | |
605 AcceleratorController::GetCurrentAcceleratorRestriction() { | |
606 return GetAcceleratorProcessingRestriction(-1); | |
607 } | |
608 | |
609 void AcceleratorController::SetImeControlDelegate( | |
610 std::unique_ptr<ImeControlDelegate> ime_control_delegate) { | |
611 ime_control_delegate_ = std::move(ime_control_delegate); | |
612 } | |
613 | |
614 bool AcceleratorController::ShouldCloseMenuAndRepostAccelerator( | |
615 const ui::Accelerator& accelerator) const { | |
616 auto itr = accelerators_.find(accelerator); | |
617 if (itr == accelerators_.end()) | |
618 return false; // Menu shouldn't be closed for an invalid accelerator. | |
619 | |
620 AcceleratorAction action = itr->second; | |
621 return actions_keeping_menu_open_.count(action) == 0; | |
622 } | |
623 | |
624 //////////////////////////////////////////////////////////////////////////////// | |
625 // AcceleratorController, ui::AcceleratorTarget implementation: | |
626 | |
627 bool AcceleratorController::AcceleratorPressed( | |
628 const ui::Accelerator& accelerator) { | |
629 std::map<ui::Accelerator, AcceleratorAction>::const_iterator it = | |
630 accelerators_.find(accelerator); | |
631 DCHECK(it != accelerators_.end()); | |
632 AcceleratorAction action = it->second; | |
633 if (!CanPerformAction(action, accelerator)) | |
634 return false; | |
635 | |
636 // Handling the deprecated accelerators (if any) only if action can be | |
637 // performed. | |
638 if (MaybeDeprecatedAcceleratorPressed(action, accelerator) == | |
639 AcceleratorProcessingStatus::STOP) { | |
640 return false; | |
641 } | |
642 | |
643 PerformAction(action, accelerator); | |
644 return ShouldActionConsumeKeyEvent(action); | |
645 } | |
646 | |
647 bool AcceleratorController::CanHandleAccelerators() const { | |
648 return true; | |
649 } | |
650 | |
651 void AcceleratorController::BindRequest( | |
652 mojom::AcceleratorControllerRequest request) { | |
653 bindings_.AddBinding(this, std::move(request)); | |
654 } | |
655 | |
656 void AcceleratorController::SetVolumeController( | |
657 mojom::VolumeControllerPtr controller) { | |
658 volume_controller_ = std::move(controller); | |
659 } | |
660 | |
661 /////////////////////////////////////////////////////////////////////////////// | |
662 // AcceleratorController, private: | |
663 | |
664 void AcceleratorController::Init() { | |
665 for (size_t i = 0; i < kActionsAllowedAtLoginOrLockScreenLength; ++i) { | |
666 actions_allowed_at_login_screen_.insert( | |
667 kActionsAllowedAtLoginOrLockScreen[i]); | |
668 actions_allowed_at_lock_screen_.insert( | |
669 kActionsAllowedAtLoginOrLockScreen[i]); | |
670 } | |
671 for (size_t i = 0; i < kActionsAllowedAtLockScreenLength; ++i) | |
672 actions_allowed_at_lock_screen_.insert(kActionsAllowedAtLockScreen[i]); | |
673 for (size_t i = 0; i < kActionsAllowedAtModalWindowLength; ++i) | |
674 actions_allowed_at_modal_window_.insert(kActionsAllowedAtModalWindow[i]); | |
675 for (size_t i = 0; i < kPreferredActionsLength; ++i) | |
676 preferred_actions_.insert(kPreferredActions[i]); | |
677 for (size_t i = 0; i < kReservedActionsLength; ++i) | |
678 reserved_actions_.insert(kReservedActions[i]); | |
679 for (size_t i = 0; i < kRepeatableActionsLength; ++i) | |
680 repeatable_actions_.insert(kRepeatableActions[i]); | |
681 for (size_t i = 0; i < kActionsAllowedInAppModeOrPinnedModeLength; ++i) { | |
682 actions_allowed_in_app_mode_.insert( | |
683 kActionsAllowedInAppModeOrPinnedMode[i]); | |
684 actions_allowed_in_pinned_mode_.insert( | |
685 kActionsAllowedInAppModeOrPinnedMode[i]); | |
686 } | |
687 for (size_t i = 0; i < kActionsAllowedInPinnedModeLength; ++i) | |
688 actions_allowed_in_pinned_mode_.insert(kActionsAllowedInPinnedMode[i]); | |
689 for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) | |
690 actions_needing_window_.insert(kActionsNeedingWindow[i]); | |
691 for (size_t i = 0; i < kActionsKeepingMenuOpenLength; ++i) | |
692 actions_keeping_menu_open_.insert(kActionsKeepingMenuOpen[i]); | |
693 | |
694 RegisterAccelerators(kAcceleratorData, kAcceleratorDataLength); | |
695 | |
696 RegisterDeprecatedAccelerators(); | |
697 | |
698 if (debug::DebugAcceleratorsEnabled()) { | |
699 RegisterAccelerators(kDebugAcceleratorData, kDebugAcceleratorDataLength); | |
700 // All debug accelerators are reserved. | |
701 for (size_t i = 0; i < kDebugAcceleratorDataLength; ++i) | |
702 reserved_actions_.insert(kDebugAcceleratorData[i].action); | |
703 } | |
704 | |
705 if (debug::DeveloperAcceleratorsEnabled()) { | |
706 RegisterAccelerators(kDeveloperAcceleratorData, | |
707 kDeveloperAcceleratorDataLength); | |
708 // Developer accelerators are also reserved. | |
709 for (size_t i = 0; i < kDeveloperAcceleratorDataLength; ++i) | |
710 reserved_actions_.insert(kDeveloperAcceleratorData[i].action); | |
711 } | |
712 } | |
713 | |
714 void AcceleratorController::RegisterAccelerators( | |
715 const AcceleratorData accelerators[], | |
716 size_t accelerators_length) { | |
717 std::vector<ui::Accelerator> ui_accelerators; | |
718 for (size_t i = 0; i < accelerators_length; ++i) { | |
719 ui::Accelerator accelerator = | |
720 CreateAccelerator(accelerators[i].keycode, accelerators[i].modifiers, | |
721 accelerators[i].trigger_on_press); | |
722 ui_accelerators.push_back(accelerator); | |
723 accelerators_.insert(std::make_pair(accelerator, accelerators[i].action)); | |
724 } | |
725 Register(ui_accelerators, this); | |
726 } | |
727 | |
728 void AcceleratorController::RegisterDeprecatedAccelerators() { | |
729 for (size_t i = 0; i < kDeprecatedAcceleratorsDataLength; ++i) { | |
730 const DeprecatedAcceleratorData* data = &kDeprecatedAcceleratorsData[i]; | |
731 actions_with_deprecations_[data->action] = data; | |
732 } | |
733 | |
734 std::vector<ui::Accelerator> ui_accelerators; | |
735 for (size_t i = 0; i < kDeprecatedAcceleratorsLength; ++i) { | |
736 const AcceleratorData& accelerator_data = kDeprecatedAccelerators[i]; | |
737 const ui::Accelerator deprecated_accelerator = | |
738 CreateAccelerator(accelerator_data.keycode, accelerator_data.modifiers, | |
739 accelerator_data.trigger_on_press); | |
740 | |
741 ui_accelerators.push_back(deprecated_accelerator); | |
742 accelerators_[deprecated_accelerator] = accelerator_data.action; | |
743 deprecated_accelerators_.insert(deprecated_accelerator); | |
744 } | |
745 Register(ui_accelerators, this); | |
746 } | |
747 | |
748 bool AcceleratorController::CanPerformAction( | |
749 AcceleratorAction action, | |
750 const ui::Accelerator& accelerator) { | |
751 if (accelerator.IsRepeat() && !repeatable_actions_.count(action)) | |
752 return false; | |
753 | |
754 AcceleratorProcessingRestriction restriction = | |
755 GetAcceleratorProcessingRestriction(action); | |
756 if (restriction != RESTRICTION_NONE) | |
757 return restriction == RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION; | |
758 | |
759 const ui::Accelerator& previous_accelerator = | |
760 accelerator_history_->previous_accelerator(); | |
761 | |
762 // True should be returned if running |action| does something. Otherwise, | |
763 // false should be returned to give the web contents a chance at handling the | |
764 // accelerator. | |
765 switch (action) { | |
766 case CYCLE_BACKWARD_MRU: | |
767 case CYCLE_FORWARD_MRU: | |
768 return CanHandleCycleMru(accelerator); | |
769 case DEBUG_PRINT_LAYER_HIERARCHY: | |
770 case DEBUG_PRINT_VIEW_HIERARCHY: | |
771 case DEBUG_PRINT_WINDOW_HIERARCHY: | |
772 case DEBUG_SHOW_TOAST: | |
773 case DEBUG_TOGGLE_TOUCH_PAD: | |
774 case DEBUG_TOGGLE_TOUCH_SCREEN: | |
775 case DEBUG_TOGGLE_TOUCH_VIEW: | |
776 case DEBUG_TOGGLE_WALLPAPER_MODE: | |
777 case DEBUG_TRIGGER_CRASH: | |
778 return debug::DebugAcceleratorsEnabled(); | |
779 case DISABLE_CAPS_LOCK: | |
780 return CanHandleDisableCapsLock(previous_accelerator); | |
781 case LOCK_SCREEN: | |
782 return CanHandleLock(); | |
783 case NEW_INCOGNITO_WINDOW: | |
784 return CanHandleNewIncognitoWindow(); | |
785 case NEXT_IME: | |
786 return CanHandleNextIme(ime_control_delegate_.get()); | |
787 case PREVIOUS_IME: | |
788 return CanHandlePreviousIme(ime_control_delegate_.get()); | |
789 case SHOW_MESSAGE_CENTER_BUBBLE: | |
790 return CanHandleShowMessageCenterBubble(); | |
791 case SHOW_STYLUS_TOOLS: | |
792 return CanHandleShowStylusTools(); | |
793 case SWITCH_IME: | |
794 return CanHandleSwitchIme(ime_control_delegate_.get(), accelerator); | |
795 case SWITCH_TO_PREVIOUS_USER: | |
796 case SWITCH_TO_NEXT_USER: | |
797 return CanHandleCycleUser(); | |
798 case TOGGLE_APP_LIST: | |
799 return CanHandleToggleAppList(accelerator, previous_accelerator); | |
800 case TOGGLE_CAPS_LOCK: | |
801 return CanHandleToggleCapsLock(accelerator, previous_accelerator); | |
802 case WINDOW_CYCLE_SNAP_DOCK_LEFT: | |
803 case WINDOW_CYCLE_SNAP_DOCK_RIGHT: | |
804 return CanHandleWindowSnapOrDock(); | |
805 case WINDOW_POSITION_CENTER: | |
806 return CanHandlePositionCenter(); | |
807 | |
808 // The following are always enabled. | |
809 case BRIGHTNESS_DOWN: | |
810 case BRIGHTNESS_UP: | |
811 case EXIT: | |
812 case FOCUS_NEXT_PANE: | |
813 case FOCUS_PREVIOUS_PANE: | |
814 case FOCUS_SHELF: | |
815 case KEYBOARD_BRIGHTNESS_DOWN: | |
816 case KEYBOARD_BRIGHTNESS_UP: | |
817 case LAUNCH_APP_0: | |
818 case LAUNCH_APP_1: | |
819 case LAUNCH_APP_2: | |
820 case LAUNCH_APP_3: | |
821 case LAUNCH_APP_4: | |
822 case LAUNCH_APP_5: | |
823 case LAUNCH_APP_6: | |
824 case LAUNCH_APP_7: | |
825 case LAUNCH_LAST_APP: | |
826 case MEDIA_NEXT_TRACK: | |
827 case MEDIA_PLAY_PAUSE: | |
828 case MEDIA_PREV_TRACK: | |
829 case NEW_TAB: | |
830 case NEW_WINDOW: | |
831 case OPEN_CROSH: | |
832 case OPEN_FEEDBACK_PAGE: | |
833 case OPEN_FILE_MANAGER: | |
834 case OPEN_GET_HELP: | |
835 case PRINT_UI_HIERARCHIES: | |
836 case RESTORE_TAB: | |
837 case SHOW_IME_MENU_BUBBLE: | |
838 case SHOW_KEYBOARD_OVERLAY: | |
839 case SHOW_TASK_MANAGER: | |
840 case SUSPEND: | |
841 case TOGGLE_FULLSCREEN: | |
842 case TOGGLE_HIGH_CONTRAST: | |
843 case TOGGLE_MAXIMIZED: | |
844 case TOGGLE_OVERVIEW: | |
845 case TOGGLE_SPOKEN_FEEDBACK: | |
846 case TOGGLE_WIFI: | |
847 case VOLUME_DOWN: | |
848 case VOLUME_MUTE: | |
849 case VOLUME_UP: | |
850 case WINDOW_MINIMIZE: | |
851 return true; | |
852 | |
853 default: | |
854 // Default switch is temporary until mash transition complete. Needed as | |
855 // some actions don't yet work with mash. | |
856 break; | |
857 } | |
858 return delegate_ && delegate_->HandlesAction(action) && | |
859 delegate_->CanPerformAction(action, accelerator, previous_accelerator); | |
860 } | |
861 | |
862 void AcceleratorController::PerformAction(AcceleratorAction action, | |
863 const ui::Accelerator& accelerator) { | |
864 AcceleratorProcessingRestriction restriction = | |
865 GetAcceleratorProcessingRestriction(action); | |
866 if (restriction != RESTRICTION_NONE) | |
867 return; | |
868 | |
869 // If your accelerator invokes more than one line of code, please either | |
870 // implement it in your module's controller code or pull it into a HandleFoo() | |
871 // function above. | |
872 switch (action) { | |
873 case BRIGHTNESS_DOWN: { | |
874 BrightnessControlDelegate* delegate = | |
875 WmShell::Get()->brightness_control_delegate(); | |
876 if (delegate) | |
877 delegate->HandleBrightnessDown(accelerator); | |
878 break; | |
879 } | |
880 case BRIGHTNESS_UP: { | |
881 BrightnessControlDelegate* delegate = | |
882 WmShell::Get()->brightness_control_delegate(); | |
883 if (delegate) | |
884 delegate->HandleBrightnessUp(accelerator); | |
885 break; | |
886 } | |
887 case CYCLE_BACKWARD_MRU: | |
888 HandleCycleBackwardMRU(accelerator); | |
889 break; | |
890 case CYCLE_FORWARD_MRU: | |
891 HandleCycleForwardMRU(accelerator); | |
892 break; | |
893 case DEBUG_PRINT_LAYER_HIERARCHY: | |
894 case DEBUG_PRINT_VIEW_HIERARCHY: | |
895 case DEBUG_PRINT_WINDOW_HIERARCHY: | |
896 case DEBUG_SHOW_TOAST: | |
897 case DEBUG_TOGGLE_TOUCH_PAD: | |
898 case DEBUG_TOGGLE_TOUCH_SCREEN: | |
899 case DEBUG_TOGGLE_TOUCH_VIEW: | |
900 case DEBUG_TOGGLE_WALLPAPER_MODE: | |
901 case DEBUG_TRIGGER_CRASH: | |
902 debug::PerformDebugActionIfEnabled(action); | |
903 break; | |
904 case DISABLE_CAPS_LOCK: | |
905 HandleDisableCapsLock(); | |
906 break; | |
907 case EXIT: | |
908 // UMA metrics are recorded in the handler. | |
909 exit_warning_handler_.HandleAccelerator(); | |
910 break; | |
911 case FOCUS_NEXT_PANE: | |
912 HandleRotatePaneFocus(FocusCycler::FORWARD); | |
913 break; | |
914 case FOCUS_PREVIOUS_PANE: | |
915 HandleRotatePaneFocus(FocusCycler::BACKWARD); | |
916 break; | |
917 case FOCUS_SHELF: | |
918 HandleFocusShelf(); | |
919 break; | |
920 case KEYBOARD_BRIGHTNESS_DOWN: { | |
921 KeyboardBrightnessControlDelegate* delegate = | |
922 WmShell::Get()->keyboard_brightness_control_delegate(); | |
923 if (delegate) | |
924 delegate->HandleKeyboardBrightnessDown(accelerator); | |
925 break; | |
926 } | |
927 case KEYBOARD_BRIGHTNESS_UP: { | |
928 KeyboardBrightnessControlDelegate* delegate = | |
929 WmShell::Get()->keyboard_brightness_control_delegate(); | |
930 if (delegate) | |
931 delegate->HandleKeyboardBrightnessUp(accelerator); | |
932 break; | |
933 } | |
934 case LAUNCH_APP_0: | |
935 HandleLaunchAppN(0); | |
936 break; | |
937 case LAUNCH_APP_1: | |
938 HandleLaunchAppN(1); | |
939 break; | |
940 case LAUNCH_APP_2: | |
941 HandleLaunchAppN(2); | |
942 break; | |
943 case LAUNCH_APP_3: | |
944 HandleLaunchAppN(3); | |
945 break; | |
946 case LAUNCH_APP_4: | |
947 HandleLaunchAppN(4); | |
948 break; | |
949 case LAUNCH_APP_5: | |
950 HandleLaunchAppN(5); | |
951 break; | |
952 case LAUNCH_APP_6: | |
953 HandleLaunchAppN(6); | |
954 break; | |
955 case LAUNCH_APP_7: | |
956 HandleLaunchAppN(7); | |
957 break; | |
958 case LAUNCH_LAST_APP: | |
959 HandleLaunchLastApp(); | |
960 break; | |
961 case LOCK_SCREEN: | |
962 HandleLock(); | |
963 break; | |
964 case MEDIA_NEXT_TRACK: | |
965 HandleMediaNextTrack(); | |
966 break; | |
967 case MEDIA_PLAY_PAUSE: | |
968 HandleMediaPlayPause(); | |
969 break; | |
970 case MEDIA_PREV_TRACK: | |
971 HandleMediaPrevTrack(); | |
972 break; | |
973 case NEW_INCOGNITO_WINDOW: | |
974 HandleNewIncognitoWindow(); | |
975 break; | |
976 case NEW_TAB: | |
977 HandleNewTab(accelerator); | |
978 break; | |
979 case NEW_WINDOW: | |
980 HandleNewWindow(); | |
981 break; | |
982 case NEXT_IME: | |
983 HandleNextIme(ime_control_delegate_.get()); | |
984 break; | |
985 case OPEN_CROSH: | |
986 HandleCrosh(); | |
987 break; | |
988 case OPEN_FEEDBACK_PAGE: | |
989 HandleOpenFeedbackPage(); | |
990 break; | |
991 case OPEN_FILE_MANAGER: | |
992 HandleFileManager(); | |
993 break; | |
994 case OPEN_GET_HELP: | |
995 HandleGetHelp(); | |
996 break; | |
997 case PREVIOUS_IME: | |
998 HandlePreviousIme(ime_control_delegate_.get(), accelerator); | |
999 break; | |
1000 case PRINT_UI_HIERARCHIES: | |
1001 debug::PrintUIHierarchies(); | |
1002 break; | |
1003 case RESTORE_TAB: | |
1004 HandleRestoreTab(); | |
1005 break; | |
1006 case SHOW_IME_MENU_BUBBLE: | |
1007 HandleShowImeMenuBubble(); | |
1008 break; | |
1009 case SHOW_KEYBOARD_OVERLAY: | |
1010 HandleShowKeyboardOverlay(); | |
1011 break; | |
1012 case SHOW_MESSAGE_CENTER_BUBBLE: | |
1013 HandleShowMessageCenterBubble(); | |
1014 break; | |
1015 case SHOW_STYLUS_TOOLS: | |
1016 HandleShowStylusTools(); | |
1017 break; | |
1018 case SHOW_TASK_MANAGER: | |
1019 HandleShowTaskManager(); | |
1020 break; | |
1021 case SUSPEND: | |
1022 HandleSuspend(); | |
1023 break; | |
1024 case SWITCH_IME: | |
1025 HandleSwitchIme(ime_control_delegate_.get(), accelerator); | |
1026 break; | |
1027 case SWITCH_TO_NEXT_USER: | |
1028 HandleCycleUser(CycleUserDirection::NEXT); | |
1029 break; | |
1030 case SWITCH_TO_PREVIOUS_USER: | |
1031 HandleCycleUser(CycleUserDirection::PREVIOUS); | |
1032 break; | |
1033 case TOGGLE_APP_LIST: | |
1034 HandleToggleAppList(accelerator); | |
1035 break; | |
1036 case TOGGLE_CAPS_LOCK: | |
1037 HandleToggleCapsLock(); | |
1038 break; | |
1039 case TOGGLE_FULLSCREEN: | |
1040 HandleToggleFullscreen(accelerator); | |
1041 break; | |
1042 case TOGGLE_HIGH_CONTRAST: | |
1043 HandleToggleHighContrast(); | |
1044 break; | |
1045 case TOGGLE_MAXIMIZED: | |
1046 accelerators::ToggleMaximized(); | |
1047 break; | |
1048 case TOGGLE_OVERVIEW: | |
1049 HandleToggleOverview(); | |
1050 break; | |
1051 case TOGGLE_SPOKEN_FEEDBACK: | |
1052 HandleToggleSpokenFeedback(); | |
1053 break; | |
1054 case TOGGLE_WIFI: | |
1055 WmShell::Get()->system_tray_notifier()->NotifyRequestToggleWifi(); | |
1056 break; | |
1057 case VOLUME_DOWN: | |
1058 HandleVolumeDown(volume_controller_.get(), accelerator); | |
1059 break; | |
1060 case VOLUME_MUTE: | |
1061 HandleVolumeMute(volume_controller_.get(), accelerator); | |
1062 break; | |
1063 case VOLUME_UP: | |
1064 HandleVolumeUp(volume_controller_.get(), accelerator); | |
1065 break; | |
1066 case WINDOW_CYCLE_SNAP_DOCK_LEFT: | |
1067 case WINDOW_CYCLE_SNAP_DOCK_RIGHT: | |
1068 HandleWindowSnapOrDock(action); | |
1069 break; | |
1070 case WINDOW_MINIMIZE: | |
1071 HandleWindowMinimize(); | |
1072 break; | |
1073 case WINDOW_POSITION_CENTER: | |
1074 HandlePositionCenter(); | |
1075 break; | |
1076 default: | |
1077 // Temporary until mash transition complete. Needed as some actions | |
1078 // don't yet work with mash. | |
1079 DCHECK(delegate_ && delegate_->HandlesAction(action)); | |
1080 delegate_->PerformAction(action, accelerator); | |
1081 break; | |
1082 } | |
1083 } | |
1084 | |
1085 bool AcceleratorController::ShouldActionConsumeKeyEvent( | |
1086 AcceleratorAction action) { | |
1087 // Adding new exceptions is *STRONGLY* discouraged. | |
1088 return true; | |
1089 } | |
1090 | |
1091 AcceleratorController::AcceleratorProcessingRestriction | |
1092 AcceleratorController::GetAcceleratorProcessingRestriction(int action) { | |
1093 WmShell* wm_shell = WmShell::Get(); | |
1094 if (wm_shell->IsPinned() && | |
1095 actions_allowed_in_pinned_mode_.find(action) == | |
1096 actions_allowed_in_pinned_mode_.end()) { | |
1097 return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION; | |
1098 } | |
1099 // TODO(xiyuan): Replace with SessionController. http://crbug.com/648964 | |
1100 if (!wm_shell->GetSessionStateDelegate()->IsActiveUserSessionStarted() && | |
1101 actions_allowed_at_login_screen_.find(action) == | |
1102 actions_allowed_at_login_screen_.end()) { | |
1103 return RESTRICTION_PREVENT_PROCESSING; | |
1104 } | |
1105 if (wm_shell->GetSessionStateDelegate()->IsScreenLocked() && | |
1106 actions_allowed_at_lock_screen_.find(action) == | |
1107 actions_allowed_at_lock_screen_.end()) { | |
1108 return RESTRICTION_PREVENT_PROCESSING; | |
1109 } | |
1110 if (wm_shell->delegate()->IsRunningInForcedAppMode() && | |
1111 actions_allowed_in_app_mode_.find(action) == | |
1112 actions_allowed_in_app_mode_.end()) { | |
1113 return RESTRICTION_PREVENT_PROCESSING; | |
1114 } | |
1115 if (WmShell::Get()->IsSystemModalWindowOpen() && | |
1116 actions_allowed_at_modal_window_.find(action) == | |
1117 actions_allowed_at_modal_window_.end()) { | |
1118 // Note we prevent the shortcut from propagating so it will not | |
1119 // be passed to the modal window. This is important for things like | |
1120 // Alt+Tab that would cause an undesired effect in the modal window by | |
1121 // cycling through its window elements. | |
1122 return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION; | |
1123 } | |
1124 if (wm_shell->mru_window_tracker()->BuildMruWindowList().empty() && | |
1125 actions_needing_window_.find(action) != actions_needing_window_.end()) { | |
1126 wm_shell->accessibility_delegate()->TriggerAccessibilityAlert( | |
1127 A11Y_ALERT_WINDOW_NEEDED); | |
1128 return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION; | |
1129 } | |
1130 return RESTRICTION_NONE; | |
1131 } | |
1132 | |
1133 AcceleratorController::AcceleratorProcessingStatus | |
1134 AcceleratorController::MaybeDeprecatedAcceleratorPressed( | |
1135 AcceleratorAction action, | |
1136 const ui::Accelerator& accelerator) const { | |
1137 auto itr = actions_with_deprecations_.find(action); | |
1138 if (itr == actions_with_deprecations_.end()) { | |
1139 // The action is not associated with any deprecated accelerators, and hence | |
1140 // should be performed normally. | |
1141 return AcceleratorProcessingStatus::PROCEED; | |
1142 } | |
1143 | |
1144 // This action is associated with new and deprecated accelerators, find which | |
1145 // one is |accelerator|. | |
1146 const DeprecatedAcceleratorData* data = itr->second; | |
1147 if (!deprecated_accelerators_.count(accelerator)) { | |
1148 // This is a new accelerator replacing the old deprecated one. | |
1149 // Record UMA stats and proceed normally to perform it. | |
1150 RecordUmaHistogram(data->uma_histogram_name, NEW_USED); | |
1151 return AcceleratorProcessingStatus::PROCEED; | |
1152 } | |
1153 | |
1154 // This accelerator has been deprecated and should be treated according | |
1155 // to its |DeprecatedAcceleratorData|. | |
1156 | |
1157 // Record UMA stats. | |
1158 RecordUmaHistogram(data->uma_histogram_name, DEPRECATED_USED); | |
1159 | |
1160 if (delegate_) { | |
1161 // We always display the notification as long as this |data| entry exists. | |
1162 delegate_->ShowDeprecatedAcceleratorNotification( | |
1163 data->uma_histogram_name, data->notification_message_id, | |
1164 data->old_shortcut_id, data->new_shortcut_id); | |
1165 } | |
1166 | |
1167 if (!data->deprecated_enabled) | |
1168 return AcceleratorProcessingStatus::STOP; | |
1169 | |
1170 return AcceleratorProcessingStatus::PROCEED; | |
1171 } | |
1172 | |
1173 } // namespace ash | |
OLD | NEW |