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