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, ¢er);
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