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/host/ash_window_tree_host.h"
     19 #include "ash/root_window_settings.h"
     20 #include "ash/session/session_state_delegate.h"
     21 #include "ash/shelf/shelf_layout_manager.h"
     22 #include "ash/shelf/shelf_types.h"
     23 #include "ash/shelf/shelf_widget.h"
     24 #include "ash/shell.h"
     25 #include "ash/shell_delegate.h"
     26 #include "ash/shell_factory.h"
     27 #include "ash/shell_window_ids.h"
     28 #include "ash/switchable_windows.h"
     29 #include "ash/system/status_area_widget.h"
     30 #include "ash/system/tray/system_tray_delegate.h"
     31 #include "ash/system/tray/system_tray_notifier.h"
     32 #include "ash/touch/touch_hud_debug.h"
     33 #include "ash/touch/touch_hud_projection.h"
     34 #include "ash/touch/touch_observer_hud.h"
     35 #include "ash/wm/always_on_top_controller.h"
     36 #include "ash/wm/dock/docked_window_layout_manager.h"
     37 #include "ash/wm/lock_layout_manager.h"
     38 #include "ash/wm/panels/attached_panel_window_targeter.h"
     39 #include "ash/wm/panels/panel_layout_manager.h"
     40 #include "ash/wm/panels/panel_window_event_handler.h"
     41 #include "ash/wm/root_window_layout_manager.h"
     42 #include "ash/wm/screen_dimmer.h"
     43 #include "ash/wm/stacking_controller.h"
     44 #include "ash/wm/status_area_layout_manager.h"
     45 #include "ash/wm/system_background_controller.h"
     46 #include "ash/wm/system_modal_container_layout_manager.h"
     47 #include "ash/wm/window_properties.h"
     48 #include "ash/wm/window_state.h"
     49 #include "ash/wm/window_util.h"
     50 #include "ash/wm/workspace/workspace_layout_manager.h"
     51 #include "ash/wm/workspace_controller.h"
     52 #include "base/command_line.h"
     53 #include "base/time/time.h"
     54 #include "ui/aura/client/aura_constants.h"
     55 #include "ui/aura/client/screen_position_client.h"
     56 #include "ui/aura/window.h"
     57 #include "ui/aura/window_delegate.h"
     58 #include "ui/aura/window_event_dispatcher.h"
     59 #include "ui/aura/window_observer.h"
     60 #include "ui/aura/window_tracker.h"
     61 #include "ui/base/hit_test.h"
     62 #include "ui/base/models/menu_model.h"
     63 #include "ui/gfx/display.h"
     64 #include "ui/gfx/screen.h"
     65 #include "ui/keyboard/keyboard_controller.h"
     66 #include "ui/keyboard/keyboard_util.h"
     67 #include "ui/views/controls/menu/menu_runner.h"
     68 #include "ui/views/view_model.h"
     69 #include "ui/views/view_model_utils.h"
     70 #include "ui/wm/core/capture_controller.h"
     71 #include "ui/wm/core/easy_resize_window_targeter.h"
     72 #include "ui/wm/core/visibility_controller.h"
     73 #include "ui/wm/core/window_util.h"
     74 #include "ui/wm/public/drag_drop_client.h"
     75 #include "ui/wm/public/tooltip_client.h"
     76 #include "ui/wm/public/window_types.h"
     77 
     78 #if defined(OS_CHROMEOS)
     79 #include "ash/system/tray_accessibility.h"
     80 #include "ash/wm/boot_splash_screen_chromeos.h"
     81 #include "ui/chromeos/touch_exploration_controller.h"
     82 #endif
     83 
     84 namespace ash {
     85 namespace {
     86 
     87 #if defined(OS_CHROMEOS)
     88 // Duration for the animation that hides the boot splash screen, in
     89 // milliseconds.  This should be short enough in relation to
     90 // wm/window_animation.cc's brightness/grayscale fade animation that the login
     91 // background image animation isn't hidden by the splash screen animation.
     92 const int kBootSplashScreenHideDurationMs = 500;
     93 #endif
     94 
     95 // Creates a new window for use as a container.
     96 aura::Window* CreateContainer(int window_id,
     97                               const char* name,
     98                               aura::Window* parent) {
     99   aura::Window* container = new aura::Window(NULL);
    100   container->set_id(window_id);
    101   container->SetName(name);
    102   container->Init(aura::WINDOW_LAYER_NOT_DRAWN);
    103   parent->AddChild(container);
    104   if (window_id != kShellWindowId_UnparentedControlContainer)
    105     container->Show();
    106   return container;
    107 }
    108 
    109 float ToRelativeValue(int value, int src, int dst) {
    110   return static_cast<float>(value) / static_cast<float>(src) * dst;
    111 }
    112 
    113 void MoveOriginRelativeToSize(const gfx::Size& src_size,
    114                                 const gfx::Size& dst_size,
    115                                 gfx::Rect* bounds_in_out) {
    116   gfx::Point origin = bounds_in_out->origin();
    117   bounds_in_out->set_origin(gfx::Point(
    118       ToRelativeValue(origin.x(), src_size.width(), dst_size.width()),
    119       ToRelativeValue(origin.y(), src_size.height(), dst_size.height())));
    120 }
    121 
    122 // Reparents |window| to |new_parent|.
    123 void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
    124   const gfx::Size src_size = window->parent()->bounds().size();
    125   const gfx::Size dst_size = new_parent->bounds().size();
    126   // Update the restore bounds to make it relative to the display.
    127   wm::WindowState* state = wm::GetWindowState(window);
    128   gfx::Rect restore_bounds;
    129   bool has_restore_bounds = state->HasRestoreBounds();
    130 
    131   bool update_bounds = (state->IsNormalOrSnapped() || state->IsMinimized()) &&
    132                        new_parent->id() != kShellWindowId_DockedContainer;
    133   gfx::Rect local_bounds;
    134   if (update_bounds) {
    135     local_bounds = state->window()->bounds();
    136     MoveOriginRelativeToSize(src_size, dst_size, &local_bounds);
    137   }
    138 
    139   if (has_restore_bounds) {
    140     restore_bounds = state->GetRestoreBoundsInParent();
    141     MoveOriginRelativeToSize(src_size, dst_size, &restore_bounds);
    142   }
    143 
    144   new_parent->AddChild(window);
    145 
    146   // Docked windows have bounds handled by the layout manager in AddChild().
    147   if (update_bounds)
    148     window->SetBounds(local_bounds);
    149 
    150   if (has_restore_bounds)
    151     state->SetRestoreBoundsInParent(restore_bounds);
    152 }
    153 
    154 // Reparents the appropriate set of windows from |src| to |dst|.
    155 void ReparentAllWindows(aura::Window* src, aura::Window* dst) {
    156   // Set of windows to move.
    157   const int kContainerIdsToMove[] = {
    158       kShellWindowId_DefaultContainer,
    159       kShellWindowId_DockedContainer,
    160       kShellWindowId_PanelContainer,
    161       kShellWindowId_AlwaysOnTopContainer,
    162       kShellWindowId_SystemModalContainer,
    163       kShellWindowId_LockSystemModalContainer,
    164       kShellWindowId_UnparentedControlContainer, };
    165   for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) {
    166     int id = kContainerIdsToMove[i];
    167     aura::Window* src_container = Shell::GetContainer(src, id);
    168     aura::Window* dst_container = Shell::GetContainer(dst, id);
    169     while (!src_container->children().empty()) {
    170       // Restart iteration from the source container windows each time as they
    171       // may change as a result of moving other windows.
    172       aura::Window::Windows::const_iterator iter =
    173           src_container->children().begin();
    174       while (iter != src_container->children().end() &&
    175              SystemModalContainerLayoutManager::IsModalBackground(*iter)) {
    176         ++iter;
    177       }
    178       // If the entire window list is modal background windows then stop.
    179       if (iter == src_container->children().end())
    180         break;
    181       ReparentWindow(*iter, dst_container);
    182     }
    183   }
    184 }
    185 
    186 // Mark the container window so that a widget added to this container will
    187 // use the virtual screeen coordinates instead of parent.
    188 void SetUsesScreenCoordinates(aura::Window* container) {
    189   container->SetProperty(kUsesScreenCoordinatesKey, true);
    190 }
    191 
    192 // Mark the container window so that a widget added to this container will
    193 // say in the same root window regardless of the bounds specified.
    194 void DescendantShouldStayInSameRootWindow(aura::Window* container) {
    195   container->SetProperty(kStayInSameRootWindowKey, true);
    196 }
    197 
    198 void SetUsesEasyResizeTargeter(aura::Window* container) {
    199   gfx::Insets mouse_extend(-kResizeOutsideBoundsSize,
    200                            -kResizeOutsideBoundsSize,
    201                            -kResizeOutsideBoundsSize,
    202                            -kResizeOutsideBoundsSize);
    203   gfx::Insets touch_extend = mouse_extend.Scale(
    204       kResizeOutsideBoundsScaleForTouch);
    205   container->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
    206       new ::wm::EasyResizeWindowTargeter(container, mouse_extend,
    207                                          touch_extend)));
    208 }
    209 
    210 // A window delegate which does nothing. Used to create a window that
    211 // is a event target, but do nothing.
    212 class EmptyWindowDelegate : public aura::WindowDelegate {
    213  public:
    214   EmptyWindowDelegate() {}
    215   virtual ~EmptyWindowDelegate() {}
    216 
    217   // aura::WindowDelegate overrides:
    218   virtual gfx::Size GetMinimumSize() const OVERRIDE {
    219     return gfx::Size();
    220   }
    221   virtual gfx::Size GetMaximumSize() const OVERRIDE {
    222     return gfx::Size();
    223   }
    224   virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
    225                                const gfx::Rect& new_bounds) OVERRIDE {
    226   }
    227   virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
    228     return gfx::kNullCursor;
    229   }
    230   virtual int GetNonClientComponent(
    231       const gfx::Point& point) const OVERRIDE {
    232     return HTNOWHERE;
    233   }
    234   virtual bool ShouldDescendIntoChildForEventHandling(
    235       aura::Window* child,
    236       const gfx::Point& location) OVERRIDE {
    237     return false;
    238   }
    239   virtual bool CanFocus() OVERRIDE {
    240     return false;
    241   }
    242   virtual void OnCaptureLost() OVERRIDE {
    243   }
    244   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
    245   }
    246   virtual void OnDeviceScaleFactorChanged(
    247       float device_scale_factor) OVERRIDE {
    248   }
    249   virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {}
    250   virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
    251     delete this;
    252   }
    253   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
    254   }
    255   virtual bool HasHitTestMask() const OVERRIDE {
    256     return false;
    257   }
    258   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
    259 
    260  private:
    261   DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate);
    262 };
    263 
    264 #if defined(OS_CHROMEOS)
    265 // Responsible for initializing TouchExplorationController when spoken
    266 // feedback is on.
    267 class CrosAccessibilityObserver : public AccessibilityObserver {
    268  public:
    269   explicit CrosAccessibilityObserver(
    270       RootWindowController* root_window_controller)
    271       : root_window_controller_(root_window_controller) {
    272     Shell::GetInstance()->system_tray_notifier()->
    273         AddAccessibilityObserver(this);
    274     UpdateTouchExplorationState();
    275   }
    276 
    277   virtual ~CrosAccessibilityObserver() {
    278     SystemTrayNotifier* system_tray_notifier =
    279         Shell::GetInstance()->system_tray_notifier();
    280     if (system_tray_notifier)
    281       system_tray_notifier->RemoveAccessibilityObserver(this);
    282   }
    283 
    284  private:
    285   void UpdateTouchExplorationState() {
    286     AccessibilityDelegate* delegate =
    287         Shell::GetInstance()->accessibility_delegate();
    288     bool enabled = delegate->IsSpokenFeedbackEnabled();
    289 
    290     if (enabled && !touch_exploration_controller_.get()) {
    291       touch_exploration_controller_.reset(
    292           new ui::TouchExplorationController(
    293               root_window_controller_->GetRootWindow()));
    294     } else if (!enabled) {
    295       touch_exploration_controller_.reset();
    296     }
    297   }
    298 
    299   // Overridden from AccessibilityObserver.
    300   virtual void OnAccessibilityModeChanged(
    301       AccessibilityNotificationVisibility notify) OVERRIDE {
    302     UpdateTouchExplorationState();
    303   }
    304 
    305   scoped_ptr<ui::TouchExplorationController> touch_exploration_controller_;
    306   RootWindowController* root_window_controller_;
    307 
    308   DISALLOW_COPY_AND_ASSIGN(CrosAccessibilityObserver);
    309 };
    310 #endif  // OS_CHROMEOS
    311 
    312 }  // namespace
    313 
    314 void RootWindowController::CreateForPrimaryDisplay(AshWindowTreeHost* host) {
    315   RootWindowController* controller = new RootWindowController(host);
    316   controller->Init(RootWindowController::PRIMARY,
    317                    Shell::GetInstance()->delegate()->IsFirstRunAfterBoot());
    318 }
    319 
    320 void RootWindowController::CreateForSecondaryDisplay(AshWindowTreeHost* host) {
    321   RootWindowController* controller = new RootWindowController(host);
    322   controller->Init(RootWindowController::SECONDARY, false /* first run */);
    323 }
    324 
    325 void RootWindowController::CreateForVirtualKeyboardDisplay(
    326     AshWindowTreeHost* host) {
    327   RootWindowController* controller = new RootWindowController(host);
    328   controller->Init(RootWindowController::VIRTUAL_KEYBOARD,
    329                    false /* first run */);
    330 }
    331 
    332 // static
    333 RootWindowController* RootWindowController::ForShelf(
    334     const aura::Window* window) {
    335   return GetRootWindowController(window->GetRootWindow());
    336 }
    337 
    338 // static
    339 RootWindowController* RootWindowController::ForWindow(
    340     const aura::Window* window) {
    341   return GetRootWindowController(window->GetRootWindow());
    342 }
    343 
    344 // static
    345 RootWindowController* RootWindowController::ForTargetRootWindow() {
    346   return GetRootWindowController(Shell::GetTargetRootWindow());
    347 }
    348 
    349 // static
    350 aura::Window* RootWindowController::GetContainerForWindow(
    351     aura::Window* window) {
    352   aura::Window* container = window->parent();
    353   while (container && container->type() != ui::wm::WINDOW_TYPE_UNKNOWN)
    354     container = container->parent();
    355   return container;
    356 }
    357 
    358 RootWindowController::~RootWindowController() {
    359   Shutdown();
    360   ash_host_.reset();
    361   // The CaptureClient needs to be around for as long as the RootWindow is
    362   // valid.
    363   capture_client_.reset();
    364 }
    365 
    366 aura::WindowTreeHost* RootWindowController::GetHost() {
    367   return ash_host_->AsWindowTreeHost();
    368 }
    369 
    370 const aura::WindowTreeHost* RootWindowController::GetHost() const {
    371   return ash_host_->AsWindowTreeHost();
    372 }
    373 
    374 aura::Window* RootWindowController::GetRootWindow() {
    375   return GetHost()->window();
    376 }
    377 
    378 const aura::Window* RootWindowController::GetRootWindow() const {
    379   return GetHost()->window();
    380 }
    381 
    382 void RootWindowController::SetWallpaperController(
    383     DesktopBackgroundWidgetController* controller) {
    384   wallpaper_controller_.reset(controller);
    385 }
    386 
    387 void RootWindowController::SetAnimatingWallpaperController(
    388     AnimatingDesktopController* controller) {
    389   if (animating_wallpaper_controller_.get())
    390     animating_wallpaper_controller_->StopAnimating();
    391   animating_wallpaper_controller_.reset(controller);
    392 }
    393 
    394 void RootWindowController::Shutdown() {
    395   Shell* shell = Shell::GetInstance();
    396   shell->RemoveShellObserver(this);
    397 
    398 #if defined(OS_CHROMEOS)
    399   if (cros_accessibility_observer_) {
    400     cros_accessibility_observer_.reset();
    401   }
    402 #endif
    403 
    404   if (animating_wallpaper_controller_.get())
    405     animating_wallpaper_controller_->StopAnimating();
    406   wallpaper_controller_.reset();
    407   animating_wallpaper_controller_.reset();
    408   aura::Window* root_window = GetRootWindow();
    409   // Change the target root window before closing child windows. If any child
    410   // being removed triggers a relayout of the shelf it will try to build a
    411   // window list adding windows from the target root window's containers which
    412   // may have already gone away.
    413   if (Shell::GetTargetRootWindow() == root_window) {
    414     shell->set_target_root_window(
    415         Shell::GetPrimaryRootWindow() == root_window
    416             ? NULL
    417             : Shell::GetPrimaryRootWindow());
    418   }
    419 
    420   CloseChildWindows();
    421   GetRootWindowSettings(root_window)->controller = NULL;
    422   screen_dimmer_.reset();
    423   workspace_controller_.reset();
    424   // Forget with the display ID so that display lookup
    425   // ends up with invalid display.
    426   GetRootWindowSettings(root_window)->display_id =
    427       gfx::Display::kInvalidDisplayID;
    428   ash_host_->PrepareForShutdown();
    429 
    430   system_background_.reset();
    431   aura::client::SetScreenPositionClient(root_window, NULL);
    432 }
    433 
    434 SystemModalContainerLayoutManager*
    435 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
    436   aura::Window* modal_container = NULL;
    437   if (window) {
    438     aura::Window* window_container = GetContainerForWindow(window);
    439     if (window_container &&
    440         window_container->id() >= kShellWindowId_LockScreenContainer) {
    441       modal_container = GetContainer(kShellWindowId_LockSystemModalContainer);
    442     } else {
    443       modal_container = GetContainer(kShellWindowId_SystemModalContainer);
    444     }
    445   } else {
    446     int modal_window_id = Shell::GetInstance()->session_state_delegate()
    447         ->IsUserSessionBlocked() ? kShellWindowId_LockSystemModalContainer :
    448                                    kShellWindowId_SystemModalContainer;
    449     modal_container = GetContainer(modal_window_id);
    450   }
    451   return modal_container ? static_cast<SystemModalContainerLayoutManager*>(
    452       modal_container->layout_manager()) : NULL;
    453 }
    454 
    455 aura::Window* RootWindowController::GetContainer(int container_id) {
    456   return GetRootWindow()->GetChildById(container_id);
    457 }
    458 
    459 const aura::Window* RootWindowController::GetContainer(int container_id) const {
    460   return ash_host_->AsWindowTreeHost()->window()->GetChildById(container_id);
    461 }
    462 
    463 void RootWindowController::ShowShelf() {
    464   if (!shelf_->shelf())
    465     return;
    466   shelf_->shelf()->SetVisible(true);
    467   shelf_->status_area_widget()->Show();
    468 }
    469 
    470 void RootWindowController::OnShelfCreated() {
    471   if (panel_layout_manager_)
    472     panel_layout_manager_->SetShelf(shelf_->shelf());
    473   if (docked_layout_manager_) {
    474     docked_layout_manager_->SetShelf(shelf_->shelf());
    475     if (shelf_->shelf_layout_manager())
    476       docked_layout_manager_->AddObserver(shelf_->shelf_layout_manager());
    477   }
    478 
    479   // Notify shell observers that the shelf has been created.
    480   Shell::GetInstance()->OnShelfCreatedForRootWindow(GetRootWindow());
    481 }
    482 
    483 void RootWindowController::UpdateAfterLoginStatusChange(
    484     user::LoginStatus status) {
    485   if (status != user::LOGGED_IN_NONE)
    486     mouse_event_target_.reset();
    487   if (shelf_->status_area_widget())
    488     shelf_->status_area_widget()->UpdateAfterLoginStatusChange(status);
    489 }
    490 
    491 void RootWindowController::HandleInitialDesktopBackgroundAnimationStarted() {
    492 #if defined(OS_CHROMEOS)
    493   if (CommandLine::ForCurrentProcess()->HasSwitch(
    494           switches::kAshAnimateFromBootSplashScreen) &&
    495       boot_splash_screen_.get()) {
    496     // Make the splash screen fade out so it doesn't obscure the desktop
    497     // wallpaper's brightness/grayscale animation.
    498     boot_splash_screen_->StartHideAnimation(
    499         base::TimeDelta::FromMilliseconds(kBootSplashScreenHideDurationMs));
    500   }
    501 #endif
    502 }
    503 
    504 void RootWindowController::OnWallpaperAnimationFinished(views::Widget* widget) {
    505   // Make sure the wallpaper is visible.
    506   system_background_->SetColor(SK_ColorBLACK);
    507 #if defined(OS_CHROMEOS)
    508   boot_splash_screen_.reset();
    509 #endif
    510 
    511   Shell::GetInstance()->user_wallpaper_delegate()->
    512       OnWallpaperAnimationFinished();
    513   // Only removes old component when wallpaper animation finished. If we
    514   // remove the old one before the new wallpaper is done fading in there will
    515   // be a white flash during the animation.
    516   if (animating_wallpaper_controller()) {
    517     DesktopBackgroundWidgetController* controller =
    518         animating_wallpaper_controller()->GetController(true);
    519     // |desktop_widget_| should be the same animating widget we try to move
    520     // to |kDesktopController|. Otherwise, we may close |desktop_widget_|
    521     // before move it to |kDesktopController|.
    522     DCHECK_EQ(controller->widget(), widget);
    523     // Release the old controller and close its background widget.
    524     SetWallpaperController(controller);
    525   }
    526 }
    527 
    528 void RootWindowController::CloseChildWindows() {
    529   mouse_event_target_.reset();
    530 
    531   // Remove observer as deactivating keyboard causes |docked_layout_manager_|
    532   // to fire notifications.
    533   if (docked_layout_manager_ && shelf_ && shelf_->shelf_layout_manager())
    534     docked_layout_manager_->RemoveObserver(shelf_->shelf_layout_manager());
    535 
    536   // Deactivate keyboard container before closing child windows and shutting
    537   // down associated layout managers.
    538   DeactivateKeyboard(keyboard::KeyboardController::GetInstance());
    539 
    540   // panel_layout_manager_ needs to be shut down before windows are destroyed.
    541   if (panel_layout_manager_) {
    542     panel_layout_manager_->Shutdown();
    543     panel_layout_manager_ = NULL;
    544   }
    545   // docked_layout_manager_ needs to be shut down before windows are destroyed.
    546   if (docked_layout_manager_) {
    547     docked_layout_manager_->Shutdown();
    548     docked_layout_manager_ = NULL;
    549   }
    550   aura::Window* root_window = GetRootWindow();
    551   aura::client::SetDragDropClient(root_window, NULL);
    552 
    553   // TODO(harrym): Remove when Status Area Widget is a child view.
    554   if (shelf_) {
    555     shelf_->ShutdownStatusAreaWidget();
    556 
    557     if (shelf_->shelf_layout_manager())
    558       shelf_->shelf_layout_manager()->PrepareForShutdown();
    559   }
    560 
    561   // Close background widget first as it depends on tooltip.
    562   wallpaper_controller_.reset();
    563   animating_wallpaper_controller_.reset();
    564 
    565   workspace_controller_.reset();
    566   aura::client::SetTooltipClient(root_window, NULL);
    567 
    568   // Explicitly destroy top level windows. We do this as during part of
    569   // destruction such windows may query the RootWindow for state.
    570   std::queue<aura::Window*> non_toplevel_windows;
    571   non_toplevel_windows.push(root_window);
    572   while (!non_toplevel_windows.empty()) {
    573     aura::Window* non_toplevel_window = non_toplevel_windows.front();
    574     non_toplevel_windows.pop();
    575     aura::WindowTracker toplevel_windows;
    576     for (size_t i = 0; i < non_toplevel_window->children().size(); ++i) {
    577       aura::Window* child = non_toplevel_window->children()[i];
    578       if (!child->owned_by_parent())
    579         continue;
    580       if (child->delegate())
    581         toplevel_windows.Add(child);
    582       else
    583         non_toplevel_windows.push(child);
    584     }
    585     while (!toplevel_windows.windows().empty())
    586       delete *toplevel_windows.windows().begin();
    587   }
    588   // And then remove the containers.
    589   while (!root_window->children().empty()) {
    590     aura::Window* window = root_window->children()[0];
    591     if (window->owned_by_parent()) {
    592       delete window;
    593     } else {
    594       root_window->RemoveChild(window);
    595     }
    596   }
    597 
    598   shelf_.reset();
    599 }
    600 
    601 void RootWindowController::MoveWindowsTo(aura::Window* dst) {
    602   // Forget the shelf early so that shelf don't update itself using wrong
    603   // display info.
    604   workspace_controller_->SetShelf(NULL);
    605   ReparentAllWindows(GetRootWindow(), dst);
    606 }
    607 
    608 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
    609   return shelf_->shelf_layout_manager();
    610 }
    611 
    612 SystemTray* RootWindowController::GetSystemTray() {
    613   // We assume in throughout the code that this will not return NULL. If code
    614   // triggers this for valid reasons, it should test status_area_widget first.
    615   CHECK(shelf_->status_area_widget());
    616   return shelf_->status_area_widget()->system_tray();
    617 }
    618 
    619 void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen,
    620                                            ui::MenuSourceType source_type) {
    621   DCHECK(Shell::GetInstance()->delegate());
    622   scoped_ptr<ui::MenuModel> menu_model(
    623       Shell::GetInstance()->delegate()->CreateContextMenu(
    624           GetRootWindow(), NULL, NULL));
    625   if (!menu_model)
    626     return;
    627 
    628   // Background controller may not be set yet if user clicked on status are
    629   // before initial animation completion. See crbug.com/222218
    630   if (!wallpaper_controller_.get())
    631     return;
    632 
    633   views::MenuRunner menu_runner(menu_model.get());
    634   if (menu_runner.RunMenuAt(wallpaper_controller_->widget(),
    635                             NULL,
    636                             gfx::Rect(location_in_screen, gfx::Size()),
    637                             views::MENU_ANCHOR_TOPLEFT,
    638                             source_type,
    639                             views::MenuRunner::CONTEXT_MENU) ==
    640       views::MenuRunner::MENU_DELETED) {
    641     return;
    642   }
    643 
    644   Shell::GetInstance()->UpdateShelfVisibility();
    645 }
    646 
    647 void RootWindowController::UpdateShelfVisibility() {
    648   shelf_->shelf_layout_manager()->UpdateVisibilityState();
    649 }
    650 
    651 const aura::Window* RootWindowController::GetWindowForFullscreenMode() const {
    652   const aura::Window* topmost_window = NULL;
    653   const aura::Window* active_window = wm::GetActiveWindow();
    654   if (active_window && active_window->GetRootWindow() == GetRootWindow() &&
    655       IsSwitchableContainer(active_window->parent())) {
    656     // Use the active window when it is on the current root window to determine
    657     // the fullscreen state to allow temporarily using a panel or docked window
    658     // (which are always above the default container) while a fullscreen
    659     // window is open. We only use the active window when in a switchable
    660     // container as the launcher should not exit fullscreen mode.
    661     topmost_window = active_window;
    662   } else {
    663     // Otherwise, use the topmost window on the root window's default container
    664     // when there is no active window on this root window.
    665     const aura::Window::Windows& windows =
    666         GetContainer(kShellWindowId_DefaultContainer)->children();
    667     for (aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
    668          iter != windows.rend(); ++iter) {
    669       if (((*iter)->type() == ui::wm::WINDOW_TYPE_NORMAL ||
    670            (*iter)->type() == ui::wm::WINDOW_TYPE_PANEL) &&
    671           (*iter)->layer()->GetTargetVisibility()) {
    672         topmost_window = *iter;
    673         break;
    674       }
    675     }
    676   }
    677   while (topmost_window) {
    678     if (wm::GetWindowState(topmost_window)->IsFullscreen())
    679       return topmost_window;
    680     topmost_window = ::wm::GetTransientParent(topmost_window);
    681   }
    682   return NULL;
    683 }
    684 
    685 void RootWindowController::ActivateKeyboard(
    686     keyboard::KeyboardController* keyboard_controller) {
    687   if (!keyboard::IsKeyboardEnabled() ||
    688       GetContainer(kShellWindowId_VirtualKeyboardContainer)) {
    689     return;
    690   }
    691   DCHECK(keyboard_controller);
    692   if (!keyboard::IsKeyboardUsabilityExperimentEnabled()) {
    693     keyboard_controller->AddObserver(shelf()->shelf_layout_manager());
    694     keyboard_controller->AddObserver(panel_layout_manager_);
    695     keyboard_controller->AddObserver(docked_layout_manager_);
    696     keyboard_controller->AddObserver(workspace_controller_->layout_manager());
    697     Shell::GetInstance()->delegate()->VirtualKeyboardActivated(true);
    698   }
    699   aura::Window* parent = GetContainer(
    700       kShellWindowId_VirtualKeyboardParentContainer);
    701   DCHECK(parent);
    702   aura::Window* keyboard_container =
    703       keyboard_controller->GetContainerWindow();
    704   keyboard_container->set_id(kShellWindowId_VirtualKeyboardContainer);
    705   parent->AddChild(keyboard_container);
    706   // TODO(oshima): Bounds of keyboard container should be handled by
    707   // RootWindowLayoutManager. Remove this after fixed RootWindowLayoutManager.
    708   keyboard_container->SetBounds(parent->bounds());
    709 }
    710 
    711 void RootWindowController::DeactivateKeyboard(
    712     keyboard::KeyboardController* keyboard_controller) {
    713   if (!keyboard_controller ||
    714       !keyboard_controller->keyboard_container_initialized()) {
    715     return;
    716   }
    717   aura::Window* keyboard_container =
    718       keyboard_controller->GetContainerWindow();
    719   if (keyboard_container->GetRootWindow() == GetRootWindow()) {
    720     aura::Window* parent = GetContainer(
    721         kShellWindowId_VirtualKeyboardParentContainer);
    722     DCHECK(parent);
    723     parent->RemoveChild(keyboard_container);
    724     if (!keyboard::IsKeyboardUsabilityExperimentEnabled()) {
    725       // Virtual keyboard may be deactivated while still showing, notify all
    726       // observers that keyboard bounds changed to 0 before remove them.
    727       keyboard_controller->NotifyKeyboardBoundsChanging(gfx::Rect());
    728       keyboard_controller->RemoveObserver(shelf()->shelf_layout_manager());
    729       keyboard_controller->RemoveObserver(panel_layout_manager_);
    730       keyboard_controller->RemoveObserver(docked_layout_manager_);
    731       keyboard_controller->RemoveObserver(
    732           workspace_controller_->layout_manager());
    733       Shell::GetInstance()->delegate()->VirtualKeyboardActivated(false);
    734     }
    735   }
    736 }
    737 
    738 bool RootWindowController::IsVirtualKeyboardWindow(aura::Window* window) {
    739   aura::Window* parent = GetContainer(
    740       kShellWindowId_VirtualKeyboardParentContainer);
    741   return parent ? parent->Contains(window) : false;
    742 }
    743 
    744 ////////////////////////////////////////////////////////////////////////////////
    745 // RootWindowController, private:
    746 
    747 RootWindowController::RootWindowController(AshWindowTreeHost* ash_host)
    748     : ash_host_(ash_host),
    749       root_window_layout_(NULL),
    750       docked_layout_manager_(NULL),
    751       panel_layout_manager_(NULL),
    752       touch_hud_debug_(NULL),
    753       touch_hud_projection_(NULL) {
    754   aura::Window* root_window = GetRootWindow();
    755   GetRootWindowSettings(root_window)->controller = this;
    756   screen_dimmer_.reset(new ScreenDimmer(root_window));
    757 
    758   stacking_controller_.reset(new StackingController);
    759   aura::client::SetWindowTreeClient(root_window, stacking_controller_.get());
    760   capture_client_.reset(new ::wm::ScopedCaptureClient(root_window));
    761 }
    762 
    763 void RootWindowController::Init(RootWindowType root_window_type,
    764                                 bool first_run_after_boot) {
    765   aura::Window* root_window = GetRootWindow();
    766   Shell* shell = Shell::GetInstance();
    767   shell->InitRootWindow(root_window);
    768 
    769   ash_host_->AsWindowTreeHost()->SetCursor(ui::kCursorPointer);
    770   CreateContainersInRootWindow(root_window);
    771 
    772   if (root_window_type == VIRTUAL_KEYBOARD) {
    773     aura::Window* virtual_keyboard_parent_container = GetContainer(
    774         kShellWindowId_VirtualKeyboardParentContainer);
    775     virtual_keyboard_parent_container->SetBounds(root_window->bounds());
    776     shell->InitKeyboard();
    777     return;
    778   }
    779 
    780   CreateSystemBackground(first_run_after_boot);
    781 
    782   InitLayoutManagers();
    783   InitTouchHuds();
    784 
    785   if (Shell::GetPrimaryRootWindowController()->
    786       GetSystemModalLayoutManager(NULL)->has_modal_background()) {
    787     GetSystemModalLayoutManager(NULL)->CreateModalBackground();
    788   }
    789 
    790   shell->AddShellObserver(this);
    791 
    792   if (root_window_type == PRIMARY) {
    793     root_window_layout()->OnWindowResized();
    794     if (!keyboard::IsKeyboardUsabilityExperimentEnabled())
    795       shell->InitKeyboard();
    796   } else {
    797     root_window_layout()->OnWindowResized();
    798     ash_host_->AsWindowTreeHost()->Show();
    799 
    800     // Create a shelf if a user is already logged in.
    801     if (shell->session_state_delegate()->NumberOfLoggedInUsers())
    802       shelf()->CreateShelf();
    803 
    804     // Notify shell observers about new root window.
    805     shell->OnRootWindowAdded(root_window);
    806   }
    807 
    808 #if defined(OS_CHROMEOS)
    809   if (CommandLine::ForCurrentProcess()->HasSwitch(
    810           switches::kAshEnableTouchExplorationMode)) {
    811     cros_accessibility_observer_.reset(new CrosAccessibilityObserver(this));
    812   }
    813 #endif
    814 }
    815 
    816 void RootWindowController::InitLayoutManagers() {
    817   aura::Window* root_window = GetRootWindow();
    818   root_window_layout_ = new RootWindowLayoutManager(root_window);
    819   root_window->SetLayoutManager(root_window_layout_);
    820 
    821   aura::Window* default_container =
    822       GetContainer(kShellWindowId_DefaultContainer);
    823   // Workspace manager has its own layout managers.
    824   workspace_controller_.reset(
    825       new WorkspaceController(default_container));
    826 
    827   aura::Window* always_on_top_container =
    828       GetContainer(kShellWindowId_AlwaysOnTopContainer);
    829   always_on_top_container->SetLayoutManager(
    830       new WorkspaceLayoutManager(always_on_top_container));
    831   always_on_top_controller_.reset(new AlwaysOnTopController);
    832   always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container);
    833 
    834   DCHECK(!shelf_.get());
    835   aura::Window* shelf_container = GetContainer(kShellWindowId_ShelfContainer);
    836   // TODO(harrym): Remove when status area is view.
    837   aura::Window* status_container = GetContainer(kShellWindowId_StatusContainer);
    838   shelf_.reset(new ShelfWidget(
    839       shelf_container, status_container, workspace_controller()));
    840 
    841   if (!Shell::GetInstance()->session_state_delegate()->
    842       IsActiveUserSessionStarted()) {
    843     // This window exists only to be a event target on login screen.
    844     // It does not have to handle events, nor be visible.
    845     mouse_event_target_.reset(new aura::Window(new EmptyWindowDelegate));
    846     mouse_event_target_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
    847 
    848     aura::Window* lock_background_container =
    849         GetContainer(kShellWindowId_LockScreenBackgroundContainer);
    850     lock_background_container->AddChild(mouse_event_target_.get());
    851     mouse_event_target_->Show();
    852   }
    853 
    854   // Create Docked windows layout manager
    855   aura::Window* docked_container = GetContainer(kShellWindowId_DockedContainer);
    856   docked_layout_manager_ =
    857       new DockedWindowLayoutManager(docked_container, workspace_controller());
    858   docked_container->SetLayoutManager(docked_layout_manager_);
    859 
    860   // Create Panel layout manager
    861   aura::Window* panel_container = GetContainer(kShellWindowId_PanelContainer);
    862   panel_layout_manager_ = new PanelLayoutManager(panel_container);
    863   panel_container->SetLayoutManager(panel_layout_manager_);
    864   panel_container_handler_.reset(new PanelWindowEventHandler);
    865   panel_container->AddPreTargetHandler(panel_container_handler_.get());
    866 
    867   // Install an AttachedPanelWindowTargeter on the panel container to make it
    868   // easier to correctly target shelf buttons with touch.
    869   gfx::Insets mouse_extend(-kResizeOutsideBoundsSize,
    870                            -kResizeOutsideBoundsSize,
    871                            -kResizeOutsideBoundsSize,
    872                            -kResizeOutsideBoundsSize);
    873   gfx::Insets touch_extend = mouse_extend.Scale(
    874       kResizeOutsideBoundsScaleForTouch);
    875   panel_container->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
    876       new AttachedPanelWindowTargeter(panel_container,
    877                                       mouse_extend,
    878                                       touch_extend,
    879                                       panel_layout_manager_)));
    880 }
    881 
    882 void RootWindowController::InitTouchHuds() {
    883   CommandLine* command_line = CommandLine::ForCurrentProcess();
    884   if (command_line->HasSwitch(switches::kAshTouchHud))
    885     set_touch_hud_debug(new TouchHudDebug(GetRootWindow()));
    886   if (Shell::GetInstance()->is_touch_hud_projection_enabled())
    887     EnableTouchHudProjection();
    888 }
    889 
    890 void RootWindowController::CreateSystemBackground(
    891     bool is_first_run_after_boot) {
    892   SkColor color = SK_ColorBLACK;
    893 #if defined(OS_CHROMEOS)
    894   if (is_first_run_after_boot)
    895     color = kChromeOsBootColor;
    896 #endif
    897   system_background_.reset(
    898       new SystemBackgroundController(GetRootWindow(), color));
    899 
    900 #if defined(OS_CHROMEOS)
    901   // Make a copy of the system's boot splash screen so we can composite it
    902   // onscreen until the desktop background is ready.
    903   if (is_first_run_after_boot &&
    904       (CommandLine::ForCurrentProcess()->HasSwitch(
    905            switches::kAshCopyHostBackgroundAtBoot) ||
    906        CommandLine::ForCurrentProcess()->HasSwitch(
    907            switches::kAshAnimateFromBootSplashScreen)))
    908     boot_splash_screen_.reset(new BootSplashScreen(GetHost()));
    909 #endif
    910 }
    911 
    912 void RootWindowController::CreateContainersInRootWindow(
    913     aura::Window* root_window) {
    914   // These containers are just used by PowerButtonController to animate groups
    915   // of containers simultaneously without messing up the current transformations
    916   // on those containers. These are direct children of the root window; all of
    917   // the other containers are their children.
    918 
    919   // The desktop background container is not part of the lock animation, so it
    920   // is not included in those animate groups.
    921   // When screen is locked desktop background is moved to lock screen background
    922   // container (moved back on unlock). We want to make sure that there's an
    923   // opaque layer occluding the non-lock-screen layers.
    924   aura::Window* desktop_background_container = CreateContainer(
    925       kShellWindowId_DesktopBackgroundContainer,
    926       "DesktopBackgroundContainer",
    927       root_window);
    928   ::wm::SetChildWindowVisibilityChangesAnimated(desktop_background_container);
    929 
    930   aura::Window* non_lock_screen_containers = CreateContainer(
    931       kShellWindowId_NonLockScreenContainersContainer,
    932       "NonLockScreenContainersContainer",
    933       root_window);
    934 
    935   aura::Window* lock_background_containers = CreateContainer(
    936       kShellWindowId_LockScreenBackgroundContainer,
    937       "LockScreenBackgroundContainer",
    938       root_window);
    939   ::wm::SetChildWindowVisibilityChangesAnimated(lock_background_containers);
    940 
    941   aura::Window* lock_screen_containers = CreateContainer(
    942       kShellWindowId_LockScreenContainersContainer,
    943       "LockScreenContainersContainer",
    944       root_window);
    945   aura::Window* lock_screen_related_containers = CreateContainer(
    946       kShellWindowId_LockScreenRelatedContainersContainer,
    947       "LockScreenRelatedContainersContainer",
    948       root_window);
    949 
    950   CreateContainer(kShellWindowId_UnparentedControlContainer,
    951                   "UnparentedControlContainer",
    952                   non_lock_screen_containers);
    953 
    954   aura::Window* default_container = CreateContainer(
    955       kShellWindowId_DefaultContainer,
    956       "DefaultContainer",
    957       non_lock_screen_containers);
    958   ::wm::SetChildWindowVisibilityChangesAnimated(default_container);
    959   SetUsesScreenCoordinates(default_container);
    960   SetUsesEasyResizeTargeter(default_container);
    961 
    962   aura::Window* always_on_top_container = CreateContainer(
    963       kShellWindowId_AlwaysOnTopContainer,
    964       "AlwaysOnTopContainer",
    965       non_lock_screen_containers);
    966   ::wm::SetChildWindowVisibilityChangesAnimated(always_on_top_container);
    967   SetUsesScreenCoordinates(always_on_top_container);
    968 
    969   aura::Window* docked_container = CreateContainer(
    970       kShellWindowId_DockedContainer,
    971       "DockedContainer",
    972       non_lock_screen_containers);
    973   ::wm::SetChildWindowVisibilityChangesAnimated(docked_container);
    974   SetUsesScreenCoordinates(docked_container);
    975   SetUsesEasyResizeTargeter(docked_container);
    976 
    977   aura::Window* shelf_container =
    978       CreateContainer(kShellWindowId_ShelfContainer,
    979                       "ShelfContainer",
    980                       non_lock_screen_containers);
    981   SetUsesScreenCoordinates(shelf_container);
    982   DescendantShouldStayInSameRootWindow(shelf_container);
    983 
    984   aura::Window* panel_container = CreateContainer(
    985       kShellWindowId_PanelContainer,
    986       "PanelContainer",
    987       non_lock_screen_containers);
    988   SetUsesScreenCoordinates(panel_container);
    989 
    990   aura::Window* shelf_bubble_container =
    991       CreateContainer(kShellWindowId_ShelfBubbleContainer,
    992                       "ShelfBubbleContainer",
    993                       non_lock_screen_containers);
    994   SetUsesScreenCoordinates(shelf_bubble_container);
    995   DescendantShouldStayInSameRootWindow(shelf_bubble_container);
    996 
    997   aura::Window* app_list_container =
    998       CreateContainer(kShellWindowId_AppListContainer,
    999                       "AppListContainer",
   1000                       non_lock_screen_containers);
   1001   SetUsesScreenCoordinates(app_list_container);
   1002 
   1003   aura::Window* modal_container = CreateContainer(
   1004       kShellWindowId_SystemModalContainer,
   1005       "SystemModalContainer",
   1006       non_lock_screen_containers);
   1007   modal_container->SetLayoutManager(
   1008       new SystemModalContainerLayoutManager(modal_container));
   1009   ::wm::SetChildWindowVisibilityChangesAnimated(modal_container);
   1010   SetUsesScreenCoordinates(modal_container);
   1011   SetUsesEasyResizeTargeter(modal_container);
   1012 
   1013   // TODO(beng): Figure out if we can make this use
   1014   // SystemModalContainerEventFilter instead of stops_event_propagation.
   1015   aura::Window* lock_container = CreateContainer(
   1016       kShellWindowId_LockScreenContainer,
   1017       "LockScreenContainer",
   1018       lock_screen_containers);
   1019   if (CommandLine::ForCurrentProcess()->HasSwitch(
   1020           switches::kAshDisableLockLayoutManager)) {
   1021     lock_container->SetLayoutManager(
   1022             new WorkspaceLayoutManager(lock_container));
   1023   } else {
   1024     lock_container->SetLayoutManager(new LockLayoutManager(lock_container));
   1025   }
   1026   SetUsesScreenCoordinates(lock_container);
   1027   // TODO(beng): stopsevents
   1028 
   1029   aura::Window* lock_modal_container = CreateContainer(
   1030       kShellWindowId_LockSystemModalContainer,
   1031       "LockSystemModalContainer",
   1032       lock_screen_containers);
   1033   lock_modal_container->SetLayoutManager(
   1034       new SystemModalContainerLayoutManager(lock_modal_container));
   1035   ::wm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
   1036   SetUsesScreenCoordinates(lock_modal_container);
   1037   SetUsesEasyResizeTargeter(lock_modal_container);
   1038 
   1039   aura::Window* status_container =
   1040       CreateContainer(kShellWindowId_StatusContainer,
   1041                       "StatusContainer",
   1042                       lock_screen_related_containers);
   1043   SetUsesScreenCoordinates(status_container);
   1044   DescendantShouldStayInSameRootWindow(status_container);
   1045 
   1046   aura::Window* settings_bubble_container = CreateContainer(
   1047       kShellWindowId_SettingBubbleContainer,
   1048       "SettingBubbleContainer",
   1049       lock_screen_related_containers);
   1050   ::wm::SetChildWindowVisibilityChangesAnimated(settings_bubble_container);
   1051   SetUsesScreenCoordinates(settings_bubble_container);
   1052   DescendantShouldStayInSameRootWindow(settings_bubble_container);
   1053 
   1054   aura::Window* menu_container = CreateContainer(
   1055       kShellWindowId_MenuContainer,
   1056       "MenuContainer",
   1057       lock_screen_related_containers);
   1058   ::wm::SetChildWindowVisibilityChangesAnimated(menu_container);
   1059   SetUsesScreenCoordinates(menu_container);
   1060 
   1061   aura::Window* drag_drop_container = CreateContainer(
   1062       kShellWindowId_DragImageAndTooltipContainer,
   1063       "DragImageAndTooltipContainer",
   1064       lock_screen_related_containers);
   1065   ::wm::SetChildWindowVisibilityChangesAnimated(drag_drop_container);
   1066   SetUsesScreenCoordinates(drag_drop_container);
   1067 
   1068   aura::Window* overlay_container = CreateContainer(
   1069       kShellWindowId_OverlayContainer,
   1070       "OverlayContainer",
   1071       lock_screen_related_containers);
   1072   SetUsesScreenCoordinates(overlay_container);
   1073 
   1074   aura::Window* virtual_keyboard_parent_container = CreateContainer(
   1075       kShellWindowId_VirtualKeyboardParentContainer,
   1076       "VirtualKeyboardParentContainer",
   1077       root_window);
   1078   SetUsesScreenCoordinates(virtual_keyboard_parent_container);
   1079 
   1080 #if defined(OS_CHROMEOS)
   1081   aura::Window* mouse_cursor_container = CreateContainer(
   1082       kShellWindowId_MouseCursorContainer,
   1083       "MouseCursorContainer",
   1084       root_window);
   1085   SetUsesScreenCoordinates(mouse_cursor_container);
   1086 #endif
   1087 
   1088   CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
   1089                   "PowerButtonAnimationContainer", root_window);
   1090 }
   1091 
   1092 void RootWindowController::EnableTouchHudProjection() {
   1093   if (touch_hud_projection_)
   1094     return;
   1095   set_touch_hud_projection(new TouchHudProjection(GetRootWindow()));
   1096 }
   1097 
   1098 void RootWindowController::DisableTouchHudProjection() {
   1099   if (!touch_hud_projection_)
   1100     return;
   1101   touch_hud_projection_->Remove();
   1102 }
   1103 
   1104 void RootWindowController::OnLoginStateChanged(user::LoginStatus status) {
   1105   shelf_->shelf_layout_manager()->UpdateVisibilityState();
   1106 }
   1107 
   1108 void RootWindowController::OnTouchHudProjectionToggled(bool enabled) {
   1109   if (enabled)
   1110     EnableTouchHudProjection();
   1111   else
   1112     DisableTouchHudProjection();
   1113 }
   1114 
   1115 RootWindowController* GetRootWindowController(
   1116     const aura::Window* root_window) {
   1117   return root_window ? GetRootWindowSettings(root_window)->controller : NULL;
   1118 }
   1119 
   1120 }  // namespace ash
   1121