• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 namespace ash {
22 namespace internal {
23 
24 typedef test::AshTestBase WindowModalityControllerTest;
25 
26 namespace {
27 
ValidateStacking(aura::Window * parent,int ids[],int count)28 bool 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.
TEST_F(WindowModalityControllerTest,BasicActivation)44 TEST_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.
TEST_F(WindowModalityControllerTest,NestedModals)89 TEST_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.
TEST_F(WindowModalityControllerTest,NestedModalsOuterClosed)142 TEST_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.
TEST_F(WindowModalityControllerTest,Events)181 TEST_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.
TEST_F(WindowModalityControllerTest,GetModalTransient)212 TEST_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.
TEST_F(WindowModalityControllerTest,ChangeCapture)243 TEST_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 
288 class TouchTrackerWindowDelegate : public aura::test::TestWindowDelegate {
289  public:
TouchTrackerWindowDelegate()290   TouchTrackerWindowDelegate()
291       : received_touch_(false),
292         last_event_type_(ui::ET_UNKNOWN) {
293   }
~TouchTrackerWindowDelegate()294   virtual ~TouchTrackerWindowDelegate() {}
295 
reset()296   void reset() {
297     received_touch_ = false;
298     last_event_type_ = ui::ET_UNKNOWN;
299   }
300 
received_touch() const301   bool received_touch() const { return received_touch_; }
last_event_type() const302   ui::EventType last_event_type() const { return last_event_type_; }
303 
304  private:
305   // Overridden from aura::test::TestWindowDelegate.
OnTouchEvent(ui::TouchEvent * event)306   virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
307     received_touch_ = true;
308     last_event_type_ = event->type();
309     aura::test::TestWindowDelegate::OnTouchEvent(event);
310   }
311 
312   bool received_touch_;
313   ui::EventType last_event_type_;
314 
315   DISALLOW_COPY_AND_ASSIGN(TouchTrackerWindowDelegate);
316 };
317 
318 // Modality should prevent events from being passed to the transient parent.
TEST_F(WindowModalityControllerTest,TouchEvent)319 TEST_F(WindowModalityControllerTest, TouchEvent) {
320   TouchTrackerWindowDelegate d1;
321   scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(&d1,
322       -1, gfx::Rect(0, 0, 100, 100)));
323   TouchTrackerWindowDelegate d11;
324   scoped_ptr<aura::Window> w11(CreateTestWindowInShellWithDelegate(&d11,
325       -11, gfx::Rect(20, 20, 50, 50)));
326   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
327                                        gfx::Point(10, 10));
328 
329   w1->AddTransientChild(w11.get());
330   d1.reset();
331   d11.reset();
332 
333   {
334     // Clicking a point within w1 should activate that window.
335     generator.PressMoveAndReleaseTouchTo(gfx::Point(10, 10));
336     EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
337     EXPECT_TRUE(d1.received_touch());
338     EXPECT_FALSE(d11.received_touch());
339   }
340 
341   {
342     // Adding a modal window while a touch is down should fire a touch cancel.
343     generator.PressTouch();
344     generator.MoveTouch(gfx::Point(10, 10));
345     d1.reset();
346     d11.reset();
347 
348     w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
349     EXPECT_TRUE(d1.received_touch());
350     EXPECT_EQ(ui::ET_TOUCH_CANCELLED, d1.last_event_type());
351     EXPECT_FALSE(d11.received_touch());
352   }
353 }
354 
355 // Child-modal test.
356 // Creates:
357 // - A |parent| window that hosts a |modal_parent| window within itself. The
358 //   |parent| and |modal_parent| windows are not the same window.  The
359 //   |modal_parent| window is not activatable, because it's contained within the
360 //   |parent| window.
361 // - A |child| window with parent window |parent|, but is modal to
362 //   |modal_parent| window.
363 // Validates:
364 // - Clicking on the |modal_parent| should activate the |child| window.
365 // - Clicking on the |parent| window outside of the |modal_parent| bounds should
366 //   activate the |parent| window.
367 // - Clicking on the |child| while |parent| is active should activate the
368 //   |child| window.
369 // - Focus should follow the active window.
TEST_F(WindowModalityControllerTest,ChildModal)370 TEST_F(WindowModalityControllerTest, ChildModal) {
371   views::test::ChildModalParent* delegate =
372       new views::test::ChildModalParent(CurrentContext());
373   views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
374       delegate, CurrentContext(), gfx::Rect(0, 0, 400, 400));
375   widget->Show();
376 
377   aura::Window* parent = widget->GetNativeView();
378   EXPECT_TRUE(wm::IsActiveWindow(parent));
379 
380   aura::Window* modal_parent = delegate->GetModalParent();
381   EXPECT_NE(static_cast<aura::Window*>(NULL), modal_parent);
382   EXPECT_NE(parent, modal_parent);
383   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
384 
385   delegate->ShowChild();
386   aura::Window* child = delegate->GetChild();
387   EXPECT_NE(static_cast<aura::Window*>(NULL), child);
388 
389   EXPECT_TRUE(wm::IsActiveWindow(child));
390   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
391   EXPECT_FALSE(wm::IsActiveWindow(parent));
392 
393   EXPECT_TRUE(child->HasFocus());
394   EXPECT_FALSE(modal_parent->HasFocus());
395   EXPECT_FALSE(parent->HasFocus());
396 
397   wm::ActivateWindow(modal_parent);
398 
399   EXPECT_TRUE(wm::IsActiveWindow(child));
400   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
401   EXPECT_FALSE(wm::IsActiveWindow(parent));
402 
403   EXPECT_TRUE(child->HasFocus());
404   EXPECT_FALSE(modal_parent->HasFocus());
405   EXPECT_FALSE(parent->HasFocus());
406 
407   wm::ActivateWindow(parent);
408 
409   EXPECT_FALSE(wm::IsActiveWindow(child));
410   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
411   EXPECT_TRUE(wm::IsActiveWindow(parent));
412 
413   EXPECT_FALSE(child->HasFocus());
414   EXPECT_FALSE(modal_parent->HasFocus());
415   EXPECT_TRUE(parent->HasFocus());
416 
417   wm::ActivateWindow(child);
418 
419   EXPECT_TRUE(wm::IsActiveWindow(child));
420   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
421   EXPECT_FALSE(wm::IsActiveWindow(parent));
422 
423   EXPECT_TRUE(child->HasFocus());
424   EXPECT_FALSE(modal_parent->HasFocus());
425   EXPECT_FALSE(parent->HasFocus());
426 }
427 
428 // Same as |ChildModal| test, but using |EventGenerator| rather than bypassing
429 // it by calling |ActivateWindow|.
TEST_F(WindowModalityControllerTest,ChildModalEventGenerator)430 TEST_F(WindowModalityControllerTest, ChildModalEventGenerator) {
431   views::test::ChildModalParent* delegate =
432       new views::test::ChildModalParent(CurrentContext());
433   views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
434       delegate, CurrentContext(), gfx::Rect(0, 0, 400, 400));
435   widget->Show();
436 
437   aura::Window* parent = widget->GetNativeView();
438   EXPECT_TRUE(wm::IsActiveWindow(parent));
439 
440   aura::Window* modal_parent = delegate->GetModalParent();
441   EXPECT_NE(static_cast<aura::Window*>(NULL), modal_parent);
442   EXPECT_NE(parent, modal_parent);
443   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
444 
445   delegate->ShowChild();
446   aura::Window* child = delegate->GetChild();
447   EXPECT_NE(static_cast<aura::Window*>(NULL), child);
448 
449   EXPECT_TRUE(wm::IsActiveWindow(child));
450   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
451   EXPECT_FALSE(wm::IsActiveWindow(parent));
452 
453   EXPECT_TRUE(child->HasFocus());
454   EXPECT_FALSE(modal_parent->HasFocus());
455   EXPECT_FALSE(parent->HasFocus());
456 
457   {
458     aura::test::EventGenerator generator(
459         Shell::GetPrimaryRootWindow(),
460         parent->bounds().origin() +
461             gfx::Vector2d(10, parent->bounds().height() - 10));
462     generator.ClickLeftButton();
463     generator.ClickLeftButton();
464 
465     EXPECT_TRUE(wm::IsActiveWindow(child));
466     EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
467     EXPECT_FALSE(wm::IsActiveWindow(parent));
468 
469     EXPECT_TRUE(child->HasFocus());
470     EXPECT_FALSE(modal_parent->HasFocus());
471     EXPECT_FALSE(parent->HasFocus());
472   }
473 
474   {
475     aura::test::EventGenerator generator(
476         Shell::GetPrimaryRootWindow(),
477         parent->bounds().origin() + gfx::Vector2d(10, 10));
478     generator.ClickLeftButton();
479 
480     EXPECT_FALSE(wm::IsActiveWindow(child));
481     EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
482     EXPECT_TRUE(wm::IsActiveWindow(parent));
483 
484     EXPECT_FALSE(child->HasFocus());
485     EXPECT_FALSE(modal_parent->HasFocus());
486     EXPECT_TRUE(parent->HasFocus());
487   }
488 
489   {
490     aura::test::EventGenerator generator(
491         Shell::GetPrimaryRootWindow(),
492         child->bounds().origin() + gfx::Vector2d(10, 10));
493     generator.ClickLeftButton();
494 
495     EXPECT_TRUE(wm::IsActiveWindow(child));
496     EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
497     EXPECT_FALSE(wm::IsActiveWindow(parent));
498 
499     EXPECT_TRUE(child->HasFocus());
500     EXPECT_FALSE(modal_parent->HasFocus());
501     EXPECT_FALSE(parent->HasFocus());
502   }
503 }
504 
505 // Window-modal test for the case when the originally clicked window is an
506 // ancestor of the modal parent.
TEST_F(WindowModalityControllerTest,WindowModalAncestor)507 TEST_F(WindowModalityControllerTest, WindowModalAncestor) {
508   aura::test::TestWindowDelegate d;
509   scoped_ptr<aura::Window> w1(
510       CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
511   scoped_ptr<aura::Window> w2(
512       aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get()));
513   scoped_ptr<aura::Window> w3(
514       aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w2.get()));
515   scoped_ptr<aura::Window> w4(
516       CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect()));
517   w4->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
518   w1->AddTransientChild(w4.get());
519 
520   wm::ActivateWindow(w1.get());
521   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
522 
523   wm::ActivateWindow(w2.get());
524   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
525 
526   wm::ActivateWindow(w3.get());
527   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
528 
529   wm::ActivateWindow(w4.get());
530   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
531 }
532 
533 // Child-modal test for the case when the originally clicked window is an
534 // ancestor of the modal parent.
TEST_F(WindowModalityControllerTest,ChildModalAncestor)535 TEST_F(WindowModalityControllerTest, ChildModalAncestor) {
536   aura::test::TestWindowDelegate d;
537   scoped_ptr<aura::Window> w1(
538       CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
539   scoped_ptr<aura::Window> w2(
540       aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get()));
541   scoped_ptr<aura::Window> w3(
542       aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w2.get()));
543   scoped_ptr<aura::Window> w4(
544       CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect()));
545   w4->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_CHILD);
546   views::corewm::SetModalParent(w4.get(), w2.get());
547   w1->AddTransientChild(w4.get());
548 
549   wm::ActivateWindow(w1.get());
550   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
551 
552   wm::ActivateWindow(w2.get());
553   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
554 
555   wm::ActivateWindow(w3.get());
556   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
557 
558   wm::ActivateWindow(w4.get());
559   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
560 }
561 
562 }  // namespace internal
563 }  // namespace ash
564