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

Side by Side Diff: ui/views/corewm/transient_window_manager_unittest.cc

Issue 194843004: Move files from ui/views/corewm to ui/wm/core (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 9 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 | Annotate | Revision Log
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 "ui/views/corewm/transient_window_manager.h"
6
7 #include "ui/aura/client/visibility_client.h"
8 #include "ui/aura/client/window_tree_client.h"
9 #include "ui/aura/layout_manager.h"
10 #include "ui/aura/test/aura_test_base.h"
11 #include "ui/aura/test/test_windows.h"
12 #include "ui/aura/window.h"
13 #include "ui/views/corewm/transient_window_observer.h"
14 #include "ui/views/corewm/window_util.h"
15 #include "ui/views/corewm/wm_state.h"
16
17 using aura::Window;
18
19 using aura::test::ChildWindowIDsAsString;
20 using aura::test::CreateTestWindowWithId;
21
22 namespace views {
23 namespace corewm {
24
25 class TestTransientWindowObserver : public TransientWindowObserver {
26 public:
27 TestTransientWindowObserver() : add_count_(0), remove_count_(0) {
28 }
29
30 virtual ~TestTransientWindowObserver() {
31 }
32
33 int add_count() const { return add_count_; }
34 int remove_count() const { return remove_count_; }
35
36 // TransientWindowObserver overrides:
37 virtual void OnTransientChildAdded(Window* window,
38 Window* transient) OVERRIDE {
39 add_count_++;
40 }
41 virtual void OnTransientChildRemoved(Window* window,
42 Window* transient) OVERRIDE {
43 remove_count_++;
44 }
45
46 private:
47 int add_count_;
48 int remove_count_;
49
50 DISALLOW_COPY_AND_ASSIGN(TestTransientWindowObserver);
51 };
52
53 class TransientWindowManagerTest : public aura::test::AuraTestBase {
54 public:
55 TransientWindowManagerTest() {}
56 virtual ~TransientWindowManagerTest() {}
57
58 virtual void SetUp() OVERRIDE {
59 AuraTestBase::SetUp();
60 wm_state_.reset(new views::corewm::WMState);
61 }
62
63 virtual void TearDown() OVERRIDE {
64 wm_state_.reset();
65 AuraTestBase::TearDown();
66 }
67
68 protected:
69 // Creates a transient window that is transient to |parent|.
70 Window* CreateTransientChild(int id, Window* parent) {
71 Window* window = new Window(NULL);
72 window->set_id(id);
73 window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
74 window->Init(aura::WINDOW_LAYER_TEXTURED);
75 aura::client::ParentWindowWithContext(window, root_window(), gfx::Rect());
76 AddTransientChild(parent, window);
77 return window;
78 }
79
80 private:
81 scoped_ptr<views::corewm::WMState> wm_state_;
82
83 DISALLOW_COPY_AND_ASSIGN(TransientWindowManagerTest);
84 };
85
86 // Various assertions for transient children.
87 TEST_F(TransientWindowManagerTest, TransientChildren) {
88 scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window()));
89 scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get()));
90 scoped_ptr<Window> w3(CreateTestWindowWithId(3, parent.get()));
91 Window* w2 = CreateTestWindowWithId(2, parent.get());
92 // w2 is now owned by w1.
93 AddTransientChild(w1.get(), w2);
94 // Stack w1 at the top (end), this should force w2 to be last (on top of w1).
95 parent->StackChildAtTop(w1.get());
96 ASSERT_EQ(3u, parent->children().size());
97 EXPECT_EQ(w2, parent->children().back());
98
99 // Destroy w1, which should also destroy w3 (since it's a transient child).
100 w1.reset();
101 w2 = NULL;
102 ASSERT_EQ(1u, parent->children().size());
103 EXPECT_EQ(w3.get(), parent->children()[0]);
104
105 w1.reset(CreateTestWindowWithId(4, parent.get()));
106 w2 = CreateTestWindowWithId(5, w3.get());
107 AddTransientChild(w1.get(), w2);
108 parent->StackChildAtTop(w3.get());
109 // Stack w1 at the top (end), this shouldn't affect w2 since it has a
110 // different parent.
111 parent->StackChildAtTop(w1.get());
112 ASSERT_EQ(2u, parent->children().size());
113 EXPECT_EQ(w3.get(), parent->children()[0]);
114 EXPECT_EQ(w1.get(), parent->children()[1]);
115
116 // Hiding parent should hide transient children.
117 EXPECT_TRUE(w2->IsVisible());
118 w1->Hide();
119 EXPECT_FALSE(w2->IsVisible());
120 }
121
122 // Tests that transient children are stacked as a unit when using stack above.
123 TEST_F(TransientWindowManagerTest, TransientChildrenGroupAbove) {
124 scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window()));
125 scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get()));
126 Window* w11 = CreateTestWindowWithId(11, parent.get());
127 scoped_ptr<Window> w2(CreateTestWindowWithId(2, parent.get()));
128 Window* w21 = CreateTestWindowWithId(21, parent.get());
129 Window* w211 = CreateTestWindowWithId(211, parent.get());
130 Window* w212 = CreateTestWindowWithId(212, parent.get());
131 Window* w213 = CreateTestWindowWithId(213, parent.get());
132 Window* w22 = CreateTestWindowWithId(22, parent.get());
133 ASSERT_EQ(8u, parent->children().size());
134
135 // w11 is now owned by w1.
136 AddTransientChild(w1.get(), w11);
137 // w21 is now owned by w2.
138 AddTransientChild(w2.get(), w21);
139 // w22 is now owned by w2.
140 AddTransientChild(w2.get(), w22);
141 // w211 is now owned by w21.
142 AddTransientChild(w21, w211);
143 // w212 is now owned by w21.
144 AddTransientChild(w21, w212);
145 // w213 is now owned by w21.
146 AddTransientChild(w21, w213);
147 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
148
149 // Stack w1 at the top (end), this should force w11 to be last (on top of w1).
150 parent->StackChildAtTop(w1.get());
151 EXPECT_EQ(w11, parent->children().back());
152 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
153
154 // This tests that the order in children_ array rather than in
155 // transient_children_ array is used when reinserting transient children.
156 // If transient_children_ array was used '22' would be following '21'.
157 parent->StackChildAtTop(w2.get());
158 EXPECT_EQ(w22, parent->children().back());
159 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
160
161 parent->StackChildAbove(w11, w2.get());
162 EXPECT_EQ(w11, parent->children().back());
163 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
164
165 parent->StackChildAbove(w21, w1.get());
166 EXPECT_EQ(w22, parent->children().back());
167 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
168
169 parent->StackChildAbove(w21, w22);
170 EXPECT_EQ(w213, parent->children().back());
171 EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent.get()));
172
173 parent->StackChildAbove(w11, w21);
174 EXPECT_EQ(w11, parent->children().back());
175 EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent.get()));
176
177 parent->StackChildAbove(w213, w21);
178 EXPECT_EQ(w11, parent->children().back());
179 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
180
181 // No change when stacking a transient parent above its transient child.
182 parent->StackChildAbove(w21, w211);
183 EXPECT_EQ(w11, parent->children().back());
184 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
185
186 // This tests that the order in children_ array rather than in
187 // transient_children_ array is used when reinserting transient children.
188 // If transient_children_ array was used '22' would be following '21'.
189 parent->StackChildAbove(w2.get(), w1.get());
190 EXPECT_EQ(w212, parent->children().back());
191 EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent.get()));
192
193 parent->StackChildAbove(w11, w213);
194 EXPECT_EQ(w11, parent->children().back());
195 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
196 }
197
198 // Tests that transient children are stacked as a unit when using stack below.
199 TEST_F(TransientWindowManagerTest, TransientChildrenGroupBelow) {
200 scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window()));
201 scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get()));
202 Window* w11 = CreateTestWindowWithId(11, parent.get());
203 scoped_ptr<Window> w2(CreateTestWindowWithId(2, parent.get()));
204 Window* w21 = CreateTestWindowWithId(21, parent.get());
205 Window* w211 = CreateTestWindowWithId(211, parent.get());
206 Window* w212 = CreateTestWindowWithId(212, parent.get());
207 Window* w213 = CreateTestWindowWithId(213, parent.get());
208 Window* w22 = CreateTestWindowWithId(22, parent.get());
209 ASSERT_EQ(8u, parent->children().size());
210
211 // w11 is now owned by w1.
212 AddTransientChild(w1.get(), w11);
213 // w21 is now owned by w2.
214 AddTransientChild(w2.get(), w21);
215 // w22 is now owned by w2.
216 AddTransientChild(w2.get(), w22);
217 // w211 is now owned by w21.
218 AddTransientChild(w21, w211);
219 // w212 is now owned by w21.
220 AddTransientChild(w21, w212);
221 // w213 is now owned by w21.
222 AddTransientChild(w21, w213);
223 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
224
225 // Stack w2 at the bottom, this should force w11 to be last (on top of w1).
226 // This also tests that the order in children_ array rather than in
227 // transient_children_ array is used when reinserting transient children.
228 // If transient_children_ array was used '22' would be following '21'.
229 parent->StackChildAtBottom(w2.get());
230 EXPECT_EQ(w11, parent->children().back());
231 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
232
233 parent->StackChildAtBottom(w1.get());
234 EXPECT_EQ(w22, parent->children().back());
235 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
236
237 parent->StackChildBelow(w21, w1.get());
238 EXPECT_EQ(w11, parent->children().back());
239 EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
240
241 parent->StackChildBelow(w11, w2.get());
242 EXPECT_EQ(w22, parent->children().back());
243 EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
244
245 parent->StackChildBelow(w22, w21);
246 EXPECT_EQ(w213, parent->children().back());
247 EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent.get()));
248
249 parent->StackChildBelow(w21, w11);
250 EXPECT_EQ(w11, parent->children().back());
251 EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent.get()));
252
253 parent->StackChildBelow(w213, w211);
254 EXPECT_EQ(w11, parent->children().back());
255 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
256
257 // No change when stacking a transient parent below its transient child.
258 parent->StackChildBelow(w21, w211);
259 EXPECT_EQ(w11, parent->children().back());
260 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
261
262 parent->StackChildBelow(w1.get(), w2.get());
263 EXPECT_EQ(w212, parent->children().back());
264 EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent.get()));
265
266 parent->StackChildBelow(w213, w11);
267 EXPECT_EQ(w11, parent->children().back());
268 EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
269 }
270
271 namespace {
272
273 // Used by NotifyDelegateAfterDeletingTransients. Adds a string to a vector when
274 // OnWindowDestroyed() is invoked so that destruction order can be verified.
275 class DestroyedTrackingDelegate : public aura::test::TestWindowDelegate {
276 public:
277 explicit DestroyedTrackingDelegate(const std::string& name,
278 std::vector<std::string>* results)
279 : name_(name),
280 results_(results) {}
281
282 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
283 results_->push_back(name_);
284 }
285
286 private:
287 const std::string name_;
288 std::vector<std::string>* results_;
289
290 DISALLOW_COPY_AND_ASSIGN(DestroyedTrackingDelegate);
291 };
292
293 } // namespace
294
295 // Verifies the delegate is notified of destruction after transients are
296 // destroyed.
297 TEST_F(TransientWindowManagerTest, NotifyDelegateAfterDeletingTransients) {
298 std::vector<std::string> destruction_order;
299
300 DestroyedTrackingDelegate parent_delegate("parent", &destruction_order);
301 scoped_ptr<Window> parent(new Window(&parent_delegate));
302 parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
303
304 DestroyedTrackingDelegate transient_delegate("transient", &destruction_order);
305 Window* transient = new Window(&transient_delegate); // Owned by |parent|.
306 transient->Init(aura::WINDOW_LAYER_NOT_DRAWN);
307 AddTransientChild(parent.get(), transient);
308 parent.reset();
309
310 ASSERT_EQ(2u, destruction_order.size());
311 EXPECT_EQ("transient", destruction_order[0]);
312 EXPECT_EQ("parent", destruction_order[1]);
313 }
314
315 TEST_F(TransientWindowManagerTest, StackTransientsWhoseLayersHaveNoDelegate) {
316 // Create a window with several transients, then a couple windows on top.
317 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
318 scoped_ptr<Window> window11(CreateTransientChild(11, window1.get()));
319 scoped_ptr<Window> window12(CreateTransientChild(12, window1.get()));
320 scoped_ptr<Window> window13(CreateTransientChild(13, window1.get()));
321 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
322 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
323
324 EXPECT_EQ("1 11 12 13 2 3", ChildWindowIDsAsString(root_window()));
325
326 // Remove the delegates of a couple of transients, as if they are closing
327 // and animating out.
328 window11->layer()->set_delegate(NULL);
329 window13->layer()->set_delegate(NULL);
330
331 // Move window1 to the front. All transients should move with it, and their
332 // order should be preserved.
333 root_window()->StackChildAtTop(window1.get());
334
335 EXPECT_EQ("2 3 1 11 12 13", ChildWindowIDsAsString(root_window()));
336 }
337
338 TEST_F(TransientWindowManagerTest,
339 StackTransientsLayersRelativeToOtherTransients) {
340 // Create a window with several transients, then a couple windows on top.
341 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
342 scoped_ptr<Window> window11(CreateTransientChild(11, window1.get()));
343 scoped_ptr<Window> window12(CreateTransientChild(12, window1.get()));
344 scoped_ptr<Window> window13(CreateTransientChild(13, window1.get()));
345
346 EXPECT_EQ("1 11 12 13", ChildWindowIDsAsString(root_window()));
347
348 // Stack 11 above 12.
349 root_window()->StackChildAbove(window11.get(), window12.get());
350 EXPECT_EQ("1 12 11 13", ChildWindowIDsAsString(root_window()));
351
352 // Stack 13 below 12.
353 root_window()->StackChildBelow(window13.get(), window12.get());
354 EXPECT_EQ("1 13 12 11", ChildWindowIDsAsString(root_window()));
355
356 // Stack 11 above 1.
357 root_window()->StackChildAbove(window11.get(), window1.get());
358 EXPECT_EQ("1 11 13 12", ChildWindowIDsAsString(root_window()));
359
360 // Stack 12 below 13.
361 root_window()->StackChildBelow(window12.get(), window13.get());
362 EXPECT_EQ("1 11 12 13", ChildWindowIDsAsString(root_window()));
363 }
364
365 TEST_F(TransientWindowManagerTest,
366 StackTransientsLayersRelativeToOtherTransientsNoLayerDelegate) {
367 // Create a window with several transients, then a couple windows on top.
368 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
369 scoped_ptr<Window> window11(CreateTransientChild(11, window1.get()));
370 scoped_ptr<Window> window12(CreateTransientChild(12, window1.get()));
371 scoped_ptr<Window> window13(CreateTransientChild(13, window1.get()));
372 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
373 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
374
375 EXPECT_EQ("1 11 12 13 2 3", ChildWindowIDsAsString(root_window()));
376
377 window1->layer()->set_delegate(NULL);
378
379 // Stack 1 at top.
380 root_window()->StackChildAtTop(window1.get());
381 EXPECT_EQ("2 3 1 11 12 13", ChildWindowIDsAsString(root_window()));
382 }
383
384 class StackingMadrigalLayoutManager : public aura::LayoutManager {
385 public:
386 explicit StackingMadrigalLayoutManager(Window* root_window)
387 : root_window_(root_window) {
388 root_window_->SetLayoutManager(this);
389 }
390 virtual ~StackingMadrigalLayoutManager() {
391 }
392
393 private:
394 // Overridden from LayoutManager:
395 virtual void OnWindowResized() OVERRIDE {}
396 virtual void OnWindowAddedToLayout(Window* child) OVERRIDE {}
397 virtual void OnWillRemoveWindowFromLayout(Window* child) OVERRIDE {}
398 virtual void OnWindowRemovedFromLayout(Window* child) OVERRIDE {}
399 virtual void OnChildWindowVisibilityChanged(Window* child,
400 bool visible) OVERRIDE {
401 Window::Windows::const_iterator it = root_window_->children().begin();
402 Window* last_window = NULL;
403 for (; it != root_window_->children().end(); ++it) {
404 if (*it == child && last_window) {
405 if (!visible)
406 root_window_->StackChildAbove(last_window, *it);
407 else
408 root_window_->StackChildAbove(*it, last_window);
409 break;
410 }
411 last_window = *it;
412 }
413 }
414 virtual void SetChildBounds(Window* child,
415 const gfx::Rect& requested_bounds) OVERRIDE {
416 SetChildBoundsDirect(child, requested_bounds);
417 }
418
419 Window* root_window_;
420
421 DISALLOW_COPY_AND_ASSIGN(StackingMadrigalLayoutManager);
422 };
423
424 class StackingMadrigalVisibilityClient : public aura::client::VisibilityClient {
425 public:
426 explicit StackingMadrigalVisibilityClient(Window* root_window)
427 : ignored_window_(NULL) {
428 aura::client::SetVisibilityClient(root_window, this);
429 }
430 virtual ~StackingMadrigalVisibilityClient() {
431 }
432
433 void set_ignored_window(Window* ignored_window) {
434 ignored_window_ = ignored_window;
435 }
436
437 private:
438 // Overridden from client::VisibilityClient:
439 virtual void UpdateLayerVisibility(Window* window, bool visible) OVERRIDE {
440 if (!visible) {
441 if (window == ignored_window_)
442 window->layer()->set_delegate(NULL);
443 else
444 window->layer()->SetVisible(visible);
445 } else {
446 window->layer()->SetVisible(visible);
447 }
448 }
449
450 Window* ignored_window_;
451
452 DISALLOW_COPY_AND_ASSIGN(StackingMadrigalVisibilityClient);
453 };
454
455 // This test attempts to reconstruct a circumstance that can happen when the
456 // aura client attempts to manipulate the visibility and delegate of a layer
457 // independent of window visibility.
458 // A use case is where the client attempts to keep a window visible onscreen
459 // even after code has called Hide() on the window. The use case for this would
460 // be that window hides are animated (e.g. the window fades out). To prevent
461 // spurious updating the client code may also clear window's layer's delegate,
462 // so that the window cannot attempt to paint or update it further. The window
463 // uses the presence of a NULL layer delegate as a signal in stacking to note
464 // that the window is being manipulated by such a use case and its stacking
465 // should not be adjusted.
466 // One issue that can arise when a window opens two transient children, and the
467 // first is hidden. Subsequent attempts to activate the transient parent can
468 // result in the transient parent being stacked above the second transient
469 // child. A fix is made to Window::StackAbove to prevent this, and this test
470 // verifies this fix.
471 TEST_F(TransientWindowManagerTest, StackingMadrigal) {
472 new StackingMadrigalLayoutManager(root_window());
473 StackingMadrigalVisibilityClient visibility_client(root_window());
474
475 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
476 scoped_ptr<Window> window11(CreateTransientChild(11, window1.get()));
477
478 visibility_client.set_ignored_window(window11.get());
479
480 window11->Show();
481 window11->Hide();
482
483 // As a transient, window11 should still be stacked above window1, even when
484 // hidden.
485 EXPECT_TRUE(aura::test::WindowIsAbove(window11.get(), window1.get()));
486 EXPECT_TRUE(aura::test::LayerIsAbove(window11.get(), window1.get()));
487
488 // A new transient should still be above window1. It will appear behind
489 // window11 because we don't stack windows on top of targets with NULL
490 // delegates.
491 scoped_ptr<Window> window12(CreateTransientChild(12, window1.get()));
492 window12->Show();
493
494 EXPECT_TRUE(aura::test::WindowIsAbove(window12.get(), window1.get()));
495 EXPECT_TRUE(aura::test::LayerIsAbove(window12.get(), window1.get()));
496
497 // In earlier versions of the StackChildAbove() method, attempting to stack
498 // window1 above window12 at this point would actually restack the layers
499 // resulting in window12's layer being below window1's layer (though the
500 // windows themselves would still be correctly stacked, so events would pass
501 // through.)
502 root_window()->StackChildAbove(window1.get(), window12.get());
503
504 // Both window12 and its layer should be stacked above window1.
505 EXPECT_TRUE(aura::test::WindowIsAbove(window12.get(), window1.get()));
506 EXPECT_TRUE(aura::test::LayerIsAbove(window12.get(), window1.get()));
507 }
508
509 // Test for an issue where attempting to stack a primary window on top of a
510 // transient with a NULL layer delegate causes that primary window to be moved,
511 // but the layer order not changed to match. http://crbug.com/112562
512 TEST_F(TransientWindowManagerTest, StackOverClosingTransient) {
513 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
514 scoped_ptr<Window> transient1(CreateTransientChild(11, window1.get()));
515 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
516 scoped_ptr<Window> transient2(CreateTransientChild(21, window2.get()));
517
518 // Both windows and layers are stacked in creation order.
519 Window* root = root_window();
520 ASSERT_EQ(4u, root->children().size());
521 EXPECT_EQ(root->children()[0], window1.get());
522 EXPECT_EQ(root->children()[1], transient1.get());
523 EXPECT_EQ(root->children()[2], window2.get());
524 EXPECT_EQ(root->children()[3], transient2.get());
525 ASSERT_EQ(4u, root->layer()->children().size());
526 EXPECT_EQ(root->layer()->children()[0], window1->layer());
527 EXPECT_EQ(root->layer()->children()[1], transient1->layer());
528 EXPECT_EQ(root->layer()->children()[2], window2->layer());
529 EXPECT_EQ(root->layer()->children()[3], transient2->layer());
530 EXPECT_EQ("1 11 2 21", ChildWindowIDsAsString(root_window()));
531
532 // This brings window1 and its transient to the front.
533 root->StackChildAtTop(window1.get());
534 EXPECT_EQ("2 21 1 11", ChildWindowIDsAsString(root_window()));
535
536 EXPECT_EQ(root->children()[0], window2.get());
537 EXPECT_EQ(root->children()[1], transient2.get());
538 EXPECT_EQ(root->children()[2], window1.get());
539 EXPECT_EQ(root->children()[3], transient1.get());
540 EXPECT_EQ(root->layer()->children()[0], window2->layer());
541 EXPECT_EQ(root->layer()->children()[1], transient2->layer());
542 EXPECT_EQ(root->layer()->children()[2], window1->layer());
543 EXPECT_EQ(root->layer()->children()[3], transient1->layer());
544
545 // Pretend we're closing the top-most transient, then bring window2 to the
546 // front. This mimics activating a browser window while the status bubble
547 // is fading out. The transient should stay topmost.
548 transient1->layer()->set_delegate(NULL);
549 root->StackChildAtTop(window2.get());
550
551 EXPECT_EQ(root->children()[0], window1.get());
552 EXPECT_EQ(root->children()[1], window2.get());
553 EXPECT_EQ(root->children()[2], transient2.get());
554 EXPECT_EQ(root->children()[3], transient1.get());
555 EXPECT_EQ(root->layer()->children()[0], window1->layer());
556 EXPECT_EQ(root->layer()->children()[1], window2->layer());
557 EXPECT_EQ(root->layer()->children()[2], transient2->layer());
558 EXPECT_EQ(root->layer()->children()[3], transient1->layer());
559
560 // Close the transient. Remaining windows are stable.
561 transient1.reset();
562
563 ASSERT_EQ(3u, root->children().size());
564 EXPECT_EQ(root->children()[0], window1.get());
565 EXPECT_EQ(root->children()[1], window2.get());
566 EXPECT_EQ(root->children()[2], transient2.get());
567 ASSERT_EQ(3u, root->layer()->children().size());
568 EXPECT_EQ(root->layer()->children()[0], window1->layer());
569 EXPECT_EQ(root->layer()->children()[1], window2->layer());
570 EXPECT_EQ(root->layer()->children()[2], transient2->layer());
571
572 // Open another window on top.
573 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
574
575 ASSERT_EQ(4u, root->children().size());
576 EXPECT_EQ(root->children()[0], window1.get());
577 EXPECT_EQ(root->children()[1], window2.get());
578 EXPECT_EQ(root->children()[2], transient2.get());
579 EXPECT_EQ(root->children()[3], window3.get());
580 ASSERT_EQ(4u, root->layer()->children().size());
581 EXPECT_EQ(root->layer()->children()[0], window1->layer());
582 EXPECT_EQ(root->layer()->children()[1], window2->layer());
583 EXPECT_EQ(root->layer()->children()[2], transient2->layer());
584 EXPECT_EQ(root->layer()->children()[3], window3->layer());
585
586 // Pretend we're closing the topmost non-transient window, then bring
587 // window2 to the top. It should not move.
588 window3->layer()->set_delegate(NULL);
589 root->StackChildAtTop(window2.get());
590
591 ASSERT_EQ(4u, root->children().size());
592 EXPECT_EQ(root->children()[0], window1.get());
593 EXPECT_EQ(root->children()[1], window2.get());
594 EXPECT_EQ(root->children()[2], transient2.get());
595 EXPECT_EQ(root->children()[3], window3.get());
596 ASSERT_EQ(4u, root->layer()->children().size());
597 EXPECT_EQ(root->layer()->children()[0], window1->layer());
598 EXPECT_EQ(root->layer()->children()[1], window2->layer());
599 EXPECT_EQ(root->layer()->children()[2], transient2->layer());
600 EXPECT_EQ(root->layer()->children()[3], window3->layer());
601
602 // Bring window1 to the top. It should move ahead of window2, but not
603 // ahead of window3 (with NULL delegate).
604 root->StackChildAtTop(window1.get());
605
606 ASSERT_EQ(4u, root->children().size());
607 EXPECT_EQ(root->children()[0], window2.get());
608 EXPECT_EQ(root->children()[1], transient2.get());
609 EXPECT_EQ(root->children()[2], window1.get());
610 EXPECT_EQ(root->children()[3], window3.get());
611 ASSERT_EQ(4u, root->layer()->children().size());
612 EXPECT_EQ(root->layer()->children()[0], window2->layer());
613 EXPECT_EQ(root->layer()->children()[1], transient2->layer());
614 EXPECT_EQ(root->layer()->children()[2], window1->layer());
615 EXPECT_EQ(root->layer()->children()[3], window3->layer());
616 }
617
618 // Verifies TransientWindowObserver is notified appropriately.
619 TEST_F(TransientWindowManagerTest, TransientWindowObserverNotified) {
620 scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window()));
621 scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get()));
622
623 TestTransientWindowObserver test_observer;
624 TransientWindowManager::Get(parent.get())->AddObserver(&test_observer);
625
626 AddTransientChild(parent.get(), w1.get());
627 EXPECT_EQ(1, test_observer.add_count());
628 EXPECT_EQ(0, test_observer.remove_count());
629
630 RemoveTransientChild(parent.get(), w1.get());
631 EXPECT_EQ(1, test_observer.add_count());
632 EXPECT_EQ(1, test_observer.remove_count());
633
634 TransientWindowManager::Get(parent.get())->RemoveObserver(&test_observer);
635 }
636
637 } // namespace corewm
638 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/corewm/transient_window_manager.cc ('k') | ui/views/corewm/transient_window_observer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698