Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: components/mus/ws/window_manager_state_unittest.cc

Issue 2119963002: Move mus to //services/ui (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "components/mus/ws/window_manager_state.h"
6
7 #include <memory>
8
9 #include "base/macros.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/test/test_simple_task_runner.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "components/mus/common/event_matcher_util.h"
15 #include "components/mus/surfaces/surfaces_state.h"
16 #include "components/mus/ws/accelerator.h"
17 #include "components/mus/ws/display.h"
18 #include "components/mus/ws/display_binding.h"
19 #include "components/mus/ws/platform_display.h"
20 #include "components/mus/ws/platform_display_init_params.h"
21 #include "components/mus/ws/server_window_surface_manager_test_api.h"
22 #include "components/mus/ws/test_change_tracker.h"
23 #include "components/mus/ws/test_server_window_delegate.h"
24 #include "components/mus/ws/test_utils.h"
25 #include "components/mus/ws/window_manager_access_policy.h"
26 #include "components/mus/ws/window_manager_display_root.h"
27 #include "components/mus/ws/window_manager_state.h"
28 #include "components/mus/ws/window_server.h"
29 #include "components/mus/ws/window_tree.h"
30 #include "services/shell/public/interfaces/connector.mojom.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "ui/events/event.h"
33
34 namespace mus {
35 namespace ws {
36 namespace test {
37
38 class WindowManagerStateTest : public testing::Test {
39 public:
40 WindowManagerStateTest();
41 ~WindowManagerStateTest() override {}
42
43 std::unique_ptr<Accelerator> CreateAccelerator();
44
45 // Creates a child |server_window| with associataed |window_tree| and
46 // |test_client|. The window is setup for processing input.
47 void CreateSecondaryTree(TestWindowTreeClient** test_client,
48 WindowTree** window_tree,
49 ServerWindow** server_window);
50
51 void DispatchInputEventToWindow(ServerWindow* target,
52 const ui::Event& event,
53 Accelerator* accelerator);
54 void OnEventAckTimeout(ClientSpecificId client_id);
55
56 WindowTree* tree() {
57 return window_event_targeting_helper_.window_server()->GetTreeWithId(1);
58 }
59 WindowTree* window_tree() { return window_tree_; }
60 TestWindowTreeClient* window_tree_client() { return window_tree_client_; }
61 ServerWindow* window() { return window_; }
62 TestWindowManager* window_manager() { return &window_manager_; }
63 TestWindowTreeClient* wm_client() {
64 return window_event_targeting_helper_.wm_client();
65 }
66 TestWindowTreeClient* last_tree_client() {
67 return window_event_targeting_helper_.last_window_tree_client();
68 }
69 WindowTree* last_tree() {
70 return window_event_targeting_helper_.last_binding()->tree();
71 }
72 WindowManagerState* window_manager_state() { return window_manager_state_; }
73
74 void EmbedAt(WindowTree* tree,
75 const ClientWindowId& embed_window_id,
76 uint32_t embed_flags,
77 WindowTree** embed_tree,
78 TestWindowTreeClient** embed_client_proxy) {
79 mojom::WindowTreeClientPtr embed_client;
80 mojom::WindowTreeClientRequest client_request = GetProxy(&embed_client);
81 ASSERT_TRUE(
82 tree->Embed(embed_window_id, std::move(embed_client), embed_flags));
83 TestWindowTreeClient* client =
84 window_event_targeting_helper_.last_window_tree_client();
85 ASSERT_EQ(1u, client->tracker()->changes()->size());
86 EXPECT_EQ(CHANGE_TYPE_EMBED, (*client->tracker()->changes())[0].type);
87 client->tracker()->changes()->clear();
88 *embed_client_proxy = client;
89 *embed_tree = window_event_targeting_helper_.last_binding()->tree();
90 }
91
92 // testing::Test:
93 void SetUp() override;
94
95 private:
96 WindowEventTargetingHelper window_event_targeting_helper_;
97
98 WindowManagerState* window_manager_state_;
99
100 // Handles WindowStateManager ack timeouts.
101 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
102 TestWindowManager window_manager_;
103 ServerWindow* window_ = nullptr;
104 WindowTree* window_tree_ = nullptr;
105 TestWindowTreeClient* window_tree_client_ = nullptr;
106
107 DISALLOW_COPY_AND_ASSIGN(WindowManagerStateTest);
108 };
109
110 WindowManagerStateTest::WindowManagerStateTest()
111 : task_runner_(new base::TestSimpleTaskRunner) {}
112
113 std::unique_ptr<Accelerator> WindowManagerStateTest::CreateAccelerator() {
114 mojom::EventMatcherPtr matcher = mus::CreateKeyMatcher(
115 ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown);
116 matcher->accelerator_phase = ui::mojom::AcceleratorPhase::POST_TARGET;
117 uint32_t accelerator_id = 1;
118 std::unique_ptr<Accelerator> accelerator(
119 new Accelerator(accelerator_id, *matcher));
120 return accelerator;
121 }
122
123 void WindowManagerStateTest::CreateSecondaryTree(
124 TestWindowTreeClient** test_client,
125 WindowTree** window_tree,
126 ServerWindow** server_window) {
127 window_event_targeting_helper_.CreateSecondaryTree(
128 window_, gfx::Rect(20, 20, 20, 20), test_client, window_tree,
129 server_window);
130 }
131
132 void WindowManagerStateTest::DispatchInputEventToWindow(
133 ServerWindow* target,
134 const ui::Event& event,
135 Accelerator* accelerator) {
136 WindowManagerStateTestApi test_api(window_manager_state_);
137 ClientSpecificId client_id = test_api.GetEventTargetClientId(target, false);
138 test_api.DispatchInputEventToWindow(target, client_id, event, accelerator);
139 }
140
141 void WindowManagerStateTest::OnEventAckTimeout(
142 ClientSpecificId client_id) {
143 WindowManagerStateTestApi test_api(window_manager_state_);
144 test_api.OnEventAckTimeout(client_id);
145 }
146
147 void WindowManagerStateTest::SetUp() {
148 window_event_targeting_helper_.SetTaskRunner(task_runner_);
149 window_manager_state_ = window_event_targeting_helper_.display()
150 ->GetActiveWindowManagerDisplayRoot()
151 ->window_manager_state();
152 window_ = window_event_targeting_helper_.CreatePrimaryTree(
153 gfx::Rect(0, 0, 100, 100), gfx::Rect(0, 0, 50, 50));
154 window_tree_ = window_event_targeting_helper_.last_binding()->tree();
155 window_tree_client_ =
156 window_event_targeting_helper_.last_window_tree_client();
157 DCHECK(window_tree_->HasRoot(window_));
158
159 WindowTreeTestApi(tree()).set_window_manager_internal(&window_manager_);
160 wm_client()->tracker()->changes()->clear();
161 window_tree_client_->tracker()->changes()->clear();
162 }
163
164 // Tests that when an event is dispatched with no accelerator, that post target
165 // accelerator is not triggered.
166 TEST_F(WindowManagerStateTest, NullAccelerator) {
167 WindowManagerState* state = window_manager_state();
168 EXPECT_TRUE(state);
169
170 ServerWindow* target = window();
171 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
172 DispatchInputEventToWindow(target, key, nullptr);
173 WindowTree* target_tree = window_tree();
174 TestChangeTracker* tracker = window_tree_client()->tracker();
175 ASSERT_EQ(1u, tracker->changes()->size());
176 EXPECT_EQ("InputEvent window=1,1 event_action=7",
177 ChangesToDescription1(*tracker->changes())[0]);
178
179 WindowTreeTestApi(target_tree).AckOldestEvent();
180 EXPECT_FALSE(window_manager()->on_accelerator_called());
181 }
182
183 // Tests that when a post target accelerator is provided on an event, that it is
184 // called on ack.
185 TEST_F(WindowManagerStateTest, PostTargetAccelerator) {
186 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
187 std::unique_ptr<Accelerator> accelerator = CreateAccelerator();
188
189 ServerWindow* target = window();
190 DispatchInputEventToWindow(target, key, accelerator.get());
191 TestChangeTracker* tracker = window_tree_client()->tracker();
192 ASSERT_EQ(1u, tracker->changes()->size());
193 EXPECT_EQ("InputEvent window=1,1 event_action=7",
194 ChangesToDescription1(*tracker->changes())[0]);
195
196 WindowTreeTestApi(window_tree()).AckOldestEvent();
197 EXPECT_TRUE(window_manager()->on_accelerator_called());
198 EXPECT_EQ(accelerator->id(), window_manager()->on_accelerator_id());
199 }
200
201 // Tests that when a client handles an event that post target accelerators are
202 // not called.
203 TEST_F(WindowManagerStateTest, ClientHandlesEvent) {
204 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
205 std::unique_ptr<Accelerator> accelerator = CreateAccelerator();
206
207 ServerWindow* target = window();
208 DispatchInputEventToWindow(target, key, accelerator.get());
209 TestChangeTracker* tracker = window_tree_client()->tracker();
210 ASSERT_EQ(1u, tracker->changes()->size());
211 EXPECT_EQ("InputEvent window=1,1 event_action=7",
212 ChangesToDescription1(*tracker->changes())[0]);
213
214 window_manager_state()->OnEventAck(tree(), mojom::EventResult::HANDLED);
215 EXPECT_FALSE(window_manager()->on_accelerator_called());
216 }
217
218 // Tests that when an accelerator is deleted before an ack, that it is not
219 // called.
220 TEST_F(WindowManagerStateTest, AcceleratorDeleted) {
221 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
222 std::unique_ptr<Accelerator> accelerator(CreateAccelerator());
223
224 ServerWindow* target = window();
225 DispatchInputEventToWindow(target, key, accelerator.get());
226 TestChangeTracker* tracker = window_tree_client()->tracker();
227 ASSERT_EQ(1u, tracker->changes()->size());
228 EXPECT_EQ("InputEvent window=1,1 event_action=7",
229 ChangesToDescription1(*tracker->changes())[0]);
230
231 accelerator.reset();
232 window_manager_state()->OnEventAck(tree(), mojom::EventResult::UNHANDLED);
233 EXPECT_FALSE(window_manager()->on_accelerator_called());
234 }
235
236 // Tests that a events arriving before an ack don't notify the tree until the
237 // ack arrives, and that the correct accelerator is called.
238 TEST_F(WindowManagerStateTest, EnqueuedAccelerators) {
239 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
240 std::unique_ptr<Accelerator> accelerator(CreateAccelerator());
241
242 ServerWindow* target = window();
243 DispatchInputEventToWindow(target, key, accelerator.get());
244 TestChangeTracker* tracker = window_tree_client()->tracker();
245 ASSERT_EQ(1u, tracker->changes()->size());
246 EXPECT_EQ("InputEvent window=1,1 event_action=7",
247 ChangesToDescription1(*tracker->changes())[0]);
248
249 tracker->changes()->clear();
250 ui::KeyEvent key2(ui::ET_KEY_PRESSED, ui::VKEY_Y, ui::EF_CONTROL_DOWN);
251 mojom::EventMatcherPtr matcher = mus::CreateKeyMatcher(
252 ui::mojom::KeyboardCode::Y, ui::mojom::kEventFlagControlDown);
253 matcher->accelerator_phase = ui::mojom::AcceleratorPhase::POST_TARGET;
254 uint32_t accelerator_id = 2;
255 std::unique_ptr<Accelerator> accelerator2(
256 new Accelerator(accelerator_id, *matcher));
257 DispatchInputEventToWindow(target, key2, accelerator2.get());
258 EXPECT_TRUE(tracker->changes()->empty());
259
260 WindowTreeTestApi(window_tree()).AckOldestEvent();
261 ASSERT_EQ(1u, tracker->changes()->size());
262 EXPECT_EQ("InputEvent window=1,1 event_action=7",
263 ChangesToDescription1(*tracker->changes())[0]);
264 EXPECT_TRUE(window_manager()->on_accelerator_called());
265 EXPECT_EQ(accelerator->id(), window_manager()->on_accelerator_id());
266 }
267
268 // Tests that the accelerator is not sent when the tree is dying.
269 TEST_F(WindowManagerStateTest, DeleteTree) {
270 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
271 std::unique_ptr<Accelerator> accelerator = CreateAccelerator();
272
273 ServerWindow* target = window();
274 DispatchInputEventToWindow(target, key, accelerator.get());
275 TestChangeTracker* tracker = window_tree_client()->tracker();
276 ASSERT_EQ(1u, tracker->changes()->size());
277 EXPECT_EQ("InputEvent window=1,1 event_action=7",
278 ChangesToDescription1(*tracker->changes())[0]);
279
280 window_manager_state()->OnWillDestroyTree(tree());
281 EXPECT_FALSE(window_manager()->on_accelerator_called());
282 }
283
284 // Tests that if a tree is destroyed before acking, that the accelerator is
285 // still sent if it is not the root tree.
286 TEST_F(WindowManagerStateTest, DeleteNonRootTree) {
287 TestWindowTreeClient* embed_connection = nullptr;
288 WindowTree* target_tree = nullptr;
289 ServerWindow* target = nullptr;
290 CreateSecondaryTree(&embed_connection, &target_tree, &target);
291 TestWindowManager target_window_manager;
292 WindowTreeTestApi(target_tree)
293 .set_window_manager_internal(&target_window_manager);
294
295 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
296 std::unique_ptr<Accelerator> accelerator = CreateAccelerator();
297 DispatchInputEventToWindow(target, key, accelerator.get());
298 TestChangeTracker* tracker = embed_connection->tracker();
299 ASSERT_EQ(1u, tracker->changes()->size());
300 EXPECT_EQ("InputEvent window=2,1 event_action=7",
301 ChangesToDescription1(*tracker->changes())[0]);
302 EXPECT_TRUE(wm_client()->tracker()->changes()->empty());
303
304 window_manager_state()->OnWillDestroyTree(target_tree);
305 EXPECT_FALSE(target_window_manager.on_accelerator_called());
306 EXPECT_TRUE(window_manager()->on_accelerator_called());
307 }
308
309 // Tests that when an ack times out that the accelerator is notified.
310 TEST_F(WindowManagerStateTest, AckTimeout) {
311 ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
312 std::unique_ptr<Accelerator> accelerator = CreateAccelerator();
313 DispatchInputEventToWindow(window(), key, accelerator.get());
314 TestChangeTracker* tracker = window_tree_client()->tracker();
315 ASSERT_EQ(1u, tracker->changes()->size());
316 EXPECT_EQ("InputEvent window=1,1 event_action=7",
317 ChangesToDescription1(*tracker->changes())[0]);
318
319 OnEventAckTimeout(window()->id().client_id);
320 EXPECT_TRUE(window_manager()->on_accelerator_called());
321 EXPECT_EQ(accelerator->id(), window_manager()->on_accelerator_id());
322 }
323
324 TEST_F(WindowManagerStateTest, InterceptingEmbedderReceivesEvents) {
325 WindowTree* embedder_tree = tree();
326 ServerWindow* embedder_root = window();
327 const ClientWindowId embed_window_id(
328 WindowIdToTransportId(WindowId(embedder_tree->id(), 12)));
329 embedder_tree->NewWindow(embed_window_id, ServerWindow::Properties());
330 ServerWindow* embedder_window =
331 embedder_tree->GetWindowByClientId(embed_window_id);
332 ASSERT_TRUE(embedder_tree->AddWindow(
333 ClientWindowId(WindowIdToTransportId(embedder_root->id())),
334 embed_window_id));
335
336 TestWindowTreeClient* embedder_client = wm_client();
337
338 {
339 // Do a normal embed.
340 const uint32_t embed_flags = 0;
341 WindowTree* embed_tree = nullptr;
342 TestWindowTreeClient* embed_client_proxy = nullptr;
343 EmbedAt(embedder_tree, embed_window_id, embed_flags, &embed_tree,
344 &embed_client_proxy);
345 ASSERT_TRUE(embed_client_proxy);
346
347 // Send an event to the embed window. It should go to the embedded client.
348 ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
349 base::TimeTicks(), 0, 0);
350 DispatchInputEventToWindow(embedder_window, mouse, nullptr);
351 ASSERT_EQ(1u, embed_client_proxy->tracker()->changes()->size());
352 EXPECT_EQ(CHANGE_TYPE_INPUT_EVENT,
353 (*embed_client_proxy->tracker()->changes())[0].type);
354 WindowTreeTestApi(embed_tree).AckLastEvent(mojom::EventResult::UNHANDLED);
355 embed_client_proxy->tracker()->changes()->clear();
356 }
357
358 {
359 // Do an embed where the embedder wants to intercept events to the embedded
360 // tree.
361 const uint32_t embed_flags = mojom::kEmbedFlagEmbedderInterceptsEvents;
362 WindowTree* embed_tree = nullptr;
363 TestWindowTreeClient* embed_client_proxy = nullptr;
364 EmbedAt(embedder_tree, embed_window_id, embed_flags, &embed_tree,
365 &embed_client_proxy);
366 ASSERT_TRUE(embed_client_proxy);
367 embedder_client->tracker()->changes()->clear();
368
369 // Send an event to the embed window. But this time, it should reach the
370 // embedder.
371 ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
372 base::TimeTicks(), 0, 0);
373 DispatchInputEventToWindow(embedder_window, mouse, nullptr);
374 ASSERT_EQ(0u, embed_client_proxy->tracker()->changes()->size());
375 ASSERT_EQ(1u, embedder_client->tracker()->changes()->size());
376 EXPECT_EQ(CHANGE_TYPE_INPUT_EVENT,
377 (*embedder_client->tracker()->changes())[0].type);
378 WindowTreeTestApi(embedder_tree)
379 .AckLastEvent(mojom::EventResult::UNHANDLED);
380 embedder_client->tracker()->changes()->clear();
381
382 // Embed another tree in the embedded tree.
383 const ClientWindowId nested_embed_window_id(
384 WindowIdToTransportId(WindowId(embed_tree->id(), 23)));
385 embed_tree->NewWindow(nested_embed_window_id, ServerWindow::Properties());
386 const ClientWindowId embed_root_id(
387 WindowIdToTransportId((*embed_tree->roots().begin())->id()));
388 ASSERT_TRUE(embed_tree->AddWindow(embed_root_id, nested_embed_window_id));
389
390 WindowTree* nested_embed_tree = nullptr;
391 TestWindowTreeClient* nested_embed_client_proxy = nullptr;
392 EmbedAt(embed_tree, nested_embed_window_id, embed_flags, &nested_embed_tree,
393 &nested_embed_client_proxy);
394 ASSERT_TRUE(nested_embed_client_proxy);
395 embed_client_proxy->tracker()->changes()->clear();
396 embedder_client->tracker()->changes()->clear();
397
398 // Send an event to the nested embed window. The event should still reach
399 // the outermost embedder.
400 ServerWindow* nested_embed_window =
401 embed_tree->GetWindowByClientId(nested_embed_window_id);
402 DCHECK(nested_embed_window->parent());
403 mouse = ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
404 base::TimeTicks(), 0, 0);
405 DispatchInputEventToWindow(nested_embed_window, mouse, nullptr);
406 ASSERT_EQ(0u, nested_embed_client_proxy->tracker()->changes()->size());
407 ASSERT_EQ(0u, embed_client_proxy->tracker()->changes()->size());
408
409 ASSERT_EQ(1u, embedder_client->tracker()->changes()->size());
410 EXPECT_EQ(CHANGE_TYPE_INPUT_EVENT,
411 (*embedder_client->tracker()->changes())[0].type);
412 WindowTreeTestApi(embedder_tree)
413 .AckLastEvent(mojom::EventResult::UNHANDLED);
414 }
415 }
416
417 } // namespace test
418 } // namespace ws
419 } // namespace mus
OLDNEW
« no previous file with comments | « components/mus/ws/window_manager_state.cc ('k') | components/mus/ws/window_manager_window_tree_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698