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