Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ash / root_window_controller.cc
index caa1228..8eda3b0 100644 (file)
@@ -15,8 +15,9 @@
 #include "ash/display/display_manager.h"
 #include "ash/focus_cycler.h"
 #include "ash/high_contrast/high_contrast_controller.h"
+#include "ash/host/ash_window_tree_host.h"
 #include "ash/root_window_settings.h"
-#include "ash/session_state_delegate.h"
+#include "ash/session/session_state_delegate.h"
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shelf/shelf_types.h"
 #include "ash/shelf/shelf_widget.h"
 #include "ash/switchable_windows.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/tray/system_tray_delegate.h"
+#include "ash/system/tray/system_tray_notifier.h"
 #include "ash/touch/touch_hud_debug.h"
 #include "ash/touch/touch_hud_projection.h"
 #include "ash/touch/touch_observer_hud.h"
 #include "ash/wm/always_on_top_controller.h"
 #include "ash/wm/dock/docked_window_layout_manager.h"
+#include "ash/wm/lock_layout_manager.h"
+#include "ash/wm/panels/attached_panel_window_targeter.h"
 #include "ash/wm/panels/panel_layout_manager.h"
 #include "ash/wm/panels/panel_window_event_handler.h"
 #include "ash/wm/root_window_layout_manager.h"
@@ -40,6 +44,7 @@
 #include "ash/wm/status_area_layout_manager.h"
 #include "ash/wm/system_background_controller.h"
 #include "ash/wm/system_modal_container_layout_manager.h"
+#include "ash/wm/virtual_keyboard_container_layout_manager.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
@@ -72,7 +77,9 @@
 #include "ui/wm/public/window_types.h"
 
 #if defined(OS_CHROMEOS)
+#include "ash/ash_touch_exploration_manager_chromeos.h"
 #include "ash/wm/boot_splash_screen_chromeos.h"
