• 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/wm/core/window_modality_controller.h"
6 
7 #include "ash/shell.h"
8 #include "ash/test/ash_test_base.h"
9 #include "ash/test/child_modal_window.h"
10 #include "ash/wm/window_util.h"
11 #include "ui/aura/client/aura_constants.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/aura/window_event_dispatcher.h"
17 #include "ui/base/ui_base_types.h"
18 #include "ui/views/test/capture_tracking_view.h"
19 #include "ui/views/widget/widget.h"
20 #include "ui/wm/core/window_util.h"
21 
22 namespace ash {
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   ::wm::AddTransientChild(w1.get(), 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   ::wm::AddTransientChild(w1.get(), 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   ::wm::AddTransientChild(w1.get(), w11.get());
101   ::wm::AddTransientChild(w11.get(), 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   ::wm::AddTransientChild(w1.get(), w11.get());
155   ::wm::AddTransientChild(w11.get(), 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   ::wm::AddTransientChild(w1.get(), 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 // Events on modal parent activate.
TEST_F(WindowModalityControllerTest,EventsForEclipsedWindows)210 TEST_F(WindowModalityControllerTest, EventsForEclipsedWindows) {
211   aura::test::TestWindowDelegate d;
212   scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(&d, -1,
213       gfx::Rect(0, 0, 100, 100)));
214   scoped_ptr<aura::Window> w11(CreateTestWindowInShellWithDelegate(&d, -11,
215       gfx::Rect(20, 20, 50, 50)));
216   ::wm::AddTransientChild(w1.get(), w11.get());
217   scoped_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate(&d, -2,
218       gfx::Rect(0, 0, 50, 50)));
219 
220   w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
221 
222   // Partially eclipse w1 with w2.
223   wm::ActivateWindow(w2.get());
224   {
225     // Clicking a point on w1 that is not eclipsed by w2.
226     aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
227                                          gfx::Point(90, 90));
228     generator.ClickLeftButton();
229     EXPECT_TRUE(wm::IsActiveWindow(w11.get()));
230   }
231 }
232 
233 // Creates windows w1 and non activatiable child w11. Creates transient window
234 // w2 and adds it as a transeint child of w1. Ensures that w2 is parented to
235 // the parent of w1, and that GetModalTransient(w11) returns w2.
TEST_F(WindowModalityControllerTest,GetModalTransient)236 TEST_F(WindowModalityControllerTest, GetModalTransient) {
237   aura::test::TestWindowDelegate d;
238   scoped_ptr<aura::Window> w1(
239       CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
240   scoped_ptr<aura::Window> w11(
241       aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get()));
242   scoped_ptr<aura::Window> w2(
243       CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect()));
244   w2->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
245 
246   aura::Window* wt;
247   wt = ::wm::GetModalTransient(w1.get());
248   ASSERT_EQ(static_cast<aura::Window*>(NULL), wt);
249 
250   // Parent w2 to w1. It should get parented to the parent of w1.
251   ::wm::AddTransientChild(w1.get(), w2.get());
252   ASSERT_EQ(2U, w1->parent()->children().size());
253   EXPECT_EQ(-2, w1->parent()->children().at(1)->id());
254 
255   // Request the modal transient window for w1, it should be w2.
256   wt = ::wm::GetModalTransient(w1.get());
257   ASSERT_NE(static_cast<aura::Window*>(NULL), wt);
258   EXPECT_EQ(-2, wt->id());
259 
260   // Request the modal transient window for w11, it should also be w2.
261   wt = ::wm::GetModalTransient(w11.get());
262   ASSERT_NE(static_cast<aura::Window*>(NULL), wt);
263   EXPECT_EQ(-2, wt->id());
264 }
265 
266 // Verifies we generate a capture lost when showing a modal window.
TEST_F(WindowModalityControllerTest,ChangeCapture)267 TEST_F(WindowModalityControllerTest, ChangeCapture) {
268   views::Widget* widget = views::Widget::CreateWindowWithContext(
269       NULL, Shell::GetPrimaryRootWindow());
270   scoped_ptr<aura::Window> widget_window(widget->GetNativeView());
271   views::test::CaptureTrackingView* view = new views::test::CaptureTrackingView;
272   widget->client_view()->AddChildView(view);
273   widget->SetBounds(gfx::Rect(0, 0, 200, 200));
274   view->SetBoundsRect(widget->client_view()->GetLocalBounds());
275   widget->Show();
276 
277   gfx::Point center(view->width() / 2, view->height() / 2);
278   views::View::ConvertPointToScreen(view, &center);
279   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), center);
280   generator.PressLeftButton();
281   EXPECT_TRUE(view->got_press());
282 
283   views::Widget* modal_widget =
284       views::Widget::CreateWindowWithParent(NULL, widget->GetNativeView());
285   scoped_ptr<aura::Window> modal_window(modal_widget->GetNativeView());
286   modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
287   views::test::CaptureTrackingView* modal_view =
288       new views::test::CaptureTrackingView;
289   modal_widget->client_view()->AddChildView(modal_view);
290   modal_widget->SetBounds(gfx::Rect(50, 50, 200, 200));
291   modal_view->SetBoundsRect(modal_widget->client_view()->GetLocalBounds());
292   modal_widget->Show();
293 
294   EXPECT_TRUE(view->got_capture_lost());
295   generator.ReleaseLeftButton();
296 
297   view->reset();
298 
299   EXPECT_FALSE(modal_view->got_capture_lost());
300   EXPECT_FALSE(modal_view->got_press());
301 
302   gfx::Point modal_center(modal_view->width() / 2, modal_view->height() / 2);
303   views::View::ConvertPointToScreen(modal_view, &modal_center);
304   generator.MoveMouseTo(modal_center, 1);
305   generator.PressLeftButton();
306   EXPECT_TRUE(modal_view->got_press());
307   EXPECT_FALSE(modal_view->got_capture_lost());
308   EXPECT_FALSE(view->got_capture_lost());
309   EXPECT_FALSE(view->got_press());
310 }
311 
312 class TouchTrackerWindowDelegate : public aura::test::TestWindowDelegate {
313  public:
TouchTrackerWindowDelegate()314   TouchTrackerWindowDelegate()
315       : received_touch_(false),
316         last_event_type_(ui::ET_UNKNOWN) {
317   }
~TouchTrackerWindowDelegate()318   virtual ~TouchTrackerWindowDelegate() {}
319 
reset()320   void reset() {
321     received_touch_ = false;
322     last_event_type_ = ui::ET_UNKNOWN;
323   }
324 
received_touch() const325   bool received_touch() const { return received_touch_; }
last_event_type() const326   ui::EventType last_event_type() const { return last_event_type_; }
327 
328  private:
329   // Overridden from aura::test::TestWindowDelegate.
OnTouchEvent(ui::TouchEvent * event)330   virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
331     received_touch_ = true;
332     last_event_type_ = event->type();
333     aura::test::TestWindowDelegate::OnTouchEvent(event);
334   }
335 
336   bool received_touch_;
337   ui::EventType last_event_type_;
338 
339   DISALLOW_COPY_AND_ASSIGN(TouchTrackerWindowDelegate);
340 };
341 
342 // Modality should prevent events from being passed to the transient parent.
TEST_F(WindowModalityControllerTest,TouchEvent)343 TEST_F(WindowModalityControllerTest, TouchEvent) {
344   TouchTrackerWindowDelegate d1;
345   scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(&d1,
346       -1, gfx::Rect(0, 0, 100, 100)));
347   TouchTrackerWindowDelegate d11;
348   scoped_ptr<aura::Window> w11(CreateTestWindowInShellWithDelegate(&d11,
349       -11, gfx::Rect(20, 20, 50, 50)));
350   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
351                                        gfx::Point(10, 10));
352 
353   ::wm::AddTransientChild(w1.get(), w11.get());
354   d1.reset();
355   d11.reset();
356 
357   {
358     // Clicking a point within w1 should activate that window.
359     generator.PressMoveAndReleaseTouchTo(gfx::Point(10, 10));
360     EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
361     EXPECT_TRUE(d1.received_touch());
362     EXPECT_FALSE(d11.received_touch());
363   }
364 
365   {
366     // Adding a modal window while a touch is down should fire a touch cancel.
367     generator.PressTouch();
368     generator.MoveTouch(gfx::Point(10, 10));
369     d1.reset();
370     d11.reset();
371 
372     w11->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
373     EXPECT_TRUE(d1.received_touch());
374     EXPECT_EQ(ui::ET_TOUCH_CANCELLED, d1.last_event_type());
375     EXPECT_FALSE(d11.received_touch());
376   }
377 }
378 
379 // Child-modal test.
380 // Creates:
381 // - A |parent| window that hosts a |modal_parent| window within itself. The
382 //   |parent| and |modal_parent| windows are not the same window.  The
383 //   |modal_parent| window is not activatable, because it's contained within the
384 //   |parent| window.
385 // - A |child| window with parent window |parent|, but is modal to
386 //   |modal_parent| window.
387 // Validates:
388 // - Clicking on the |modal_parent| should activate the |child| window.
389 // - Clicking on the |parent| window outside of the |modal_parent| bounds should
390 //   activate the |parent| window.
391 // - Clicking on the |child| while |parent| is active should activate the
392 //   |child| window.
393 // - Focus should follow the active window.
TEST_F(WindowModalityControllerTest,ChildModal)394 TEST_F(WindowModalityControllerTest, ChildModal) {
395   test::ChildModalParent* delegate =
396       new test::ChildModalParent(CurrentContext());
397   views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
398       delegate, CurrentContext(), gfx::Rect(0, 0, 400, 400));
399   widget->Show();
400 
401   aura::Window* parent = widget->GetNativeView();
402   EXPECT_TRUE(wm::IsActiveWindow(parent));
403 
404   aura::Window* modal_parent = delegate->GetModalParent();
405   EXPECT_NE(static_cast<aura::Window*>(NULL), modal_parent);
406   EXPECT_NE(parent, modal_parent);
407   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
408 
409   delegate->ShowChild();
410   aura::Window* child = delegate->GetChild();
411   EXPECT_NE(static_cast<aura::Window*>(NULL), 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   wm::ActivateWindow(modal_parent);
422 
423   EXPECT_TRUE(wm::IsActiveWindow(child));
424   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
425   EXPECT_FALSE(wm::IsActiveWindow(parent));
426 
427   EXPECT_TRUE(child->HasFocus());
428   EXPECT_FALSE(modal_parent->HasFocus());
429   EXPECT_FALSE(parent->HasFocus());
430 
431   wm::ActivateWindow(parent);
432 
433   EXPECT_FALSE(wm::IsActiveWindow(child));
434   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
435   EXPECT_TRUE(wm::IsActiveWindow(parent));
436 
437   EXPECT_FALSE(child->HasFocus());
438   EXPECT_FALSE(modal_parent->HasFocus());
439   EXPECT_TRUE(parent->HasFocus());
440 
441   wm::ActivateWindow(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 // Same as |ChildModal| test, but using |EventGenerator| rather than bypassing
453 // it by calling |ActivateWindow|.
TEST_F(WindowModalityControllerTest,ChildModalEventGenerator)454 TEST_F(WindowModalityControllerTest, ChildModalEventGenerator) {
455   test::ChildModalParent* delegate =
456       new test::ChildModalParent(CurrentContext());
457   views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
458       delegate, CurrentContext(), gfx::Rect(0, 0, 400, 400));
459   widget->Show();
460 
461   aura::Window* parent = widget->GetNativeView();
462   EXPECT_TRUE(wm::IsActiveWindow(parent));
463 
464   aura::Window* modal_parent = delegate->GetModalParent();
465   EXPECT_NE(static_cast<aura::Window*>(NULL), modal_parent);
466   EXPECT_NE(parent, modal_parent);
467   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
468 
469   delegate->ShowChild();
470   aura::Window* child = delegate->GetChild();
471   EXPECT_NE(static_cast<aura::Window*>(NULL), child);
472 
473   EXPECT_TRUE(wm::IsActiveWindow(child));
474   EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
475   EXPECT_FALSE(wm::IsActiveWindow(parent));
476 
477   EXPECT_TRUE(child->HasFocus());
478   EXPECT_FALSE(modal_parent->HasFocus());
479   EXPECT_FALSE(parent->HasFocus());
480 
481   {
482     aura::test::EventGenerator generator(
483         Shell::GetPrimaryRootWindow(),
484         parent->bounds().origin() +
485             gfx::Vector2d(10, parent->bounds().height() - 10));
486     generator.ClickLeftButton();
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     aura::test::EventGenerator generator(
500         Shell::GetPrimaryRootWindow(),
501         parent->bounds().origin() + gfx::Vector2d(10, 10));
502     generator.ClickLeftButton();
503 
504     EXPECT_FALSE(wm::IsActiveWindow(child));
505     EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
506     EXPECT_TRUE(wm::IsActiveWindow(parent));
507 
508     EXPECT_FALSE(child->HasFocus());
509     EXPECT_FALSE(modal_parent->HasFocus());
510     EXPECT_TRUE(parent->HasFocus());
511   }
512 
513   {
514     aura::test::EventGenerator generator(
515         Shell::GetPrimaryRootWindow(),
516         child->bounds().origin() + gfx::Vector2d(10, 10));
517     generator.ClickLeftButton();
518 
519     EXPECT_TRUE(wm::IsActiveWindow(child));
520     EXPECT_FALSE(wm::IsActiveWindow(modal_parent));
521     EXPECT_FALSE(wm::IsActiveWindow(parent));
522 
523     EXPECT_TRUE(child->HasFocus());
524     EXPECT_FALSE(modal_parent->HasFocus());
525     EXPECT_FALSE(parent->HasFocus());
526   }
527 }
528 
529 // Window-modal test for the case when the originally clicked window is an
530 // ancestor of the modal parent.
TEST_F(WindowModalityControllerTest,WindowModalAncestor)531 TEST_F(WindowModalityControllerTest, WindowModalAncestor) {
532   aura::test::TestWindowDelegate d;
533   scoped_ptr<aura::Window> w1(
534       CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
535   scoped_ptr<aura::Window> w2(
536       aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get()));
537   scoped_ptr<aura::Window> w3(
538       aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w2.get()));
539   scoped_ptr<aura::Window> w4(
540       CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect()));
541   w4->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
542   ::wm::AddTransientChild(w1.get(), w4.get());
543 
544   wm::ActivateWindow(w1.get());
545   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
546 
547   wm::ActivateWindow(w2.get());
548   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
549 
550   wm::ActivateWindow(w3.get());
551   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
552 
553   wm::ActivateWindow(w4.get());
554   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
555 }
556 
557 // Child-modal test for the case when the originally clicked window is an
558 // ancestor of the modal parent.
TEST_F(WindowModalityControllerTest,ChildModalAncestor)559 TEST_F(WindowModalityControllerTest, ChildModalAncestor) {
560   aura::test::TestWindowDelegate d;
561   scoped_ptr<aura::Window> w1(
562       CreateTestWindowInShellWithDelegate(&d, -1, gfx::Rect()));
563   scoped_ptr<aura::Window> w2(
564       aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w1.get()));
565   scoped_ptr<aura::Window> w3(
566       aura::test::CreateTestWindowWithDelegate(&d, -11, gfx::Rect(), w2.get()));
567   scoped_ptr<aura::Window> w4(
568       CreateTestWindowInShellWithDelegate(&d, -2, gfx::Rect()));
569   w4->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_CHILD);
570   ::wm::SetModalParent(w4.get(), w2.get());
571   ::wm::AddTransientChild(w1.get(), w4.get());
572 
573   wm::ActivateWindow(w1.get());
574   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
575 
576   wm::ActivateWindow(w2.get());
577   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
578 
579   wm::ActivateWindow(w3.get());
580   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
581 
582   wm::ActivateWindow(w4.get());
583   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
584 }
585 
586 }  // namespace ash
587