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 "ash/root_window_controller.h" 6 7 #include "ash/session_state_delegate.h" 8 #include "ash/shelf/shelf_layout_manager.h" 9 #include "ash/shell.h" 10 #include "ash/shell_window_ids.h" 11 #include "ash/system/tray/system_tray_delegate.h" 12 #include "ash/test/ash_test_base.h" 13 #include "ash/wm/system_modal_container_layout_manager.h" 14 #include "ash/wm/window_properties.h" 15 #include "ash/wm/window_state.h" 16 #include "ash/wm/window_util.h" 17 #include "base/command_line.h" 18 #include "ui/aura/client/focus_change_observer.h" 19 #include "ui/aura/client/focus_client.h" 20 #include "ui/aura/client/window_tree_client.h" 21 #include "ui/aura/env.h" 22 #include "ui/aura/root_window.h" 23 #include "ui/aura/test/event_generator.h" 24 #include "ui/aura/test/test_event_handler.h" 25 #include "ui/aura/test/test_window_delegate.h" 26 #include "ui/aura/test/test_windows.h" 27 #include "ui/aura/window.h" 28 #include "ui/aura/window_tracker.h" 29 #include "ui/keyboard/keyboard_controller_proxy.h" 30 #include "ui/keyboard/keyboard_switches.h" 31 #include "ui/views/controls/menu/menu_controller.h" 32 #include "ui/views/widget/widget.h" 33 #include "ui/views/widget/widget_delegate.h" 34 35 using aura::Window; 36 using views::Widget; 37 38 namespace ash { 39 namespace { 40 41 class TestDelegate : public views::WidgetDelegateView { 42 public: 43 explicit TestDelegate(bool system_modal) : system_modal_(system_modal) {} 44 virtual ~TestDelegate() {} 45 46 // Overridden from views::WidgetDelegate: 47 virtual views::View* GetContentsView() OVERRIDE { 48 return this; 49 } 50 51 virtual ui::ModalType GetModalType() const OVERRIDE { 52 return system_modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_NONE; 53 } 54 55 private: 56 bool system_modal_; 57 58 DISALLOW_COPY_AND_ASSIGN(TestDelegate); 59 }; 60 61 class DeleteOnBlurDelegate : public aura::test::TestWindowDelegate, 62 public aura::client::FocusChangeObserver { 63 public: 64 DeleteOnBlurDelegate() : window_(NULL) {} 65 virtual ~DeleteOnBlurDelegate() {} 66 67 void SetWindow(aura::Window* window) { 68 window_ = window; 69 aura::client::SetFocusChangeObserver(window_, this); 70 } 71 72 private: 73 // aura::test::TestWindowDelegate overrides: 74 virtual bool CanFocus() OVERRIDE { 75 return true; 76 } 77 78 // aura::client::FocusChangeObserver implementation: 79 virtual void OnWindowFocused(aura::Window* gained_focus, 80 aura::Window* lost_focus) OVERRIDE { 81 if (window_ == lost_focus) 82 delete window_; 83 } 84 85 aura::Window* window_; 86 87 DISALLOW_COPY_AND_ASSIGN(DeleteOnBlurDelegate); 88 }; 89 90 } // namespace 91 92 namespace test { 93 94 class RootWindowControllerTest : public test::AshTestBase { 95 public: 96 views::Widget* CreateTestWidget(const gfx::Rect& bounds) { 97 views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds( 98 NULL, CurrentContext(), bounds); 99 widget->Show(); 100 return widget; 101 } 102 103 views::Widget* CreateModalWidget(const gfx::Rect& bounds) { 104 views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds( 105 new TestDelegate(true), CurrentContext(), bounds); 106 widget->Show(); 107 return widget; 108 } 109 110 views::Widget* CreateModalWidgetWithParent(const gfx::Rect& bounds, 111 gfx::NativeWindow parent) { 112 views::Widget* widget = 113 views::Widget::CreateWindowWithParentAndBounds(new TestDelegate(true), 114 parent, 115 bounds); 116 widget->Show(); 117 return widget; 118 } 119 120 aura::Window* GetModalContainer(aura::Window* root_window) { 121 return Shell::GetContainer( 122 root_window, 123 ash::internal::kShellWindowId_SystemModalContainer); 124 } 125 }; 126 127 TEST_F(RootWindowControllerTest, MoveWindows_Basic) { 128 if (!SupportsMultipleDisplays()) 129 return; 130 131 UpdateDisplay("600x600,500x500"); 132 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 133 internal::RootWindowController* controller = 134 Shell::GetPrimaryRootWindowController(); 135 internal::ShelfLayoutManager* shelf_layout_manager = 136 controller->GetShelfLayoutManager(); 137 shelf_layout_manager->SetAutoHideBehavior( 138 ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); 139 140 views::Widget* normal = CreateTestWidget(gfx::Rect(650, 10, 100, 100)); 141 EXPECT_EQ(root_windows[1], normal->GetNativeView()->GetRootWindow()); 142 EXPECT_EQ("650,10 100x100", normal->GetWindowBoundsInScreen().ToString()); 143 EXPECT_EQ("50,10 100x100", 144 normal->GetNativeView()->GetBoundsInRootWindow().ToString()); 145 146 views::Widget* maximized = CreateTestWidget(gfx::Rect(700, 10, 100, 100)); 147 maximized->Maximize(); 148 EXPECT_EQ(root_windows[1], maximized->GetNativeView()->GetRootWindow()); 149 EXPECT_EQ("600,0 500x453", maximized->GetWindowBoundsInScreen().ToString()); 150 EXPECT_EQ("0,0 500x453", 151 maximized->GetNativeView()->GetBoundsInRootWindow().ToString()); 152 153 views::Widget* minimized = CreateTestWidget(gfx::Rect(800, 10, 100, 100)); 154 minimized->Minimize(); 155 EXPECT_EQ(root_windows[1], minimized->GetNativeView()->GetRootWindow()); 156 EXPECT_EQ("800,10 100x100", 157 minimized->GetWindowBoundsInScreen().ToString()); 158 159 views::Widget* fullscreen = CreateTestWidget(gfx::Rect(900, 10, 100, 100)); 160 fullscreen->SetFullscreen(true); 161 EXPECT_EQ(root_windows[1], fullscreen->GetNativeView()->GetRootWindow()); 162 163 EXPECT_EQ("600,0 500x500", 164 fullscreen->GetWindowBoundsInScreen().ToString()); 165 EXPECT_EQ("0,0 500x500", 166 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString()); 167 168 views::Widget* unparented_control = new Widget; 169 Widget::InitParams params; 170 params.bounds = gfx::Rect(650, 10, 100, 100); 171 params.context = CurrentContext(); 172 params.type = Widget::InitParams::TYPE_CONTROL; 173 unparented_control->Init(params); 174 EXPECT_EQ(root_windows[1], 175 unparented_control->GetNativeView()->GetRootWindow()); 176 EXPECT_EQ(internal::kShellWindowId_UnparentedControlContainer, 177 unparented_control->GetNativeView()->parent()->id()); 178 179 aura::Window* panel = CreateTestWindowInShellWithDelegateAndType( 180 NULL, aura::client::WINDOW_TYPE_PANEL, 0, gfx::Rect(700, 100, 100, 100)); 181 EXPECT_EQ(root_windows[1], panel->GetRootWindow()); 182 EXPECT_EQ(internal::kShellWindowId_PanelContainer, panel->parent()->id()); 183 184 // Make sure a window that will delete itself when losing focus 185 // will not crash. 186 aura::WindowTracker tracker; 187 DeleteOnBlurDelegate delete_on_blur_delegate; 188 aura::Window* d2 = CreateTestWindowInShellWithDelegate( 189 &delete_on_blur_delegate, 0, gfx::Rect(50, 50, 100, 100)); 190 delete_on_blur_delegate.SetWindow(d2); 191 aura::client::GetFocusClient(root_windows[0])->FocusWindow(d2); 192 tracker.Add(d2); 193 194 UpdateDisplay("600x600"); 195 196 // d2 must have been deleted. 197 EXPECT_FALSE(tracker.Contains(d2)); 198 199 EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow()); 200 EXPECT_EQ("50,10 100x100", normal->GetWindowBoundsInScreen().ToString()); 201 EXPECT_EQ("50,10 100x100", 202 normal->GetNativeView()->GetBoundsInRootWindow().ToString()); 203 204 // Maximized area on primary display has 3px (given as 205 // kAutoHideSize in shelf_layout_manager.cc) inset at the bottom. 206 207 // First clear fullscreen status, since both fullscreen and maximized windows 208 // share the same desktop workspace, which cancels the shelf status. 209 fullscreen->SetFullscreen(false); 210 EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow()); 211 EXPECT_EQ("0,0 600x597", 212 maximized->GetWindowBoundsInScreen().ToString()); 213 EXPECT_EQ("0,0 600x597", 214 maximized->GetNativeView()->GetBoundsInRootWindow().ToString()); 215 216 // Set fullscreen to true. In that case the 3px inset becomes invisible so 217 // the maximized window can also use the area fully. 218 fullscreen->SetFullscreen(true); 219 EXPECT_EQ(root_windows[0], maximized->GetNativeView()->GetRootWindow()); 220 EXPECT_EQ("0,0 600x600", 221 maximized->GetWindowBoundsInScreen().ToString()); 222 EXPECT_EQ("0,0 600x600", 223 maximized->GetNativeView()->GetBoundsInRootWindow().ToString()); 224 225 EXPECT_EQ(root_windows[0], minimized->GetNativeView()->GetRootWindow()); 226 EXPECT_EQ("200,10 100x100", 227 minimized->GetWindowBoundsInScreen().ToString()); 228 229 EXPECT_EQ(root_windows[0], fullscreen->GetNativeView()->GetRootWindow()); 230 EXPECT_TRUE(fullscreen->IsFullscreen()); 231 EXPECT_EQ("0,0 600x600", 232 fullscreen->GetWindowBoundsInScreen().ToString()); 233 EXPECT_EQ("0,0 600x600", 234 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString()); 235 236 // Test if the restore bounds are correctly updated. 237 wm::GetWindowState(maximized->GetNativeView())->Restore(); 238 EXPECT_EQ("100,10 100x100", maximized->GetWindowBoundsInScreen().ToString()); 239 EXPECT_EQ("100,10 100x100", 240 maximized->GetNativeView()->GetBoundsInRootWindow().ToString()); 241 242 fullscreen->SetFullscreen(false); 243 EXPECT_EQ("300,10 100x100", 244 fullscreen->GetWindowBoundsInScreen().ToString()); 245 EXPECT_EQ("300,10 100x100", 246 fullscreen->GetNativeView()->GetBoundsInRootWindow().ToString()); 247 248 // Test if the unparented widget has moved. 249 EXPECT_EQ(root_windows[0], 250 unparented_control->GetNativeView()->GetRootWindow()); 251 EXPECT_EQ(internal::kShellWindowId_UnparentedControlContainer, 252 unparented_control->GetNativeView()->parent()->id()); 253 254 // Test if the panel has moved. 255 EXPECT_EQ(root_windows[0], panel->GetRootWindow()); 256 EXPECT_EQ(internal::kShellWindowId_PanelContainer, panel->parent()->id()); 257 } 258 259 TEST_F(RootWindowControllerTest, MoveWindows_Modal) { 260 if (!SupportsMultipleDisplays()) 261 return; 262 263 UpdateDisplay("500x500,500x500"); 264 265 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 266 // Emulate virtual screen coordinate system. 267 root_windows[0]->SetBounds(gfx::Rect(0, 0, 500, 500)); 268 root_windows[1]->SetBounds(gfx::Rect(500, 0, 500, 500)); 269 270 views::Widget* normal = CreateTestWidget(gfx::Rect(300, 10, 100, 100)); 271 EXPECT_EQ(root_windows[0], normal->GetNativeView()->GetRootWindow()); 272 EXPECT_TRUE(wm::IsActiveWindow(normal->GetNativeView())); 273 274 views::Widget* modal = CreateModalWidget(gfx::Rect(650, 10, 100, 100)); 275 EXPECT_EQ(root_windows[1], modal->GetNativeView()->GetRootWindow()); 276 EXPECT_TRUE(GetModalContainer(root_windows[1])->Contains( 277 modal->GetNativeView())); 278 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView())); 279 280 aura::test::EventGenerator generator_1st(root_windows[0]); 281 generator_1st.ClickLeftButton(); 282 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView())); 283 284 UpdateDisplay("500x500"); 285 EXPECT_EQ(root_windows[0], modal->GetNativeView()->GetRootWindow()); 286 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView())); 287 generator_1st.ClickLeftButton(); 288 EXPECT_TRUE(wm::IsActiveWindow(modal->GetNativeView())); 289 } 290 291 TEST_F(RootWindowControllerTest, ModalContainer) { 292 UpdateDisplay("600x600"); 293 Shell* shell = Shell::GetInstance(); 294 internal::RootWindowController* controller = 295 shell->GetPrimaryRootWindowController(); 296 EXPECT_EQ(user::LOGGED_IN_USER, 297 shell->system_tray_delegate()->GetUserLoginStatus()); 298 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 299 internal::kShellWindowId_SystemModalContainer)->layout_manager(), 300 controller->GetSystemModalLayoutManager(NULL)); 301 302 views::Widget* session_modal_widget = 303 CreateModalWidget(gfx::Rect(300, 10, 100, 100)); 304 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 305 internal::kShellWindowId_SystemModalContainer)->layout_manager(), 306 controller->GetSystemModalLayoutManager( 307 session_modal_widget->GetNativeView())); 308 309 shell->session_state_delegate()->LockScreen(); 310 EXPECT_EQ(user::LOGGED_IN_LOCKED, 311 shell->system_tray_delegate()->GetUserLoginStatus()); 312 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 313 internal::kShellWindowId_LockSystemModalContainer)->layout_manager(), 314 controller->GetSystemModalLayoutManager(NULL)); 315 316 aura::Window* lock_container = 317 Shell::GetContainer(controller->root_window(), 318 internal::kShellWindowId_LockScreenContainer); 319 views::Widget* lock_modal_widget = 320 CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container); 321 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 322 internal::kShellWindowId_LockSystemModalContainer)->layout_manager(), 323 controller->GetSystemModalLayoutManager( 324 lock_modal_widget->GetNativeView())); 325 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 326 internal::kShellWindowId_SystemModalContainer)->layout_manager(), 327 controller->GetSystemModalLayoutManager( 328 session_modal_widget->GetNativeView())); 329 330 shell->session_state_delegate()->UnlockScreen(); 331 } 332 333 TEST_F(RootWindowControllerTest, ModalContainerNotLoggedInLoggedIn) { 334 UpdateDisplay("600x600"); 335 Shell* shell = Shell::GetInstance(); 336 337 // Configure login screen environment. 338 SetUserLoggedIn(false); 339 EXPECT_EQ(user::LOGGED_IN_NONE, 340 shell->system_tray_delegate()->GetUserLoginStatus()); 341 EXPECT_EQ(0, shell->session_state_delegate()->NumberOfLoggedInUsers()); 342 EXPECT_FALSE(shell->session_state_delegate()->IsActiveUserSessionStarted()); 343 344 internal::RootWindowController* controller = 345 shell->GetPrimaryRootWindowController(); 346 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 347 internal::kShellWindowId_LockSystemModalContainer)->layout_manager(), 348 controller->GetSystemModalLayoutManager(NULL)); 349 350 aura::Window* lock_container = 351 Shell::GetContainer(controller->root_window(), 352 internal::kShellWindowId_LockScreenContainer); 353 views::Widget* login_modal_widget = 354 CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), lock_container); 355 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 356 internal::kShellWindowId_LockSystemModalContainer)->layout_manager(), 357 controller->GetSystemModalLayoutManager( 358 login_modal_widget->GetNativeView())); 359 login_modal_widget->Close(); 360 361 // Configure user session environment. 362 SetUserLoggedIn(true); 363 SetSessionStarted(true); 364 EXPECT_EQ(user::LOGGED_IN_USER, 365 shell->system_tray_delegate()->GetUserLoginStatus()); 366 EXPECT_EQ(1, shell->session_state_delegate()->NumberOfLoggedInUsers()); 367 EXPECT_TRUE(shell->session_state_delegate()->IsActiveUserSessionStarted()); 368 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 369 internal::kShellWindowId_SystemModalContainer)->layout_manager(), 370 controller->GetSystemModalLayoutManager(NULL)); 371 372 views::Widget* session_modal_widget = 373 CreateModalWidget(gfx::Rect(300, 10, 100, 100)); 374 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 375 internal::kShellWindowId_SystemModalContainer)->layout_manager(), 376 controller->GetSystemModalLayoutManager( 377 session_modal_widget->GetNativeView())); 378 } 379 380 TEST_F(RootWindowControllerTest, ModalContainerBlockedSession) { 381 UpdateDisplay("600x600"); 382 Shell* shell = Shell::GetInstance(); 383 internal::RootWindowController* controller = 384 shell->GetPrimaryRootWindowController(); 385 aura::Window* lock_container = 386 Shell::GetContainer(controller->root_window(), 387 internal::kShellWindowId_LockScreenContainer); 388 for (int block_reason = FIRST_BLOCK_REASON; 389 block_reason < NUMBER_OF_BLOCK_REASONS; 390 ++block_reason) { 391 views::Widget* session_modal_widget = 392 CreateModalWidget(gfx::Rect(300, 10, 100, 100)); 393 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 394 internal::kShellWindowId_SystemModalContainer)->layout_manager(), 395 controller->GetSystemModalLayoutManager( 396 session_modal_widget->GetNativeView())); 397 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 398 internal::kShellWindowId_SystemModalContainer)->layout_manager(), 399 controller->GetSystemModalLayoutManager(NULL)); 400 session_modal_widget->Close(); 401 402 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason)); 403 404 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 405 internal::kShellWindowId_LockSystemModalContainer)->layout_manager(), 406 controller->GetSystemModalLayoutManager(NULL)); 407 408 views::Widget* lock_modal_widget = 409 CreateModalWidgetWithParent(gfx::Rect(300, 10, 100, 100), 410 lock_container); 411 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 412 internal::kShellWindowId_LockSystemModalContainer)->layout_manager(), 413 controller->GetSystemModalLayoutManager( 414 lock_modal_widget->GetNativeView())); 415 416 session_modal_widget = 417 CreateModalWidget(gfx::Rect(300, 10, 100, 100)); 418 EXPECT_EQ(Shell::GetContainer(controller->root_window(), 419 internal::kShellWindowId_SystemModalContainer)->layout_manager(), 420 controller->GetSystemModalLayoutManager( 421 session_modal_widget->GetNativeView())); 422 session_modal_widget->Close(); 423 424 lock_modal_widget->Close(); 425 UnblockUserSession(); 426 } 427 } 428 429 TEST_F(RootWindowControllerTest, GetWindowForFullscreenMode) { 430 UpdateDisplay("600x600"); 431 internal::RootWindowController* controller = 432 Shell::GetInstance()->GetPrimaryRootWindowController(); 433 434 Widget* w1 = CreateTestWidget(gfx::Rect(0, 0, 100, 100)); 435 w1->Maximize(); 436 Widget* w2 = CreateTestWidget(gfx::Rect(0, 0, 100, 100)); 437 w2->SetFullscreen(true); 438 // |w3| is a transient child of |w2|. 439 Widget* w3 = Widget::CreateWindowWithParentAndBounds(NULL, 440 w2->GetNativeWindow(), gfx::Rect(0, 0, 100, 100)); 441 442 // Test that GetWindowForFullscreenMode() finds the fullscreen window when one 443 // of its transient children is active. 444 w3->Activate(); 445 EXPECT_EQ(w2->GetNativeWindow(), controller->GetWindowForFullscreenMode()); 446 447 // If the topmost window is not fullscreen, it returns NULL. 448 w1->Activate(); 449 EXPECT_EQ(NULL, controller->GetWindowForFullscreenMode()); 450 w1->Close(); 451 w3->Close(); 452 453 // Only w2 remains, if minimized GetWindowForFullscreenMode should return 454 // NULL. 455 w2->Activate(); 456 EXPECT_EQ(w2->GetNativeWindow(), controller->GetWindowForFullscreenMode()); 457 w2->Minimize(); 458 EXPECT_EQ(NULL, controller->GetWindowForFullscreenMode()); 459 } 460 461 // Test that user session window can't be focused if user session blocked by 462 // some overlapping UI. 463 TEST_F(RootWindowControllerTest, FocusBlockedWindow) { 464 UpdateDisplay("600x600"); 465 internal::RootWindowController* controller = 466 Shell::GetInstance()->GetPrimaryRootWindowController(); 467 aura::Window* lock_container = 468 Shell::GetContainer(controller->root_window(), 469 internal::kShellWindowId_LockScreenContainer); 470 aura::Window* lock_window = Widget::CreateWindowWithParentAndBounds(NULL, 471 lock_container, gfx::Rect(0, 0, 100, 100))->GetNativeView(); 472 lock_window->Show(); 473 aura::Window* session_window = 474 CreateTestWidget(gfx::Rect(0, 0, 100, 100))->GetNativeView(); 475 session_window->Show(); 476 477 for (int block_reason = FIRST_BLOCK_REASON; 478 block_reason < NUMBER_OF_BLOCK_REASONS; 479 ++block_reason) { 480 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason)); 481 lock_window->Focus(); 482 EXPECT_TRUE(lock_window->HasFocus()); 483 session_window->Focus(); 484 EXPECT_FALSE(session_window->HasFocus()); 485 UnblockUserSession(); 486 } 487 } 488 489 // Tracks whether OnWindowDestroying() has been invoked. 490 class DestroyedWindowObserver : public aura::WindowObserver { 491 public: 492 DestroyedWindowObserver() : destroyed_(false), window_(NULL) {} 493 virtual ~DestroyedWindowObserver() { 494 Shutdown(); 495 } 496 497 void SetWindow(Window* window) { 498 window_ = window; 499 window->AddObserver(this); 500 } 501 502 bool destroyed() const { return destroyed_; } 503 504 // WindowObserver overrides: 505 virtual void OnWindowDestroying(Window* window) OVERRIDE { 506 destroyed_ = true; 507 Shutdown(); 508 } 509 510 private: 511 void Shutdown() { 512 if (!window_) 513 return; 514 window_->RemoveObserver(this); 515 window_ = NULL; 516 } 517 518 bool destroyed_; 519 Window* window_; 520 521 DISALLOW_COPY_AND_ASSIGN(DestroyedWindowObserver); 522 }; 523 524 // Verifies shutdown doesn't delete windows that are not owned by the parent. 525 TEST_F(RootWindowControllerTest, DontDeleteWindowsNotOwnedByParent) { 526 DestroyedWindowObserver observer1; 527 aura::test::TestWindowDelegate delegate1; 528 aura::Window* window1 = new aura::Window(&delegate1); 529 window1->SetType(aura::client::WINDOW_TYPE_CONTROL); 530 window1->set_owned_by_parent(false); 531 observer1.SetWindow(window1); 532 window1->Init(ui::LAYER_NOT_DRAWN); 533 aura::client::ParentWindowWithContext( 534 window1, Shell::GetInstance()->GetPrimaryRootWindow(), gfx::Rect()); 535 536 DestroyedWindowObserver observer2; 537 aura::Window* window2 = new aura::Window(NULL); 538 window2->set_owned_by_parent(false); 539 observer2.SetWindow(window2); 540 window2->Init(ui::LAYER_NOT_DRAWN); 541 Shell::GetInstance()->GetPrimaryRootWindow()->AddChild(window2); 542 543 Shell::GetInstance()->GetPrimaryRootWindowController()->CloseChildWindows(); 544 545 ASSERT_FALSE(observer1.destroyed()); 546 delete window1; 547 548 ASSERT_FALSE(observer2.destroyed()); 549 delete window2; 550 } 551 552 typedef test::NoSessionAshTestBase NoSessionRootWindowControllerTest; 553 554 // Make sure that an event handler exists for entire display area. 555 TEST_F(NoSessionRootWindowControllerTest, Event) { 556 aura::Window* root = Shell::GetPrimaryRootWindow(); 557 const gfx::Size size = root->bounds().size(); 558 aura::Window* event_target = root->GetEventHandlerForPoint(gfx::Point(0, 0)); 559 EXPECT_TRUE(event_target); 560 EXPECT_EQ(event_target, 561 root->GetEventHandlerForPoint(gfx::Point(0, size.height() - 1))); 562 EXPECT_EQ(event_target, 563 root->GetEventHandlerForPoint(gfx::Point(size.width() - 1, 0))); 564 EXPECT_EQ(event_target, 565 root->GetEventHandlerForPoint(gfx::Point(0, size.height() - 1))); 566 EXPECT_EQ(event_target, 567 root->GetEventHandlerForPoint( 568 gfx::Point(size.width() - 1, size.height() - 1))); 569 } 570 571 class VirtualKeyboardRootWindowControllerTest : public test::AshTestBase { 572 public: 573 VirtualKeyboardRootWindowControllerTest() {}; 574 virtual ~VirtualKeyboardRootWindowControllerTest() {}; 575 576 virtual void SetUp() OVERRIDE { 577 CommandLine::ForCurrentProcess()->AppendSwitch( 578 keyboard::switches::kEnableVirtualKeyboard); 579 test::AshTestBase::SetUp(); 580 Shell::GetPrimaryRootWindowController()->ActivateKeyboard( 581 Shell::GetInstance()->keyboard_controller()); 582 } 583 584 private: 585 DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardRootWindowControllerTest); 586 }; 587 588 // Test for http://crbug.com/297858. Virtual keyboard container should only show 589 // on primary root window. 590 TEST_F(VirtualKeyboardRootWindowControllerTest, 591 VirtualKeyboardOnPrimaryRootWindowOnly) { 592 if (!SupportsMultipleDisplays()) 593 return; 594 595 UpdateDisplay("500x500,500x500"); 596 597 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 598 aura::Window* primary_root_window = Shell::GetPrimaryRootWindow(); 599 aura::Window* secondary_root_window = 600 root_windows[0] == primary_root_window ? 601 root_windows[1] : root_windows[0]; 602 603 ASSERT_TRUE(Shell::GetContainer( 604 primary_root_window, 605 internal::kShellWindowId_VirtualKeyboardContainer)); 606 ASSERT_FALSE(Shell::GetContainer( 607 secondary_root_window, 608 internal::kShellWindowId_VirtualKeyboardContainer)); 609 } 610 611 // Test for http://crbug.com/263599. Virtual keyboard should be able to receive 612 // events at blocked user session. 613 TEST_F(VirtualKeyboardRootWindowControllerTest, 614 ClickVirtualKeyboardInBlockedWindow) { 615 aura::Window* root_window = Shell::GetPrimaryRootWindow(); 616 aura::Window* keyboard_container = Shell::GetContainer(root_window, 617 internal::kShellWindowId_VirtualKeyboardContainer); 618 ASSERT_TRUE(keyboard_container); 619 keyboard_container->Show(); 620 621 aura::Window* keyboard_window = Shell::GetInstance()->keyboard_controller()-> 622 proxy()->GetKeyboardWindow(); 623 keyboard_container->AddChild(keyboard_window); 624 keyboard_window->SetBounds(gfx::Rect()); 625 keyboard_window->Show(); 626 627 aura::test::TestEventHandler* handler = new aura::test::TestEventHandler; 628 root_window->SetEventFilter(handler); 629 630 aura::test::EventGenerator event_generator(root_window, keyboard_window); 631 event_generator.ClickLeftButton(); 632 int expected_mouse_presses = 1; 633 EXPECT_EQ(expected_mouse_presses, handler->num_mouse_events() / 2); 634 635 for (int block_reason = FIRST_BLOCK_REASON; 636 block_reason < NUMBER_OF_BLOCK_REASONS; 637 ++block_reason) { 638 BlockUserSession(static_cast<UserSessionBlockReason>(block_reason)); 639 event_generator.ClickLeftButton(); 640 expected_mouse_presses++; 641 EXPECT_EQ(expected_mouse_presses, handler->num_mouse_events() / 2); 642 UnblockUserSession(); 643 } 644 } 645 646 // Test for http://crbug.com/299787. RootWindowController should delete 647 // the old container since the keyboard controller creates a new window in 648 // GetWindowContainer(). 649 TEST_F(VirtualKeyboardRootWindowControllerTest, 650 DeleteOldContainerOnVirtualKeyboardInit) { 651 aura::Window* root_window = ash::Shell::GetPrimaryRootWindow(); 652 aura::Window* keyboard_container = Shell::GetContainer(root_window, 653 internal::kShellWindowId_VirtualKeyboardContainer); 654 ASSERT_TRUE(keyboard_container); 655 // Track the keyboard container window. 656 aura::WindowTracker tracker; 657 tracker.Add(keyboard_container); 658 // Mock a login user profile change to reinitialize the keyboard. 659 ash::Shell::GetInstance()->OnLoginUserProfilePrepared(); 660 // keyboard_container should no longer be present. 661 EXPECT_FALSE(tracker.Contains(keyboard_container)); 662 } 663 664 } // namespace test 665 } // namespace ash 666