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
ash / accelerators / accelerator_filter_unittest.cc [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/wm/core/accelerator_filter.h"
#include <memory>
#include "ash/accelerators/accelerator_controller_impl.h"
#include "ash/accelerators/pre_target_accelerator_handler.h"
#include "ash/app_list/test/app_list_test_helper.h"
#include "ash/capture_mode/capture_mode_controller.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/base/mojom/window_show_state.mojom.h"
#include "ui/events/event.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/geometry/rect.h"
namespace ash {
using AcceleratorFilterTest = AshTestBase;
// Tests if AcceleratorFilter works without a focused window.
TEST_F(AcceleratorFilterTest, TestFilterWithoutFocus) {
// VKEY_SNAPSHOT opens capture mode.
PressAndReleaseKey(ui::VKEY_SNAPSHOT);
EXPECT_TRUE(CaptureModeController::Get()->IsActive());
}
// Tests if AcceleratorFilter works as expected with a focused window.
TEST_F(AcceleratorFilterTest, TestFilterWithFocus) {
aura::test::TestWindowDelegate test_delegate;
std::unique_ptr<aura::Window> window(
CreateTestWindowInShellWithDelegate(&test_delegate, -1, gfx::Rect()));
wm::ActivateWindow(window.get());
// AcceleratorFilter should ignore the key events since the root window is
// not focused.
PressAndReleaseKey(ui::VKEY_SNAPSHOT);
EXPECT_FALSE(CaptureModeController::Get()->IsActive());
// Reset window before |test_delegate| gets deleted.
window.reset();
}
// Tests if AcceleratorFilter ignores the flag for Caps Lock.
TEST_F(AcceleratorFilterTest, TestCapsLockMask) {
PressAndReleaseKey(ui::VKEY_SNAPSHOT);
auto* controller = CaptureModeController::Get();
EXPECT_TRUE(controller->IsActive());
controller->Stop();
// Check if AcceleratorFilter ignores the mask for Caps Lock. Note that there
// is no ui::EF_ mask for Num Lock.
PressAndReleaseKey(ui::VKEY_SNAPSHOT, ui::EF_CAPS_LOCK_ON);
EXPECT_TRUE(controller->IsActive());
}
// Tests if special hardware keys like brightness and volume are consumed as
// expected by the shell.
TEST_F(AcceleratorFilterTest, CanConsumeSystemKeys) {
::wm::AcceleratorFilter filter(
std::make_unique<PreTargetAcceleratorHandler>());
aura::Window* root_window = Shell::GetPrimaryRootWindow();
// Normal keys are not consumed.
ui::KeyEvent press_a(ui::EventType::kKeyPressed, ui::VKEY_A, ui::EF_NONE);
{
ui::Event::DispatcherApi dispatch_helper(&press_a);
dispatch_helper.set_target(root_window);
}
filter.OnKeyEvent(&press_a);
EXPECT_FALSE(press_a.stopped_propagation());
// System keys are directly consumed.
ui::KeyEvent press_mute(ui::EventType::kKeyPressed, ui::VKEY_VOLUME_MUTE,
ui::EF_NONE);
{
ui::Event::DispatcherApi dispatch_helper(&press_mute);
dispatch_helper.set_target(root_window);
}
filter.OnKeyEvent(&press_mute);
EXPECT_TRUE(press_mute.stopped_propagation());
// Setting a window property on the target allows system keys to pass through.
std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(1));
WindowState::Get(window.get())->SetCanConsumeSystemKeys(true);
ui::KeyEvent press_volume_up(ui::EventType::kKeyPressed, ui::VKEY_VOLUME_UP,
ui::EF_NONE);
ui::Event::DispatcherApi dispatch_helper(&press_volume_up);
dispatch_helper.set_target(window.get());
filter.OnKeyEvent(&press_volume_up);
EXPECT_FALSE(press_volume_up.stopped_propagation());
// System keys pass through to a child window if the parent (top level)
// window has the property set.
std::unique_ptr<aura::Window> child(CreateTestWindowInShellWithId(2));
window->AddChild(child.get());
dispatch_helper.set_target(child.get());
filter.OnKeyEvent(&press_volume_up);
EXPECT_FALSE(press_volume_up.stopped_propagation());
}
TEST_F(AcceleratorFilterTest, SearchKeyShortcutsAreAlwaysHandled) {
SessionControllerImpl* const session_controller =
Shell::Get()->session_controller();
EXPECT_FALSE(session_controller->IsScreenLocked());
// We can lock the screen (Search+L) if a window is not present.
PressAndReleaseKey(ui::VKEY_L, ui::EF_COMMAND_DOWN);
GetSessionControllerClient()->FlushForTest(); // LockScreen is an async call.
EXPECT_TRUE(session_controller->IsScreenLocked());
UnblockUserSession();
EXPECT_FALSE(session_controller->IsScreenLocked());
// Search+L is processed when the app_list target visibility is false.
GetAppListTestHelper()->DismissAndRunLoop();
GetAppListTestHelper()->CheckVisibility(false);
PressAndReleaseKey(ui::VKEY_L, ui::EF_COMMAND_DOWN);
GetSessionControllerClient()->FlushForTest(); // LockScreen is an async call.
EXPECT_TRUE(session_controller->IsScreenLocked());
UnblockUserSession();
EXPECT_FALSE(session_controller->IsScreenLocked());
// Search+L is also processed when there is a full screen window.
aura::test::TestWindowDelegate window_delegate;
std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
&window_delegate, 0, gfx::Rect(200, 200)));
window->SetProperty(aura::client::kShowStateKey,
ui::mojom::WindowShowState::kFullscreen);
PressAndReleaseKey(ui::VKEY_L, ui::EF_COMMAND_DOWN);
GetSessionControllerClient()->FlushForTest(); // LockScreen is an async call.
EXPECT_TRUE(session_controller->IsScreenLocked());
UnblockUserSession();
EXPECT_FALSE(session_controller->IsScreenLocked());
}
TEST_F(AcceleratorFilterTest, ToggleAppListInterruptedByMouseEvent) {
ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
GetAppListTestHelper()->CheckVisibility(false);
// The AppList should toggle if no mouse event occurs between key press and
// key release.
generator.PressKey(ui::VKEY_LWIN, ui::EF_NONE);
generator.ReleaseKey(ui::VKEY_LWIN, ui::EF_NONE);
GetAppListTestHelper()->WaitUntilIdle();
GetAppListTestHelper()->CheckVisibility(true);
// Close the app list.
GetAppListTestHelper()->DismissAndRunLoop();
GetAppListTestHelper()->CheckVisibility(false);
// When pressed key is interrupted by mouse, the AppList should not toggle.
generator.PressKey(ui::VKEY_LWIN, ui::EF_NONE);
generator.ClickLeftButton();
generator.ReleaseKey(ui::VKEY_LWIN, ui::EF_NONE);
GetAppListTestHelper()->WaitUntilIdle();
GetAppListTestHelper()->CheckVisibility(false);
}
} // namespace ash