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