Home | History | Annotate | Download | only in ash
      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