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

Side by Side Diff: ui/aura/mus/window_tree_client_unittest.cc

Issue 2445163002: Make aura work with mus (Closed)
Patch Set: NON_EXPORTED_BASE_CLASS Created 4 years, 1 month 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
« no previous file with comments | « ui/aura/mus/window_tree_client_observer.h ('k') | ui/aura/mus/window_tree_host_mus.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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 "ui/aura/mus/window_tree_client.h"
6
7 #include <stdint.h>
8
9 #include "base/logging.h"
10 #include "base/macros.h"
11 #include "mojo/common/common_type_converters.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/aura/client/aura_constants.h"
14 #include "ui/aura/client/capture_client.h"
15 #include "ui/aura/client/focus_client.h"
16 #include "ui/aura/mus/property_converter.h"
17 #include "ui/aura/mus/window_mus.h"
18 #include "ui/aura/mus/window_tree_client_delegate.h"
19 #include "ui/aura/mus/window_tree_client_observer.h"
20 #include "ui/aura/test/aura_mus_test_base.h"
21 #include "ui/aura/test/mus/test_window_tree.h"
22 #include "ui/aura/test/mus/window_tree_client_private.h"
23 #include "ui/aura/test/test_window_delegate.h"
24 #include "ui/aura/window.h"
25 #include "ui/aura/window_property.h"
26 #include "ui/aura/window_tracker.h"
27 #include "ui/events/event.h"
28 #include "ui/events/event_utils.h"
29 #include "ui/gfx/geometry/rect.h"
30
31 DECLARE_WINDOW_PROPERTY_TYPE(uint8_t)
32
33 namespace aura {
34
35 namespace {
36
37 DEFINE_WINDOW_PROPERTY_KEY(uint8_t, kTestPropertyKey1, 0);
38 DEFINE_WINDOW_PROPERTY_KEY(uint8_t, kTestPropertyKey2, 0);
39
40 Id server_id(Window* window) {
41 return WindowMus::Get(window)->server_id();
42 }
43
44 void SetWindowVisibility(Window* window, bool visible) {
45 if (visible)
46 window->Show();
47 else
48 window->Hide();
49 }
50
51 Window* GetFirstRoot(WindowTreeClient* client) {
52 return client->GetRoots().empty() ? nullptr : *client->GetRoots().begin();
53 }
54
55 const char kAlwaysOnTopServerKey[] = "always-on-top-server";
56 const char kTestPropertyServerKey1[] = "test-property-server1";
57 const char kTestPropertyServerKey2[] = "test-property-server2";
58
59 class TestPropertyConverter : public PropertyConverter {
60 public:
61 TestPropertyConverter() {}
62 ~TestPropertyConverter() override {}
63
64 // PropertyConverter:
65 bool ConvertPropertyForTransport(
66 Window* window,
67 const void* key,
68 std::string* server_property_name,
69 std::unique_ptr<std::vector<uint8_t>>* server_property_value) override {
70 if (key == client::kAlwaysOnTopKey) {
71 *server_property_name = kAlwaysOnTopServerKey;
72 *server_property_value = base::MakeUnique<std::vector<uint8_t>>(1);
73 (*server_property_value->get())[0] =
74 window->GetProperty(client::kAlwaysOnTopKey);
75 return true;
76 }
77 if (key == kTestPropertyKey1) {
78 *server_property_name = kTestPropertyServerKey1;
79 *server_property_value = base::MakeUnique<std::vector<uint8_t>>(1);
80 (*server_property_value->get())[0] =
81 window->GetProperty(kTestPropertyKey1);
82 return true;
83 }
84 if (key == kTestPropertyKey2) {
85 *server_property_name = kTestPropertyServerKey2;
86 *server_property_value = base::MakeUnique<std::vector<uint8_t>>(1);
87 (*server_property_value->get())[0] =
88 window->GetProperty(kTestPropertyKey2);
89 return true;
90 }
91 return false;
92 }
93
94 std::string GetTransportNameForPropertyKey(const void* key) override {
95 if (key == client::kAlwaysOnTopKey)
96 return kAlwaysOnTopServerKey;
97 if (key == kTestPropertyKey1)
98 return kTestPropertyServerKey1;
99 if (key == kTestPropertyKey2)
100 return kTestPropertyServerKey2;
101 return std::string();
102 }
103
104 void SetPropertyFromTransportValue(
105 Window* window,
106 const std::string& server_property_name,
107 const std::vector<uint8_t>* data) override {
108 if (server_property_name == kAlwaysOnTopServerKey) {
109 window->SetProperty(client::kAlwaysOnTopKey,
110 static_cast<bool>((*data)[0]));
111 } else if (server_property_name == kTestPropertyServerKey1) {
112 window->SetProperty(kTestPropertyKey1, (*data)[0]);
113 } else if (server_property_name == kTestPropertyServerKey2) {
114 window->SetProperty(kTestPropertyKey2, (*data)[0]);
115 }
116 }
117
118 private:
119 DISALLOW_COPY_AND_ASSIGN(TestPropertyConverter);
120 };
121
122 } // namespace
123
124 mojo::Array<uint8_t> Uint8ToPropertyTransportValue(uint8_t value) {
125 mojo::Array<uint8_t> transport_value(1);
126 transport_value[0] = value;
127 return transport_value;
128 }
129
130 using WindowTreeClientWmTest = test::AuraMusWmTestBase;
131 using WindowTreeClientClientTest = test::AuraMusClientTestBase;
132
133 // Verifies bounds are reverted if the server replied that the change failed.
134 TEST_F(WindowTreeClientWmTest, SetBoundsFailed) {
135 Window window(nullptr);
136 window.Init(ui::LAYER_NOT_DRAWN);
137 const gfx::Rect original_bounds(window.bounds());
138 const gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100));
139 ASSERT_NE(new_bounds, window.bounds());
140 window.SetBounds(new_bounds);
141 EXPECT_EQ(new_bounds, window.bounds());
142 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(WindowTreeChangeType::BOUNDS,
143 false));
144 EXPECT_EQ(original_bounds, window.bounds());
145 }
146
147 // Verifies a new window from the server doesn't result in attempting to add
148 // the window back to the server.
149 TEST_F(WindowTreeClientWmTest, AddFromServerDoesntAddAgain) {
150 const Id child_window_id = server_id(root_window()) + 11;
151 ui::mojom::WindowDataPtr data = ui::mojom::WindowData::New();
152 data->parent_id = server_id(root_window());
153 data->window_id = child_window_id;
154 data->bounds = gfx::Rect(1, 2, 3, 4);
155 data->visible = false;
156 mojo::Array<ui::mojom::WindowDataPtr> data_array(1);
157 data_array[0] = std::move(data);
158 ASSERT_TRUE(root_window()->children().empty());
159 window_tree_client()->OnWindowHierarchyChanged(
160 child_window_id, 0, server_id(root_window()), std::move(data_array));
161 ASSERT_FALSE(window_tree()->has_change());
162 ASSERT_EQ(1u, root_window()->children().size());
163 Window* child = root_window()->children()[0];
164 EXPECT_FALSE(child->TargetVisibility());
165 }
166
167 // Verifies a reparent from the server doesn't attempt signal the server.
168 TEST_F(WindowTreeClientWmTest, ReparentFromServerDoesntAddAgain) {
169 Window window1(nullptr);
170 window1.Init(ui::LAYER_NOT_DRAWN);
171 Window window2(nullptr);
172 window2.Init(ui::LAYER_NOT_DRAWN);
173 root_window()->AddChild(&window1);
174 root_window()->AddChild(&window2);
175
176 window_tree()->AckAllChanges();
177 // Simulate moving |window1| to be a child of |window2| from the server.
178 window_tree_client()->OnWindowHierarchyChanged(server_id(&window1),
179 server_id(root_window()),
180 server_id(&window2), nullptr);
181 ASSERT_FALSE(window_tree()->has_change());
182 EXPECT_EQ(&window2, window1.parent());
183 EXPECT_EQ(root_window(), window2.parent());
184 window1.parent()->RemoveChild(&window1);
185 }
186
187 // Verifies properties passed in OnWindowHierarchyChanged() make there way to
188 // the new window.
189 TEST_F(WindowTreeClientWmTest, OnWindowHierarchyChangedWithProperties) {
190 SetPropertyConverter(base::MakeUnique<TestPropertyConverter>());
191 window_tree()->AckAllChanges();
192 const Id child_window_id = server_id(root_window()) + 11;
193 ui::mojom::WindowDataPtr data = ui::mojom::WindowData::New();
194 const uint8_t server_test_property1_value = 91;
195 data->properties[kTestPropertyServerKey1] =
196 Uint8ToPropertyTransportValue(server_test_property1_value);
197 data->parent_id = server_id(root_window());
198 data->window_id = child_window_id;
199 data->bounds = gfx::Rect(1, 2, 3, 4);
200 data->visible = false;
201 mojo::Array<ui::mojom::WindowDataPtr> data_array(1);
202 data_array[0] = std::move(data);
203 ASSERT_TRUE(root_window()->children().empty());
204 window_tree_client()->OnWindowHierarchyChanged(
205 child_window_id, 0, server_id(root_window()), std::move(data_array));
206 ASSERT_FALSE(window_tree()->has_change());
207 ASSERT_EQ(1u, root_window()->children().size());
208 Window* child = root_window()->children()[0];
209 EXPECT_FALSE(child->TargetVisibility());
210 EXPECT_EQ(server_test_property1_value, child->GetProperty(kTestPropertyKey1));
211 }
212
213 // Verifies a move from the server doesn't attempt signal the server.
214 TEST_F(WindowTreeClientWmTest, MoveFromServerDoesntAddAgain) {
215 Window window1(nullptr);
216 window1.Init(ui::LAYER_NOT_DRAWN);
217 Window window2(nullptr);
218 window2.Init(ui::LAYER_NOT_DRAWN);
219 root_window()->AddChild(&window1);
220 root_window()->AddChild(&window2);
221
222 window_tree()->AckAllChanges();
223 // Simulate moving |window1| to be a child of |window2| from the server.
224 window_tree_client()->OnWindowReordered(server_id(&window2),
225 server_id(&window1),
226 ui::mojom::OrderDirection::BELOW);
227 ASSERT_FALSE(window_tree()->has_change());
228 ASSERT_EQ(2u, root_window()->children().size());
229 EXPECT_EQ(&window2, root_window()->children()[0]);
230 EXPECT_EQ(&window1, root_window()->children()[1]);
231 }
232
233 TEST_F(WindowTreeClientWmTest, FocusFromServer) {
234 Window window1(nullptr);
235 window1.Init(ui::LAYER_NOT_DRAWN);
236 Window window2(nullptr);
237 window2.Init(ui::LAYER_NOT_DRAWN);
238 root_window()->AddChild(&window1);
239 root_window()->AddChild(&window2);
240
241 ASSERT_TRUE(window1.CanFocus());
242 window_tree()->AckAllChanges();
243 EXPECT_FALSE(window1.HasFocus());
244 // Simulate moving |window1| to be a child of |window2| from the server.
245 window_tree_client()->OnWindowFocused(server_id(&window1));
246 ASSERT_FALSE(window_tree()->has_change());
247 EXPECT_TRUE(window1.HasFocus());
248 }
249
250 // Simulates a bounds change, and while the bounds change is in flight the
251 // server replies with a new bounds and the original bounds change fails.
252 TEST_F(WindowTreeClientWmTest, SetBoundsFailedWithPendingChange) {
253 const gfx::Rect original_bounds(root_window()->bounds());
254 const gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100));
255 ASSERT_NE(new_bounds, root_window()->bounds());
256 root_window()->SetBounds(new_bounds);
257 EXPECT_EQ(new_bounds, root_window()->bounds());
258
259 // Simulate the server responding with a bounds change.
260 const gfx::Rect server_changed_bounds(gfx::Rect(0, 0, 101, 102));
261 window_tree_client()->OnWindowBoundsChanged(
262 server_id(root_window()), original_bounds, server_changed_bounds);
263
264 // This shouldn't trigger the bounds changing yet.
265 EXPECT_EQ(new_bounds, root_window()->bounds());
266
267 // Tell the client the change failed, which should trigger failing to the
268 // most recent bounds from server.
269 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(WindowTreeChangeType::BOUNDS,
270 false));
271 EXPECT_EQ(server_changed_bounds, root_window()->bounds());
272
273 // Simulate server changing back to original bounds. Should take immediately.
274 window_tree_client()->OnWindowBoundsChanged(
275 server_id(root_window()), server_changed_bounds, original_bounds);
276 EXPECT_EQ(original_bounds, root_window()->bounds());
277 }
278
279 TEST_F(WindowTreeClientWmTest, TwoInFlightBoundsChangesBothCanceled) {
280 const gfx::Rect original_bounds(root_window()->bounds());
281 const gfx::Rect bounds1(gfx::Rect(0, 0, 100, 100));
282 const gfx::Rect bounds2(gfx::Rect(0, 0, 100, 102));
283 root_window()->SetBounds(bounds1);
284 EXPECT_EQ(bounds1, root_window()->bounds());
285
286 root_window()->SetBounds(bounds2);
287 EXPECT_EQ(bounds2, root_window()->bounds());
288
289 // Tell the client the first bounds failed. As there is a still a change in
290 // flight nothing should happen.
291 ASSERT_TRUE(
292 window_tree()->AckFirstChangeOfType(WindowTreeChangeType::BOUNDS, false));
293 EXPECT_EQ(bounds2, root_window()->bounds());
294
295 // Tell the client the seconds bounds failed. Should now fallback to original
296 // value.
297 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(WindowTreeChangeType::BOUNDS,
298 false));
299 EXPECT_EQ(original_bounds, root_window()->bounds());
300 }
301
302 // Verifies properties are reverted if the server replied that the change
303 // failed.
304 TEST_F(WindowTreeClientWmTest, SetPropertyFailed) {
305 SetPropertyConverter(base::MakeUnique<TestPropertyConverter>());
306 ASSERT_FALSE(root_window()->GetProperty(client::kAlwaysOnTopKey));
307 root_window()->SetProperty(client::kAlwaysOnTopKey, true);
308 EXPECT_TRUE(root_window()->GetProperty(client::kAlwaysOnTopKey));
309 mojo::Array<uint8_t> transport_value = window_tree()->GetLastPropertyValue();
310 ASSERT_FALSE(transport_value.is_null());
311 ASSERT_EQ(1u, transport_value.size());
312 EXPECT_EQ(1, transport_value[0]);
313 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
314 WindowTreeChangeType::PROPERTY, false));
315 EXPECT_FALSE(root_window()->GetProperty(client::kAlwaysOnTopKey));
316 }
317
318 // Simulates a property change, and while the property change is in flight the
319 // server replies with a new property and the original property change fails.
320 TEST_F(WindowTreeClientWmTest, SetPropertyFailedWithPendingChange) {
321 SetPropertyConverter(base::MakeUnique<TestPropertyConverter>());
322 const uint8_t value1 = 11;
323 root_window()->SetProperty(kTestPropertyKey1, value1);
324 EXPECT_EQ(value1, root_window()->GetProperty(kTestPropertyKey1));
325
326 // Simulate the server responding with a different value.
327 const uint8_t server_value = 12;
328 window_tree_client()->OnWindowSharedPropertyChanged(
329 server_id(root_window()), kTestPropertyServerKey1,
330 Uint8ToPropertyTransportValue(server_value));
331
332 // This shouldn't trigger the property changing yet.
333 EXPECT_EQ(value1, root_window()->GetProperty(kTestPropertyKey1));
334
335 // Tell the client the change failed, which should trigger failing to the
336 // most recent value from server.
337 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
338 WindowTreeChangeType::PROPERTY, false));
339 EXPECT_EQ(server_value, root_window()->GetProperty(kTestPropertyKey1));
340
341 // Simulate server changing back to value1. Should take immediately.
342 window_tree_client()->OnWindowSharedPropertyChanged(
343 server_id(root_window()), kTestPropertyServerKey1,
344 Uint8ToPropertyTransportValue(value1));
345 EXPECT_EQ(value1, root_window()->GetProperty(kTestPropertyKey1));
346 }
347
348 // Verifies visible is reverted if the server replied that the change failed.
349 TEST_F(WindowTreeClientWmTest, SetVisibleFailed) {
350 const bool original_visible = root_window()->TargetVisibility();
351 const bool new_visible = !original_visible;
352 SetWindowVisibility(root_window(), new_visible);
353 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
354 WindowTreeChangeType::VISIBLE, false));
355 EXPECT_EQ(original_visible, root_window()->TargetVisibility());
356 }
357
358 // Simulates a visible change, and while the visible change is in flight the
359 // server replies with a new visible and the original visible change fails.
360 TEST_F(WindowTreeClientWmTest, SetVisibleFailedWithPendingChange) {
361 const bool original_visible = root_window()->TargetVisibility();
362 const bool new_visible = !original_visible;
363 SetWindowVisibility(root_window(), new_visible);
364 EXPECT_EQ(new_visible, root_window()->TargetVisibility());
365
366 // Simulate the server responding with a visible change.
367 const bool server_changed_visible = !new_visible;
368 window_tree_client()->OnWindowVisibilityChanged(server_id(root_window()),
369 server_changed_visible);
370
371 // This shouldn't trigger visible changing yet.
372 EXPECT_EQ(new_visible, root_window()->TargetVisibility());
373
374 // Tell the client the change failed, which should trigger failing to the
375 // most recent visible from server.
376 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
377 WindowTreeChangeType::VISIBLE, false));
378 EXPECT_EQ(server_changed_visible, root_window()->TargetVisibility());
379
380 // Simulate server changing back to original visible. Should take immediately.
381 window_tree_client()->OnWindowVisibilityChanged(server_id(root_window()),
382 original_visible);
383 EXPECT_EQ(original_visible, root_window()->TargetVisibility());
384 }
385
386 /*
387 // Verifies |is_modal| is reverted if the server replied that the change failed.
388 TEST_F(WindowTreeClientWmTest, SetModalFailed) {
389 WindowTreeSetup setup;
390 Window* root = GetFirstRoot();
391 ASSERT_TRUE(root);
392 EXPECT_FALSE(root->is_modal());
393 root->SetModal();
394 uint32_t change_id;
395 ASSERT_TRUE(window_tree()->GetAndClearChangeId(&change_id));
396 EXPECT_TRUE(root->is_modal());
397 window_tree_client()->OnChangeCompleted(change_id, false);
398 EXPECT_FALSE(root->is_modal());
399 }
400 */
401
402 namespace {
403
404 class InputEventBasicTestWindowDelegate : public test::TestWindowDelegate {
405 public:
406 static uint32_t constexpr kEventId = 1;
407
408 explicit InputEventBasicTestWindowDelegate(TestWindowTree* test_window_tree)
409 : test_window_tree_(test_window_tree) {}
410 ~InputEventBasicTestWindowDelegate() override {}
411
412 bool got_move() const { return got_move_; }
413 bool was_acked() const { return was_acked_; }
414
415 // TestWindowDelegate::
416 void OnMouseEvent(ui::MouseEvent* event) override {
417 was_acked_ = test_window_tree_->WasEventAcked(kEventId);
418 if (event->type() == ui::ET_MOUSE_MOVED)
419 got_move_ = true;
420 }
421
422 private:
423 TestWindowTree* test_window_tree_;
424 bool was_acked_ = false;
425 bool got_move_ = false;
426
427 DISALLOW_COPY_AND_ASSIGN(InputEventBasicTestWindowDelegate);
428 };
429
430 } // namespace
431
432 TEST_F(WindowTreeClientClientTest, InputEventBasic) {
433 InputEventBasicTestWindowDelegate window_delegate(window_tree());
434 std::unique_ptr<Window> top_level(base::MakeUnique<Window>(&window_delegate));
435 top_level->SetType(ui::wm::WINDOW_TYPE_NORMAL);
436 top_level->Init(ui::LAYER_NOT_DRAWN);
437 top_level->SetBounds(gfx::Rect(0, 0, 100, 100));
438 top_level->Show();
439 EXPECT_FALSE(window_delegate.got_move());
440 EXPECT_FALSE(window_delegate.was_acked());
441 std::unique_ptr<ui::Event> ui_event(
442 new ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
443 ui::EventTimeForNow(), ui::EF_NONE, 0));
444 window_tree_client()->OnWindowInputEvent(
445 InputEventBasicTestWindowDelegate::kEventId, server_id(top_level.get()),
446 ui::Event::Clone(*ui_event.get()), 0);
447 EXPECT_TRUE(window_tree()->WasEventAcked(1));
448 EXPECT_TRUE(window_delegate.got_move());
449 EXPECT_FALSE(window_delegate.was_acked());
450 }
451
452 class WindowTreeClientPointerObserverTest : public WindowTreeClientClientTest {
453 public:
454 WindowTreeClientPointerObserverTest() {}
455 ~WindowTreeClientPointerObserverTest() override {}
456
457 void DeleteLastEventObserved() { last_event_observed_.reset(); }
458 const ui::PointerEvent* last_event_observed() const {
459 return last_event_observed_.get();
460 }
461
462 // WindowTreeClientClientTest:
463 void OnPointerEventObserved(const ui::PointerEvent& event,
464 Window* target) override {
465 last_event_observed_.reset(new ui::PointerEvent(event));
466 }
467
468 private:
469 std::unique_ptr<ui::PointerEvent> last_event_observed_;
470
471 DISALLOW_COPY_AND_ASSIGN(WindowTreeClientPointerObserverTest);
472 };
473
474 // Tests pointer watchers triggered by events that did not hit a target in this
475 // window tree.
476 TEST_F(WindowTreeClientPointerObserverTest, OnPointerEventObserved) {
477 std::unique_ptr<Window> top_level(base::MakeUnique<Window>(nullptr));
478 top_level->SetType(ui::wm::WINDOW_TYPE_NORMAL);
479 top_level->Init(ui::LAYER_NOT_DRAWN);
480 top_level->SetBounds(gfx::Rect(0, 0, 100, 100));
481 top_level->Show();
482
483 // Start a pointer watcher for all events excluding move events.
484 window_tree_client_impl()->StartPointerWatcher(false /* want_moves */);
485
486 // Simulate the server sending an observed event.
487 std::unique_ptr<ui::PointerEvent> pointer_event_down(new ui::PointerEvent(
488 ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_CONTROL_DOWN, 1,
489 0, ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH),
490 base::TimeTicks()));
491 window_tree_client()->OnPointerEventObserved(std::move(pointer_event_down),
492 0u);
493
494 // Delegate sensed the event.
495 const ui::PointerEvent* last_event = last_event_observed();
496 ASSERT_TRUE(last_event);
497 EXPECT_EQ(ui::ET_POINTER_DOWN, last_event->type());
498 EXPECT_EQ(ui::EF_CONTROL_DOWN, last_event->flags());
499 DeleteLastEventObserved();
500
501 // Stop the pointer watcher.
502 window_tree_client_impl()->StopPointerWatcher();
503
504 // Simulate another event from the server.
505 std::unique_ptr<ui::PointerEvent> pointer_event_up(new ui::PointerEvent(
506 ui::ET_POINTER_UP, gfx::Point(), gfx::Point(), ui::EF_CONTROL_DOWN, 1, 0,
507 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH),
508 base::TimeTicks()));
509 window_tree_client()->OnPointerEventObserved(std::move(pointer_event_up), 0u);
510
511 // No event was sensed.
512 EXPECT_FALSE(last_event_observed());
513 }
514
515 // Tests pointer watchers triggered by events that hit this window tree.
516 TEST_F(WindowTreeClientPointerObserverTest,
517 OnWindowInputEventWithPointerWatcher) {
518 std::unique_ptr<Window> top_level(base::MakeUnique<Window>(nullptr));
519 top_level->SetType(ui::wm::WINDOW_TYPE_NORMAL);
520 top_level->Init(ui::LAYER_NOT_DRAWN);
521 top_level->SetBounds(gfx::Rect(0, 0, 100, 100));
522 top_level->Show();
523
524 // Start a pointer watcher for all events excluding move events.
525 window_tree_client_impl()->StartPointerWatcher(false /* want_moves */);
526
527 // Simulate the server dispatching an event that also matched the observer.
528 std::unique_ptr<ui::PointerEvent> pointer_event_down(new ui::PointerEvent(
529 ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_CONTROL_DOWN, 1,
530 0, ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH),
531 base::TimeTicks::Now()));
532 window_tree_client()->OnWindowInputEvent(1, server_id(top_level.get()),
533 std::move(pointer_event_down), true);
534
535 // Delegate sensed the event.
536 const ui::Event* last_event = last_event_observed();
537 ASSERT_TRUE(last_event);
538 EXPECT_EQ(ui::ET_POINTER_DOWN, last_event->type());
539 EXPECT_EQ(ui::EF_CONTROL_DOWN, last_event->flags());
540 }
541
542 // Verifies focus is reverted if the server replied that the change failed.
543 TEST_F(WindowTreeClientWmTest, SetFocusFailed) {
544 Window child(nullptr);
545 child.Init(ui::LAYER_NOT_DRAWN);
546 root_window()->AddChild(&child);
547 child.Focus();
548 ASSERT_TRUE(child.HasFocus());
549 ASSERT_TRUE(
550 window_tree()->AckSingleChangeOfType(WindowTreeChangeType::FOCUS, false));
551 EXPECT_EQ(nullptr, client::GetFocusClient(&child)->GetFocusedWindow());
552 }
553
554 // Simulates a focus change, and while the focus change is in flight the server
555 // replies with a new focus and the original focus change fails.
556 TEST_F(WindowTreeClientWmTest, SetFocusFailedWithPendingChange) {
557 Window child1(nullptr);
558 child1.Init(ui::LAYER_NOT_DRAWN);
559 root_window()->AddChild(&child1);
560 Window child2(nullptr);
561 child2.Init(ui::LAYER_NOT_DRAWN);
562 root_window()->AddChild(&child2);
563 Window* original_focus = client::GetFocusClient(&child1)->GetFocusedWindow();
564 Window* new_focus = &child1;
565 ASSERT_NE(new_focus, original_focus);
566 new_focus->Focus();
567 ASSERT_TRUE(new_focus->HasFocus());
568
569 // Simulate the server responding with a focus change.
570 window_tree_client()->OnWindowFocused(server_id(&child2));
571
572 // This shouldn't trigger focus changing yet.
573 EXPECT_TRUE(child1.HasFocus());
574
575 // Tell the client the change failed, which should trigger failing to the
576 // most recent focus from server.
577 ASSERT_TRUE(
578 window_tree()->AckSingleChangeOfType(WindowTreeChangeType::FOCUS, false));
579 EXPECT_FALSE(child1.HasFocus());
580 EXPECT_TRUE(child2.HasFocus());
581 EXPECT_EQ(&child2, client::GetFocusClient(&child1)->GetFocusedWindow());
582
583 // Simulate server changing focus to child1. Should take immediately.
584 window_tree_client()->OnWindowFocused(server_id(&child1));
585 EXPECT_TRUE(child1.HasFocus());
586 }
587
588 TEST_F(WindowTreeClientWmTest, FocusOnRemovedWindowWithInFlightFocusChange) {
589 std::unique_ptr<Window> child1(base::MakeUnique<Window>(nullptr));
590 child1->Init(ui::LAYER_NOT_DRAWN);
591 root_window()->AddChild(child1.get());
592 Window child2(nullptr);
593 child2.Init(ui::LAYER_NOT_DRAWN);
594 root_window()->AddChild(&child2);
595
596 child1->Focus();
597
598 // Destroy child1, which should set focus to null.
599 child1.reset(nullptr);
600 EXPECT_EQ(nullptr, client::GetFocusClient(root_window())->GetFocusedWindow());
601
602 // Server changes focus to 2.
603 window_tree_client()->OnWindowFocused(server_id(&child2));
604 // Shouldn't take immediately.
605 EXPECT_FALSE(child2.HasFocus());
606
607 // Ack both changes, focus should still be null.
608 ASSERT_TRUE(
609 window_tree()->AckFirstChangeOfType(WindowTreeChangeType::FOCUS, true));
610 EXPECT_EQ(nullptr, client::GetFocusClient(root_window())->GetFocusedWindow());
611 ASSERT_TRUE(
612 window_tree()->AckSingleChangeOfType(WindowTreeChangeType::FOCUS, true));
613 EXPECT_EQ(nullptr, client::GetFocusClient(root_window())->GetFocusedWindow());
614
615 // Change to 2 again, this time it should take.
616 window_tree_client()->OnWindowFocused(server_id(&child2));
617 EXPECT_TRUE(child2.HasFocus());
618 }
619
620 class ToggleVisibilityFromDestroyedObserver : public WindowObserver {
621 public:
622 explicit ToggleVisibilityFromDestroyedObserver(Window* window)
623 : window_(window) {
624 window_->AddObserver(this);
625 }
626
627 ToggleVisibilityFromDestroyedObserver() { EXPECT_FALSE(window_); }
628
629 // WindowObserver:
630 void OnWindowDestroyed(Window* window) override {
631 SetWindowVisibility(window, !window->TargetVisibility());
632 window_->RemoveObserver(this);
633 window_ = nullptr;
634 }
635
636 private:
637 Window* window_;
638
639 DISALLOW_COPY_AND_ASSIGN(ToggleVisibilityFromDestroyedObserver);
640 };
641
642 TEST_F(WindowTreeClientWmTest, ToggleVisibilityFromWindowDestroyed) {
643 std::unique_ptr<Window> child(base::MakeUnique<Window>(nullptr));
644 child->Init(ui::LAYER_NOT_DRAWN);
645 root_window()->AddChild(child.get());
646 ToggleVisibilityFromDestroyedObserver toggler(child.get());
647 // Destroying the window triggers
648 // ToggleVisibilityFromDestroyedObserver::OnWindowDestroyed(), which toggles
649 // the visibility of the window. Ack the change, which should not crash or
650 // trigger DCHECKs.
651 child.reset();
652 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
653 WindowTreeChangeType::VISIBLE, true));
654 }
655
656 TEST_F(WindowTreeClientClientTest, NewTopLevelWindow) {
657 const size_t initial_root_count =
658 window_tree_client_impl()->GetRoots().size();
659 std::unique_ptr<Window> top_level(base::MakeUnique<Window>(nullptr));
660 top_level->SetType(ui::wm::WINDOW_TYPE_NORMAL);
661 top_level->Init(ui::LAYER_NOT_DRAWN);
662 // TODO: need to check WindowTreeHost visibility.
663 // EXPECT_TRUE(WindowPrivate(root2).parent_drawn());
664 EXPECT_NE(server_id(top_level.get()), server_id(root_window()));
665 EXPECT_EQ(initial_root_count + 1,
666 window_tree_client_impl()->GetRoots().size());
667 EXPECT_TRUE(window_tree_client_impl()->GetRoots().count(top_level.get()) >
668 0u);
669
670 // Ack the request to the windowtree to create the new window.
671 uint32_t change_id;
672 ASSERT_TRUE(window_tree()->GetAndRemoveFirstChangeOfType(
673 WindowTreeChangeType::NEW_TOP_LEVEL, &change_id));
674 EXPECT_EQ(window_tree()->window_id(), server_id(top_level.get()));
675
676 ui::mojom::WindowDataPtr data = ui::mojom::WindowData::New();
677 data->window_id = server_id(top_level.get());
678 const int64_t display_id = 1;
679 window_tree_client()->OnTopLevelCreated(change_id, std::move(data),
680 display_id, false);
681
682 // TODO: need to check WindowTreeHost visibility.
683 // EXPECT_FALSE(WindowPrivate(root2).parent_drawn());
684
685 // Should not be able to add a top level as a child of another window.
686 // TODO(sky): decide how to handle this.
687 // root_window()->AddChild(top_level.get());
688 // ASSERT_EQ(nullptr, top_level->parent());
689
690 // Destroy the first root, shouldn't initiate tear down.
691 top_level.reset();
692 EXPECT_EQ(initial_root_count, window_tree_client_impl()->GetRoots().size());
693 }
694
695 TEST_F(WindowTreeClientClientTest, NewTopLevelWindowGetsPropertiesFromData) {
696 const size_t initial_root_count =
697 window_tree_client_impl()->GetRoots().size();
698 std::unique_ptr<Window> top_level(base::MakeUnique<Window>(nullptr));
699 top_level->SetType(ui::wm::WINDOW_TYPE_NORMAL);
700 top_level->Init(ui::LAYER_NOT_DRAWN);
701 EXPECT_EQ(initial_root_count + 1,
702 window_tree_client_impl()->GetRoots().size());
703
704 // TODO: check drawn.
705 // EXPECT_FALSE(root2->IsDrawn());
706 EXPECT_FALSE(top_level->TargetVisibility());
707
708 // Ack the request to the windowtree to create the new window.
709 EXPECT_EQ(window_tree()->window_id(), server_id(top_level.get()));
710
711 ui::mojom::WindowDataPtr data = ui::mojom::WindowData::New();
712 data->window_id = server_id(top_level.get());
713 data->bounds.SetRect(1, 2, 3, 4);
714 data->visible = true;
715 const int64_t display_id = 1;
716 uint32_t change_id;
717 ASSERT_TRUE(window_tree()->GetAndRemoveFirstChangeOfType(
718 WindowTreeChangeType::NEW_TOP_LEVEL, &change_id));
719 window_tree_client()->OnTopLevelCreated(change_id, std::move(data),
720 display_id, true);
721
722 // Make sure all the properties took.
723 // EXPECT_TRUE(root2->IsDrawn());
724 EXPECT_TRUE(top_level->TargetVisibility());
725 // TODO: check display_id.
726 // EXPECT_EQ(1, root2->display_id());
727 EXPECT_EQ(gfx::Rect(1, 2, 3, 4), top_level->bounds());
728 }
729
730 TEST_F(WindowTreeClientClientTest, NewWindowGetsAllChangesInFlight) {
731 SetPropertyConverter(base::MakeUnique<TestPropertyConverter>());
732
733 Window window(nullptr);
734 window.Init(ui::LAYER_NOT_DRAWN);
735
736 EXPECT_FALSE(window.TargetVisibility());
737
738 // Make visibility go from false->true->false. Don't ack immediately.
739 window.Show();
740 window.Hide();
741
742 // Change bounds to 5, 6, 7, 8.
743 window.SetBounds(gfx::Rect(5, 6, 7, 8));
744
745 const uint8_t explicitly_set_test_property1_value = 2;
746 window.SetProperty(kTestPropertyKey1, explicitly_set_test_property1_value);
747
748 // Ack the new window top level window. Vis and bounds shouldn't change.
749 ui::mojom::WindowDataPtr data = ui::mojom::WindowData::New();
750 data->window_id = server_id(&window);
751 data->bounds.SetRect(1, 2, 3, 4);
752 data->visible = true;
753 const uint8_t server_test_property1_value = 3;
754 data->properties[kTestPropertyServerKey1] =
755 Uint8ToPropertyTransportValue(server_test_property1_value);
756 const uint8_t server_test_property2_value = 4;
757 data->properties[kTestPropertyServerKey2] =
758 Uint8ToPropertyTransportValue(server_test_property2_value);
759 const int64_t display_id = 1;
760 // Get the id of the in flight change for creating the new window.
761 uint32_t new_window_in_flight_change_id;
762 ASSERT_TRUE(window_tree()->GetAndRemoveFirstChangeOfType(
763 WindowTreeChangeType::NEW_WINDOW, &new_window_in_flight_change_id));
764 window_tree_client()->OnTopLevelCreated(new_window_in_flight_change_id,
765 std::move(data), display_id, true);
766
767 // The only value that should take effect is the property for 'yy' as it was
768 // not in flight.
769 EXPECT_FALSE(window.TargetVisibility());
770 EXPECT_EQ(gfx::Rect(5, 6, 7, 8), window.bounds());
771 EXPECT_EQ(explicitly_set_test_property1_value,
772 window.GetProperty(kTestPropertyKey1));
773 EXPECT_EQ(server_test_property2_value, window.GetProperty(kTestPropertyKey2));
774
775 // Tell the client the changes failed. This should cause the values to change
776 // to that of the server.
777 ASSERT_TRUE(window_tree()->AckFirstChangeOfType(WindowTreeChangeType::VISIBLE,
778 false));
779 EXPECT_FALSE(window.TargetVisibility());
780 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
781 WindowTreeChangeType::VISIBLE, false));
782 EXPECT_TRUE(window.TargetVisibility());
783 window_tree()->AckAllChangesOfType(WindowTreeChangeType::BOUNDS, false);
784 EXPECT_EQ(gfx::Rect(1, 2, 3, 4), window.bounds());
785 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
786 WindowTreeChangeType::PROPERTY, false));
787 EXPECT_EQ(server_test_property1_value, window.GetProperty(kTestPropertyKey1));
788 EXPECT_EQ(server_test_property2_value, window.GetProperty(kTestPropertyKey2));
789 }
790
791 TEST_F(WindowTreeClientClientTest, NewWindowGetsProperties) {
792 SetPropertyConverter(base::MakeUnique<TestPropertyConverter>());
793 Window window(nullptr);
794 const uint8_t explicitly_set_test_property1_value = 29;
795 window.SetProperty(kTestPropertyKey1, explicitly_set_test_property1_value);
796 window.Init(ui::LAYER_NOT_DRAWN);
797 mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties =
798 window_tree()->GetLastNewWindowProperties();
799 ASSERT_FALSE(transport_properties.is_null());
800 std::map<std::string, std::vector<uint8_t>> properties =
801 transport_properties.To<std::map<std::string, std::vector<uint8_t>>>();
802 ASSERT_EQ(1u, properties.count(kTestPropertyServerKey1));
803 ASSERT_EQ(1u, properties[kTestPropertyServerKey1].size());
804 EXPECT_EQ(explicitly_set_test_property1_value,
805 properties[kTestPropertyServerKey1][0]);
806 ASSERT_EQ(0u, properties.count(kTestPropertyServerKey2));
807 }
808
809 /*
810 // Tests that if the client has multiple unowned windows, and one of them is a
811 // transient child to another, the teardown can happen cleanly.
812 TEST_F(WindowTreeClientWmTest, MultipleUnOwnedWindowsDuringDestruction) {
813 std::unique_ptr<WindowTreeSetup> setup(new WindowTreeSetup());
814 Window* root1 = setup->GetFirstRoot();
815 ASSERT_TRUE(root1);
816 Window* root2 = setup->client()->NewTopLevelWindow(nullptr);
817 ASSERT_TRUE(root2);
818 root1->AddTransientWindow(root2);
819
820 WindowTracker tracker;
821 tracker.Add(root1);
822 tracker.Add(root2);
823 reset();
824 EXPECT_TRUE(tracker.windows().empty());
825 }
826 */
827
828 TEST_F(WindowTreeClientClientTest,
829 TopLevelWindowDestroyedBeforeCreateComplete) {
830 const size_t initial_root_count =
831 window_tree_client_impl()->GetRoots().size();
832 std::unique_ptr<Window> top_level(base::MakeUnique<Window>(nullptr));
833 top_level->SetType(ui::wm::WINDOW_TYPE_NORMAL);
834 top_level->Init(ui::LAYER_NOT_DRAWN);
835 EXPECT_EQ(initial_root_count + 1,
836 window_tree_client_impl()->GetRoots().size());
837
838 ui::mojom::WindowDataPtr data = ui::mojom::WindowData::New();
839 data->window_id = server_id(top_level.get());
840
841 // Destroy the window before the server has a chance to ack the window
842 // creation.
843 top_level.reset();
844 EXPECT_EQ(initial_root_count, window_tree_client_impl()->GetRoots().size());
845
846 // Get the id of the in flight change for creating the new window.
847 uint32_t change_id;
848 ASSERT_TRUE(window_tree()->GetAndRemoveFirstChangeOfType(
849 WindowTreeChangeType::NEW_TOP_LEVEL, &change_id));
850
851 const int64_t display_id = 1;
852 window_tree_client()->OnTopLevelCreated(change_id, std::move(data),
853 display_id, true);
854 EXPECT_EQ(initial_root_count, window_tree_client_impl()->GetRoots().size());
855 }
856
857 // Tests both SetCapture and ReleaseCapture, to ensure that Window is properly
858 // updated on failures.
859 TEST_F(WindowTreeClientWmTest, ExplicitCapture) {
860 root_window()->SetCapture();
861 EXPECT_TRUE(root_window()->HasCapture());
862 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
863 WindowTreeChangeType::CAPTURE, false));
864 EXPECT_FALSE(root_window()->HasCapture());
865
866 root_window()->SetCapture();
867 EXPECT_TRUE(root_window()->HasCapture());
868 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
869 WindowTreeChangeType::CAPTURE, true));
870 EXPECT_TRUE(root_window()->HasCapture());
871
872 root_window()->ReleaseCapture();
873 EXPECT_FALSE(root_window()->HasCapture());
874 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
875 WindowTreeChangeType::CAPTURE, false));
876 EXPECT_TRUE(root_window()->HasCapture());
877
878 root_window()->ReleaseCapture();
879 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
880 WindowTreeChangeType::CAPTURE, true));
881 EXPECT_FALSE(root_window()->HasCapture());
882 }
883
884 // Tests that when capture is lost, while there is a release capture request
885 // inflight, that the revert value of that request is updated correctly.
886 TEST_F(WindowTreeClientWmTest, LostCaptureDifferentInFlightChange) {
887 root_window()->SetCapture();
888 EXPECT_TRUE(root_window()->HasCapture());
889 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
890 WindowTreeChangeType::CAPTURE, true));
891 EXPECT_TRUE(root_window()->HasCapture());
892
893 // The ReleaseCapture should be updated to the revert of the SetCapture.
894 root_window()->ReleaseCapture();
895
896 window_tree_client()->OnCaptureChanged(0, server_id(root_window()));
897 EXPECT_FALSE(root_window()->HasCapture());
898
899 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
900 WindowTreeChangeType::CAPTURE, false));
901 EXPECT_FALSE(root_window()->HasCapture());
902 }
903
904 // Tests that while two windows can inflight capture requests, that the
905 // WindowTreeClient only identifies one as having the current capture.
906 TEST_F(WindowTreeClientWmTest, TwoWindowsRequestCapture) {
907 Window child(nullptr);
908 child.Init(ui::LAYER_NOT_DRAWN);
909 root_window()->AddChild(&child);
910 child.Show();
911
912 root_window()->SetCapture();
913 EXPECT_TRUE(root_window()->HasCapture());
914
915 child.SetCapture();
916 EXPECT_TRUE(child.HasCapture());
917 EXPECT_FALSE(root_window()->HasCapture());
918
919 ASSERT_TRUE(
920 window_tree()->AckFirstChangeOfType(WindowTreeChangeType::CAPTURE, true));
921 EXPECT_FALSE(root_window()->HasCapture());
922 EXPECT_TRUE(child.HasCapture());
923
924 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
925 WindowTreeChangeType::CAPTURE, false));
926 EXPECT_FALSE(child.HasCapture());
927 EXPECT_TRUE(root_window()->HasCapture());
928
929 window_tree_client()->OnCaptureChanged(0, server_id(root_window()));
930 EXPECT_FALSE(root_window()->HasCapture());
931 }
932
933 /*
934 TEST_F(WindowTreeClientWmTest, WindowDestroyedWhileTransientChildHasCapture) {
935 WindowTreeSetup setup;
936 Window* root = GetFirstRoot();
937 Window* transient_parent = client()->NewWindow();
938 Window* transient_child = client()->NewWindow();
939 transient_parent->SetVisible(true);
940 transient_child->SetVisible(true);
941 root->AddChild(transient_parent);
942 root->AddChild(transient_child);
943
944 transient_parent->AddTransientWindow(transient_child);
945
946 WindowTracker tracker;
947 tracker.Add(transient_parent);
948 tracker.Add(transient_child);
949 // Request a capture on the transient child, then destroy the transient
950 // parent. That will destroy both windows, and should reset the capture window
951 // correctly.
952 transient_child->SetCapture();
953 transient_parent->Destroy();
954 EXPECT_TRUE(tracker.windows().empty());
955
956 // Create a new Window, and attempt to place capture on that.
957 Window* child = client()->NewWindow();
958 child->SetVisible(true);
959 root->AddChild(child);
960 child->SetCapture();
961 EXPECT_TRUE(child->HasCapture());
962 }
963 */
964
965 namespace {
966
967 class CaptureRecorder : public client::CaptureClientObserver {
968 public:
969 explicit CaptureRecorder(Window* root_window) : root_window_(root_window) {
970 client::GetCaptureClient(root_window)->AddObserver(this);
971 }
972
973 ~CaptureRecorder() override {
974 client::GetCaptureClient(root_window_)->RemoveObserver(this);
975 }
976
977 void reset_capture_captured_count() { capture_changed_count_ = 0; }
978 int capture_changed_count() const { return capture_changed_count_; }
979 int last_gained_capture_window_id() const {
980 return last_gained_capture_window_id_;
981 }
982 int last_lost_capture_window_id() const {
983 return last_lost_capture_window_id_;
984 }
985
986 // client::CaptureClientObserver:
987 void OnCaptureChanged(Window* lost_capture, Window* gained_capture) override {
988 capture_changed_count_++;
989 last_gained_capture_window_id_ = gained_capture ? gained_capture->id() : 0;
990 last_lost_capture_window_id_ = lost_capture ? lost_capture->id() : 0;
991 }
992
993 private:
994 Window* root_window_;
995 int capture_changed_count_ = 0;
996 int last_gained_capture_window_id_ = 0;
997 int last_lost_capture_window_id_ = 0;
998
999 DISALLOW_COPY_AND_ASSIGN(CaptureRecorder);
1000 };
1001
1002 } // namespace
1003
1004 TEST_F(WindowTreeClientWmTest, OnWindowTreeCaptureChanged) {
1005 CaptureRecorder capture_recorder(root_window());
1006
1007 std::unique_ptr<Window> child1(base::MakeUnique<Window>(nullptr));
1008 const int child1_id = 1;
1009 child1->Init(ui::LAYER_NOT_DRAWN);
1010 child1->set_id(child1_id);
1011 child1->Show();
1012 root_window()->AddChild(child1.get());
1013
1014 Window child2(nullptr);
1015 const int child2_id = 2;
1016 child2.Init(ui::LAYER_NOT_DRAWN);
1017 child2.set_id(child2_id);
1018 child2.Show();
1019 root_window()->AddChild(&child2);
1020
1021 EXPECT_EQ(0, capture_recorder.capture_changed_count());
1022 // Give capture to child1 and ensure everyone is notified correctly.
1023 child1->SetCapture();
1024 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
1025 WindowTreeChangeType::CAPTURE, true));
1026 EXPECT_EQ(1, capture_recorder.capture_changed_count());
1027 EXPECT_EQ(child1_id, capture_recorder.last_gained_capture_window_id());
1028 EXPECT_EQ(0, capture_recorder.last_lost_capture_window_id());
1029 capture_recorder.reset_capture_captured_count();
1030
1031 // Deleting a window with capture should notify observers as well.
1032 child1.reset();
1033
1034 // Deletion implicitly releases focus.
1035 ASSERT_TRUE(window_tree()->AckSingleChangeOfType(
1036 WindowTreeChangeType::CAPTURE, true));
1037
1038 EXPECT_EQ(1, capture_recorder.capture_changed_count());
1039 EXPECT_EQ(0, capture_recorder.last_gained_capture_window_id());
1040 EXPECT_EQ(child1_id, capture_recorder.last_lost_capture_window_id());
1041 capture_recorder.reset_capture_captured_count();
1042
1043 // Changes originating from server should notify observers too.
1044 window_tree_client()->OnCaptureChanged(server_id(&child2), 0);
1045 EXPECT_EQ(1, capture_recorder.capture_changed_count());
1046 EXPECT_EQ(child2_id, capture_recorder.last_gained_capture_window_id());
1047 EXPECT_EQ(0, capture_recorder.last_lost_capture_window_id());
1048 capture_recorder.reset_capture_captured_count();
1049 }
1050
1051 } // namespace aura
OLDNEW
« no previous file with comments | « ui/aura/mus/window_tree_client_observer.h ('k') | ui/aura/mus/window_tree_host_mus.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698