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