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

Side by Side Diff: services/ui/public/cpp/tests/window_unittest.cc

Issue 2651593002: mus: Remove the old client lib. (Closed)
Patch Set: restore test Created 3 years, 10 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 2014 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 "services/ui/public/cpp/window.h"
6
7 #include <limits.h>
8 #include <stdint.h>
9
10 #include "base/logging.h"
11 #include "base/macros.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringprintf.h"
14 #include "services/ui/common/util.h"
15 #include "services/ui/public/cpp/property_type_converters.h"
16 #include "services/ui/public/cpp/tests/test_window.h"
17 #include "services/ui/public/cpp/window_observer.h"
18 #include "services/ui/public/cpp/window_private.h"
19 #include "services/ui/public/cpp/window_property.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/gfx/geometry/rect.h"
22
23 namespace ui {
24
25 namespace {
26
27 TestWindow* CreateTestWindow(TestWindow* parent) {
28 TestWindow* window = new TestWindow;
29 if (parent)
30 parent->AddChild(window);
31 return window;
32 }
33
34 TestWindow* CreateTestWindow(int id, TestWindow* parent) {
35 TestWindow* window = new TestWindow(0);
36 window->set_local_id(id);
37 if (parent)
38 parent->AddChild(window);
39 return window;
40 }
41
42 std::string ChildWindowIDsAsString(TestWindow* parent) {
43 std::string result;
44 for (Window* child : parent->children()) {
45 if (!result.empty())
46 result += " ";
47 result += base::IntToString(child->local_id());
48 }
49 return result;
50 }
51
52 } // namespace
53 // Window ---------------------------------------------------------------------
54
55 using WindowTest = testing::Test;
56
57 TEST_F(WindowTest, AddChild) {
58 TestWindow w1;
59 TestWindow w11;
60 w1.AddChild(&w11);
61 EXPECT_EQ(1U, w1.children().size());
62 }
63
64 TEST_F(WindowTest, RemoveChild) {
65 TestWindow w1;
66 TestWindow w11;
67 w1.AddChild(&w11);
68 EXPECT_EQ(1U, w1.children().size());
69 w1.RemoveChild(&w11);
70 EXPECT_EQ(0U, w1.children().size());
71 }
72
73 TEST_F(WindowTest, Reparent) {
74 TestWindow w1;
75 TestWindow w2;
76 TestWindow w11;
77 w1.AddChild(&w11);
78 EXPECT_EQ(1U, w1.children().size());
79 w2.AddChild(&w11);
80 EXPECT_EQ(1U, w2.children().size());
81 EXPECT_EQ(0U, w1.children().size());
82 }
83
84 TEST_F(WindowTest, Contains) {
85 TestWindow w1;
86
87 // Direct descendant.
88 TestWindow w11;
89 w1.AddChild(&w11);
90 EXPECT_TRUE(w1.Contains(&w11));
91
92 // Indirect descendant.
93 TestWindow w111;
94 w11.AddChild(&w111);
95 EXPECT_TRUE(w1.Contains(&w111));
96 }
97 TEST_F(WindowTest, GetChildByLocalId) {
98 TestWindow w1;
99 w1.set_local_id(0);
100 EXPECT_EQ(&w1, w1.GetChildByLocalId(0));
101
102 TestWindow w11;
103 w11.set_local_id(11);
104 w1.AddChild(&w11);
105
106 TestWindow w12;
107 w12.set_local_id(w1.local_id());
108 w1.AddChild(&w12);
109
110 TestWindow w111;
111 w111.set_local_id(111);
112 w11.AddChild(&w111);
113
114 // Find direct & indirect descendents.
115 EXPECT_EQ(&w11, w1.GetChildByLocalId(w11.local_id()));
116 EXPECT_EQ(&w111, w1.GetChildByLocalId(w111.local_id()));
117 // Verifies parent returned by child with same id.
118 EXPECT_EQ(&w1, w1.GetChildByLocalId(w1.local_id()));
119 }
120
121 TEST_F(WindowTest, DrawnAndVisible) {
122 TestWindow w1;
123 EXPECT_FALSE(w1.visible());
124 w1.SetVisible(true);
125 EXPECT_TRUE(w1.visible());
126 EXPECT_FALSE(w1.IsDrawn());
127
128 WindowPrivate(&w1).set_parent_drawn(true);
129
130 TestWindow w11;
131 w11.SetVisible(true);
132 w1.AddChild(&w11);
133 EXPECT_TRUE(w11.visible());
134 EXPECT_TRUE(w11.IsDrawn());
135
136 w1.RemoveChild(&w11);
137 EXPECT_TRUE(w11.visible());
138 EXPECT_FALSE(w11.IsDrawn());
139 }
140
141 namespace {
142 MUS_DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2);
143 MUS_DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
144 }
145
146 TEST_F(WindowTest, Property) {
147 TestWindow w;
148
149 // Non-existent properties should return the default values.
150 EXPECT_EQ(-2, w.GetLocalProperty(kIntKey));
151 EXPECT_EQ(std::string("squeamish"), w.GetLocalProperty(kStringKey));
152
153 // A set property value should be returned again (even if it's the default
154 // value).
155 w.SetLocalProperty(kIntKey, INT_MAX);
156 EXPECT_EQ(INT_MAX, w.GetLocalProperty(kIntKey));
157 w.SetLocalProperty(kIntKey, -2);
158 EXPECT_EQ(-2, w.GetLocalProperty(kIntKey));
159 w.SetLocalProperty(kIntKey, INT_MIN);
160 EXPECT_EQ(INT_MIN, w.GetLocalProperty(kIntKey));
161
162 w.SetLocalProperty(kStringKey, static_cast<const char*>(NULL));
163 EXPECT_EQ(NULL, w.GetLocalProperty(kStringKey));
164 w.SetLocalProperty(kStringKey, "squeamish");
165 EXPECT_EQ(std::string("squeamish"), w.GetLocalProperty(kStringKey));
166 w.SetLocalProperty(kStringKey, "ossifrage");
167 EXPECT_EQ(std::string("ossifrage"), w.GetLocalProperty(kStringKey));
168
169 // ClearProperty should restore the default value.
170 w.ClearLocalProperty(kIntKey);
171 EXPECT_EQ(-2, w.GetLocalProperty(kIntKey));
172 w.ClearLocalProperty(kStringKey);
173 EXPECT_EQ(std::string("squeamish"), w.GetLocalProperty(kStringKey));
174 }
175
176 namespace {
177
178 class TestProperty {
179 public:
180 TestProperty() {}
181 virtual ~TestProperty() { last_deleted_ = this; }
182 static TestProperty* last_deleted() { return last_deleted_; }
183
184 private:
185 static TestProperty* last_deleted_;
186 DISALLOW_COPY_AND_ASSIGN(TestProperty);
187 };
188
189 TestProperty* TestProperty::last_deleted_ = NULL;
190
191 MUS_DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
192
193 } // namespace
194
195 TEST_F(WindowTest, OwnedProperty) {
196 TestProperty* p3 = NULL;
197 {
198 TestWindow w;
199 EXPECT_EQ(NULL, w.GetLocalProperty(kOwnedKey));
200 TestProperty* p1 = new TestProperty();
201 w.SetLocalProperty(kOwnedKey, p1);
202 EXPECT_EQ(p1, w.GetLocalProperty(kOwnedKey));
203 EXPECT_EQ(NULL, TestProperty::last_deleted());
204
205 TestProperty* p2 = new TestProperty();
206 w.SetLocalProperty(kOwnedKey, p2);
207 EXPECT_EQ(p2, w.GetLocalProperty(kOwnedKey));
208 EXPECT_EQ(p1, TestProperty::last_deleted());
209
210 w.ClearLocalProperty(kOwnedKey);
211 EXPECT_EQ(NULL, w.GetLocalProperty(kOwnedKey));
212 EXPECT_EQ(p2, TestProperty::last_deleted());
213
214 p3 = new TestProperty();
215 w.SetLocalProperty(kOwnedKey, p3);
216 EXPECT_EQ(p3, w.GetLocalProperty(kOwnedKey));
217 EXPECT_EQ(p2, TestProperty::last_deleted());
218 }
219
220 EXPECT_EQ(p3, TestProperty::last_deleted());
221 }
222
223 // WindowObserver --------------------------------------------------------
224
225 typedef testing::Test WindowObserverTest;
226
227 bool TreeChangeParamsMatch(const WindowObserver::TreeChangeParams& lhs,
228 const WindowObserver::TreeChangeParams& rhs) {
229 return lhs.target == rhs.target && lhs.old_parent == rhs.old_parent &&
230 lhs.new_parent == rhs.new_parent && lhs.receiver == rhs.receiver;
231 }
232
233 class TreeChangeObserver : public WindowObserver {
234 public:
235 explicit TreeChangeObserver(Window* observee) : observee_(observee) {
236 observee_->AddObserver(this);
237 }
238 ~TreeChangeObserver() override { observee_->RemoveObserver(this); }
239
240 void Reset() { received_params_.clear(); }
241
242 const std::vector<TreeChangeParams>& received_params() {
243 return received_params_;
244 }
245
246 private:
247 // Overridden from WindowObserver:
248 void OnTreeChanging(const TreeChangeParams& params) override {
249 received_params_.push_back(params);
250 }
251 void OnTreeChanged(const TreeChangeParams& params) override {
252 received_params_.push_back(params);
253 }
254
255 Window* observee_;
256 std::vector<TreeChangeParams> received_params_;
257
258 DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver);
259 };
260
261 // Adds/Removes w11 to w1.
262 TEST_F(WindowObserverTest, TreeChange_SimpleAddRemove) {
263 TestWindow w1;
264 w1.set_local_id(1);
265 TreeChangeObserver o1(&w1);
266 EXPECT_TRUE(o1.received_params().empty());
267
268 TestWindow w11;
269 w11.set_local_id(11);
270 TreeChangeObserver o11(&w11);
271 EXPECT_TRUE(o11.received_params().empty());
272
273 // Add.
274
275 w1.AddChild(&w11);
276
277 EXPECT_EQ(2U, o1.received_params().size());
278 WindowObserver::TreeChangeParams p1;
279 p1.target = &w11;
280 p1.receiver = &w1;
281 p1.old_parent = NULL;
282 p1.new_parent = &w1;
283 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
284
285 EXPECT_EQ(2U, o11.received_params().size());
286 WindowObserver::TreeChangeParams p11 = p1;
287 p11.receiver = &w11;
288 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
289 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
290
291 o1.Reset();
292 o11.Reset();
293 EXPECT_TRUE(o1.received_params().empty());
294 EXPECT_TRUE(o11.received_params().empty());
295
296 // Remove.
297
298 w1.RemoveChild(&w11);
299
300 EXPECT_EQ(2U, o1.received_params().size());
301 p1.target = &w11;
302 p1.receiver = &w1;
303 p1.old_parent = &w1;
304 p1.new_parent = NULL;
305 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
306
307 EXPECT_EQ(2U, o11.received_params().size());
308 p11 = p1;
309 p11.receiver = &w11;
310 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
311 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
312 }
313
314 // Creates these two trees:
315 // w1
316 // +- w11
317 // w111
318 // +- w1111
319 // +- w1112
320 // Then adds/removes w111 from w11.
321 TEST_F(WindowObserverTest, TreeChange_NestedAddRemove) {
322 TestWindow w1, w11, w111, w1111, w1112;
323
324 // Root tree.
325 w1.AddChild(&w11);
326
327 // Tree to be attached.
328 w111.AddChild(&w1111);
329 w111.AddChild(&w1112);
330
331 TreeChangeObserver o1(&w1), o11(&w11), o111(&w111), o1111(&w1111),
332 o1112(&w1112);
333 WindowObserver::TreeChangeParams p1, p11, p111, p1111, p1112;
334
335 // Add.
336
337 w11.AddChild(&w111);
338
339 EXPECT_EQ(2U, o1.received_params().size());
340 p1.target = &w111;
341 p1.receiver = &w1;
342 p1.old_parent = NULL;
343 p1.new_parent = &w11;
344 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
345
346 EXPECT_EQ(2U, o11.received_params().size());
347 p11 = p1;
348 p11.receiver = &w11;
349 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
350
351 EXPECT_EQ(2U, o111.received_params().size());
352 p111 = p11;
353 p111.receiver = &w111;
354 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
355 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
356
357 EXPECT_EQ(2U, o1111.received_params().size());
358 p1111 = p111;
359 p1111.receiver = &w1111;
360 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front()));
361 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back()));
362
363 EXPECT_EQ(2U, o1112.received_params().size());
364 p1112 = p111;
365 p1112.receiver = &w1112;
366 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front()));
367 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back()));
368
369 // Remove.
370 o1.Reset();
371 o11.Reset();
372 o111.Reset();
373 o1111.Reset();
374 o1112.Reset();
375 EXPECT_TRUE(o1.received_params().empty());
376 EXPECT_TRUE(o11.received_params().empty());
377 EXPECT_TRUE(o111.received_params().empty());
378 EXPECT_TRUE(o1111.received_params().empty());
379 EXPECT_TRUE(o1112.received_params().empty());
380
381 w11.RemoveChild(&w111);
382
383 EXPECT_EQ(2U, o1.received_params().size());
384 p1.target = &w111;
385 p1.receiver = &w1;
386 p1.old_parent = &w11;
387 p1.new_parent = NULL;
388 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
389
390 EXPECT_EQ(2U, o11.received_params().size());
391 p11 = p1;
392 p11.receiver = &w11;
393 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
394
395 EXPECT_EQ(2U, o111.received_params().size());
396 p111 = p11;
397 p111.receiver = &w111;
398 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
399 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
400
401 EXPECT_EQ(2U, o1111.received_params().size());
402 p1111 = p111;
403 p1111.receiver = &w1111;
404 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front()));
405 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back()));
406
407 EXPECT_EQ(2U, o1112.received_params().size());
408 p1112 = p111;
409 p1112.receiver = &w1112;
410 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front()));
411 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back()));
412 }
413
414 TEST_F(WindowObserverTest, TreeChange_Reparent) {
415 TestWindow w1, w11, w12, w111;
416 w1.AddChild(&w11);
417 w1.AddChild(&w12);
418 w11.AddChild(&w111);
419
420 TreeChangeObserver o1(&w1), o11(&w11), o12(&w12), o111(&w111);
421
422 // Reparent.
423 w12.AddChild(&w111);
424
425 // w1 (root) should see both changing and changed notifications.
426 EXPECT_EQ(4U, o1.received_params().size());
427 WindowObserver::TreeChangeParams p1;
428 p1.target = &w111;
429 p1.receiver = &w1;
430 p1.old_parent = &w11;
431 p1.new_parent = &w12;
432 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
433 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
434
435 // w11 should see changing notifications.
436 EXPECT_EQ(2U, o11.received_params().size());
437 WindowObserver::TreeChangeParams p11;
438 p11 = p1;
439 p11.receiver = &w11;
440 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
441
442 // w12 should see changed notifications.
443 EXPECT_EQ(2U, o12.received_params().size());
444 WindowObserver::TreeChangeParams p12;
445 p12 = p1;
446 p12.receiver = &w12;
447 EXPECT_TRUE(TreeChangeParamsMatch(p12, o12.received_params().back()));
448
449 // w111 should see both changing and changed notifications.
450 EXPECT_EQ(2U, o111.received_params().size());
451 WindowObserver::TreeChangeParams p111;
452 p111 = p1;
453 p111.receiver = &w111;
454 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
455 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
456 }
457
458 namespace {
459
460 class OrderChangeObserver : public WindowObserver {
461 public:
462 struct Change {
463 Window* window;
464 Window* relative_window;
465 mojom::OrderDirection direction;
466 };
467 typedef std::vector<Change> Changes;
468
469 explicit OrderChangeObserver(Window* observee) : observee_(observee) {
470 observee_->AddObserver(this);
471 }
472 ~OrderChangeObserver() override { observee_->RemoveObserver(this); }
473
474 Changes GetAndClearChanges() {
475 Changes changes;
476 changes_.swap(changes);
477 return changes;
478 }
479
480 private:
481 // Overridden from WindowObserver:
482 void OnWindowReordering(Window* window,
483 Window* relative_window,
484 mojom::OrderDirection direction) override {
485 OnWindowReordered(window, relative_window, direction);
486 }
487
488 void OnWindowReordered(Window* window,
489 Window* relative_window,
490 mojom::OrderDirection direction) override {
491 Change change;
492 change.window = window;
493 change.relative_window = relative_window;
494 change.direction = direction;
495 changes_.push_back(change);
496 }
497
498 Window* observee_;
499 Changes changes_;
500
501 DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
502 };
503
504 } // namespace
505
506 TEST_F(WindowObserverTest, Order) {
507 TestWindow w1, w11, w12, w13;
508 w1.AddChild(&w11);
509 w1.AddChild(&w12);
510 w1.AddChild(&w13);
511
512 // Order: w11, w12, w13
513 EXPECT_EQ(3U, w1.children().size());
514 EXPECT_EQ(&w11, w1.children().front());
515 EXPECT_EQ(&w13, w1.children().back());
516
517 {
518 OrderChangeObserver observer(&w11);
519
520 // Move w11 to front.
521 // Resulting order: w12, w13, w11
522 w11.MoveToFront();
523 EXPECT_EQ(&w12, w1.children().front());
524 EXPECT_EQ(&w11, w1.children().back());
525
526 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
527 ASSERT_EQ(2U, changes.size());
528 EXPECT_EQ(&w11, changes[0].window);
529 EXPECT_EQ(&w13, changes[0].relative_window);
530 EXPECT_EQ(mojom::OrderDirection::ABOVE, changes[0].direction);
531
532 EXPECT_EQ(&w11, changes[1].window);
533 EXPECT_EQ(&w13, changes[1].relative_window);
534 EXPECT_EQ(mojom::OrderDirection::ABOVE, changes[1].direction);
535 }
536
537 {
538 OrderChangeObserver observer(&w11);
539
540 // Move w11 to back.
541 // Resulting order: w11, w12, w13
542 w11.MoveToBack();
543 EXPECT_EQ(&w11, w1.children().front());
544 EXPECT_EQ(&w13, w1.children().back());
545
546 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
547 ASSERT_EQ(2U, changes.size());
548 EXPECT_EQ(&w11, changes[0].window);
549 EXPECT_EQ(&w12, changes[0].relative_window);
550 EXPECT_EQ(mojom::OrderDirection::BELOW, changes[0].direction);
551
552 EXPECT_EQ(&w11, changes[1].window);
553 EXPECT_EQ(&w12, changes[1].relative_window);
554 EXPECT_EQ(mojom::OrderDirection::BELOW, changes[1].direction);
555 }
556
557 {
558 OrderChangeObserver observer(&w11);
559
560 // Move w11 above w12.
561 // Resulting order: w12. w11, w13
562 w11.Reorder(&w12, mojom::OrderDirection::ABOVE);
563 EXPECT_EQ(&w12, w1.children().front());
564 EXPECT_EQ(&w13, w1.children().back());
565
566 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
567 ASSERT_EQ(2U, changes.size());
568 EXPECT_EQ(&w11, changes[0].window);
569 EXPECT_EQ(&w12, changes[0].relative_window);
570 EXPECT_EQ(mojom::OrderDirection::ABOVE, changes[0].direction);
571
572 EXPECT_EQ(&w11, changes[1].window);
573 EXPECT_EQ(&w12, changes[1].relative_window);
574 EXPECT_EQ(mojom::OrderDirection::ABOVE, changes[1].direction);
575 }
576
577 {
578 OrderChangeObserver observer(&w11);
579
580 // Move w11 below w12.
581 // Resulting order: w11, w12, w13
582 w11.Reorder(&w12, mojom::OrderDirection::BELOW);
583 EXPECT_EQ(&w11, w1.children().front());
584 EXPECT_EQ(&w13, w1.children().back());
585
586 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
587 ASSERT_EQ(2U, changes.size());
588 EXPECT_EQ(&w11, changes[0].window);
589 EXPECT_EQ(&w12, changes[0].relative_window);
590 EXPECT_EQ(mojom::OrderDirection::BELOW, changes[0].direction);
591
592 EXPECT_EQ(&w11, changes[1].window);
593 EXPECT_EQ(&w12, changes[1].relative_window);
594 EXPECT_EQ(mojom::OrderDirection::BELOW, changes[1].direction);
595 }
596 }
597
598 namespace {
599
600 typedef std::vector<std::string> Changes;
601
602 std::string RectToString(const gfx::Rect& rect) {
603 return base::StringPrintf("%d,%d %dx%d", rect.x(), rect.y(), rect.width(),
604 rect.height());
605 }
606
607 class BoundsChangeObserver : public WindowObserver {
608 public:
609 explicit BoundsChangeObserver(Window* window) : window_(window) {
610 window_->AddObserver(this);
611 }
612 ~BoundsChangeObserver() override { window_->RemoveObserver(this); }
613
614 Changes GetAndClearChanges() {
615 Changes changes;
616 changes.swap(changes_);
617 return changes;
618 }
619
620 private:
621 // Overridden from WindowObserver:
622 void OnWindowBoundsChanging(Window* window,
623 const gfx::Rect& old_bounds,
624 const gfx::Rect& new_bounds) override {
625 changes_.push_back(base::StringPrintf(
626 "window=%d old_bounds=%s new_bounds=%s phase=changing",
627 window->local_id(), RectToString(old_bounds).c_str(),
628 RectToString(new_bounds).c_str()));
629 }
630 void OnWindowBoundsChanged(Window* window,
631 const gfx::Rect& old_bounds,
632 const gfx::Rect& new_bounds) override {
633 changes_.push_back(base::StringPrintf(
634 "window=%d old_bounds=%s new_bounds=%s phase=changed",
635 window->local_id(), RectToString(old_bounds).c_str(),
636 RectToString(new_bounds).c_str()));
637 }
638
639 Window* window_;
640 Changes changes_;
641
642 DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver);
643 };
644
645 } // namespace
646
647 TEST_F(WindowObserverTest, SetBounds) {
648 TestWindow w1;
649 w1.set_local_id(1);
650 {
651 BoundsChangeObserver observer(&w1);
652 w1.SetBounds(gfx::Rect(0, 0, 100, 100));
653
654 Changes changes = observer.GetAndClearChanges();
655 ASSERT_EQ(2U, changes.size());
656 EXPECT_EQ(
657 "window=1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changing",
658 changes[0]);
659 EXPECT_EQ(
660 "window=1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changed",
661 changes[1]);
662 }
663 }
664
665 namespace {
666
667 class VisibilityChangeObserver : public WindowObserver {
668 public:
669 explicit VisibilityChangeObserver(Window* window) : window_(window) {
670 window_->AddObserver(this);
671 }
672 ~VisibilityChangeObserver() override { window_->RemoveObserver(this); }
673
674 Changes GetAndClearChanges() {
675 Changes changes;
676 changes.swap(changes_);
677 return changes;
678 }
679
680 private:
681 // Overridden from WindowObserver:
682 void OnWindowVisibilityChanging(Window* window, bool visible) override {
683 changes_.push_back(
684 base::StringPrintf("window=%d phase=changing visibility=%s",
685 window->local_id(), visible ? "true" : "false"));
686 }
687 void OnChildWindowVisibilityChanged(Window* window, bool visible) override {
688 changes_.push_back(
689 base::StringPrintf("window=%d phase=child-changed visibility=%s",
690 window->local_id(), visible ? "true" : "false"));
691 }
692 void OnWindowVisibilityChanged(Window* window, bool visible) override {
693 changes_.push_back(
694 base::StringPrintf("window=%d phase=changed visibility=%s",
695 window->local_id(), visible ? "true" : "false"));
696 }
697
698 Window* window_;
699 Changes changes_;
700
701 DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver);
702 };
703
704 } // namespace
705
706 TEST_F(WindowObserverTest, SetVisible) {
707 TestWindow w1;
708 EXPECT_FALSE(w1.visible());
709 w1.set_local_id(1);
710 w1.SetVisible(true);
711 EXPECT_TRUE(w1.visible());
712 {
713 // Change visibility from true to false and make sure we get notifications.
714 VisibilityChangeObserver observer(&w1);
715 w1.SetVisible(false);
716
717 Changes changes = observer.GetAndClearChanges();
718 ASSERT_EQ(2U, changes.size());
719 EXPECT_EQ("window=1 phase=changing visibility=false", changes[0]);
720 EXPECT_EQ("window=1 phase=changed visibility=false", changes[1]);
721 }
722 {
723 // Set visible to existing value and verify no notifications.
724 VisibilityChangeObserver observer(&w1);
725 w1.SetVisible(false);
726 EXPECT_TRUE(observer.GetAndClearChanges().empty());
727 }
728 }
729
730 TEST_F(WindowObserverTest, SetVisibleParent) {
731 TestWindow parent;
732 parent.SetVisible(true);
733 parent.set_local_id(1);
734 TestWindow child;
735 child.SetVisible(true);
736 child.set_local_id(2);
737 parent.AddChild(&child);
738 EXPECT_TRUE(parent.visible());
739 EXPECT_TRUE(child.visible());
740 {
741 // Change visibility from true to false and make sure we get notifications
742 // on the parent.
743 VisibilityChangeObserver observer(&parent);
744 child.SetVisible(false);
745
746 Changes changes = observer.GetAndClearChanges();
747 ASSERT_EQ(2U, changes.size());
748 EXPECT_EQ("window=2 phase=child-changed visibility=false", changes[0]);
749 EXPECT_EQ("window=2 phase=changed visibility=false", changes[1]);
750 }
751 }
752
753 TEST_F(WindowObserverTest, SetVisibleChild) {
754 TestWindow parent;
755 parent.SetVisible(true);
756 parent.set_local_id(1);
757 TestWindow child;
758 child.SetVisible(true);
759 child.set_local_id(2);
760 parent.AddChild(&child);
761 EXPECT_TRUE(parent.visible());
762 EXPECT_TRUE(child.visible());
763 {
764 // Change visibility from true to false and make sure we get notifications
765 // on the child.
766 VisibilityChangeObserver observer(&child);
767 parent.SetVisible(false);
768
769 Changes changes = observer.GetAndClearChanges();
770 ASSERT_EQ(1U, changes.size());
771 EXPECT_EQ("window=1 phase=changed visibility=false", changes[0]);
772 }
773 }
774
775 namespace {
776
777 class OpacityChangeObserver : public WindowObserver {
778 public:
779 explicit OpacityChangeObserver(Window* window) : window_(window) {
780 window_->AddObserver(this);
781 }
782 ~OpacityChangeObserver() override { window_->RemoveObserver(this); }
783
784 Changes GetAndClearChanges() {
785 Changes changes;
786 changes.swap(changes_);
787 return changes;
788 }
789
790 private:
791 // WindowObserver:
792 void OnWindowOpacityChanged(Window* window,
793 float old_opacity,
794 float new_opacity) override {
795 changes_.push_back(
796 base::StringPrintf("window=%d old_opacity=%.2f new_opacity=%.2f",
797 window->local_id(), old_opacity, new_opacity));
798 }
799
800 Window* window_;
801 Changes changes_;
802
803 DISALLOW_COPY_AND_ASSIGN(OpacityChangeObserver);
804 };
805
806 } // namespace
807
808 // Tests that WindowObserver is only notified when opacity changes.
809 TEST_F(WindowObserverTest, SetOpacity) {
810 TestWindow w1;
811 w1.set_local_id(1);
812 EXPECT_FLOAT_EQ(1.0f, w1.opacity());
813
814 // Changing the opacity should trigger a notification.
815 OpacityChangeObserver observer(&w1);
816 w1.SetOpacity(0.5f);
817 EXPECT_FLOAT_EQ(0.5f, w1.opacity());
818 Changes changes = observer.GetAndClearChanges();
819 ASSERT_EQ(1u, changes.size());
820 EXPECT_EQ("window=1 old_opacity=1.00 new_opacity=0.50", changes[0]);
821
822 // Setting to the same opacity should be rejected, no notification.
823 w1.SetOpacity(0.5f);
824 EXPECT_FLOAT_EQ(0.5f, w1.opacity());
825 changes = observer.GetAndClearChanges();
826 EXPECT_TRUE(changes.empty());
827
828 // Alternate sources of opacity changes should trigger a notification.
829 WindowPrivate(&w1).LocalSetOpacity(1.0f);
830 EXPECT_FLOAT_EQ(1.0f, w1.opacity());
831 changes = observer.GetAndClearChanges();
832 ASSERT_EQ(1u, changes.size());
833 EXPECT_EQ("window=1 old_opacity=0.50 new_opacity=1.00", changes[0]);
834 }
835
836 namespace {
837
838 class SharedPropertyChangeObserver : public WindowObserver {
839 public:
840 explicit SharedPropertyChangeObserver(Window* window) : window_(window) {
841 window_->AddObserver(this);
842 }
843 ~SharedPropertyChangeObserver() override { window_->RemoveObserver(this); }
844
845 Changes GetAndClearChanges() {
846 Changes changes;
847 changes.swap(changes_);
848 return changes;
849 }
850
851 private:
852 // Overridden from WindowObserver:
853 void OnWindowSharedPropertyChanged(
854 Window* window,
855 const std::string& name,
856 const std::vector<uint8_t>* old_data,
857 const std::vector<uint8_t>* new_data) override {
858 changes_.push_back(base::StringPrintf(
859 "window=%d shared property changed key=%s old_value=%s new_value=%s",
860 window->local_id(), name.c_str(), VectorToString(old_data).c_str(),
861 VectorToString(new_data).c_str()));
862 }
863
864 std::string VectorToString(const std::vector<uint8_t>* data) {
865 if (!data)
866 return "NULL";
867 gfx::Size size = mojo::ConvertTo<gfx::Size>(*data);
868 return base::StringPrintf("%d,%d", size.width(), size.height());
869 }
870
871 Window* window_;
872 Changes changes_;
873
874 DISALLOW_COPY_AND_ASSIGN(SharedPropertyChangeObserver);
875 };
876
877 } // namespace
878
879 TEST_F(WindowObserverTest, SetSharedProperty) {
880 TestWindow w1;
881 w1.set_local_id(1);
882 gfx::Size size(100, 100);
883
884 {
885 // Change visibility from true to false and make sure we get notifications.
886 SharedPropertyChangeObserver observer(&w1);
887 w1.SetSharedProperty<gfx::Size>("size", size);
888 Changes changes = observer.GetAndClearChanges();
889 ASSERT_EQ(1U, changes.size());
890 EXPECT_EQ(
891 "window=1 shared property changed key=size old_value=NULL "
892 "new_value=100,100",
893 changes[0]);
894 EXPECT_EQ(1U, w1.shared_properties().size());
895 EXPECT_EQ(w1.GetSharedProperty<gfx::Size>("size"), size);
896 EXPECT_TRUE(w1.HasSharedProperty("size"));
897 }
898 {
899 // Set visible to existing value and verify no notifications.
900 SharedPropertyChangeObserver observer(&w1);
901 w1.SetSharedProperty<gfx::Size>("size", size);
902 EXPECT_TRUE(observer.GetAndClearChanges().empty());
903 EXPECT_EQ(1U, w1.shared_properties().size());
904 EXPECT_TRUE(w1.HasSharedProperty("size"));
905 }
906 {
907 // Clear the shared property.
908 // Change visibility from true to false and make sure we get notifications.
909 SharedPropertyChangeObserver observer(&w1);
910 w1.ClearSharedProperty("size");
911 Changes changes = observer.GetAndClearChanges();
912 ASSERT_EQ(1U, changes.size());
913 EXPECT_EQ(
914 "window=1 shared property changed key=size old_value=100,100 "
915 "new_value=NULL",
916 changes[0]);
917 EXPECT_EQ(0U, w1.shared_properties().size());
918 EXPECT_FALSE(w1.HasSharedProperty("size"));
919 }
920 {
921 // Clearing a non-existent property shouldn't update us.
922 SharedPropertyChangeObserver observer(&w1);
923 w1.ClearSharedProperty("size");
924 EXPECT_TRUE(observer.GetAndClearChanges().empty());
925 EXPECT_EQ(0U, w1.shared_properties().size());
926 EXPECT_FALSE(w1.HasSharedProperty("size"));
927 }
928 }
929
930 namespace {
931
932 typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
933
934 class LocalPropertyChangeObserver : public WindowObserver {
935 public:
936 explicit LocalPropertyChangeObserver(Window* window)
937 : window_(window), property_key_(nullptr), old_property_value_(-1) {
938 window_->AddObserver(this);
939 }
940 ~LocalPropertyChangeObserver() override { window_->RemoveObserver(this); }
941
942 PropertyChangeInfo PropertyChangeInfoAndClear() {
943 PropertyChangeInfo result(property_key_, old_property_value_);
944 property_key_ = NULL;
945 old_property_value_ = -3;
946 return result;
947 }
948
949 private:
950 void OnWindowLocalPropertyChanged(Window* window,
951 const void* key,
952 intptr_t old) override {
953 property_key_ = key;
954 old_property_value_ = old;
955 }
956
957 Window* window_;
958 const void* property_key_;
959 intptr_t old_property_value_;
960
961 DISALLOW_COPY_AND_ASSIGN(LocalPropertyChangeObserver);
962 };
963
964 } // namespace
965
966 TEST_F(WindowObserverTest, LocalPropertyChanged) {
967 TestWindow w1;
968 LocalPropertyChangeObserver o(&w1);
969
970 static const WindowProperty<int> prop = {-2};
971
972 w1.SetLocalProperty(&prop, 1);
973 EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear());
974 w1.SetLocalProperty(&prop, -2);
975 EXPECT_EQ(PropertyChangeInfo(&prop, 1), o.PropertyChangeInfoAndClear());
976 w1.SetLocalProperty(&prop, 3);
977 EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear());
978 w1.ClearLocalProperty(&prop);
979 EXPECT_EQ(PropertyChangeInfo(&prop, 3), o.PropertyChangeInfoAndClear());
980
981 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
982 EXPECT_EQ(PropertyChangeInfo(reinterpret_cast<const void*>(NULL), -3),
983 o.PropertyChangeInfoAndClear());
984 }
985
986 TEST_F(WindowTest, RemoveTransientWindow) {
987 std::unique_ptr<TestWindow> w1(CreateTestWindow(nullptr));
988 std::unique_ptr<TestWindow> w11(CreateTestWindow(w1.get()));
989 TestWindow* w12 = CreateTestWindow(w1.get());
990 EXPECT_EQ(2u, w1->children().size());
991 // w12's lifetime is now tied to w11.
992 w11->AddTransientWindow(w12);
993 w11.reset();
994 EXPECT_EQ(0u, w1->children().size());
995 }
996
997 TEST_F(WindowTest, TransientWindow) {
998 std::unique_ptr<TestWindow> parent(CreateTestWindow(nullptr));
999 std::unique_ptr<TestWindow> w1(CreateTestWindow(parent.get()));
1000 std::unique_ptr<TestWindow> w3(CreateTestWindow(parent.get()));
1001
1002 Window* w2 = CreateTestWindow(parent.get());
1003 EXPECT_EQ(w2, parent->children().back());
1004 ASSERT_EQ(3u, parent->children().size());
1005
1006 w1->AddTransientWindow(w2);
1007 // Stack w1 at the top (end). This should force w2 to be last (on top of w1).
1008 w1->MoveToFront();
1009 ASSERT_EQ(3u, parent->children().size());
1010 EXPECT_EQ(w2, parent->children().back());
1011
1012 // Destroy w1, which should also destroy w3 (since it's a transient child).A
1013 w1.reset();
1014 w2 = nullptr;
1015 ASSERT_EQ(1u, parent->children().size());
1016 EXPECT_EQ(w3.get(), parent->children()[0]);
1017 }
1018
1019 // Tests that transient windows are stacked as a unit when using order above.
1020 TEST_F(WindowTest, TransientWindowsGroupAbove) {
1021 std::unique_ptr<TestWindow> parent(CreateTestWindow(0, nullptr));
1022 std::unique_ptr<TestWindow> w1(CreateTestWindow(1, parent.get()));
1023
1024 TestWindow* w11 = CreateTestWindow(11, parent.get());
1025 std::unique_ptr<TestWindow> w2(CreateTestWindow(2, parent.get()));
1026
1027 TestWindow* w21 = CreateTestWindow(21, parent.get());
1028 TestWindow* w211 = CreateTestWindow(211, parent.get());
1029 TestWindow* w212 = CreateTestWindow(212, parent.get());
1030 TestWindow* w213 = CreateTestWindow(213, parent.get());
1031 TestWindow* w22 = CreateTestWindow(22, parent.get());
1032 ASSERT_EQ(8u, parent->children().size());
1033
1034 // w11 is now owned by w1.
1035 w1->AddTransientWindow(w11);
1036 // w21 is now owned by w2.
1037 w2->AddTransientWindow(w21);
1038 // w22 is now owned by w2.
1039 w2->AddTransientWindow(w22);
1040 // w211 is now owned by w21.
1041 w21->AddTransientWindow(w211);
1042 // w212 is now owned by w21.
1043 w21->AddTransientWindow(w212);
1044 // w213 is now owned by w21.
1045 w21->AddTransientWindow(w213);
1046 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
1047
1048 // Stack w1 at the top (end), this should force w11 to be last (on top of w1).
1049 w1->MoveToFront();
1050 EXPECT_EQ(w11, parent->children().back());
1051 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
1052
1053 // This tests that the order in children_ array rather than in
1054 // transient_children_ array is used when reinserting transient children.
1055 // If transient_children_ array was used '22' would be following '21'.
1056 w2->MoveToFront();
1057 EXPECT_EQ(w22, parent->children().back());
1058 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
1059
1060 w11->Reorder(w2.get(), mojom::OrderDirection::ABOVE);
1061 EXPECT_EQ(w11, parent->children().back());
1062 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
1063
1064 w21->Reorder(w1.get(), mojom::OrderDirection::ABOVE);
1065 EXPECT_EQ(w22, parent->children().back());
1066 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
1067
1068 w21->Reorder(w22, mojom::OrderDirection::ABOVE);
1069 EXPECT_EQ(w213, parent->children().back());
1070 EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent.get()));
1071
1072 w11->Reorder(w21, mojom::OrderDirection::ABOVE);
1073 EXPECT_EQ(w11, parent->children().back());
1074 EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent.get()));
1075
1076 w213->Reorder(w21, mojom::OrderDirection::ABOVE);
1077 EXPECT_EQ(w11, parent->children().back());
1078 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
1079
1080 // No change when stacking a transient parent above its transient child.
1081 w21->Reorder(w211, mojom::OrderDirection::ABOVE);
1082 EXPECT_EQ(w11, parent->children().back());
1083 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
1084
1085 // This tests that the order in children_ array rather than in
1086 // transient_children_ array is used when reinserting transient children.
1087 // If transient_children_ array was used '22' would be following '21'.
1088 w2->Reorder(w1.get(), mojom::OrderDirection::ABOVE);
1089 EXPECT_EQ(w212, parent->children().back());
1090 EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent.get()));
1091
1092 w11->Reorder(w213, mojom::OrderDirection::ABOVE);
1093 EXPECT_EQ(w11, parent->children().back());
1094 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
1095 }
1096
1097 // Tests that transient children are stacked as a unit when using order below.
1098 TEST_F(WindowTest, TransientWindowsGroupBelow) {
1099 std::unique_ptr<TestWindow> parent(CreateTestWindow(0, nullptr));
1100 std::unique_ptr<TestWindow> w1(CreateTestWindow(1, parent.get()));
1101
1102 TestWindow* w11 = CreateTestWindow(11, parent.get());
1103 std::unique_ptr<TestWindow> w2(CreateTestWindow(2, parent.get()));
1104
1105 TestWindow* w21 = CreateTestWindow(21, parent.get());
1106 TestWindow* w211 = CreateTestWindow(211, parent.get());
1107 TestWindow* w212 = CreateTestWindow(212, parent.get());
1108 TestWindow* w213 = CreateTestWindow(213, parent.get());
1109 TestWindow* w22 = CreateTestWindow(22, parent.get());
1110 ASSERT_EQ(8u, parent->children().size());
1111
1112 // w11 is now owned by w1.
1113 w1->AddTransientWindow(w11);
1114 // w21 is now owned by w2.
1115 w2->AddTransientWindow(w21);
1116 // w22 is now owned by w2.
1117 w2->AddTransientWindow(w22);
1118 // w211 is now owned by w21.
1119 w21->AddTransientWindow(w211);
1120 // w212 is now owned by w21.
1121 w21->AddTransientWindow(w212);
1122 // w213 is now owned by w21.
1123 w21->AddTransientWindow(w213);
1124 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
1125
1126 // Stack w2 at the bottom, this should force w11 to be last (on top of w1).
1127 // This also tests that the order in children_ array rather than in
1128 // transient_children_ array is used when reinserting transient children.
1129 // If transient_children_ array was used '22' would be following '21'.
1130 w2->MoveToBack();
1131 EXPECT_EQ(w11, parent->children().back());
1132 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
1133
1134 w1->MoveToBack();
1135 EXPECT_EQ(w22, parent->children().back());
1136 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
1137
1138 w21->Reorder(w1.get(), mojom::OrderDirection::BELOW);
1139 EXPECT_EQ(w11, parent->children().back());
1140 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
1141
1142 w11->Reorder(w2.get(), mojom::OrderDirection::BELOW);
1143 EXPECT_EQ(w22, parent->children().back());
1144 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
1145
1146 w22->Reorder(w21, mojom::OrderDirection::BELOW);
1147 EXPECT_EQ(w213, parent->children().back());
1148 EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent.get()));
1149
1150 w21->Reorder(w11, mojom::OrderDirection::BELOW);
1151 EXPECT_EQ(w11, parent->children().back());
1152 EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent.get()));
1153
1154 w213->Reorder(w211, mojom::OrderDirection::BELOW);
1155 EXPECT_EQ(w11, parent->children().back());
1156 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
1157
1158 // No change when stacking a transient parent below its transient child.
1159 w21->Reorder(w211, mojom::OrderDirection::BELOW);
1160 EXPECT_EQ(w11, parent->children().back());
1161 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
1162
1163 w1->Reorder(w2.get(), mojom::OrderDirection::BELOW);
1164 EXPECT_EQ(w212, parent->children().back());
1165 EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent.get()));
1166
1167 w213->Reorder(w11, mojom::OrderDirection::BELOW);
1168 EXPECT_EQ(w11, parent->children().back());
1169 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
1170 }
1171
1172 // Tests that windows are restacked properly after a call to
1173 // AddTransientWindow() or RemoveTransientWindow).
1174 TEST_F(WindowTest, RestackUponAddOrRemoveTransientWindow) {
1175 std::unique_ptr<TestWindow> parent(CreateTestWindow(0, nullptr));
1176 std::unique_ptr<TestWindow> windows[4];
1177 for (int i = 0; i < 4; i++)
1178 windows[i].reset(CreateTestWindow(i, parent.get()));
1179
1180 EXPECT_EQ("0 1 2 3", ChildWindowIDsAsString(parent.get()));
1181
1182 windows[0]->AddTransientWindow(windows[2].get());
1183 EXPECT_EQ("0 2 1 3", ChildWindowIDsAsString(parent.get()));
1184
1185 windows[0]->AddTransientWindow(windows[3].get());
1186 EXPECT_EQ("0 2 3 1", ChildWindowIDsAsString(parent.get()));
1187
1188 windows[0]->RemoveTransientWindow(windows[2].get());
1189 EXPECT_EQ("0 3 2 1", ChildWindowIDsAsString(parent.get()));
1190
1191 windows[0]->RemoveTransientWindow(windows[3].get());
1192 EXPECT_EQ("0 3 2 1", ChildWindowIDsAsString(parent.get()));
1193 }
1194
1195 // Tests that transient windows are stacked properly when created.
1196 TEST_F(WindowTest, StackUponCreation) {
1197 std::unique_ptr<TestWindow> parent(CreateTestWindow(0, nullptr));
1198 std::unique_ptr<TestWindow> window0(CreateTestWindow(1, parent.get()));
1199 std::unique_ptr<TestWindow> window1(CreateTestWindow(2, parent.get()));
1200
1201 TestWindow* window2 = CreateTestWindow(3, parent.get());
1202
1203 window0->AddTransientWindow(window2);
1204 EXPECT_EQ("1 3 2", ChildWindowIDsAsString(parent.get()));
1205 }
1206
1207 namespace {
1208
1209 class TransientWindowObserver : public WindowObserver {
1210 public:
1211 TransientWindowObserver() {}
1212 ~TransientWindowObserver() override {}
1213
1214 void ResetCounts() { added_count_ = removed_count_ = 0; }
1215
1216 int added_count() const { return added_count_; }
1217 int removed_count() const { return removed_count_; }
1218
1219 // WindowObserver:
1220 void OnTransientChildAdded(ui::Window* window,
1221 ui::Window* transient) override {
1222 added_count_++;
1223 }
1224 void OnTransientChildRemoved(ui::Window* window,
1225 ui::Window* transient) override {
1226 removed_count_++;
1227 }
1228
1229 private:
1230 int added_count_ = 0;
1231 int removed_count_ = 0;
1232
1233 DISALLOW_COPY_AND_ASSIGN(TransientWindowObserver);
1234 };
1235
1236 } // namespace
1237
1238 // Verifies WindowObserver is notified of transient windows added/removed.
1239 TEST_F(WindowTest, TransientNotifiesObserver) {
1240 std::unique_ptr<TestWindow> parent(CreateTestWindow(0, nullptr));
1241 TransientWindowObserver observer;
1242 parent->AddObserver(&observer);
1243 std::unique_ptr<TestWindow> child(CreateTestWindow(0, nullptr));
1244 parent->AddTransientWindow(child.get());
1245 EXPECT_EQ(1, observer.added_count());
1246 EXPECT_EQ(0, observer.removed_count());
1247 observer.ResetCounts();
1248
1249 parent->RemoveTransientWindow(child.get());
1250 EXPECT_EQ(0, observer.added_count());
1251 EXPECT_EQ(1, observer.removed_count());
1252 observer.ResetCounts();
1253
1254 parent->AddTransientWindow(child.get());
1255 EXPECT_EQ(1, observer.added_count());
1256 EXPECT_EQ(0, observer.removed_count());
1257 observer.ResetCounts();
1258
1259 child.reset();
1260 EXPECT_EQ(0, observer.added_count());
1261 EXPECT_EQ(1, observer.removed_count());
1262 observer.ResetCounts();
1263 }
1264
1265 } // namespace ui
OLDNEW
« no previous file with comments | « services/ui/public/cpp/tests/window_tree_client_unittest.cc ('k') | services/ui/public/cpp/window.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698