1// Copyright (c) 2012 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/window_modality_controller.h"
6
7#include "ash/shell.h"
8#include "ash/test/ash_test_base.h"
9#include "ash/wm/window_util.h"
10#include "ui/aura/client/aura_constants.h"
11#include "ui/aura/root_window.h"
12#include "ui/aura/test/event_generator.h"
13#include "ui/aura/test/test_window_delegate.h"
14#include "ui/aura/test/test_windows.h"
15#include "ui/aura/window.h"
16#include "ui/base/ui_base_types.h"
17#include "ui/views/test/capture_tracking_view.h"
18#include "ui/views/test/child_modal_window.h"
19#include "ui/views/widget/widget.h"
20
21namespace ash {
22namespace internal {
23
24typedef test::AshTestBase WindowModalityControllerTest;
25
26namespace {
27
28bool ValidateStacking(aura::Window* parent, int ids[], int count) {
29  for (int i = 0; i < count; ++i) {
30    if (parent->children().at(i)->id() != ids[i])
31      return false;
32  }
33  return true;
34}
35
36}  // namespace
37
38// Creates three windows, w1, w11, and w12. w11 is a non-modal transient, w12 is
39// a modal transient.
40// Validates:
41// - it should be possible to activate w12 even when w11 is open.
42// - activating w1 activates w12 and updates stacking order appropriately.
43// - closing a window passes focus up the stack.
44TEST_F(WindowModalityControllerTest, BasicActivation) {
45  aura::test::TestWindowDelegate d;
46  scoped_ptr<aura::Window> w1(
47      CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
48  scoped_ptr<aura::Window> w11(
49      CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect()));
50  scoped_ptr<aura::Window> w12(
51      CreateTestWindowInShellWithDelegate(&d, -12, gfx::Rect()));
52
53  w1->AddTransientChild(w11.get());
54  wm::ActivateWindow(w1.get());
55  EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
56  wm::ActivateWindow(w11.get());
57  EXPECT_TRUE(wm::IsActiveWindow(w11.get()));
58
59  w12->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
60  w1->AddTransientChild(w12.get());
61  wm::ActivateWindow(w12.get());
62  EXPECT_TRUE(wm::IsActiveWindow(w12.get()));
63
64  wm::ActivateWindow(w11.get());
65  EXPECT_TRUE(wm::IsActiveWindow(w11.get()));
66
67  int check1[] = { -1, -12, -11 };
68  EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1)));
69
70  wm::ActivateWindow(w1.get());
71  EXPECT_TRUE(wm::IsActiveWindow(w12.get()));
72  // Transient children are always stacked above their transient parent, which
73  // is why this order is not -11, -1, -12.
74  int check2[] = { -1, -11, -12 };
75  EXPECT_TRUE(ValidateStacking(w1->parent(), check2, arraysize(check2)));
76
77  w12.reset();
78  EXPECT_TRUE(wm::IsActiveWindow(w11.get()));
79  w11.reset();
80  EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
81}
82
83// Create two toplevel windows w1 and w2, and nest two modals w11 and w111 below
84// w1.
85// Validates:
86// - activating w1 while w11/w111 is showing always activates most deeply nested
87//   descendant.
88// - closing a window passes focus up the stack.
89TEST_F(WindowModalityControllerTest, NestedModals) {
90  aura::test::TestWindowDelegate d;
91  scoped_ptr<aura::Window> w1(
92      CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
93  scoped_ptr<aura::Window> w11(
94      CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect()));
95  scoped_ptr<aura::Window> w111(
96      CreateTestWindowInShellWithDelegate(&d, -111, gfx::Rect()));
97  scoped_ptr<aura::Window> w2(
98      CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect()));
99
100  w1->AddTransientChild(w11.get());
101  w11->AddTransientChild(w111.get());
102
103  wm::ActivateWindow(w1.get());
104  EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
105  wm::ActivateWindow(w2.get());
106  EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
107
108  // Set up modality.
109  w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
110  w111->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
111
112  wm::ActivateWindow(w1.get());
113  EXPECT_TRUE(wm::IsActiveWindow(w111.get()));
114  int check1[] = { -2, -1, -11, -111 };
115  EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1)));
116
117  wm::ActivateWindow(w11.get());
118  EXPECT_TRUE(wm::IsActiveWindow(w111.get()));
119  EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1)));
120
121  wm::ActivateWindow(w111.get());
122  EXPECT_TRUE(wm::IsActiveWindow(w111.get()));
123  EXPECT_TRUE(ValidateStacking(w1->parent(), check1, arraysize(check1)));
124
125  wm::ActivateWindow(w2.get());
126  EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
127  int check2[] = { -1, -11, -111, -2 };
128  EXPECT_TRUE(ValidateStacking(w1->parent(), check2, arraysize(check2)));
129
130  w2.reset();
131  EXPECT_TRUE(wm::IsActiveWindow(w111.get()));
132  w111.reset();
133  EXPECT_TRUE(wm::IsActiveWindow(w11.get()));
134  w11.reset();
135  EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
136}
137
138// Create two toplevel windows w1 and w2, and nest two modals w11 and w111 below
139// w1.
140// Validates:
141// - destroying w11 while w111 is focused activates w1.
142TEST_F(WindowModalityControllerTest, NestedModalsOuterClosed) {
143  aura::test::TestWindowDelegate d;
144  scoped_ptr<aura::Window> w1(
145      CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
146  scoped_ptr<aura::Window> w11(
147      CreateTestWindowInShellWithDelegate(&d, -11, gfx::Rect()));
148  // |w111| will be owned and deleted by |w11|.
149  aura::Window* w111 =
150      CreateTestWindowInShellWithDelegate(&d, -111, gfx::Rect());
151  scoped_ptr<aura::Window> w2(
152      CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect()));
153
154  w1->AddTransientChild(w11.get());
155  w11->AddTransientChild(w111);
156
157  wm::ActivateWindow(w1.get());
158  EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
159  wm::ActivateWindow(w2.get());
160  EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
161
162  // Set up modality.
163  w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
164  w111->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
165
166  wm::ActivateWindow(w1.get());
167  EXPECT_TRUE(wm::IsActiveWindow(w111));
168
169  w111->Hide();
170  EXPECT_TRUE(wm::IsActiveWindow(w11.get()));
171
172  // TODO(oshima): Re-showing doesn't set the focus back to
173  // modal window. There is no such use case right now, but it
174  // probably should.
175
176  w11.reset();
177  EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
178}
179
180// Modality also prevents events from being passed to the transient parent.
181TEST_F(WindowModalityControllerTest, Events) {
182  aura::test::TestWindowDelegate d;
183  scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(&d, -1,
184      gfx::Rect(0, 0, 100, 100)));
185  scoped_ptr<aura::Window> w11(CreateTestWindowInShellWithDelegate(&d, -11,
186      gfx::Rect(20, 20, 50, 50)));
187
188  w1->AddTransientChild(w11.get());
189
190  {
191    // Clicking a point within w1 should activate that window.
192    aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
193                                         gfx::Point(10, 10));
194    generator.ClickLeftButton();
195    EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
196  }
197
198  w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
199
200  {
201    // Clicking a point within w1 should activate w11.
202    aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
203                                         gfx::Point(10, 10));
204    generator.ClickLeftButton();
205    EXPECT_TRUE(wm::IsActiveWindow(w11.get()));
206  }
207}
208
209// Creates windows w1 and non activatiable child w11. Creates transient window
210// w2 and adds it as a transeint child of w1. Ensures that w2 is parented to
211// the parent of w1, and that GetModalTransient(w11) returns w2.
212TEST_F(WindowModalityControllerTest, GetModalTransient) {
213  aura::test::TestWindowDelegate d;
214  scoped_ptr<aura::Window> w1(
215      CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
216  scoped_ptr<aura::Window> w11(
217      aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get()));
218  scoped_ptr<aura::Window> w2(
219      CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect()));
220  w2->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
221
222  aura::Window* wt;
223  wt = views::corewm::GetModalTransient(w1.get());
224  ASSERT_EQ(static_cast<aura::Window*>(NULL), wt);
225
226  // Parent w2 to w1. It should get parented to the parent of w1.
227  w1->AddTransientChild(w2.get());
228  ASSERT_EQ(2U, w1->parent()->children().size());
229  EXPECT_EQ(-2, w1->parent()->children().at(1)->id());
230
231  // Request the modal transient window for w1, it should be w2.
232  wt = views::corewm::GetModalTransient(w1.get());
233  ASSERT_NE(static_cast<aura::Window*>(NULL), wt);
234  EXPECT_EQ(-2, wt->id());
235
236  // Request the modal transient window for w11, it should also be w2.
237  wt = views::corewm::GetModalTransient(w11.get());
238  ASSERT_NE(static_cast<aura::Window*>(NULL), wt);
239  EXPECT_EQ(-2, wt->id());
240}
241
242// Verifies we generate a capture lost when showing a modal window.
243TEST_F(WindowModalityControllerTest, ChangeCapture) {
244  views::Widget* widget = views::Widget::CreateWindowWithContext(
245      NULL, Shell::GetPrimaryRootWindow());
246  scoped_ptr<aura::Window> widget_window(widget->GetNativeView());
247  views::test::CaptureTrackingView* view = new views::test::CaptureTrackingView;
248  widget->client_view()->AddChildView(view);
249  widget->SetBounds(gfx::Rect(0, 0, 200, 200));
250  view->SetBoundsRect(widget->client_view()->GetLocalBounds());
251  widget->Show();
252
253  gfx::Point center(view->width() / 2, view->height() / 2);
254  views::View::ConvertPointToScreen(view, &center);
255  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), center);
256  generator.PressLeftButton();
257  EXPECT_TRUE(view->got_press());
258
259  views::Widget* modal_widget =
260      views::Widget::CreateWindowWithParent(NULL, widget->GetNativeView());
261  scoped_ptr<aura::Window> modal_window(modal_widget->GetNativeView());
262  modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
263  views::test::CaptureTrackingView* modal_view =
264      new views::test::CaptureTrackingView;
265  modal_widget->client_view()->AddChildView(modal_view);
266  modal_widget->SetBounds(gfx::Rect(50, 50, 200, 200));
267  modal_view->SetBoundsRect(modal_widget->client_view()->GetLocalBounds());
268  modal_widget->Show();
269
270  EXPECT_TRUE(view->got_capture_lost());
271  generator.ReleaseLeftButton();
272
273  view->reset();
274
275  EXPECT_FALSE(modal_view->got_capture_lost());
276  EXPECT_FALSE(modal_view->got_press());
277
278  gfx::Point modal_center(modal_view->width() / 2, modal_view->height() / 2);
279  views::View::ConvertPointToScreen(modal_view, &modal_center);
280  generator.MoveMouseTo(modal_center, 1);
281  generator.PressLeftButton();
282  EXPECT_TRUE(modal_view->got_press());
283  EXPECT_FALSE(modal_view->got_capture_lost());
284  EXPECT_FALSE(view->got_capture_lost());
285  EXPECT_FALSE(view->got_press());
286}
287
288class TouchTrackerWindowDelegate : public aura::test::TestWindowDelegate {
289 public:
290  TouchTrackerWindowDelegate() : received_touch_(false) {}
291  virtual ~TouchTrackerWindowDelegate() {}
292
293  void reset() {
294    received_touch_ = false;
295  }
296
297  bool received_touch() const { return received_touch_; }
298
299 private:
300  // Overridden from aura::test::TestWindowDelegate.
301  virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
302    received_touch_ = true;
303    aura::test::TestWindowDelegate::OnTouchEvent(event);
304  }
305
306  bool received_touch_;
307
308  DISALLOW_COPY_AND_ASSIGN(TouchTrackerWindowDelegate);
309};
310
311// Modality should prevent events from being passed to the transient parent.
312TEST_F(WindowModalityControllerTest, TouchEvent) {
313  TouchTrackerWindowDelegate d1;
314  scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(&d1,
315      -1, gfx::Rect(0, 0, 100, 100)));
316  TouchTrackerWindowDelegate d11;
317  scoped_ptr<aura::Window> w11(CreateTestWindowInShellWithDelegate(&d11,
318      -11, gfx::Rect(20, 20, 50, 50)));
319
320  w1->AddTransientChild(w11.get());
321  d1.reset();
322  d11.reset();
323
324  {
325    // Clicking a point within w1 should activate that window.
326    aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
327                                         gfx::Point(10, 10));
328    generator.PressMoveAndReleaseTouchTo(gfx::Point(10, 10));
329    EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
330    EXPECT_TRUE(d1.received_touch());
331    EXPECT_FALSE(d11.received_touch());
332  }
333
334  w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
335  d1.reset();
336  d11.reset();
337
338  {
339    // Clicking a point within w1 should activate w11.
340    aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
341                                         gfx::Point(10, 10));
342    generator.PressMoveAndReleaseTouchTo(gfx::Point(10, 10));
343    EXPECT_TRUE(wm::IsActiveWindow(w11.get()));
344    EXPECT_FALSE(d1.received_touch());
345    EXPECT_FALSE(d11.received_touch());
346  }
347}
348
349// Child-modal test.
350// Creates:
351// - A |parent| window that hosts a |modal_parent| window within itself. The
352//   |parent| and |modal_parent| windows are not the same window.  The
353//   |modal_parent| window is not activatable, because it's contained within the
354//   |parent| window.
355// - A |child| window with parent window |parent|, but is modal to
356//   |modal_parent| window.
357// Validates:
358// - Clicking on the |modal_parent| should activate the |child| window.
359// - Clicking on the |parent| window outside of the |modal_parent| bounds should
360//   activate the |parent| window.
361// - Clicking on the |child| while |parent| is active should activate the
362//   |child| window.
363// - Focus should follow the active window.
364TEST_F(WindowModalityControllerTest, ChildModal) {
365  views::test::ChildModalParent* delegate =
366      new views::test::ChildModalParent(CurrentContext());
367  views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
368      delegate, CurrentContext(), gfx::Rect(0, 0, 400, 400));
369  widget->Show();
370
371  aura::Window* parent = widget->GetNativeView();
372  EXPECT_TRUE(wm::IsActiveWindow(parent));
373
374  aura::Window* modal_parent = delegate->GetModalParent();
375  EXPECT_NE(static_cast<aura::Window*>(NULL), modal_parent);
376  EXPECT_NE(parent, modal_parent);
377  EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
378
379  delegate->ShowChild();
380  aura::Window* child = delegate->GetChild();
381  EXPECT_NE(static_cast<aura::Window*>(NULL), child);
382
383  EXPECT_TRUE(wm::IsActiveWindow(child));
384  EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
385  EXPECT_FALSE(wm::IsActiveWindow(parent));
386
387  EXPECT_TRUE(child->HasFocus());
388  EXPECT_FALSE(modal_parent->HasFocus());
389  EXPECT_FALSE(parent->HasFocus());
390
391  wm::ActivateWindow(modal_parent);
392
393  EXPECT_TRUE(wm::IsActiveWindow(child));
394  EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
395  EXPECT_FALSE(wm::IsActiveWindow(parent));
396
397  EXPECT_TRUE(child->HasFocus());
398  EXPECT_FALSE(modal_parent->HasFocus());
399  EXPECT_FALSE(parent->HasFocus());
400
401  wm::ActivateWindow(parent);
402
403  EXPECT_FALSE(wm::IsActiveWindow(child));
404  EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
405  EXPECT_TRUE(wm::IsActiveWindow(parent));
406
407  EXPECT_FALSE(child->HasFocus());
408  EXPECT_FALSE(modal_parent->HasFocus());
409  EXPECT_TRUE(parent->HasFocus());
410
411  wm::ActivateWindow(child);
412
413  EXPECT_TRUE(wm::IsActiveWindow(child));
414  EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
415  EXPECT_FALSE(wm::IsActiveWindow(parent));
416
417  EXPECT_TRUE(child->HasFocus());
418  EXPECT_FALSE(modal_parent->HasFocus());
419  EXPECT_FALSE(parent->HasFocus());
420}
421
422// Same as |ChildModal| test, but using |EventGenerator| rather than bypassing
423// it by calling |ActivateWindow|.
424TEST_F(WindowModalityControllerTest, ChildModalEventGenerator) {
425  views::test::ChildModalParent* delegate =
426      new views::test::ChildModalParent(CurrentContext());
427  views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
428      delegate, CurrentContext(), gfx::Rect(0, 0, 400, 400));
429  widget->Show();
430
431  aura::Window* parent = widget->GetNativeView();
432  EXPECT_TRUE(wm::IsActiveWindow(parent));
433
434  aura::Window* modal_parent = delegate->GetModalParent();
435  EXPECT_NE(static_cast<aura::Window*>(NULL), modal_parent);
436  EXPECT_NE(parent, modal_parent);
437  EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
438
439  delegate->ShowChild();
440  aura::Window* child = delegate->GetChild();
441  EXPECT_NE(static_cast<aura::Window*>(NULL), child);
442
443  EXPECT_TRUE(wm::IsActiveWindow(child));
444  EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
445  EXPECT_FALSE(wm::IsActiveWindow(parent));
446
447  EXPECT_TRUE(child->HasFocus());
448  EXPECT_FALSE(modal_parent->HasFocus());
449  EXPECT_FALSE(parent->HasFocus());
450
451  {
452    aura::test::EventGenerator generator(
453        Shell::GetPrimaryRootWindow(),
454        parent->bounds().origin() +
455            gfx::Vector2d(10, parent->bounds().height() - 10));
456    generator.ClickLeftButton();
457    generator.ClickLeftButton();
458
459    EXPECT_TRUE(wm::IsActiveWindow(child));
460    EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
461    EXPECT_FALSE(wm::IsActiveWindow(parent));
462
463    EXPECT_TRUE(child->HasFocus());
464    EXPECT_FALSE(modal_parent->HasFocus());
465    EXPECT_FALSE(parent->HasFocus());
466  }
467
468  {
469    aura::test::EventGenerator generator(
470        Shell::GetPrimaryRootWindow(),
471        parent->bounds().origin() + gfx::Vector2d(10, 10));
472    generator.ClickLeftButton();
473
474    EXPECT_FALSE(wm::IsActiveWindow(child));
475    EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
476    EXPECT_TRUE(wm::IsActiveWindow(parent));
477
478    EXPECT_FALSE(child->HasFocus());
479    EXPECT_FALSE(modal_parent->HasFocus());
480    EXPECT_TRUE(parent->HasFocus());
481  }
482
483  {
484    aura::test::EventGenerator generator(
485        Shell::GetPrimaryRootWindow(),
486        child->bounds().origin() + gfx::Vector2d(10, 10));
487    generator.ClickLeftButton();
488
489    EXPECT_TRUE(wm::IsActiveWindow(child));
490    EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
491    EXPECT_FALSE(wm::IsActiveWindow(parent));
492
493    EXPECT_TRUE(child->HasFocus());
494    EXPECT_FALSE(modal_parent->HasFocus());
495    EXPECT_FALSE(parent->HasFocus());
496  }
497}
498
499// Window-modal test for the case when the originally clicked window is an
500// ancestor of the modal parent.
501TEST_F(WindowModalityControllerTest, WindowModalAncestor) {
502  aura::test::TestWindowDelegate d;
503  scoped_ptr<aura::Window> w1(
504      CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
505  scoped_ptr<aura::Window> w2(
506      aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get()));
507  scoped_ptr<aura::Window> w3(
508      aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w2.get()));
509  scoped_ptr<aura::Window> w4(
510      CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect()));
511  w4->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
512  w1->AddTransientChild(w4.get());
513
514  wm::ActivateWindow(w1.get());
515  EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
516
517  wm::ActivateWindow(w2.get());
518  EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
519
520  wm::ActivateWindow(w3.get());
521  EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
522
523  wm::ActivateWindow(w4.get());
524  EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
525}
526
527// Child-modal test for the case when the originally clicked window is an
528// ancestor of the modal parent.
529TEST_F(WindowModalityControllerTest, ChildModalAncestor) {
530  aura::test::TestWindowDelegate d;
531  scoped_ptr<aura::Window> w1(
532      CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
533  scoped_ptr<aura::Window> w2(
534      aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get()));
535  scoped_ptr<aura::Window> w3(
536      aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w2.get()));
537  scoped_ptr<aura::Window> w4(
538      CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect()));
539  w4->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_CHILD);
540  views::corewm::SetModalParent(w4.get(), w2.get());
541  w1->AddTransientChild(w4.get());
542
543  wm::ActivateWindow(w1.get());
544  EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
545
546  wm::ActivateWindow(w2.get());
547  EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
548
549  wm::ActivateWindow(w3.get());
550  EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
551
552  wm::ActivateWindow(w4.get());
553  EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
554}
555
556}  // namespace internal
557}  // namespace ash
558