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