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, ¢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 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