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 <queue> 8 #include <vector> 9 10 #include "ash/ash_constants.h" 11 #include "ash/ash_switches.h" 12 #include "ash/desktop_background/desktop_background_widget_controller.h" 13 #include "ash/desktop_background/user_wallpaper_delegate.h" 14 #include "ash/display/display_manager.h" 15 #include "ash/focus_cycler.h" 16 #include "ash/session_state_delegate.h" 17 #include "ash/shelf/shelf_layout_manager.h" 18 #include "ash/shelf/shelf_types.h" 19 #include "ash/shelf/shelf_widget.h" 20 #include "ash/shell.h" 21 #include "ash/shell_delegate.h" 22 #include "ash/shell_factory.h" 23 #include "ash/shell_window_ids.h" 24 #include "ash/system/status_area_widget.h" 25 #include "ash/system/tray/system_tray_delegate.h" 26 #include "ash/touch/touch_hud_debug.h" 27 #include "ash/touch/touch_hud_projection.h" 28 #include "ash/touch/touch_observer_hud.h" 29 #include "ash/wm/always_on_top_controller.h" 30 #include "ash/wm/base_layout_manager.h" 31 #include "ash/wm/boot_splash_screen.h" 32 #include "ash/wm/dock/docked_window_layout_manager.h" 33 #include "ash/wm/panels/panel_layout_manager.h" 34 #include "ash/wm/panels/panel_window_event_handler.h" 35 #include "ash/wm/property_util.h" 36 #include "ash/wm/root_window_layout_manager.h" 37 #include "ash/wm/screen_dimmer.h" 38 #include "ash/wm/stacking_controller.h" 39 #include "ash/wm/status_area_layout_manager.h" 40 #include "ash/wm/system_background_controller.h" 41 #include "ash/wm/system_modal_container_layout_manager.h" 42 #include "ash/wm/toplevel_window_event_handler.h" 43 #include "ash/wm/window_properties.h" 44 #include "ash/wm/window_util.h" 45 #include "ash/wm/workspace_controller.h" 46 #include "base/command_line.h" 47 #include "base/time/time.h" 48 #include "ui/aura/client/aura_constants.h" 49 #include "ui/aura/client/drag_drop_client.h" 50 #include "ui/aura/client/tooltip_client.h" 51 #include "ui/aura/root_window.h" 52 #include "ui/aura/window.h" 53 #include "ui/aura/window_delegate.h" 54 #include "ui/aura/window_observer.h" 55 #include "ui/aura/window_tracker.h" 56 #include "ui/base/hit_test.h" 57 #include "ui/base/models/menu_model.h" 58 #include "ui/gfx/screen.h" 59 #include "ui/keyboard/keyboard_controller.h" 60 #include "ui/keyboard/keyboard_util.h" 61 #include "ui/views/controls/menu/menu_runner.h" 62 #include "ui/views/corewm/visibility_controller.h" 63 #include "ui/views/view_model.h" 64 #include "ui/views/view_model_utils.h" 65 66 namespace ash { 67 namespace { 68 69 // Duration for the animation that hides the boot splash screen, in 70 // milliseconds. This should be short enough in relation to 71 // wm/window_animation.cc's brightness/grayscale fade animation that the login 72 // background image animation isn't hidden by the splash screen animation. 73 const int kBootSplashScreenHideDurationMs = 500; 74 75 // Creates a new window for use as a container. 76 aura::Window* CreateContainer(int window_id, 77 const char* name, 78 aura::Window* parent) { 79 aura::Window* container = new aura::Window(NULL); 80 container->set_id(window_id); 81 container->SetName(name); 82 container->Init(ui::LAYER_NOT_DRAWN); 83 parent->AddChild(container); 84 if (window_id != internal::kShellWindowId_UnparentedControlContainer) 85 container->Show(); 86 return container; 87 } 88 89 // Reparents |window| to |new_parent|. 90 void ReparentWindow(aura::Window* window, aura::Window* new_parent) { 91 // Update the restore bounds to make it relative to the display. 92 gfx::Rect restore_bounds(GetRestoreBoundsInParent(window)); 93 new_parent->AddChild(window); 94 if (!restore_bounds.IsEmpty()) 95 SetRestoreBoundsInParent(window, restore_bounds); 96 } 97 98 // Reparents the appropriate set of windows from |src| to |dst|. 99 void ReparentAllWindows(aura::RootWindow* src, aura::RootWindow* dst) { 100 // Set of windows to move. 101 const int kContainerIdsToMove[] = { 102 internal::kShellWindowId_DefaultContainer, 103 internal::kShellWindowId_DockedContainer, 104 internal::kShellWindowId_PanelContainer, 105 internal::kShellWindowId_AlwaysOnTopContainer, 106 internal::kShellWindowId_SystemModalContainer, 107 internal::kShellWindowId_LockSystemModalContainer, 108 internal::kShellWindowId_InputMethodContainer, 109 internal::kShellWindowId_UnparentedControlContainer, 110 }; 111 for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) { 112 int id = kContainerIdsToMove[i]; 113 aura::Window* src_container = Shell::GetContainer(src, id); 114 aura::Window* dst_container = Shell::GetContainer(dst, id); 115 while (!src_container->children().empty()) { 116 // Restart iteration from the source container windows each time as they 117 // may change as a result of moving other windows. 118 aura::Window::Windows::const_iterator iter = 119 src_container->children().begin(); 120 while (iter != src_container->children().end() && 121 internal::SystemModalContainerLayoutManager::IsModalBackground( 122 *iter)) { 123 ++iter; 124 } 125 // If the entire window list is modal background windows then stop. 126 if (iter == src_container->children().end()) 127 break; 128 ReparentWindow(*iter, dst_container); 129 } 130 } 131 } 132 133 // Mark the container window so that a widget added to this container will 134 // use the virtual screeen coordinates instead of parent. 135 void SetUsesScreenCoordinates(aura::Window* container) { 136 container->SetProperty(internal::kUsesScreenCoordinatesKey, true); 137 } 138 139 // Mark the container window so that a widget added to this container will 140 // say in the same root window regardless of the bounds specified. 141 void DescendantShouldStayInSameRootWindow(aura::Window* container) { 142 container->SetProperty(internal::kStayInSameRootWindowKey, true); 143 } 144 145 // A window delegate which does nothing. Used to create a window that 146 // is a event target, but do nothing. 147 class EmptyWindowDelegate : public aura::WindowDelegate { 148 public: 149 EmptyWindowDelegate() {} 150 virtual ~EmptyWindowDelegate() {} 151 152 // aura::WindowDelegate overrides: 153 virtual gfx::Size GetMinimumSize() const OVERRIDE { 154 return gfx::Size(); 155 } 156 virtual gfx::Size GetMaximumSize() const OVERRIDE { 157 return gfx::Size(); 158 } 159 virtual void OnBoundsChanged(const gfx::Rect& old_bounds, 160 const gfx::Rect& new_bounds) OVERRIDE { 161 } 162 virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE { 163 return gfx::kNullCursor; 164 } 165 virtual int GetNonClientComponent( 166 const gfx::Point& point) const OVERRIDE { 167 return HTNOWHERE; 168 } 169 virtual bool ShouldDescendIntoChildForEventHandling( 170 aura::Window* child, 171 const gfx::Point& location) OVERRIDE { 172 return false; 173 } 174 virtual bool CanFocus() OVERRIDE { 175 return false; 176 } 177 virtual void OnCaptureLost() OVERRIDE { 178 } 179 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { 180 } 181 virtual void OnDeviceScaleFactorChanged( 182 float device_scale_factor) OVERRIDE { 183 } 184 virtual void OnWindowDestroying() OVERRIDE {} 185 virtual void OnWindowDestroyed() OVERRIDE { 186 delete this; 187 } 188 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE { 189 } 190 virtual bool HasHitTestMask() const OVERRIDE { 191 return false; 192 } 193 virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {} 194 virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE { 195 NOTREACHED(); 196 return scoped_refptr<ui::Texture>(); 197 } 198 199 private: 200 DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate); 201 }; 202 203 } // namespace 204 205 namespace internal { 206 207 RootWindowController::RootWindowController(aura::RootWindow* root_window) 208 : root_window_(root_window), 209 root_window_layout_(NULL), 210 docked_layout_manager_(NULL), 211 panel_layout_manager_(NULL), 212 touch_hud_debug_(NULL), 213 touch_hud_projection_(NULL) { 214 SetRootWindowController(root_window, this); 215 screen_dimmer_.reset(new ScreenDimmer(root_window)); 216 217 stacking_controller_.reset(new StackingController); 218 aura::client::SetStackingClient(root_window, stacking_controller_.get()); 219 } 220 221 RootWindowController::~RootWindowController() { 222 Shutdown(); 223 root_window_.reset(); 224 } 225 226 // static 227 RootWindowController* RootWindowController::ForLauncher(aura::Window* window) { 228 return GetRootWindowController(window->GetRootWindow()); 229 } 230 231 // static 232 RootWindowController* RootWindowController::ForWindow( 233 const aura::Window* window) { 234 return GetRootWindowController(window->GetRootWindow()); 235 } 236 237 // static 238 RootWindowController* RootWindowController::ForActiveRootWindow() { 239 return GetRootWindowController(Shell::GetActiveRootWindow()); 240 } 241 242 void RootWindowController::SetWallpaperController( 243 DesktopBackgroundWidgetController* controller) { 244 wallpaper_controller_.reset(controller); 245 } 246 247 void RootWindowController::SetAnimatingWallpaperController( 248 AnimatingDesktopController* controller) { 249 if (animating_wallpaper_controller_.get()) 250 animating_wallpaper_controller_->StopAnimating(); 251 animating_wallpaper_controller_.reset(controller); 252 } 253 254 void RootWindowController::Shutdown() { 255 Shell::GetInstance()->RemoveShellObserver(this); 256 257 if (animating_wallpaper_controller_.get()) 258 animating_wallpaper_controller_->StopAnimating(); 259 wallpaper_controller_.reset(); 260 animating_wallpaper_controller_.reset(); 261 262 // Change the active root window before closing child windows. If any child 263 // being removed triggers a relayout of the shelf it will try to build a 264 // window list adding windows from the active root window's containers which 265 // may have already gone away. 266 if (Shell::GetActiveRootWindow() == root_window_) { 267 Shell::GetInstance()->set_active_root_window( 268 Shell::GetPrimaryRootWindow() == root_window_.get() ? 269 NULL : Shell::GetPrimaryRootWindow()); 270 } 271 272 CloseChildWindows(); 273 SetRootWindowController(root_window_.get(), NULL); 274 screen_dimmer_.reset(); 275 workspace_controller_.reset(); 276 // Forget with the display ID so that display lookup 277 // ends up with invalid display. 278 root_window_->ClearProperty(kDisplayIdKey); 279 // And this root window should no longer process events. 280 root_window_->PrepareForShutdown(); 281 282 system_background_.reset(); 283 } 284 285 SystemModalContainerLayoutManager* 286 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) { 287 aura::Window* container = NULL; 288 if (window) { 289 if (window->parent() && 290 window->parent()->id() >= kShellWindowId_LockScreenContainer) { 291 container = GetContainer(kShellWindowId_LockSystemModalContainer); 292 } else { 293 container = GetContainer(kShellWindowId_SystemModalContainer); 294 } 295 } else { 296 int modal_window_id = Shell::GetInstance()->session_state_delegate() 297 ->IsUserSessionBlocked() ? kShellWindowId_LockSystemModalContainer : 298 kShellWindowId_SystemModalContainer; 299 container = GetContainer(modal_window_id); 300 } 301 return container ? static_cast<SystemModalContainerLayoutManager*>( 302 container->layout_manager()) : NULL; 303 } 304 305 aura::Window* RootWindowController::GetContainer(int container_id) { 306 return root_window_->GetChildById(container_id); 307 } 308 309 const aura::Window* RootWindowController::GetContainer(int container_id) const { 310 return root_window_->GetChildById(container_id); 311 } 312 313 void RootWindowController::Init(bool first_run_after_boot) { 314 root_window_->SetCursor(ui::kCursorPointer); 315 CreateContainersInRootWindow(root_window_.get()); 316 CreateSystemBackground(first_run_after_boot); 317 318 InitLayoutManagers(); 319 InitKeyboard(); 320 InitTouchHuds(); 321 322 if (Shell::GetPrimaryRootWindowController()-> 323 GetSystemModalLayoutManager(NULL)->has_modal_background()) { 324 GetSystemModalLayoutManager(NULL)->CreateModalBackground(); 325 } 326 327 Shell::GetInstance()->AddShellObserver(this); 328 } 329 330 void RootWindowController::ShowLauncher() { 331 if (!shelf_->launcher()) 332 return; 333 shelf_->launcher()->SetVisible(true); 334 shelf_->status_area_widget()->Show(); 335 } 336 337 void RootWindowController::OnLauncherCreated() { 338 if (panel_layout_manager_) 339 panel_layout_manager_->SetLauncher(shelf_->launcher()); 340 if (docked_layout_manager_) { 341 docked_layout_manager_->SetLauncher(shelf_->launcher()); 342 if (shelf_->shelf_layout_manager()) 343 docked_layout_manager_->AddObserver(shelf_->shelf_layout_manager()); 344 } 345 } 346 347 void RootWindowController::UpdateAfterLoginStatusChange( 348 user::LoginStatus status) { 349 if (status != user::LOGGED_IN_NONE) 350 mouse_event_target_.reset(); 351 if (shelf_->status_area_widget()) 352 shelf_->status_area_widget()->UpdateAfterLoginStatusChange(status); 353 } 354 355 void RootWindowController::HandleInitialDesktopBackgroundAnimationStarted() { 356 if (CommandLine::ForCurrentProcess()->HasSwitch( 357 switches::kAshAnimateFromBootSplashScreen) && 358 boot_splash_screen_.get()) { 359 // Make the splash screen fade out so it doesn't obscure the desktop 360 // wallpaper's brightness/grayscale animation. 361 boot_splash_screen_->StartHideAnimation( 362 base::TimeDelta::FromMilliseconds(kBootSplashScreenHideDurationMs)); 363 } 364 } 365 366 void RootWindowController::OnWallpaperAnimationFinished(views::Widget* widget) { 367 // Make sure the wallpaper is visible. 368 system_background_->SetColor(SK_ColorBLACK); 369 boot_splash_screen_.reset(); 370 371 Shell::GetInstance()->user_wallpaper_delegate()-> 372 OnWallpaperAnimationFinished(); 373 // Only removes old component when wallpaper animation finished. If we 374 // remove the old one before the new wallpaper is done fading in there will 375 // be a white flash during the animation. 376 if (animating_wallpaper_controller()) { 377 DesktopBackgroundWidgetController* controller = 378 animating_wallpaper_controller()->GetController(true); 379 // |desktop_widget_| should be the same animating widget we try to move 380 // to |kDesktopController|. Otherwise, we may close |desktop_widget_| 381 // before move it to |kDesktopController|. 382 DCHECK_EQ(controller->widget(), widget); 383 // Release the old controller and close its background widget. 384 SetWallpaperController(controller); 385 } 386 } 387 388 void RootWindowController::CloseChildWindows() { 389 mouse_event_target_.reset(); 390 391 if (!shelf_.get()) 392 return; 393 // panel_layout_manager_ needs to be shut down before windows are destroyed. 394 if (panel_layout_manager_) { 395 panel_layout_manager_->Shutdown(); 396 panel_layout_manager_ = NULL; 397 } 398 // docked_layout_manager_ needs to be shut down before windows are destroyed. 399 if (docked_layout_manager_) { 400 if (shelf_->shelf_layout_manager()) 401 docked_layout_manager_->RemoveObserver(shelf_->shelf_layout_manager()); 402 docked_layout_manager_->Shutdown(); 403 docked_layout_manager_ = NULL; 404 } 405 406 aura::client::SetDragDropClient(root_window_.get(), NULL); 407 408 // TODO(harrym): Remove when Status Area Widget is a child view. 409 shelf_->ShutdownStatusAreaWidget(); 410 411 if (shelf_->shelf_layout_manager()) 412 shelf_->shelf_layout_manager()->PrepareForShutdown(); 413 414 // Close background widget first as it depends on tooltip. 415 wallpaper_controller_.reset(); 416 animating_wallpaper_controller_.reset(); 417 418 workspace_controller_.reset(); 419 aura::client::SetTooltipClient(root_window_.get(), NULL); 420 421 // Remove all toplevel windows first. 422 std::queue<aura::Window*> non_toplevel_windows; 423 non_toplevel_windows.push(root_window_.get()); 424 while (!non_toplevel_windows.empty()) { 425 aura::Window* non_toplevel_window = non_toplevel_windows.front(); 426 non_toplevel_windows.pop(); 427 aura::WindowTracker toplevel_windows; 428 for (size_t i = 0; i < non_toplevel_window->children().size(); ++i) { 429 aura::Window* child = non_toplevel_window->children()[i]; 430 if (child->delegate()) 431 toplevel_windows.Add(child); 432 else 433 non_toplevel_windows.push(child); 434 } 435 while (!toplevel_windows.windows().empty()) 436 delete *toplevel_windows.windows().begin(); 437 } 438 // And then remove the containers. 439 while (!root_window_->children().empty()) 440 delete root_window_->children()[0]; 441 442 shelf_.reset(NULL); 443 } 444 445 void RootWindowController::MoveWindowsTo(aura::RootWindow* dst) { 446 // Forget the shelf early so that shelf don't update itself using wrong 447 // display info. 448 workspace_controller_->SetShelf(NULL); 449 ReparentAllWindows(root_window_.get(), dst); 450 } 451 452 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() { 453 return shelf_->shelf_layout_manager(); 454 } 455 456 SystemTray* RootWindowController::GetSystemTray() { 457 // We assume in throughout the code that this will not return NULL. If code 458 // triggers this for valid reasons, it should test status_area_widget first. 459 CHECK(shelf_->status_area_widget()); 460 return shelf_->status_area_widget()->system_tray(); 461 } 462 463 void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen, 464 ui::MenuSourceType source_type) { 465 DCHECK(Shell::GetInstance()->delegate()); 466 scoped_ptr<ui::MenuModel> menu_model( 467 Shell::GetInstance()->delegate()->CreateContextMenu(root_window())); 468 if (!menu_model) 469 return; 470 471 // Background controller may not be set yet if user clicked on status are 472 // before initial animation completion. See crbug.com/222218 473 if (!wallpaper_controller_.get()) 474 return; 475 476 views::MenuRunner menu_runner(menu_model.get()); 477 if (menu_runner.RunMenuAt(wallpaper_controller_->widget(), 478 NULL, gfx::Rect(location_in_screen, gfx::Size()), 479 views::MenuItemView::TOPLEFT, source_type, 480 views::MenuRunner::CONTEXT_MENU) == 481 views::MenuRunner::MENU_DELETED) { 482 return; 483 } 484 485 Shell::GetInstance()->UpdateShelfVisibility(); 486 } 487 488 void RootWindowController::UpdateShelfVisibility() { 489 shelf_->shelf_layout_manager()->UpdateVisibilityState(); 490 } 491 492 const aura::Window* RootWindowController::GetFullscreenWindow() const { 493 const aura::Window* container = GetContainer(kShellWindowId_DefaultContainer); 494 for (size_t i = 0; i < container->children().size(); ++i) { 495 aura::Window* child = container->children()[i]; 496 if (wm::IsWindowFullscreen(child)) 497 return child; 498 } 499 return NULL; 500 } 501 502 void RootWindowController::InitKeyboard() { 503 if (keyboard::IsKeyboardEnabled()) { 504 aura::Window* parent = root_window(); 505 506 keyboard::KeyboardControllerProxy* proxy = 507 Shell::GetInstance()->delegate()->CreateKeyboardControllerProxy(); 508 keyboard_controller_.reset( 509 new keyboard::KeyboardController(proxy)); 510 511 keyboard_controller_->AddObserver(shelf()->shelf_layout_manager()); 512 keyboard_controller_->AddObserver(panel_layout_manager_); 513 514 aura::Window* keyboard_container = 515 keyboard_controller_->GetContainerWindow(); 516 parent->AddChild(keyboard_container); 517 keyboard_container->SetBounds(parent->bounds()); 518 } 519 } 520 521 522 //////////////////////////////////////////////////////////////////////////////// 523 // RootWindowController, private: 524 525 void RootWindowController::InitLayoutManagers() { 526 root_window_layout_ = 527 new RootWindowLayoutManager(root_window_.get()); 528 root_window_->SetLayoutManager(root_window_layout_); 529 530 aura::Window* default_container = 531 GetContainer(kShellWindowId_DefaultContainer); 532 // Workspace manager has its own layout managers. 533 workspace_controller_.reset( 534 new WorkspaceController(default_container)); 535 536 aura::Window* always_on_top_container = 537 GetContainer(kShellWindowId_AlwaysOnTopContainer); 538 always_on_top_container->SetLayoutManager( 539 new BaseLayoutManager( 540 always_on_top_container->GetRootWindow())); 541 always_on_top_controller_.reset(new internal::AlwaysOnTopController); 542 always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container); 543 544 DCHECK(!shelf_.get()); 545 aura::Window* shelf_container = 546 GetContainer(internal::kShellWindowId_ShelfContainer); 547 // TODO(harrym): Remove when status area is view. 548 aura::Window* status_container = 549 GetContainer(internal::kShellWindowId_StatusContainer); 550 shelf_.reset(new ShelfWidget( 551 shelf_container, status_container, workspace_controller())); 552 553 if (!Shell::GetInstance()->session_state_delegate()-> 554 IsActiveUserSessionStarted()) { 555 // This window exists only to be a event target on login screen. 556 // It does not have to handle events, nor be visible. 557 mouse_event_target_.reset(new aura::Window(new EmptyWindowDelegate)); 558 mouse_event_target_->Init(ui::LAYER_NOT_DRAWN); 559 560 aura::Window* lock_background_container = 561 GetContainer(internal::kShellWindowId_LockScreenBackgroundContainer); 562 lock_background_container->AddChild(mouse_event_target_.get()); 563 mouse_event_target_->Show(); 564 } 565 566 // Create Docked windows layout manager 567 aura::Window* docked_container = GetContainer( 568 internal::kShellWindowId_DockedContainer); 569 docked_layout_manager_ = 570 new internal::DockedWindowLayoutManager(docked_container); 571 docked_container_handler_.reset( 572 new ToplevelWindowEventHandler(docked_container)); 573 docked_container->SetLayoutManager(docked_layout_manager_); 574 575 // Create Panel layout manager 576 aura::Window* panel_container = GetContainer( 577 internal::kShellWindowId_PanelContainer); 578 panel_layout_manager_ = 579 new internal::PanelLayoutManager(panel_container); 580 panel_container_handler_.reset( 581 new PanelWindowEventHandler(panel_container)); 582 panel_container->SetLayoutManager(panel_layout_manager_); 583 } 584 585 void RootWindowController::InitTouchHuds() { 586 CommandLine* command_line = CommandLine::ForCurrentProcess(); 587 if (command_line->HasSwitch(switches::kAshTouchHud)) 588 set_touch_hud_debug(new TouchHudDebug(root_window_.get())); 589 if (Shell::GetInstance()->is_touch_hud_projection_enabled()) 590 EnableTouchHudProjection(); 591 } 592 593 void RootWindowController::CreateSystemBackground( 594 bool is_first_run_after_boot) { 595 SkColor color = SK_ColorBLACK; 596 #if defined(OS_CHROMEOS) 597 if (is_first_run_after_boot) 598 color = kChromeOsBootColor; 599 #endif 600 system_background_.reset( 601 new SystemBackgroundController(root_window_.get(), color)); 602 603 #if defined(OS_CHROMEOS) 604 // Make a copy of the system's boot splash screen so we can composite it 605 // onscreen until the desktop background is ready. 606 if (is_first_run_after_boot && 607 (CommandLine::ForCurrentProcess()->HasSwitch( 608 switches::kAshCopyHostBackgroundAtBoot) || 609 CommandLine::ForCurrentProcess()->HasSwitch( 610 switches::kAshAnimateFromBootSplashScreen))) 611 boot_splash_screen_.reset(new BootSplashScreen(root_window_.get())); 612 #endif 613 } 614 615 void RootWindowController::CreateContainersInRootWindow( 616 aura::RootWindow* root_window) { 617 // These containers are just used by PowerButtonController to animate groups 618 // of containers simultaneously without messing up the current transformations 619 // on those containers. These are direct children of the root window; all of 620 // the other containers are their children. 621 622 // The desktop background container is not part of the lock animation, so it 623 // is not included in those animate groups. 624 // When screen is locked desktop background is moved to lock screen background 625 // container (moved back on unlock). We want to make sure that there's an 626 // opaque layer occluding the non-lock-screen layers. 627 aura::Window* desktop_background_container = CreateContainer( 628 kShellWindowId_DesktopBackgroundContainer, 629 "DesktopBackgroundContainer", 630 root_window); 631 views::corewm::SetChildWindowVisibilityChangesAnimated( 632 desktop_background_container); 633 634 aura::Window* non_lock_screen_containers = CreateContainer( 635 kShellWindowId_NonLockScreenContainersContainer, 636 "NonLockScreenContainersContainer", 637 root_window); 638 639 aura::Window* lock_background_containers = CreateContainer( 640 kShellWindowId_LockScreenBackgroundContainer, 641 "LockScreenBackgroundContainer", 642 root_window); 643 views::corewm::SetChildWindowVisibilityChangesAnimated( 644 lock_background_containers); 645 646 aura::Window* lock_screen_containers = CreateContainer( 647 kShellWindowId_LockScreenContainersContainer, 648 "LockScreenContainersContainer", 649 root_window); 650 aura::Window* lock_screen_related_containers = CreateContainer( 651 kShellWindowId_LockScreenRelatedContainersContainer, 652 "LockScreenRelatedContainersContainer", 653 root_window); 654 655 CreateContainer(kShellWindowId_UnparentedControlContainer, 656 "UnparentedControlContainer", 657 non_lock_screen_containers); 658 659 aura::Window* default_container = CreateContainer( 660 kShellWindowId_DefaultContainer, 661 "DefaultContainer", 662 non_lock_screen_containers); 663 views::corewm::SetChildWindowVisibilityChangesAnimated(default_container); 664 SetUsesScreenCoordinates(default_container); 665 666 aura::Window* always_on_top_container = CreateContainer( 667 kShellWindowId_AlwaysOnTopContainer, 668 "AlwaysOnTopContainer", 669 non_lock_screen_containers); 670 always_on_top_container_handler_.reset( 671 new ToplevelWindowEventHandler(always_on_top_container)); 672 views::corewm::SetChildWindowVisibilityChangesAnimated( 673 always_on_top_container); 674 SetUsesScreenCoordinates(always_on_top_container); 675 676 aura::Window* docked_container = CreateContainer( 677 kShellWindowId_DockedContainer, 678 "DockedContainer", 679 non_lock_screen_containers); 680 SetUsesScreenCoordinates(docked_container); 681 682 aura::Window* panel_container = CreateContainer( 683 kShellWindowId_PanelContainer, 684 "PanelContainer", 685 non_lock_screen_containers); 686 SetUsesScreenCoordinates(panel_container); 687 688 aura::Window* shelf_container = 689 CreateContainer(kShellWindowId_ShelfContainer, 690 "ShelfContainer", 691 non_lock_screen_containers); 692 SetUsesScreenCoordinates(shelf_container); 693 DescendantShouldStayInSameRootWindow(shelf_container); 694 695 aura::Window* app_list_container = 696 CreateContainer(kShellWindowId_AppListContainer, 697 "AppListContainer", 698 non_lock_screen_containers); 699 SetUsesScreenCoordinates(app_list_container); 700 701 aura::Window* modal_container = CreateContainer( 702 kShellWindowId_SystemModalContainer, 703 "SystemModalContainer", 704 non_lock_screen_containers); 705 modal_container_handler_.reset( 706 new ToplevelWindowEventHandler(modal_container)); 707 modal_container->SetLayoutManager( 708 new SystemModalContainerLayoutManager(modal_container)); 709 views::corewm::SetChildWindowVisibilityChangesAnimated(modal_container); 710 SetUsesScreenCoordinates(modal_container); 711 712 aura::Window* input_method_container = CreateContainer( 713 kShellWindowId_InputMethodContainer, 714 "InputMethodContainer", 715 non_lock_screen_containers); 716 SetUsesScreenCoordinates(input_method_container); 717 718 // TODO(beng): Figure out if we can make this use 719 // SystemModalContainerEventFilter instead of stops_event_propagation. 720 aura::Window* lock_container = CreateContainer( 721 kShellWindowId_LockScreenContainer, 722 "LockScreenContainer", 723 lock_screen_containers); 724 lock_container->SetLayoutManager( 725 new BaseLayoutManager(root_window)); 726 SetUsesScreenCoordinates(lock_container); 727 // TODO(beng): stopsevents 728 729 aura::Window* lock_modal_container = CreateContainer( 730 kShellWindowId_LockSystemModalContainer, 731 "LockSystemModalContainer", 732 lock_screen_containers); 733 lock_modal_container_handler_.reset( 734 new ToplevelWindowEventHandler(lock_modal_container)); 735 lock_modal_container->SetLayoutManager( 736 new SystemModalContainerLayoutManager(lock_modal_container)); 737 views::corewm::SetChildWindowVisibilityChangesAnimated(lock_modal_container); 738 SetUsesScreenCoordinates(lock_modal_container); 739 740 aura::Window* status_container = 741 CreateContainer(kShellWindowId_StatusContainer, 742 "StatusContainer", 743 lock_screen_related_containers); 744 SetUsesScreenCoordinates(status_container); 745 DescendantShouldStayInSameRootWindow(status_container); 746 747 aura::Window* settings_bubble_container = CreateContainer( 748 kShellWindowId_SettingBubbleContainer, 749 "SettingBubbleContainer", 750 lock_screen_related_containers); 751 views::corewm::SetChildWindowVisibilityChangesAnimated( 752 settings_bubble_container); 753 SetUsesScreenCoordinates(settings_bubble_container); 754 DescendantShouldStayInSameRootWindow(settings_bubble_container); 755 756 aura::Window* menu_container = CreateContainer( 757 kShellWindowId_MenuContainer, 758 "MenuContainer", 759 lock_screen_related_containers); 760 views::corewm::SetChildWindowVisibilityChangesAnimated(menu_container); 761 SetUsesScreenCoordinates(menu_container); 762 763 aura::Window* drag_drop_container = CreateContainer( 764 kShellWindowId_DragImageAndTooltipContainer, 765 "DragImageAndTooltipContainer", 766 lock_screen_related_containers); 767 views::corewm::SetChildWindowVisibilityChangesAnimated(drag_drop_container); 768 SetUsesScreenCoordinates(drag_drop_container); 769 770 aura::Window* overlay_container = CreateContainer( 771 kShellWindowId_OverlayContainer, 772 "OverlayContainer", 773 lock_screen_related_containers); 774 SetUsesScreenCoordinates(overlay_container); 775 776 CreateContainer(kShellWindowId_PowerButtonAnimationContainer, 777 "PowerButtonAnimationContainer", root_window) ; 778 } 779 780 void RootWindowController::EnableTouchHudProjection() { 781 if (touch_hud_projection_) 782 return; 783 set_touch_hud_projection(new TouchHudProjection(root_window_.get())); 784 } 785 786 void RootWindowController::DisableTouchHudProjection() { 787 if (!touch_hud_projection_) 788 return; 789 touch_hud_projection_->Remove(); 790 } 791 792 void RootWindowController::OnLoginStateChanged(user::LoginStatus status) { 793 shelf_->shelf_layout_manager()->UpdateVisibilityState(); 794 } 795 796 void RootWindowController::OnTouchHudProjectionToggled(bool enabled) { 797 if (enabled) 798 EnableTouchHudProjection(); 799 else 800 DisableTouchHudProjection(); 801 } 802 803 } // namespace internal 804 } // namespace ash 805