summaryrefslogtreecommitdiff
path: root/chromium/ash/root_window_controller.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ash/root_window_controller.cc')
-rw-r--r--chromium/ash/root_window_controller.cc788
1 files changed, 788 insertions, 0 deletions
diff --git a/chromium/ash/root_window_controller.cc b/chromium/ash/root_window_controller.cc
new file mode 100644
index 00000000000..dd237436cff
--- /dev/null
+++ b/chromium/ash/root_window_controller.cc
@@ -0,0 +1,788 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/root_window_controller.h"
+
+#include <vector>
+
+#include "ash/ash_constants.h"
+#include "ash/ash_switches.h"
+#include "ash/desktop_background/desktop_background_widget_controller.h"
+#include "ash/desktop_background/user_wallpaper_delegate.h"
+#include "ash/display/display_manager.h"
+#include "ash/focus_cycler.h"
+#include "ash/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/shell.h"
+#include "ash/shell_delegate.h"
+#include "ash/shell_factory.h"
+#include "ash/shell_window_ids.h"
+#include "ash/system/status_area_widget.h"
+#include "ash/system/tray/system_tray_delegate.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/base_layout_manager.h"
+#include "ash/wm/dock/docked_window_layout_manager.h"
+#include "ash/wm/panels/panel_layout_manager.h"
+#include "ash/wm/panels/panel_window_event_handler.h"
+#include "ash/wm/property_util.h"
+#include "ash/wm/root_window_layout_manager.h"
+#include "ash/wm/screen_dimmer.h"
+#include "ash/wm/stacking_controller.h"
+#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/toplevel_window_event_handler.h"
+#include "ash/wm/window_properties.h"
+#include "ash/wm/window_util.h"
+#include "ash/wm/workspace_controller.h"
+#include "base/command_line.h"
+#include "base/time/time.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/client/tooltip_client.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_delegate.h"
+#include "ui/aura/window_observer.h"
+#include "ui/base/hit_test.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/gfx/screen.h"
+#include "ui/keyboard/keyboard_controller.h"
+#include "ui/keyboard/keyboard_util.h"
+#include "ui/views/controls/menu/menu_runner.h"
+#include "ui/views/corewm/visibility_controller.h"
+#include "ui/views/view_model.h"
+#include "ui/views/view_model_utils.h"
+
+#if defined(OS_CHROMEOS)
+#include "ash/wm/boot_splash_screen_chromeos.h"
+#endif
+
+namespace ash {
+namespace {
+
+#if defined(OS_CHROMEOS)
+// Duration for the animation that hides the boot splash screen, in
+// milliseconds. This should be short enough in relation to
+// wm/window_animation.cc's brightness/grayscale fade animation that the login
+// background image animation isn't hidden by the splash screen animation.
+const int kBootSplashScreenHideDurationMs = 500;
+#endif
+
+// Creates a new window for use as a container.
+aura::Window* CreateContainer(int window_id,
+ const char* name,
+ aura::Window* parent) {
+ aura::Window* container = new aura::Window(NULL);
+ container->set_id(window_id);
+ container->SetName(name);
+ container->Init(ui::LAYER_NOT_DRAWN);
+ parent->AddChild(container);
+ if (window_id != internal::kShellWindowId_UnparentedControlContainer)
+ container->Show();
+ return container;
+}
+
+// Reparents |window| to |new_parent|.
+void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
+ // Update the restore bounds to make it relative to the display.
+ gfx::Rect restore_bounds(GetRestoreBoundsInParent(window));
+ new_parent->AddChild(window);
+ if (!restore_bounds.IsEmpty())
+ SetRestoreBoundsInParent(window, restore_bounds);
+}
+
+// Reparents the appropriate set of windows from |src| to |dst|.
+void ReparentAllWindows(aura::RootWindow* src, aura::RootWindow* 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,
+ };
+ for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) {
+ int id = kContainerIdsToMove[i];
+ aura::Window* src_container = Shell::GetContainer(src, id);
+ aura::Window* dst_container = Shell::GetContainer(dst, id);
+ while (!src_container->children().empty()) {
+ // Restart iteration from the source container windows each time as they
+ // may change as a result of moving other windows.
+ aura::Window::Windows::const_iterator iter =
+ src_container->children().begin();
+ while (iter != src_container->children().end() &&
+ internal::SystemModalContainerLayoutManager::IsModalBackground(
+ *iter)) {
+ ++iter;
+ }
+ // If the entire window list is modal background windows then stop.
+ if (iter == src_container->children().end())
+ break;
+ ReparentWindow(*iter, dst_container);
+ }
+ }
+}
+
+// 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);
+}
+
+// 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);
+}
+
+// A window delegate which does nothing. Used to create a window that
+// is a event target, but do nothing.
+class EmptyWindowDelegate : public aura::WindowDelegate {
+ public:
+ EmptyWindowDelegate() {}
+ virtual ~EmptyWindowDelegate() {}
+
+ // aura::WindowDelegate overrides:
+ virtual gfx::Size GetMinimumSize() const OVERRIDE {
+ return gfx::Size();
+ }
+ virtual gfx::Size GetMaximumSize() const OVERRIDE {
+ return gfx::Size();
+ }
+ virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) OVERRIDE {
+ }
+ virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
+ return gfx::kNullCursor;
+ }
+ virtual int GetNonClientComponent(
+ const gfx::Point& point) const OVERRIDE {
+ return HTNOWHERE;
+ }
+ virtual bool ShouldDescendIntoChildForEventHandling(
+ aura::Window* child,
+ const gfx::Point& location) OVERRIDE {
+ return false;
+ }
+ virtual bool CanFocus() OVERRIDE {
+ return false;
+ }
+ virtual void OnCaptureLost() OVERRIDE {
+ }
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
+ }
+ virtual void OnDeviceScaleFactorChanged(
+ float device_scale_factor) OVERRIDE {
+ }
+ virtual void OnWindowDestroying() OVERRIDE {}
+ virtual void OnWindowDestroyed() OVERRIDE {
+ delete this;
+ }
+ virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
+ }
+ virtual bool HasHitTestMask() const OVERRIDE {
+ return false;
+ }
+ virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
+ virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE {
+ NOTREACHED();
+ return scoped_refptr<ui::Texture>();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate);
+};
+
+} // namespace
+
+namespace internal {
+
+RootWindowController::RootWindowController(aura::RootWindow* root_window)
+ : root_window_(root_window),
+ root_window_layout_(NULL),
+ docked_layout_manager_(NULL),
+ panel_layout_manager_(NULL),
+ touch_hud_debug_(NULL),
+ touch_hud_projection_(NULL) {
+ SetRootWindowController(root_window, this);
+ screen_dimmer_.reset(new ScreenDimmer(root_window));
+
+ stacking_controller_.reset(new StackingController);
+ aura::client::SetStackingClient(root_window, stacking_controller_.get());
+}
+
+RootWindowController::~RootWindowController() {
+ Shutdown();
+ root_window_.reset();
+}
+
+// static
+RootWindowController* RootWindowController::ForLauncher(aura::Window* window) {
+ return GetRootWindowController(window->GetRootWindow());
+}
+
+// static
+RootWindowController* RootWindowController::ForWindow(
+ const aura::Window* window) {
+ return GetRootWindowController(window->GetRootWindow());
+}
+
+// static
+RootWindowController* RootWindowController::ForActiveRootWindow() {
+ return GetRootWindowController(Shell::GetActiveRootWindow());
+}
+
+void RootWindowController::SetWallpaperController(
+ DesktopBackgroundWidgetController* controller) {
+ wallpaper_controller_.reset(controller);
+}
+
+void RootWindowController::SetAnimatingWallpaperController(
+ AnimatingDesktopController* controller) {
+ if (animating_wallpaper_controller_.get())
+ animating_wallpaper_controller_->StopAnimating();
+ animating_wallpaper_controller_.reset(controller);
+}
+
+void RootWindowController::Shutdown() {
+ Shell::GetInstance()->RemoveShellObserver(this);
+
+ if (animating_wallpaper_controller_.get())
+ animating_wallpaper_controller_->StopAnimating();
+ wallpaper_controller_.reset();
+ animating_wallpaper_controller_.reset();
+
+ CloseChildWindows();
+ if (Shell::GetActiveRootWindow() == root_window_) {
+ Shell::GetInstance()->set_active_root_window(
+ Shell::GetPrimaryRootWindow() == root_window_.get() ?
+ NULL : Shell::GetPrimaryRootWindow());
+ }
+ SetRootWindowController(root_window_.get(), NULL);
+ screen_dimmer_.reset();
+ workspace_controller_.reset();
+ // Forget with the display ID so that display lookup
+ // ends up with invalid display.
+ root_window_->ClearProperty(kDisplayIdKey);
+ // And this root window should no longer process events.
+ root_window_->PrepareForShutdown();
+
+ system_background_.reset();
+}
+
+SystemModalContainerLayoutManager*
+RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
+ aura::Window* container = NULL;
+ if (window) {
+ if (window->parent() &&
+ window->parent()->id() >= kShellWindowId_LockScreenContainer) {
+ container = GetContainer(kShellWindowId_LockSystemModalContainer);
+ } else {
+ container = GetContainer(kShellWindowId_SystemModalContainer);
+ }
+ } else {
+ int modal_window_id = Shell::GetInstance()->session_state_delegate()
+ ->IsUserSessionBlocked() ? kShellWindowId_LockSystemModalContainer :
+ kShellWindowId_SystemModalContainer;
+ container = GetContainer(modal_window_id);
+ }
+ return container ? static_cast<SystemModalContainerLayoutManager*>(
+ container->layout_manager()) : NULL;
+}
+
+aura::Window* RootWindowController::GetContainer(int container_id) {
+ return root_window_->GetChildById(container_id);
+}
+
+const aura::Window* RootWindowController::GetContainer(int container_id) const {
+ return root_window_->GetChildById(container_id);
+}
+
+void RootWindowController::Init(bool first_run_after_boot) {
+ root_window_->SetCursor(ui::kCursorPointer);
+ CreateContainersInRootWindow(root_window_.get());
+ CreateSystemBackground(first_run_after_boot);
+
+ InitLayoutManagers();
+ InitKeyboard();
+ InitTouchHuds();
+
+ if (Shell::GetPrimaryRootWindowController()->
+ GetSystemModalLayoutManager(NULL)->has_modal_background()) {
+ GetSystemModalLayoutManager(NULL)->CreateModalBackground();
+ }
+
+ Shell::GetInstance()->AddShellObserver(this);
+}
+
+void RootWindowController::ShowLauncher() {
+ if (!shelf_->launcher())
+ return;
+ shelf_->launcher()->SetVisible(true);
+ shelf_->status_area_widget()->Show();
+}
+
+void RootWindowController::OnLauncherCreated() {
+ if (panel_layout_manager_)
+ panel_layout_manager_->SetLauncher(shelf_->launcher());
+ if (docked_layout_manager_) {
+ docked_layout_manager_->SetLauncher(shelf_->launcher());
+ if (shelf_->shelf_layout_manager())
+ docked_layout_manager_->AddObserver(shelf_->shelf_layout_manager());
+ }
+}
+
+void RootWindowController::UpdateAfterLoginStatusChange(
+ user::LoginStatus status) {
+ if (status != user::LOGGED_IN_NONE)
+ mouse_event_target_.reset();
+ if (shelf_->status_area_widget())
+ shelf_->status_area_widget()->UpdateAfterLoginStatusChange(status);
+}
+
+void RootWindowController::HandleInitialDesktopBackgroundAnimationStarted() {
+#if defined(OS_CHROMEOS)
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshAnimateFromBootSplashScreen) &&
+ boot_splash_screen_.get()) {
+ // Make the splash screen fade out so it doesn't obscure the desktop
+ // wallpaper's brightness/grayscale animation.
+ boot_splash_screen_->StartHideAnimation(
+ base::TimeDelta::FromMilliseconds(kBootSplashScreenHideDurationMs));
+ }
+#endif
+}
+
+void RootWindowController::OnWallpaperAnimationFinished(views::Widget* widget) {
+ // Make sure the wallpaper is visible.
+ system_background_->SetColor(SK_ColorBLACK);
+#if defined(OS_CHROMEOS)
+ boot_splash_screen_.reset();
+#endif
+
+ Shell::GetInstance()->user_wallpaper_delegate()->
+ OnWallpaperAnimationFinished();
+ // Only removes old component when wallpaper animation finished. If we
+ // remove the old one before the new wallpaper is done fading in there will
+ // be a white flash during the animation.
+ if (animating_wallpaper_controller()) {
+ DesktopBackgroundWidgetController* controller =
+ animating_wallpaper_controller()->GetController(true);
+ // |desktop_widget_| should be the same animating widget we try to move
+ // to |kDesktopController|. Otherwise, we may close |desktop_widget_|
+ // before move it to |kDesktopController|.
+ DCHECK_EQ(controller->widget(), widget);
+ // Release the old controller and close its background widget.
+ SetWallpaperController(controller);
+ }
+}
+
+void RootWindowController::CloseChildWindows() {
+ mouse_event_target_.reset();
+
+ if (!shelf_.get())
+ return;
+ // panel_layout_manager_ needs to be shut down before windows are destroyed.
+ if (panel_layout_manager_) {
+ panel_layout_manager_->Shutdown();
+ panel_layout_manager_ = NULL;
+ }
+ // docked_layout_manager_ needs to be shut down before windows are destroyed.
+ if (docked_layout_manager_) {
+ if (shelf_->shelf_layout_manager())
+ docked_layout_manager_->RemoveObserver(shelf_->shelf_layout_manager());
+ docked_layout_manager_->Shutdown();
+ docked_layout_manager_ = NULL;
+ }
+
+ // TODO(harrym): Remove when Status Area Widget is a child view.
+ shelf_->ShutdownStatusAreaWidget();
+
+ if (shelf_->shelf_layout_manager())
+ shelf_->shelf_layout_manager()->PrepareForShutdown();
+
+ // Close background widget first as it depends on tooltip.
+ wallpaper_controller_.reset();
+ animating_wallpaper_controller_.reset();
+
+ workspace_controller_.reset();
+ aura::client::SetTooltipClient(root_window_.get(), NULL);
+
+ while (!root_window_->children().empty()) {
+ aura::Window* child = root_window_->children()[0];
+ delete child;
+ }
+
+ shelf_.reset(NULL);
+}
+
+void RootWindowController::MoveWindowsTo(aura::RootWindow* dst) {
+ // Forget the shelf early so that shelf don't update itself using wrong
+ // display info.
+ workspace_controller_->SetShelf(NULL);
+ ReparentAllWindows(root_window_.get(), dst);
+}
+
+ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
+ return shelf_->shelf_layout_manager();
+}
+
+SystemTray* RootWindowController::GetSystemTray() {
+ // We assume in throughout the code that this will not return NULL. If code
+ // triggers this for valid reasons, it should test status_area_widget first.
+ CHECK(shelf_->status_area_widget());
+ return shelf_->status_area_widget()->system_tray();
+}
+
+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()));
+ if (!menu_model)
+ return;
+
+ // Background controller may not be set yet if user clicked on status are
+ // before initial animation completion. See crbug.com/222218
+ if (!wallpaper_controller_.get())
+ return;
+
+ views::MenuRunner menu_runner(menu_model.get());
+ 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) {
+ return;
+ }
+
+ Shell::GetInstance()->UpdateShelfVisibility();
+}
+
+void RootWindowController::UpdateShelfVisibility() {
+ shelf_->shelf_layout_manager()->UpdateVisibilityState();
+}
+
+const aura::Window* RootWindowController::GetFullscreenWindow() const {
+ const aura::Window* container = GetContainer(kShellWindowId_DefaultContainer);
+ for (size_t i = 0; i < container->children().size(); ++i) {
+ aura::Window* child = container->children()[i];
+ if (wm::IsWindowFullscreen(child))
+ return child;
+ }
+ return NULL;
+}
+
+void RootWindowController::InitKeyboard() {
+ if (keyboard::IsKeyboardEnabled()) {
+ aura::Window* parent = root_window();
+
+ keyboard::KeyboardControllerProxy* proxy =
+ Shell::GetInstance()->delegate()->CreateKeyboardControllerProxy();
+ keyboard_controller_.reset(
+ new keyboard::KeyboardController(proxy));
+
+ keyboard_controller_->AddObserver(shelf()->shelf_layout_manager());
+ keyboard_controller_->AddObserver(panel_layout_manager_);
+
+ aura::Window* keyboard_container =
+ keyboard_controller_->GetContainerWindow();
+ keyboard_container->set_id(kShellWindowId_VirtualKeyboardContainer);
+ parent->AddChild(keyboard_container);
+ keyboard_container->SetBounds(parent->bounds());
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// RootWindowController, private:
+
+void RootWindowController::InitLayoutManagers() {
+ root_window_layout_ =
+ new RootWindowLayoutManager(root_window_.get());
+ root_window_->SetLayoutManager(root_window_layout_);
+
+ aura::Window* default_container =
+ GetContainer(kShellWindowId_DefaultContainer);
+ // Workspace manager has its own layout managers.
+ workspace_controller_.reset(
+ new WorkspaceController(default_container));
+
+ aura::Window* always_on_top_container =
+ GetContainer(kShellWindowId_AlwaysOnTopContainer);
+ always_on_top_container->SetLayoutManager(
+ new BaseLayoutManager(
+ always_on_top_container->GetRootWindow()));
+ always_on_top_controller_.reset(new internal::AlwaysOnTopController);
+ always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container);
+
+ DCHECK(!shelf_.get());
+ aura::Window* shelf_container =
+ GetContainer(internal::kShellWindowId_ShelfContainer);
+ // TODO(harrym): Remove when status area is view.
+ aura::Window* status_container =
+ GetContainer(internal::kShellWindowId_StatusContainer);
+ shelf_.reset(new ShelfWidget(
+ shelf_container, status_container, workspace_controller()));
+
+ if (!Shell::GetInstance()->session_state_delegate()->
+ IsActiveUserSessionStarted()) {
+ // This window exists only to be a event target on login screen.
+ // It does not have to handle events, nor be visible.
+ mouse_event_target_.reset(new aura::Window(new EmptyWindowDelegate));
+ mouse_event_target_->Init(ui::LAYER_NOT_DRAWN);
+
+ aura::Window* lock_background_container =
+ GetContainer(internal::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);
+ docked_layout_manager_ =
+ new internal::DockedWindowLayoutManager(docked_container);
+ docked_container_handler_.reset(
+ new ToplevelWindowEventHandler(docked_container));
+ docked_container->SetLayoutManager(docked_layout_manager_);
+
+ // Create Panel layout manager
+ aura::Window* panel_container = GetContainer(
+ internal::kShellWindowId_PanelContainer);
+ panel_layout_manager_ =
+ new internal::PanelLayoutManager(panel_container);
+ panel_container_handler_.reset(
+ new PanelWindowEventHandler(panel_container));
+ panel_container->SetLayoutManager(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_.get()));
+ if (Shell::GetInstance()->is_touch_hud_projection_enabled())
+ EnableTouchHudProjection();
+}
+
+void RootWindowController::CreateSystemBackground(
+ bool is_first_run_after_boot) {
+ SkColor color = SK_ColorBLACK;
+#if defined(OS_CHROMEOS)
+ if (is_first_run_after_boot)
+ color = kChromeOsBootColor;
+#endif
+ system_background_.reset(
+ new SystemBackgroundController(root_window_.get(), color));
+
+#if defined(OS_CHROMEOS)
+ // Make a copy of the system's boot splash screen so we can composite it
+ // onscreen until the desktop background is ready.
+ if (is_first_run_after_boot &&
+ (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshCopyHostBackgroundAtBoot) ||
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshAnimateFromBootSplashScreen)))
+ boot_splash_screen_.reset(new BootSplashScreen(root_window_.get()));
+#endif
+}
+
+void RootWindowController::CreateContainersInRootWindow(
+ aura::RootWindow* root_window) {
+ // These containers are just used by PowerButtonController to animate groups
+ // of containers simultaneously without messing up the current transformations
+ // on those containers. These are direct children of the root window; all of
+ // the other containers are their children.
+
+ // The desktop background container is not part of the lock animation, so it
+ // is not included in those animate groups.
+ // When screen is locked desktop background is moved to lock screen background
+ // container (moved back on unlock). We want to make sure that there's an
+ // opaque layer occluding the non-lock-screen layers.
+ aura::Window* desktop_background_container = CreateContainer(
+ kShellWindowId_DesktopBackgroundContainer,
+ "DesktopBackgroundContainer",
+ root_window);
+ views::corewm::SetChildWindowVisibilityChangesAnimated(
+ desktop_background_container);
+
+ aura::Window* non_lock_screen_containers = CreateContainer(
+ kShellWindowId_NonLockScreenContainersContainer,
+ "NonLockScreenContainersContainer",
+ root_window);
+
+ aura::Window* lock_background_containers = CreateContainer(
+ kShellWindowId_LockScreenBackgroundContainer,
+ "LockScreenBackgroundContainer",
+ root_window);
+ views::corewm::SetChildWindowVisibilityChangesAnimated(
+ lock_background_containers);
+
+ aura::Window* lock_screen_containers = CreateContainer(
+ kShellWindowId_LockScreenContainersContainer,
+ "LockScreenContainersContainer",
+ root_window);
+ aura::Window* lock_screen_related_containers = CreateContainer(
+ kShellWindowId_LockScreenRelatedContainersContainer,
+ "LockScreenRelatedContainersContainer",
+ root_window);
+
+ CreateContainer(kShellWindowId_UnparentedControlContainer,
+ "UnparentedControlContainer",
+ non_lock_screen_containers);
+
+ aura::Window* default_container = CreateContainer(
+ kShellWindowId_DefaultContainer,
+ "DefaultContainer",
+ non_lock_screen_containers);
+ views::corewm::SetChildWindowVisibilityChangesAnimated(default_container);
+ SetUsesScreenCoordinates(default_container);
+
+ aura::Window* always_on_top_container = CreateContainer(
+ kShellWindowId_AlwaysOnTopContainer,
+ "AlwaysOnTopContainer",
+ non_lock_screen_containers);
+ always_on_top_container_handler_.reset(
+ new ToplevelWindowEventHandler(always_on_top_container));
+ views::corewm::SetChildWindowVisibilityChangesAnimated(
+ always_on_top_container);
+ SetUsesScreenCoordinates(always_on_top_container);
+
+ aura::Window* docked_container = CreateContainer(
+ kShellWindowId_DockedContainer,
+ "DockedContainer",
+ non_lock_screen_containers);
+ SetUsesScreenCoordinates(docked_container);
+
+ aura::Window* panel_container = CreateContainer(
+ kShellWindowId_PanelContainer,
+ "PanelContainer",
+ non_lock_screen_containers);
+ SetUsesScreenCoordinates(panel_container);
+
+ aura::Window* shelf_container =
+ CreateContainer(kShellWindowId_ShelfContainer,
+ "ShelfContainer",
+ non_lock_screen_containers);
+ SetUsesScreenCoordinates(shelf_container);
+ DescendantShouldStayInSameRootWindow(shelf_container);
+
+ aura::Window* app_list_container =
+ CreateContainer(kShellWindowId_AppListContainer,
+ "AppListContainer",
+ non_lock_screen_containers);
+ SetUsesScreenCoordinates(app_list_container);
+
+ aura::Window* modal_container = CreateContainer(
+ kShellWindowId_SystemModalContainer,
+ "SystemModalContainer",
+ non_lock_screen_containers);
+ modal_container_handler_.reset(
+ new ToplevelWindowEventHandler(modal_container));
+ modal_container->SetLayoutManager(
+ new SystemModalContainerLayoutManager(modal_container));
+ views::corewm::SetChildWindowVisibilityChangesAnimated(modal_container);
+ SetUsesScreenCoordinates(modal_container);
+
+ aura::Window* input_method_container = CreateContainer(
+ kShellWindowId_InputMethodContainer,
+ "InputMethodContainer",
+ non_lock_screen_containers);
+ 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 BaseLayoutManager(root_window));
+ SetUsesScreenCoordinates(lock_container);
+ // TODO(beng): stopsevents
+
+ aura::Window* lock_modal_container = CreateContainer(
+ kShellWindowId_LockSystemModalContainer,
+ "LockSystemModalContainer",
+ lock_screen_containers);
+ lock_modal_container_handler_.reset(
+ new ToplevelWindowEventHandler(lock_modal_container));
+ lock_modal_container->SetLayoutManager(
+ new SystemModalContainerLayoutManager(lock_modal_container));
+ views::corewm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
+ SetUsesScreenCoordinates(lock_modal_container);
+
+ aura::Window* status_container =
+ CreateContainer(kShellWindowId_StatusContainer,
+ "StatusContainer",
+ lock_screen_related_containers);
+ SetUsesScreenCoordinates(status_container);
+ DescendantShouldStayInSameRootWindow(status_container);
+
+ aura::Window* settings_bubble_container = CreateContainer(
+ kShellWindowId_SettingBubbleContainer,
+ "SettingBubbleContainer",
+ lock_screen_related_containers);
+ views::corewm::SetChildWindowVisibilityChangesAnimated(
+ settings_bubble_container);
+ SetUsesScreenCoordinates(settings_bubble_container);
+ DescendantShouldStayInSameRootWindow(settings_bubble_container);
+
+ aura::Window* menu_container = CreateContainer(
+ kShellWindowId_MenuContainer,
+ "MenuContainer",
+ lock_screen_related_containers);
+ views::corewm::SetChildWindowVisibilityChangesAnimated(menu_container);
+ SetUsesScreenCoordinates(menu_container);
+
+ aura::Window* drag_drop_container = CreateContainer(
+ kShellWindowId_DragImageAndTooltipContainer,
+ "DragImageAndTooltipContainer",
+ lock_screen_related_containers);
+ views::corewm::SetChildWindowVisibilityChangesAnimated(drag_drop_container);
+ SetUsesScreenCoordinates(drag_drop_container);
+
+ aura::Window* overlay_container = CreateContainer(
+ kShellWindowId_OverlayContainer,
+ "OverlayContainer",
+ lock_screen_related_containers);
+ SetUsesScreenCoordinates(overlay_container);
+
+ CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
+ "PowerButtonAnimationContainer", root_window) ;
+}
+
+void RootWindowController::EnableTouchHudProjection() {
+ if (touch_hud_projection_)
+ return;
+ set_touch_hud_projection(new TouchHudProjection(root_window_.get()));
+}
+
+void RootWindowController::DisableTouchHudProjection() {
+ if (!touch_hud_projection_)
+ return;
+ touch_hud_projection_->Remove();
+}
+
+void RootWindowController::OnLoginStateChanged(user::LoginStatus status) {
+ shelf_->shelf_layout_manager()->UpdateVisibilityState();
+}
+
+void RootWindowController::OnTouchHudProjectionToggled(bool enabled) {
+ if (enabled)
+ EnableTouchHudProjection();
+ else
+ DisableTouchHudProjection();
+}
+
+} // namespace internal
+} // namespace ash