forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaccelerator_controller_delegate_aura.cc
490 lines (442 loc) · 17 KB
/
accelerator_controller_delegate_aura.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/accelerators/accelerator_controller_delegate_aura.h"
#include <algorithm>
#include <cmath>
#include <string>
#include <utility>
#include "ash/accelerators/accelerator_commands_aura.h"
#include "ash/common/accelerators/debug_commands.h"
#include "ash/common/accessibility_types.h"
#include "ash/common/session/session_state_delegate.h"
#include "ash/common/shelf/wm_shelf.h"
#include "ash/common/shell_delegate.h"
#include "ash/common/system/system_notifier.h"
#include "ash/common/system/tray/system_tray.h"
#include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
#include "ash/common/wm/window_state.h"
#include "ash/common/wm/wm_event.h"
#include "ash/common/wm_shell.h"
#include "ash/debug.h"
#include "ash/display/display_configuration_controller.h"
#include "ash/display/window_tree_host_manager.h"
#include "ash/host/ash_window_tree_host.h"
#include "ash/magnifier/magnification_controller.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/root_window_controller.h"
#include "ash/rotator/screen_rotation_animator.h"
#include "ash/rotator/window_rotation.h"
#include "ash/screenshot_delegate.h"
#include "ash/shell.h"
#include "ash/touch/touch_hud_debug.h"
#include "ash/utility/screenshot_controller.h"
#include "ash/wm/power_button_controller.h"
#include "ash/wm/window_state_aura.h"
#include "ash/wm/window_util.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/notification.h"
#include "ui/message_center/notifier_settings.h"
namespace ash {
namespace {
using base::UserMetricsAction;
// The notification delegate that will be used to open the keyboard shortcut
// help page when the notification is clicked.
class DeprecatedAcceleratorNotificationDelegate
: public message_center::NotificationDelegate {
public:
DeprecatedAcceleratorNotificationDelegate() {}
// message_center::NotificationDelegate:
bool HasClickedListener() override { return true; }
void Click() override {
if (!WmShell::Get()->GetSessionStateDelegate()->IsUserSessionBlocked())
WmShell::Get()->delegate()->OpenKeyboardShortcutHelpPage();
}
private:
// Private destructor since NotificationDelegate is ref-counted.
~DeprecatedAcceleratorNotificationDelegate() override {}
DISALLOW_COPY_AND_ASSIGN(DeprecatedAcceleratorNotificationDelegate);
};
// Ensures that there are no word breaks at the "+"s in the shortcut texts such
// as "Ctrl+Shift+Space".
void EnsureNoWordBreaks(base::string16* shortcut_text) {
std::vector<base::string16> keys =
base::SplitString(*shortcut_text, base::ASCIIToUTF16("+"),
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
if (keys.size() < 2U)
return;
// The plus sign surrounded by the word joiner to guarantee an non-breaking
// shortcut.
const base::string16 non_breaking_plus =
base::UTF8ToUTF16("\xe2\x81\xa0+\xe2\x81\xa0");
shortcut_text->clear();
for (size_t i = 0; i < keys.size() - 1; ++i) {
*shortcut_text += keys[i];
*shortcut_text += non_breaking_plus;
}
*shortcut_text += keys.back();
}
// Gets the notification message after it formats it in such a way that there
// are no line breaks in the middle of the shortcut texts.
base::string16 GetNotificationText(int message_id,
int old_shortcut_id,
int new_shortcut_id) {
base::string16 old_shortcut = l10n_util::GetStringUTF16(old_shortcut_id);
base::string16 new_shortcut = l10n_util::GetStringUTF16(new_shortcut_id);
EnsureNoWordBreaks(&old_shortcut);
EnsureNoWordBreaks(&new_shortcut);
return l10n_util::GetStringFUTF16(message_id, new_shortcut, old_shortcut);
}
bool CanHandleMagnifyScreen() {
return Shell::GetInstance()->magnification_controller()->IsEnabled();
}
// Magnify the screen
void HandleMagnifyScreen(int delta_index) {
if (Shell::GetInstance()->magnification_controller()->IsEnabled()) {
// TODO(yoshiki): Move the following logic to MagnificationController.
float scale = Shell::GetInstance()->magnification_controller()->GetScale();
// Calculate rounded logarithm (base kMagnificationScaleFactor) of scale.
int scale_index =
std::floor(std::log(scale) / std::log(kMagnificationScaleFactor) + 0.5);
int new_scale_index = std::max(0, std::min(8, scale_index + delta_index));
Shell::GetInstance()->magnification_controller()->SetScale(
std::pow(kMagnificationScaleFactor, new_scale_index), true);
}
}
display::Display::Rotation GetNextRotation(display::Display::Rotation current) {
switch (current) {
case display::Display::ROTATE_0:
return display::Display::ROTATE_90;
case display::Display::ROTATE_90:
return display::Display::ROTATE_180;
case display::Display::ROTATE_180:
return display::Display::ROTATE_270;
case display::Display::ROTATE_270:
return display::Display::ROTATE_0;
}
NOTREACHED() << "Unknown rotation:" << current;
return display::Display::ROTATE_0;
}
// Rotates the screen.
void HandleRotateScreen() {
if (Shell::GetInstance()->display_manager()->IsInUnifiedMode())
return;
base::RecordAction(UserMetricsAction("Accel_Rotate_Window"));
gfx::Point point = display::Screen::GetScreen()->GetCursorScreenPoint();
display::Display display =
display::Screen::GetScreen()->GetDisplayNearestPoint(point);
const display::ManagedDisplayInfo& display_info =
Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id());
ScreenRotationAnimator(display.id())
.Rotate(GetNextRotation(display_info.GetActiveRotation()),
display::Display::ROTATION_SOURCE_USER);
}
// Rotate the active window.
void HandleRotateActiveWindow() {
base::RecordAction(UserMetricsAction("Accel_Rotate_Window"));
aura::Window* active_window = wm::GetActiveWindow();
if (active_window) {
// The rotation animation bases its target transform on the current
// rotation and position. Since there could be an animation in progress
// right now, queue this animation so when it starts it picks up a neutral
// rotation and position. Use replace so we only enqueue one at a time.
active_window->layer()->GetAnimator()->set_preemption_strategy(
ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
active_window->layer()->GetAnimator()->StartAnimation(
new ui::LayerAnimationSequence(
base::MakeUnique<WindowRotation>(360, active_window->layer())));
}
}
void HandleShowSystemTrayBubble() {
base::RecordAction(UserMetricsAction("Accel_Show_System_Tray_Bubble"));
RootWindowController* controller =
RootWindowController::ForTargetRootWindow();
SystemTray* tray = controller->GetSystemTray();
if (!tray->HasSystemBubble()) {
tray->ShowDefaultView(BUBBLE_CREATE_NEW);
tray->ActivateBubble();
}
}
void HandleTakeWindowScreenshot(ScreenshotDelegate* screenshot_delegate) {
base::RecordAction(UserMetricsAction("Accel_Take_Window_Screenshot"));
DCHECK(screenshot_delegate);
Shell::GetInstance()->screenshot_controller()->StartWindowScreenshotSession(
screenshot_delegate);
}
void HandleTakePartialScreenshot(ScreenshotDelegate* screenshot_delegate) {
base::RecordAction(UserMetricsAction("Accel_Take_Partial_Screenshot"));
DCHECK(screenshot_delegate);
Shell::GetInstance()->screenshot_controller()->StartPartialScreenshotSession(
screenshot_delegate, true /* draw_overlay_immediately */);
}
void HandleTakeScreenshot(ScreenshotDelegate* screenshot_delegate) {
base::RecordAction(UserMetricsAction("Accel_Take_Screenshot"));
DCHECK(screenshot_delegate);
if (screenshot_delegate->CanTakeScreenshot())
screenshot_delegate->HandleTakeScreenshotForAllRootWindows();
}
bool CanHandleUnpin() {
// Returns true only for WINDOW_STATE_TYPE_PINNED.
// WINDOW_STATE_TYPE_TRUSTED_PINNED does not accept user's unpin operation.
wm::WindowState* window_state = wm::GetActiveWindowState();
return window_state &&
window_state->GetStateType() == wm::WINDOW_STATE_TYPE_PINNED;
}
void HandleSwapPrimaryDisplay() {
base::RecordAction(UserMetricsAction("Accel_Swap_Primary_Display"));
// TODO(rjkroege): This is not correct behaviour on devices with more than
// two screens. Behave the same as mirroring: fail and notify if there are
// three or more screens.
Shell::GetInstance()->display_configuration_controller()->SetPrimaryDisplayId(
Shell::GetInstance()->display_manager()->GetSecondaryDisplay().id(),
true /* user_action */);
}
void HandleToggleMirrorMode() {
base::RecordAction(UserMetricsAction("Accel_Toggle_Mirror_Mode"));
bool mirror = !Shell::GetInstance()->display_manager()->IsInMirrorMode();
Shell::GetInstance()->display_configuration_controller()->SetMirrorMode(
mirror, true /* user_action */);
}
bool CanHandleTouchHud() {
return RootWindowController::ForTargetRootWindow()->touch_hud_debug();
}
void HandleTouchHudClear() {
RootWindowController::ForTargetRootWindow()->touch_hud_debug()->Clear();
}
void HandleTouchHudModeChange() {
RootWindowController* controller =
RootWindowController::ForTargetRootWindow();
controller->touch_hud_debug()->ChangeToNextMode();
}
} // namespace
AcceleratorControllerDelegateAura::AcceleratorControllerDelegateAura() {}
AcceleratorControllerDelegateAura::~AcceleratorControllerDelegateAura() {}
void AcceleratorControllerDelegateAura::SetScreenshotDelegate(
std::unique_ptr<ScreenshotDelegate> screenshot_delegate) {
screenshot_delegate_ = std::move(screenshot_delegate);
}
bool AcceleratorControllerDelegateAura::HandlesAction(
AcceleratorAction action) {
// NOTE: When adding a new accelerator that only depends on //ash/common code,
// add it to accelerator_controller.cc instead. See class comment.
switch (action) {
case DEBUG_TOGGLE_DEVICE_SCALE_FACTOR:
case DEBUG_TOGGLE_SHOW_DEBUG_BORDERS:
case DEBUG_TOGGLE_SHOW_FPS_COUNTER:
case DEBUG_TOGGLE_SHOW_PAINT_RECTS:
case DEV_ADD_REMOVE_DISPLAY:
case DEV_TOGGLE_ROOT_WINDOW_FULL_SCREEN:
case DEV_TOGGLE_UNIFIED_DESKTOP:
case LOCK_PRESSED:
case LOCK_RELEASED:
case MAGNIFY_SCREEN_ZOOM_IN:
case MAGNIFY_SCREEN_ZOOM_OUT:
case POWER_PRESSED:
case POWER_RELEASED:
case ROTATE_SCREEN:
case ROTATE_WINDOW:
case SCALE_UI_DOWN:
case SCALE_UI_RESET:
case SCALE_UI_UP:
case SHOW_MESSAGE_CENTER_BUBBLE:
case SHOW_SYSTEM_TRAY_BUBBLE:
case SWAP_PRIMARY_DISPLAY:
case TAKE_PARTIAL_SCREENSHOT:
case TAKE_SCREENSHOT:
case TAKE_WINDOW_SCREENSHOT:
case TOGGLE_MIRROR_MODE:
case TOUCH_HUD_CLEAR:
case TOUCH_HUD_MODE_CHANGE:
case TOUCH_HUD_PROJECTION_TOGGLE:
case UNPIN:
return true;
default:
break;
}
return false;
}
bool AcceleratorControllerDelegateAura::CanPerformAction(
AcceleratorAction action,
const ui::Accelerator& accelerator,
const ui::Accelerator& previous_accelerator) {
switch (action) {
case DEBUG_TOGGLE_DEVICE_SCALE_FACTOR:
case DEBUG_TOGGLE_SHOW_DEBUG_BORDERS:
case DEBUG_TOGGLE_SHOW_FPS_COUNTER:
case DEBUG_TOGGLE_SHOW_PAINT_RECTS:
return debug::DebugAcceleratorsEnabled();
case DEV_ADD_REMOVE_DISPLAY:
case DEV_TOGGLE_ROOT_WINDOW_FULL_SCREEN:
case DEV_TOGGLE_UNIFIED_DESKTOP:
return debug::DeveloperAcceleratorsEnabled();
case MAGNIFY_SCREEN_ZOOM_IN:
case MAGNIFY_SCREEN_ZOOM_OUT:
return CanHandleMagnifyScreen();
case SCALE_UI_DOWN:
case SCALE_UI_RESET:
case SCALE_UI_UP:
return accelerators::IsInternalDisplayZoomEnabled();
case UNPIN:
return CanHandleUnpin();
// Following are always enabled:
case LOCK_PRESSED:
case LOCK_RELEASED:
case POWER_PRESSED:
case POWER_RELEASED:
case ROTATE_SCREEN:
case ROTATE_WINDOW:
case SHOW_SYSTEM_TRAY_BUBBLE:
case TAKE_PARTIAL_SCREENSHOT:
case TAKE_SCREENSHOT:
case TAKE_WINDOW_SCREENSHOT:
case TOGGLE_MIRROR_MODE:
case TOUCH_HUD_PROJECTION_TOGGLE:
return true;
case SWAP_PRIMARY_DISPLAY:
return display::Screen::GetScreen()->GetNumDisplays() > 1;
case TOUCH_HUD_CLEAR:
case TOUCH_HUD_MODE_CHANGE:
return CanHandleTouchHud();
default:
NOTREACHED();
break;
}
return false;
}
void AcceleratorControllerDelegateAura::PerformAction(
AcceleratorAction action,
const ui::Accelerator& accelerator) {
switch (action) {
case DEBUG_TOGGLE_DEVICE_SCALE_FACTOR:
Shell::GetInstance()->display_manager()->ToggleDisplayScaleFactor();
break;
case DEBUG_TOGGLE_SHOW_DEBUG_BORDERS:
debug::ToggleShowDebugBorders();
break;
case DEBUG_TOGGLE_SHOW_FPS_COUNTER:
debug::ToggleShowFpsCounter();
break;
case DEBUG_TOGGLE_SHOW_PAINT_RECTS:
debug::ToggleShowPaintRects();
break;
case DEV_ADD_REMOVE_DISPLAY:
Shell::GetInstance()->display_manager()->AddRemoveDisplay();
break;
case DEV_TOGGLE_ROOT_WINDOW_FULL_SCREEN:
Shell::GetPrimaryRootWindowController()->ash_host()->ToggleFullScreen();
break;
case DEV_TOGGLE_UNIFIED_DESKTOP:
Shell::GetInstance()->display_manager()->SetUnifiedDesktopEnabled(
!Shell::GetInstance()->display_manager()->unified_desktop_enabled());
break;
case LOCK_PRESSED:
case LOCK_RELEASED:
Shell::GetInstance()->power_button_controller()->OnLockButtonEvent(
action == LOCK_PRESSED, base::TimeTicks());
break;
case MAGNIFY_SCREEN_ZOOM_IN:
HandleMagnifyScreen(1);
break;
case MAGNIFY_SCREEN_ZOOM_OUT:
HandleMagnifyScreen(-1);
break;
case POWER_PRESSED: // fallthrough
case POWER_RELEASED:
if (!base::SysInfo::IsRunningOnChromeOS()) {
// There is no powerd, the Chrome OS power manager, in linux desktop,
// so call the PowerButtonController here.
Shell::GetInstance()->power_button_controller()->OnPowerButtonEvent(
action == POWER_PRESSED, base::TimeTicks());
}
// We don't do anything with these at present on the device,
// (power button events are reported to us from powerm via
// D-BUS), but we consume them to prevent them from getting
// passed to apps -- see http://crbug.com/146609.
break;
case ROTATE_SCREEN:
HandleRotateScreen();
break;
case ROTATE_WINDOW:
HandleRotateActiveWindow();
break;
case SCALE_UI_DOWN:
accelerators::ZoomInternalDisplay(false /* down */);
break;
case SCALE_UI_RESET:
accelerators::ResetInternalDisplayZoom();
break;
case SCALE_UI_UP:
accelerators::ZoomInternalDisplay(true /* up */);
break;
case SHOW_SYSTEM_TRAY_BUBBLE:
HandleShowSystemTrayBubble();
break;
case SWAP_PRIMARY_DISPLAY:
HandleSwapPrimaryDisplay();
break;
case TAKE_PARTIAL_SCREENSHOT:
HandleTakePartialScreenshot(screenshot_delegate_.get());
break;
case TAKE_SCREENSHOT:
HandleTakeScreenshot(screenshot_delegate_.get());
break;
case TAKE_WINDOW_SCREENSHOT:
HandleTakeWindowScreenshot(screenshot_delegate_.get());
break;
case TOGGLE_MIRROR_MODE:
HandleToggleMirrorMode();
break;
case TOUCH_HUD_CLEAR:
HandleTouchHudClear();
break;
case TOUCH_HUD_MODE_CHANGE:
HandleTouchHudModeChange();
break;
case TOUCH_HUD_PROJECTION_TOGGLE:
accelerators::ToggleTouchHudProjection();
break;
case UNPIN:
accelerators::Unpin();
break;
default:
break;
}
}
void AcceleratorControllerDelegateAura::ShowDeprecatedAcceleratorNotification(
const char* const notification_id,
int message_id,
int old_shortcut_id,
int new_shortcut_id) {
const base::string16 message =
GetNotificationText(message_id, old_shortcut_id, new_shortcut_id);
std::unique_ptr<message_center::Notification> notification(
new message_center::Notification(
message_center::NOTIFICATION_TYPE_SIMPLE, notification_id,
base::string16(), message,
WmShell::Get()->delegate()->GetDeprecatedAcceleratorImage(),
base::string16(), GURL(),
message_center::NotifierId(
message_center::NotifierId::SYSTEM_COMPONENT,
system_notifier::kNotifierDeprecatedAccelerator),
message_center::RichNotificationData(),
new DeprecatedAcceleratorNotificationDelegate));
message_center::MessageCenter::Get()->AddNotification(
std::move(notification));
}
} // namespace ash