+#include "ui/chromeos/touch_exploration_controller.h"
 #endif
 
 namespace ash {
@@ -95,7 +102,7 @@ aura::Window* CreateContainer(int window_id,
   container->SetName(name);
   container->Init(aura::WINDOW_LAYER_NOT_DRAWN);
   parent->AddChild(container);
-  if (window_id != internal::kShellWindowId_UnparentedControlContainer)
+  if (window_id != kShellWindowId_UnparentedControlContainer)
     container->Show();
   return container;
 }
@@ -123,7 +130,7 @@ void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
   bool has_restore_bounds = state->HasRestoreBounds();
 
   bool update_bounds = (state->IsNormalOrSnapped() || state->IsMinimized()) &&
-      new_parent->id() != internal::kShellWindowId_DockedContainer;
+                       new_parent->id() != kShellWindowId_DockedContainer;
   gfx::Rect local_bounds;
   if (update_bounds) {
     local_bounds = state->window()->bounds();
@@ -149,15 +156,13 @@ void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
 void ReparentAllWindows(aura::Window* src, aura::Window* dst) {
   // Set of windows to move.
   const int kContainerIdsToMove[] = {
-    internal::kShellWindowId_DefaultContainer,
-    internal::kShellWindowId_DockedContainer,
-    internal::kShellWindowId_PanelContainer,
-    internal::kShellWindowId_AlwaysOnTopContainer,
-    internal::kShellWindowId_SystemModalContainer,
-    internal::kShellWindowId_LockSystemModalContainer,
-    internal::kShellWindowId_InputMethodContainer,
-    internal::kShellWindowId_UnparentedControlContainer,
-  };
+      kShellWindowId_DefaultContainer,
+      kShellWindowId_DockedContainer,
+      kShellWindowId_PanelContainer,
+      kShellWindowId_AlwaysOnTopContainer,
+      kShellWindowId_SystemModalContainer,
+      kShellWindowId_LockSystemModalContainer,
+      kShellWindowId_UnparentedControlContainer, };
   for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) {
     int id = kContainerIdsToMove[i];
     aura::Window* src_container = Shell::GetContainer(src, id);
@@ -168,8 +173,7 @@ void ReparentAllWindows(aura::Window* src, aura::Window* dst) {
       aura::Window::Windows::const_iterator iter =
           src_container->children().begin();
       while (iter != src_container->children().end() &&
-             internal::SystemModalContainerLayoutManager::IsModalBackground(
-                *iter)) {
+             SystemModalContainerLayoutManager::IsModalBackground(*iter)) {
         ++iter;
       }
       // If the entire window list is modal background windows then stop.
@@ -183,13 +187,13 @@ void ReparentAllWindows(aura::Window* src, aura::Window* dst) {
 // Mark the container window so that a widget added to this container will
 // use the virtual screeen coordinates instead of parent.
 void SetUsesScreenCoordinates(aura::Window* container) {
-  container->SetProperty(internal::kUsesScreenCoordinatesKey, true);
+  container->SetProperty(kUsesScreenCoordinatesKey, true);
 }
 
 // Mark the container window so that a widget added to this container will
 // say in the same root window regardless of the bounds specified.
 void DescendantShouldStayInSameRootWindow(aura::Window* container) {
-  container->SetProperty(internal::kStayInSameRootWindowKey, true);
+  container->SetProperty(kStayInSameRootWindowKey, true);
 }
 
 void SetUsesEasyResizeTargeter(aura::Window* container) {
@@ -260,41 +264,35 @@ class EmptyWindowDelegate : public aura::WindowDelegate {
 
 }  // namespace
 
-namespace internal {
-
-void RootWindowController::CreateForPrimaryDisplay(aura::WindowTreeHost* host) {
+void RootWindowController::CreateForPrimaryDisplay(AshWindowTreeHost* host) {
   RootWindowController* controller = new RootWindowController(host);
   controller->Init(RootWindowController::PRIMARY,
                    Shell::GetInstance()->delegate()->IsFirstRunAfterBoot());
 }
 
-void RootWindowController::CreateForSecondaryDisplay(
-    aura::WindowTreeHost* host) {
+void RootWindowController::CreateForSecondaryDisplay(AshWindowTreeHost* host) {
   RootWindowController* controller = new RootWindowController(host);
   controller->Init(RootWindowController::SECONDARY, false /* first run */);
 }
 
-void RootWindowController::CreateForVirtualKeyboardDisplay(
-    aura::WindowTreeHost* host) {
-  RootWindowController* controller = new RootWindowController(host);
-  controller->Init(RootWindowController::VIRTUAL_KEYBOARD,
-                   false /* first run */);
-}
-
 // static
-RootWindowController* RootWindowController::ForShelf(aura::Window* window) {
+RootWindowController* RootWindowController::ForShelf(
+    const aura::Window* window) {
+  CHECK(Shell::HasInstance());
   return GetRootWindowController(window->GetRootWindow());
 }
 
 // static
 RootWindowController* RootWindowController::ForWindow(
     const aura::Window* window) {
+  CHECK(Shell::HasInstance());
   return GetRootWindowController(window->GetRootWindow());
 }
 
 // static
 RootWindowController* RootWindowController::ForTargetRootWindow() {
-  return internal::GetRootWindowController(Shell::GetTargetRootWindow());
+  CHECK(Shell::HasInstance());
+  return GetRootWindowController(Shell::GetTargetRootWindow());
 }
 
 // static
@@ -308,12 +306,28 @@ aura::Window* RootWindowController::GetContainerForWindow(
 
 RootWindowController::~RootWindowController() {
   Shutdown();
-  host_.reset();
+  ash_host_.reset();
   // The CaptureClient needs to be around for as long as the RootWindow is
   // valid.
   capture_client_.reset();
 }
 
+aura::WindowTreeHost* RootWindowController::GetHost() {
+  return ash_host_->AsWindowTreeHost();
+}
+
+const aura::WindowTreeHost* RootWindowController::GetHost() const {
+  return ash_host_->AsWindowTreeHost();
+}
+
+aura::Window* RootWindowController::GetRootWindow() {
+  return GetHost()->window();
+}
+
+const aura::Window* RootWindowController::GetRootWindow() const {
+  return GetHost()->window();
+}
+
 void RootWindowController::SetWallpaperController(
     DesktopBackgroundWidgetController* controller) {
   wallpaper_controller_.reset(controller);
@@ -327,35 +341,43 @@ void RootWindowController::SetAnimatingWallpaperController(
 }
 
 void RootWindowController::Shutdown() {
-  Shell::GetInstance()->RemoveShellObserver(this);
+  Shell* shell = Shell::GetInstance();
+  shell->RemoveShellObserver(this);
+
+#if defined(OS_CHROMEOS)
+  if (touch_exploration_manager_) {
+    touch_exploration_manager_.reset();
+  }
+#endif
 
   if (animating_wallpaper_controller_.get())
     animating_wallpaper_controller_->StopAnimating();
   wallpaper_controller_.reset();
   animating_wallpaper_controller_.reset();
-
+  aura::Window* root_window = GetRootWindow();
   // Change the target root window before closing child windows. If any child
   // being removed triggers a relayout of the shelf it will try to build a
   // window list adding windows from the target root window's containers which
   // may have already gone away.
-  if (Shell::GetTargetRootWindow() == root_window()) {
-    Shell::GetInstance()->set_target_root_window(
-        Shell::GetPrimaryRootWindow() == root_window() ?
-        NULL : Shell::GetPrimaryRootWindow());
+  if (Shell::GetTargetRootWindow() == root_window) {
+    shell->set_target_root_window(
+        Shell::GetPrimaryRootWindow() == root_window
+            ? NULL
+            : Shell::GetPrimaryRootWindow());
   }
 
   CloseChildWindows();
-  GetRootWindowSettings(root_window())->controller = NULL;
+  GetRootWindowSettings(root_window)->controller = NULL;
   screen_dimmer_.reset();
   workspace_controller_.reset();
   // Forget with the display ID so that display lookup
   // ends up with invalid display.
-  internal::GetRootWindowSettings(root_window())->display_id =
+  GetRootWindowSettings(root_window)->display_id =
       gfx::Display::kInvalidDisplayID;
-  internal::GetRootWindowSettings(root_window())->shutdown = true;
+  ash_host_->PrepareForShutdown();
 
   system_background_.reset();
-  aura::client::SetScreenPositionClient(root_window(), NULL);
+  aura::client::SetScreenPositionClient(root_window, NULL);
 }
 
 SystemModalContainerLayoutManager*
@@ -380,11 +402,11 @@ RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
 }
 
 aura::Window* RootWindowController::GetContainer(int container_id) {
-  return root_window()->GetChildById(container_id);
+  return GetRootWindow()->GetChildById(container_id);
 }
 
 const aura::Window* RootWindowController::GetContainer(int container_id) const {
-  return host_->window()->GetChildById(container_id);
+  return ash_host_->AsWindowTreeHost()->window()->GetChildById(container_id);
 }
 
 void RootWindowController::ShowShelf() {
@@ -402,6 +424,9 @@ void RootWindowController::OnShelfCreated() {
     if (shelf_->shelf_layout_manager())
       docked_layout_manager_->AddObserver(shelf_->shelf_layout_manager());
   }
+
+  // Notify shell observers that the shelf has been created.
+  Shell::GetInstance()->OnShelfCreatedForRootWindow(GetRootWindow());
 }
 
 void RootWindowController::UpdateAfterLoginStatusChange(
@@ -452,9 +477,14 @@ void RootWindowController::OnWallpaperAnimationFinished(views::Widget* widget) {
 void RootWindowController::CloseChildWindows() {
   mouse_event_target_.reset();
 
+  // Remove observer as deactivating keyboard causes |docked_layout_manager_|
+  // to fire notifications.
+  if (docked_layout_manager_ && shelf_ && shelf_->shelf_layout_manager())
+    docked_layout_manager_->RemoveObserver(shelf_->shelf_layout_manager());
+
   // Deactivate keyboard container before closing child windows and shutting
   // down associated layout managers.
-  DeactivateKeyboard(Shell::GetInstance()->keyboard_controller());
+  DeactivateKeyboard(keyboard::KeyboardController::GetInstance());
 
   // panel_layout_manager_ needs to be shut down before windows are destroyed.
   if (panel_layout_manager_) {
@@ -463,13 +493,11 @@ void RootWindowController::CloseChildWindows() {
   }
   // docked_layout_manager_ needs to be shut down before windows are destroyed.
   if (docked_layout_manager_) {
-    if (shelf_ && shelf_->shelf_layout_manager())
-      docked_layout_manager_->RemoveObserver(shelf_->shelf_layout_manager());
     docked_layout_manager_->Shutdown();
     docked_layout_manager_ = NULL;
   }
-
-  aura::client::SetDragDropClient(root_window(), NULL);
+  aura::Window* root_window = GetRootWindow();
+  aura::client::SetDragDropClient(root_window, NULL);
 
   // TODO(harrym): Remove when Status Area Widget is a child view.
   if (shelf_) {
@@ -484,12 +512,12 @@ void RootWindowController::CloseChildWindows() {
   animating_wallpaper_controller_.reset();
 
   workspace_controller_.reset();
-  aura::client::SetTooltipClient(root_window(), NULL);
+  aura::client::SetTooltipClient(root_window, NULL);
 
   // Explicitly destroy top level windows. We do this as during part of
   // destruction such windows may query the RootWindow for state.
   std::queue<aura::Window*> non_toplevel_windows;
-  non_toplevel_windows.push(root_window());
+  non_toplevel_windows.push(root_window);
   while (!non_toplevel_windows.empty()) {
     aura::Window* non_toplevel_window = non_toplevel_windows.front();
     non_toplevel_windows.pop();
@@ -507,12 +535,12 @@ void RootWindowController::CloseChildWindows() {
       delete *toplevel_windows.windows().begin();
   }
   // And then remove the containers.
-  while (!root_window()->children().empty()) {
-    aura::Window* window = root_window()->children()[0];
+  while (!root_window->children().empty()) {
+    aura::Window* window = root_window->children()[0];
     if (window->owned_by_parent()) {
       delete window;
     } else {
-      root_window()->RemoveChild(window);
+      root_window->RemoveChild(window);
     }
   }
 
@@ -523,7 +551,7 @@ void RootWindowController::MoveWindowsTo(aura::Window* dst) {
   // Forget the shelf early so that shelf don't update itself using wrong
   // display info.
   workspace_controller_->SetShelf(NULL);
-  ReparentAllWindows(root_window(), dst);
+  ReparentAllWindows(GetRootWindow(), dst);
 }
 
 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
@@ -541,9 +569,8 @@ void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen,
                                            ui::MenuSourceType source_type) {
   DCHECK(Shell::GetInstance()->delegate());
   scoped_ptr<ui::MenuModel> menu_model(
-      Shell::GetInstance()->delegate()->CreateContextMenu(root_window(),
-                                                          NULL,
-                                                          NULL));
+      Shell::GetInstance()->delegate()->CreateContextMenu(
+          GetRootWindow(), NULL, NULL));
   if (!menu_model)
     return;
 
@@ -552,12 +579,13 @@ void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen,
   if (!wallpaper_controller_.get())
     return;
 
-  views::MenuRunner menu_runner(menu_model.get());
+  views::MenuRunner menu_runner(menu_model.get(),
+                                views::MenuRunner::CONTEXT_MENU);
   if (menu_runner.RunMenuAt(wallpaper_controller_->widget(),
-          NULL, gfx::Rect(location_in_screen, gfx::Size()),
-          views::MenuItemView::TOPLEFT, source_type,
-          views::MenuRunner::CONTEXT_MENU) ==
-      views::MenuRunner::MENU_DELETED) {
+                            NULL,
+                            gfx::Rect(location_in_screen, gfx::Size()),
+                            views::MENU_ANCHOR_TOPLEFT,
+                            source_type) == views::MenuRunner::MENU_DELETED) {
     return;
   }
 
@@ -571,7 +599,7 @@ void RootWindowController::UpdateShelfVisibility() {
 const aura::Window* RootWindowController::GetWindowForFullscreenMode() const {
   const aura::Window* topmost_window = NULL;
   const aura::Window* active_window = wm::GetActiveWindow();
-  if (active_window && active_window->GetRootWindow() == root_window() &&
+  if (active_window && active_window->GetRootWindow() == GetRootWindow() &&
       IsSwitchableContainer(active_window->parent())) {
     // Use the active window when it is on the current root window to determine
     // the fullscreen state to allow temporarily using a panel or docked window
@@ -609,11 +637,11 @@ void RootWindowController::ActivateKeyboard(
     return;
   }
   DCHECK(keyboard_controller);
-  if (!keyboard::IsKeyboardUsabilityExperimentEnabled()) {
-    keyboard_controller->AddObserver(shelf()->shelf_layout_manager());
-    keyboard_controller->AddObserver(panel_layout_manager_);
-    keyboard_controller->AddObserver(docked_layout_manager_);
-  }
+  keyboard_controller->AddObserver(shelf()->shelf_layout_manager());
+  keyboard_controller->AddObserver(panel_layout_manager_);
+  keyboard_controller->AddObserver(docked_layout_manager_);
+  keyboard_controller->AddObserver(workspace_controller_->layout_manager());
+  Shell::GetInstance()->delegate()->VirtualKeyboardActivated(true);
   aura::Window* parent = GetContainer(
       kShellWindowId_VirtualKeyboardParentContainer);
   DCHECK(parent);
@@ -634,19 +662,20 @@ void RootWindowController::DeactivateKeyboard(
   }
   aura::Window* keyboard_container =
       keyboard_controller->GetContainerWindow();
-  if (keyboard_container->GetRootWindow() == root_window()) {
+  if (keyboard_container->GetRootWindow() == GetRootWindow()) {
     aura::Window* parent = GetContainer(
         kShellWindowId_VirtualKeyboardParentContainer);
     DCHECK(parent);
     parent->RemoveChild(keyboard_container);
-    if (!keyboard::IsKeyboardUsabilityExperimentEnabled()) {
-      // Virtual keyboard may be deactivated while still showing, notify all
-      // observers that keyboard bounds changed to 0 before remove them.
-      keyboard_controller->NotifyKeyboardBoundsChanging(gfx::Rect());
-      keyboard_controller->RemoveObserver(shelf()->shelf_layout_manager());
-      keyboard_controller->RemoveObserver(panel_layout_manager_);
-      keyboard_controller->RemoveObserver(docked_layout_manager_);
-    }
+    // Virtual keyboard may be deactivated while still showing, notify all
+    // observers that keyboard bounds changed to 0 before remove them.
+    keyboard_controller->NotifyKeyboardBoundsChanging(gfx::Rect());
+    keyboard_controller->RemoveObserver(shelf()->shelf_layout_manager());
+    keyboard_controller->RemoveObserver(panel_layout_manager_);
+    keyboard_controller->RemoveObserver(docked_layout_manager_);
+    keyboard_controller->RemoveObserver(
+        workspace_controller_->layout_manager());
+    Shell::GetInstance()->delegate()->VirtualKeyboardActivated(false);
   }
 }
 
@@ -659,33 +688,30 @@ bool RootWindowController::IsVirtualKeyboardWindow(aura::Window* window) {
 ////////////////////////////////////////////////////////////////////////////////
 // RootWindowController, private:
 
-RootWindowController::RootWindowController(aura::WindowTreeHost* host)
-    : host_(host),
+RootWindowController::RootWindowController(AshWindowTreeHost* ash_host)
+    : ash_host_(ash_host),
       root_window_layout_(NULL),
       docked_layout_manager_(NULL),
       panel_layout_manager_(NULL),
       touch_hud_debug_(NULL),
       touch_hud_projection_(NULL) {
-  GetRootWindowSettings(root_window())->controller = this;
-  screen_dimmer_.reset(new ScreenDimmer(root_window()));
+  aura::Window* root_window = GetRootWindow();
+  GetRootWindowSettings(root_window)->controller = this;
+  screen_dimmer_.reset(new ScreenDimmer(root_window));
 
   stacking_controller_.reset(new StackingController);
-  aura::client::SetWindowTreeClient(root_window(), stacking_controller_.get());
-  capture_client_.reset(new ::wm::ScopedCaptureClient(root_window()));
+  aura::client::SetWindowTreeClient(root_window, stacking_controller_.get());
+  capture_client_.reset(new ::wm::ScopedCaptureClient(root_window));
 }
 
 void RootWindowController::Init(RootWindowType root_window_type,
                                 bool first_run_after_boot) {
+  aura::Window* root_window = GetRootWindow();
   Shell* shell = Shell::GetInstance();
-  shell->InitRootWindow(root_window());
+  shell->InitRootWindow(root_window);
 
-  host_->SetCursor(ui::kCursorPointer);
-  CreateContainersInRootWindow(root_window());
-
-  if (root_window_type == VIRTUAL_KEYBOARD) {
-    shell->InitKeyboard();
-    return;
-  }
+  ash_host_->AsWindowTreeHost()->SetCursor(ui::kCursorPointer);
+  CreateContainersInRootWindow(root_window);
 
   CreateSystemBackground(first_run_after_boot);
 
@@ -701,23 +727,31 @@ void RootWindowController::Init(RootWindowType root_window_type,
 
   if (root_window_type == PRIMARY) {
     root_window_layout()->OnWindowResized();
-    if (!keyboard::IsKeyboardUsabilityExperimentEnabled())
-      shell->InitKeyboard();
+    shell->InitKeyboard();
   } else {
     root_window_layout()->OnWindowResized();
-    shell->desktop_background_controller()->OnRootWindowAdded(root_window());
-    shell->high_contrast_controller()->OnRootWindowAdded(root_window());
-    host_->Show();
+    ash_host_->AsWindowTreeHost()->Show();
 
     // Create a shelf if a user is already logged in.
     if (shell->session_state_delegate()->NumberOfLoggedInUsers())
       shelf()->CreateShelf();
+
+    // Notify shell observers about new root window.
+    shell->OnRootWindowAdded(root_window);
+  }
+
+#if defined(OS_CHROMEOS)
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kAshDisableTouchExplorationMode)) {
+    touch_exploration_manager_.reset(new AshTouchExplorationManager(this));
   }
+#endif
 }
 
 void RootWindowController::InitLayoutManagers() {
-  root_window_layout_ = new RootWindowLayoutManager(root_window());
-  root_window()->SetLayoutManager(root_window_layout_);
+  aura::Window* root_window = GetRootWindow();
+  root_window_layout_ = new RootWindowLayoutManager(root_window);
+  root_window->SetLayoutManager(root_window_layout_);
 
   aura::Window* default_container =
       GetContainer(kShellWindowId_DefaultContainer);
@@ -728,17 +762,14 @@ void RootWindowController::InitLayoutManagers() {
   aura::Window* always_on_top_container =
       GetContainer(kShellWindowId_AlwaysOnTopContainer);
   always_on_top_container->SetLayoutManager(
-      new internal::WorkspaceLayoutManager(
-          always_on_top_container));
-  always_on_top_controller_.reset(new internal::AlwaysOnTopController);
+      new WorkspaceLayoutManager(always_on_top_container));
+  always_on_top_controller_.reset(new AlwaysOnTopController);
   always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container);
 
   DCHECK(!shelf_.get());
-  aura::Window* shelf_container =
-      GetContainer(internal::kShellWindowId_ShelfContainer);
+  aura::Window* shelf_container = GetContainer(kShellWindowId_ShelfContainer);
   // TODO(harrym): Remove when status area is view.
-  aura::Window* status_container =
-      GetContainer(internal::kShellWindowId_StatusContainer);
+  aura::Window* status_container = GetContainer(kShellWindowId_StatusContainer);
   shelf_.reset(new ShelfWidget(
       shelf_container, status_container, workspace_controller()));
 
@@ -750,33 +781,47 @@ void RootWindowController::InitLayoutManagers() {
     mouse_event_target_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
 
     aura::Window* lock_background_container =
-        GetContainer(internal::kShellWindowId_LockScreenBackgroundContainer);
+        GetContainer(kShellWindowId_LockScreenBackgroundContainer);
     lock_background_container->AddChild(mouse_event_target_.get());
     mouse_event_target_->Show();
   }
 
   // Create Docked windows layout manager
-  aura::Window* docked_container = GetContainer(
-      internal::kShellWindowId_DockedContainer);
+  aura::Window* docked_container = GetContainer(kShellWindowId_DockedContainer);
   docked_layout_manager_ =
-      new internal::DockedWindowLayoutManager(docked_container,
-                                              workspace_controller());
+      new DockedWindowLayoutManager(docked_container, workspace_controller());
   docked_container->SetLayoutManager(docked_layout_manager_);
 
+  // Installs SnapLayoutManager to containers who set the
+  // |kSnapsChildrenToPhysicalPixelBoundary| property.
+  wm::InstallSnapLayoutManagerToContainers(root_window);
+
   // Create Panel layout manager
-  aura::Window* panel_container = GetContainer(
-      internal::kShellWindowId_PanelContainer);
-  panel_layout_manager_ =
-      new internal::PanelLayoutManager(panel_container);
+  aura::Window* panel_container = GetContainer(kShellWindowId_PanelContainer);
+  panel_layout_manager_ = new PanelLayoutManager(panel_container);
   panel_container->SetLayoutManager(panel_layout_manager_);
   panel_container_handler_.reset(new PanelWindowEventHandler);
   panel_container->AddPreTargetHandler(panel_container_handler_.get());
+
+  // Install an AttachedPanelWindowTargeter on the panel container to make it
+  // easier to correctly target shelf buttons with touch.
+  gfx::Insets mouse_extend(-kResizeOutsideBoundsSize,
+                           -kResizeOutsideBoundsSize,
+                           -kResizeOutsideBoundsSize,
+                           -kResizeOutsideBoundsSize);
+  gfx::Insets touch_extend = mouse_extend.Scale(
+      kResizeOutsideBoundsScaleForTouch);
+  panel_container->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
+      new AttachedPanelWindowTargeter(panel_container,
+                                      mouse_extend,
+                                      touch_extend,
+                                      panel_layout_manager_)));
 }
 
 void RootWindowController::InitTouchHuds() {
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kAshTouchHud))
-    set_touch_hud_debug(new TouchHudDebug(root_window()));
+    set_touch_hud_debug(new TouchHudDebug(GetRootWindow()));
   if (Shell::GetInstance()->is_touch_hud_projection_enabled())
     EnableTouchHudProjection();
 }
@@ -789,7 +834,7 @@ void RootWindowController::CreateSystemBackground(
     color = kChromeOsBootColor;
 #endif
   system_background_.reset(
-    new SystemBackgroundController(root_window(), color));
+      new SystemBackgroundController(GetRootWindow(), color));
 
 #if defined(OS_CHROMEOS)
   // Make a copy of the system's boot splash screen so we can composite it
@@ -799,7 +844,7 @@ void RootWindowController::CreateSystemBackground(
            switches::kAshCopyHostBackgroundAtBoot) ||
        CommandLine::ForCurrentProcess()->HasSwitch(
            switches::kAshAnimateFromBootSplashScreen)))
-    boot_splash_screen_.reset(new BootSplashScreen(host()));
+    boot_splash_screen_.reset(new BootSplashScreen(GetHost()));
 #endif
 }
 
@@ -850,6 +895,7 @@ void RootWindowController::CreateContainersInRootWindow(
       "DefaultContainer",
       non_lock_screen_containers);
   ::wm::SetChildWindowVisibilityChangesAnimated(default_container);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(default_container);
   SetUsesScreenCoordinates(default_container);
   SetUsesEasyResizeTargeter(default_container);
 
@@ -858,6 +904,7 @@ void RootWindowController::CreateContainersInRootWindow(
       "AlwaysOnTopContainer",
       non_lock_screen_containers);
   ::wm::SetChildWindowVisibilityChangesAnimated(always_on_top_container);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(always_on_top_container);
   SetUsesScreenCoordinates(always_on_top_container);
 
   aura::Window* docked_container = CreateContainer(
@@ -865,6 +912,7 @@ void RootWindowController::CreateContainersInRootWindow(
       "DockedContainer",
       non_lock_screen_containers);
   ::wm::SetChildWindowVisibilityChangesAnimated(docked_container);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(docked_container);
   SetUsesScreenCoordinates(docked_container);
   SetUsesEasyResizeTargeter(docked_container);
 
@@ -872,6 +920,7 @@ void RootWindowController::CreateContainersInRootWindow(
       CreateContainer(kShellWindowId_ShelfContainer,
                       "ShelfContainer",
                       non_lock_screen_containers);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(shelf_container);
   SetUsesScreenCoordinates(shelf_container);
   DescendantShouldStayInSameRootWindow(shelf_container);
 
@@ -879,13 +928,14 @@ void RootWindowController::CreateContainersInRootWindow(
       kShellWindowId_PanelContainer,
       "PanelContainer",
       non_lock_screen_containers);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(panel_container);
   SetUsesScreenCoordinates(panel_container);
-  SetUsesEasyResizeTargeter(panel_container);
 
   aura::Window* shelf_bubble_container =
       CreateContainer(kShellWindowId_ShelfBubbleContainer,
                       "ShelfBubbleContainer",
                       non_lock_screen_containers);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(shelf_bubble_container);
   SetUsesScreenCoordinates(shelf_bubble_container);
   DescendantShouldStayInSameRootWindow(shelf_bubble_container);
 
@@ -893,33 +943,34 @@ void RootWindowController::CreateContainersInRootWindow(
       CreateContainer(kShellWindowId_AppListContainer,
                       "AppListContainer",
                       non_lock_screen_containers);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(app_list_container);
   SetUsesScreenCoordinates(app_list_container);
 
   aura::Window* modal_container = CreateContainer(
       kShellWindowId_SystemModalContainer,
       "SystemModalContainer",
       non_lock_screen_containers);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(modal_container);
   modal_container->SetLayoutManager(
       new SystemModalContainerLayoutManager(modal_container));
   ::wm::SetChildWindowVisibilityChangesAnimated(modal_container);
   SetUsesScreenCoordinates(modal_container);
   SetUsesEasyResizeTargeter(modal_container);
 
-  aura::Window* input_method_container = CreateContainer(
-      kShellWindowId_InputMethodContainer,
-      "InputMethodContainer",
-      non_lock_screen_containers);
-  ::wm::SetChildWindowVisibilityChangesAnimated(input_method_container);
-  SetUsesScreenCoordinates(input_method_container);
-
   // TODO(beng): Figure out if we can make this use
   // SystemModalContainerEventFilter instead of stops_event_propagation.
   aura::Window* lock_container = CreateContainer(
       kShellWindowId_LockScreenContainer,
       "LockScreenContainer",
       lock_screen_containers);
-  lock_container->SetLayoutManager(
-      new internal::WorkspaceLayoutManager(lock_container));
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(lock_container);
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kAshDisableLockLayoutManager)) {
+    lock_container->SetLayoutManager(
+            new WorkspaceLayoutManager(lock_container));
+  } else {
+    lock_container->SetLayoutManager(new LockLayoutManager(lock_container));
+  }
   SetUsesScreenCoordinates(lock_container);
   // TODO(beng): stopsevents
 
@@ -927,6 +978,7 @@ void RootWindowController::CreateContainersInRootWindow(
       kShellWindowId_LockSystemModalContainer,
       "LockSystemModalContainer",
       lock_screen_containers);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(lock_modal_container);
   lock_modal_container->SetLayoutManager(
       new SystemModalContainerLayoutManager(lock_modal_container));
   ::wm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
@@ -937,6 +989,7 @@ void RootWindowController::CreateContainersInRootWindow(
       CreateContainer(kShellWindowId_StatusContainer,
                       "StatusContainer",
                       lock_screen_related_containers);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(status_container);
   SetUsesScreenCoordinates(status_container);
   DescendantShouldStayInSameRootWindow(status_container);
 
@@ -945,14 +998,27 @@ void RootWindowController::CreateContainersInRootWindow(
       "SettingBubbleContainer",
       lock_screen_related_containers);
   ::wm::SetChildWindowVisibilityChangesAnimated(settings_bubble_container);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(settings_bubble_container);
   SetUsesScreenCoordinates(settings_bubble_container);
   DescendantShouldStayInSameRootWindow(settings_bubble_container);
 
+  aura::Window* virtual_keyboard_parent_container =
+      CreateContainer(kShellWindowId_VirtualKeyboardParentContainer,
+                      "VirtualKeyboardParentContainer",
+                      lock_screen_related_containers);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(
+      virtual_keyboard_parent_container);
+  virtual_keyboard_parent_container->SetLayoutManager(
+      new VirtualKeyboardContainerLayoutManager(
+          virtual_keyboard_parent_container));
+  SetUsesScreenCoordinates(virtual_keyboard_parent_container);
+
   aura::Window* menu_container = CreateContainer(
       kShellWindowId_MenuContainer,
       "MenuContainer",
       lock_screen_related_containers);
   ::wm::SetChildWindowVisibilityChangesAnimated(menu_container);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(menu_container);
   SetUsesScreenCoordinates(menu_container);
 
   aura::Window* drag_drop_container = CreateContainer(
@@ -960,20 +1026,16 @@ void RootWindowController::CreateContainersInRootWindow(
       "DragImageAndTooltipContainer",
       lock_screen_related_containers);
   ::wm::SetChildWindowVisibilityChangesAnimated(drag_drop_container);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(drag_drop_container);
   SetUsesScreenCoordinates(drag_drop_container);
 
   aura::Window* overlay_container = CreateContainer(
       kShellWindowId_OverlayContainer,
       "OverlayContainer",
       lock_screen_related_containers);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(overlay_container);
   SetUsesScreenCoordinates(overlay_container);
 
-  aura::Window* virtual_keyboard_parent_container = CreateContainer(
-      kShellWindowId_VirtualKeyboardParentContainer,
-      "VirtualKeyboardParentContainer",
-      root_window);
-  SetUsesScreenCoordinates(virtual_keyboard_parent_container);
-
 #if defined(OS_CHROMEOS)
   aura::Window* mouse_cursor_container = CreateContainer(
       kShellWindowId_MouseCursorContainer,
@@ -989,7 +1051,7 @@ void RootWindowController::CreateContainersInRootWindow(
 void RootWindowController::EnableTouchHudProjection() {
   if (touch_hud_projection_)
     return;
-  set_touch_hud_projection(new TouchHudProjection(root_window()));
+  set_touch_hud_projection(new TouchHudProjection(GetRootWindow()));
 }
 
 void RootWindowController::DisableTouchHudProjection() {
@@ -1014,5 +1076,4 @@ RootWindowController* GetRootWindowController(
   return root_window ? GetRootWindowSettings(root_window)->controller : NULL;
 }
 
-}  // namespace internal
 }  // namespace ash