• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ash/root_window_controller.h"
6 
7 #include <queue>
8 #include <vector>
9 
10 #include "ash/ash_constants.h"
11 #include "ash/ash_switches.h"
12 #include "ash/desktop_background/desktop_background_controller.h"
13 #include "ash/desktop_background/desktop_background_widget_controller.h"
14 #include "ash/desktop_background/user_wallpaper_delegate.h"
15 #include "ash/display/display_manager.h"
16 #include "ash/focus_cycler.h"
17 #include "ash/high_contrast/high_contrast_controller.h"
18 #include "ash/root_window_settings.h"
19 #include "ash/session_state_delegate.h"
20 #include "ash/shelf/shelf_layout_manager.h"
21 #include "ash/shelf/shelf_types.h"
22 #include "ash/shelf/shelf_widget.h"
23 #include "ash/shell.h"
24 #include "ash/shell_delegate.h"
25 #include "ash/shell_factory.h"
26 #include "ash/shell_window_ids.h"
27 #include "ash/system/status_area_widget.h"
28 #include "ash/system/tray/system_tray_delegate.h"
29 #include "ash/touch/touch_hud_debug.h"
30 #include "ash/touch/touch_hud_projection.h"
31 #include "ash/touch/touch_observer_hud.h"
32 #include "ash/wm/always_on_top_controller.h"
33 #include "ash/wm/base_layout_manager.h"
34 #include "ash/wm/dock/docked_window_layout_manager.h"
35 #include "ash/wm/panels/panel_layout_manager.h"
36 #include "ash/wm/panels/panel_window_event_handler.h"
37 #include "ash/wm/root_window_layout_manager.h"
38 #include "ash/wm/screen_dimmer.h"
39 #include "ash/wm/solo_window_tracker.h"
40 #include "ash/wm/stacking_controller.h"
41 #include "ash/wm/status_area_layout_manager.h"
42 #include "ash/wm/system_background_controller.h"
43 #include "ash/wm/system_modal_container_layout_manager.h"
44 #include "ash/wm/toplevel_window_event_handler.h"
45 #include "ash/wm/window_properties.h"
46 #include "ash/wm/window_state.h"
47 #include "ash/wm/window_util.h"
48 #include "ash/wm/workspace_controller.h"
49 #include "base/command_line.h"
50 #include "base/time/time.h"
51 #include "ui/aura/client/aura_constants.h"
52 #include "ui/aura/client/drag_drop_client.h"
53 #include "ui/aura/client/tooltip_client.h"
54 #include "ui/aura/root_window.h"
55 #include "ui/aura/window.h"
56 #include "ui/aura/window_delegate.h"
57 #include "ui/aura/window_observer.h"
58 #include "ui/aura/window_tracker.h"
59 #include "ui/base/hit_test.h"
60 #include "ui/base/models/menu_model.h"
61 #include "ui/gfx/display.h"
62 #include "ui/gfx/screen.h"
63 #include "ui/keyboard/keyboard_controller.h"
64 #include "ui/keyboard/keyboard_util.h"
65 #include "ui/views/controls/menu/menu_runner.h"
66 #include "ui/views/corewm/capture_controller.h"
67 #include "ui/views/corewm/visibility_controller.h"
68 #include "ui/views/view_model.h"
69 #include "ui/views/view_model_utils.h"
70 
71 #if defined(OS_CHROMEOS)
72 #include "ash/wm/boot_splash_screen_chromeos.h"
73 #endif
74 
75 namespace ash {
76 namespace {
77 
78 #if defined(OS_CHROMEOS)
79 // Duration for the animation that hides the boot splash screen, in
80 // milliseconds.  This should be short enough in relation to
81 // wm/window_animation.cc's brightness/grayscale fade animation that the login
82 // background image animation isn't hidden by the splash screen animation.
83 const int kBootSplashScreenHideDurationMs = 500;
84 #endif
85 
86 // Creates a new window for use as a container.
CreateContainer(int window_id,const char * name,aura::Window * parent)87 aura::Window* CreateContainer(int window_id,
88                               const char* name,
89                               aura::Window* parent) {
90   aura::Window* container = new aura::Window(NULL);
91   container->set_id(window_id);
92   container->SetName(name);
93   container->Init(ui::LAYER_NOT_DRAWN);
94   parent->AddChild(container);
95   if (window_id != internal::kShellWindowId_UnparentedControlContainer)
96     container->Show();
97   return container;
98 }
99 
100 // Reparents |window| to |new_parent|.
ReparentWindow(aura::Window * window,aura::Window * new_parent)101 void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
102   // Update the restore bounds to make it relative to the display.
103   wm::WindowState* state = wm::GetWindowState(window);
104   gfx::Rect restore_bounds;
105   bool has_restore_bounds = state->HasRestoreBounds();
106   if (has_restore_bounds)
107     restore_bounds = state->GetRestoreBoundsInParent();
108   new_parent->AddChild(window);
109   if (has_restore_bounds)
110     state->SetRestoreBoundsInParent(restore_bounds);
111 }
112 
113 // Reparents the appropriate set of windows from |src| to |dst|.
ReparentAllWindows(aura::Window * src,aura::Window * dst)114 void ReparentAllWindows(aura::Window* src, aura::Window* dst) {
115   // Set of windows to move.
116   const int kContainerIdsToMove[] = {
117     internal::kShellWindowId_DefaultContainer,
118     internal::kShellWindowId_DockedContainer,
119     internal::kShellWindowId_PanelContainer,
120     internal::kShellWindowId_AlwaysOnTopContainer,
121     internal::kShellWindowId_SystemModalContainer,
122     internal::kShellWindowId_LockSystemModalContainer,
123     internal::kShellWindowId_InputMethodContainer,
124     internal::kShellWindowId_UnparentedControlContainer,
125   };
126   for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) {
127     int id = kContainerIdsToMove[i];
128     aura::Window* src_container = Shell::GetContainer(src, id);
129     aura::Window* dst_container = Shell::GetContainer(dst, id);
130     while (!src_container->children().empty()) {
131       // Restart iteration from the source container windows each time as they
132       // may change as a result of moving other windows.
133       aura::Window::Windows::const_iterator iter =
134           src_container->children().begin();
135       while (iter != src_container->children().end() &&
136              internal::SystemModalContainerLayoutManager::IsModalBackground(
137                 *iter)) {
138         ++iter;
139       }
140       // If the entire window list is modal background windows then stop.
141       if (iter == src_container->children().end())
142         break;
143       ReparentWindow(*iter, dst_container);
144     }
145   }
146 }
147 
148 // Mark the container window so that a widget added to this container will
149 // use the virtual screeen coordinates instead of parent.
SetUsesScreenCoordinates(aura::Window * container)150 void SetUsesScreenCoordinates(aura::Window* container) {
151   container->SetProperty(internal::kUsesScreenCoordinatesKey, true);
152 }
153 
154 // Mark the container window so that a widget added to this container will
155 // say in the same root window regardless of the bounds specified.
DescendantShouldStayInSameRootWindow(aura::Window * container)156 void DescendantShouldStayInSameRootWindow(aura::Window* container) {
157   container->SetProperty(internal::kStayInSameRootWindowKey, true);
158 }
159 
160 // A window delegate which does nothing. Used to create a window that
161 // is a event target, but do nothing.
162 class EmptyWindowDelegate : public aura::WindowDelegate {
163  public:
EmptyWindowDelegate()164   EmptyWindowDelegate() {}
~EmptyWindowDelegate()165   virtual ~EmptyWindowDelegate() {}
166 
167   // aura::WindowDelegate overrides:
GetMinimumSize() const168   virtual gfx::Size GetMinimumSize() const OVERRIDE {
169     return gfx::Size();
170   }
GetMaximumSize() const171   virtual gfx::Size GetMaximumSize() const OVERRIDE {
172     return gfx::Size();
173   }
OnBoundsChanged(const gfx::Rect & old_bounds,const gfx::Rect & new_bounds)174   virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
175                                const gfx::Rect& new_bounds) OVERRIDE {
176   }
GetCursor(const gfx::Point & point)177   virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
178     return gfx::kNullCursor;
179   }
GetNonClientComponent(const gfx::Point & point) const180   virtual int GetNonClientComponent(
181       const gfx::Point& point) const OVERRIDE {
182     return HTNOWHERE;
183   }
ShouldDescendIntoChildForEventHandling(aura::Window * child,const gfx::Point & location)184   virtual bool ShouldDescendIntoChildForEventHandling(
185       aura::Window* child,
186       const gfx::Point& location) OVERRIDE {
187     return false;
188   }
CanFocus()189   virtual bool CanFocus() OVERRIDE {
190     return false;
191   }
OnCaptureLost()192   virtual void OnCaptureLost() OVERRIDE {
193   }
OnPaint(gfx::Canvas * canvas)194   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
195   }
OnDeviceScaleFactorChanged(float device_scale_factor)196   virtual void OnDeviceScaleFactorChanged(
197       float device_scale_factor) OVERRIDE {
198   }
OnWindowDestroying()199   virtual void OnWindowDestroying() OVERRIDE {}
OnWindowDestroyed()200   virtual void OnWindowDestroyed() OVERRIDE {
201     delete this;
202   }
OnWindowTargetVisibilityChanged(bool visible)203   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
204   }
HasHitTestMask() const205   virtual bool HasHitTestMask() const OVERRIDE {
206     return false;
207   }
GetHitTestMask(gfx::Path * mask) const208   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
DidRecreateLayer(ui::Layer * old_layer,ui::Layer * new_layer)209   virtual void DidRecreateLayer(ui::Layer* old_layer,
210                                 ui::Layer* new_layer) OVERRIDE {}
211 
212  private:
213   DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate);
214 };
215 
216 }  // namespace
217 
218 namespace internal {
219 
CreateForPrimaryDisplay(aura::RootWindow * root)220 void RootWindowController::CreateForPrimaryDisplay(
221     aura::RootWindow* root) {
222   RootWindowController* controller = new RootWindowController(root);
223   controller->Init(RootWindowController::PRIMARY,
224                    Shell::GetInstance()->delegate()->IsFirstRunAfterBoot());
225 }
226 
CreateForSecondaryDisplay(aura::RootWindow * root)227 void RootWindowController::CreateForSecondaryDisplay(aura::RootWindow * root) {
228   RootWindowController* controller = new RootWindowController(root);
229   controller->Init(RootWindowController::SECONDARY, false /* first run */);
230 }
231 
CreateForVirtualKeyboardDisplay(aura::RootWindow * root)232 void RootWindowController::CreateForVirtualKeyboardDisplay(
233     aura::RootWindow * root) {
234   RootWindowController* controller = new RootWindowController(root);
235   controller->Init(RootWindowController::VIRTUAL_KEYBOARD,
236                    false /* first run */);
237 }
238 
239 // static
ForLauncher(aura::Window * window)240 RootWindowController* RootWindowController::ForLauncher(aura::Window* window) {
241   return GetRootWindowController(window->GetRootWindow());
242 }
243 
244 // static
ForWindow(const aura::Window * window)245 RootWindowController* RootWindowController::ForWindow(
246     const aura::Window* window) {
247   return GetRootWindowController(window->GetRootWindow());
248 }
249 
250 // static
ForTargetRootWindow()251 RootWindowController* RootWindowController::ForTargetRootWindow() {
252   return internal::GetRootWindowController(Shell::GetTargetRootWindow());
253 }
254 
255 // static
GetContainerForWindow(aura::Window * window)256 aura::Window* RootWindowController::GetContainerForWindow(
257     aura::Window* window) {
258   aura::Window* container = window->parent();
259   while (container && container->type() != aura::client::WINDOW_TYPE_UNKNOWN)
260     container = container->parent();
261   return container;
262 }
263 
~RootWindowController()264 RootWindowController::~RootWindowController() {
265   Shutdown();
266   root_window_.reset();
267   // The CaptureClient needs to be around for as long as the RootWindow is
268   // valid.
269   capture_client_.reset();
270 }
271 
SetWallpaperController(DesktopBackgroundWidgetController * controller)272 void RootWindowController::SetWallpaperController(
273     DesktopBackgroundWidgetController* controller) {
274   wallpaper_controller_.reset(controller);
275 }
276 
SetAnimatingWallpaperController(AnimatingDesktopController * controller)277 void RootWindowController::SetAnimatingWallpaperController(
278     AnimatingDesktopController* controller) {
279   if (animating_wallpaper_controller_.get())
280     animating_wallpaper_controller_->StopAnimating();
281   animating_wallpaper_controller_.reset(controller);
282 }
283 
Shutdown()284 void RootWindowController::Shutdown() {
285   Shell::GetInstance()->RemoveShellObserver(this);
286 
287   if (animating_wallpaper_controller_.get())
288     animating_wallpaper_controller_->StopAnimating();
289   wallpaper_controller_.reset();
290   animating_wallpaper_controller_.reset();
291 
292   // Change the target root window before closing child windows. If any child
293   // being removed triggers a relayout of the shelf it will try to build a
294   // window list adding windows from the target root window's containers which
295   // may have already gone away.
296   if (Shell::GetTargetRootWindow() == root_window()) {
297     Shell::GetInstance()->set_target_root_window(
298         Shell::GetPrimaryRootWindow() == root_window() ?
299         NULL : Shell::GetPrimaryRootWindow());
300   }
301 
302   CloseChildWindows();
303   GetRootWindowSettings(root_window())->controller = NULL;
304   screen_dimmer_.reset();
305   workspace_controller_.reset();
306   // Forget with the display ID so that display lookup
307   // ends up with invalid display.
308   internal::GetRootWindowSettings(root_window())->display_id =
309       gfx::Display::kInvalidDisplayID;
310   // And this root window should no longer process events.
311   root_window_->PrepareForShutdown();
312 
313   system_background_.reset();
314 }
315 
316 SystemModalContainerLayoutManager*
GetSystemModalLayoutManager(aura::Window * window)317 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
318   aura::Window* modal_container = NULL;
319   if (window) {
320     aura::Window* window_container = GetContainerForWindow(window);
321     if (window_container &&
322         window_container->id() >= kShellWindowId_LockScreenContainer) {
323       modal_container = GetContainer(kShellWindowId_LockSystemModalContainer);
324     } else {
325       modal_container = GetContainer(kShellWindowId_SystemModalContainer);
326     }
327   } else {
328     int modal_window_id = Shell::GetInstance()->session_state_delegate()
329         ->IsUserSessionBlocked() ? kShellWindowId_LockSystemModalContainer :
330                                    kShellWindowId_SystemModalContainer;
331     modal_container = GetContainer(modal_window_id);
332   }
333   return modal_container ? static_cast<SystemModalContainerLayoutManager*>(
334       modal_container->layout_manager()) : NULL;
335 }
336 
GetContainer(int container_id)337 aura::Window* RootWindowController::GetContainer(int container_id) {
338   return root_window()->GetChildById(container_id);
339 }
340 
GetContainer(int container_id) const341 const aura::Window* RootWindowController::GetContainer(int container_id) const {
342   return root_window_->window()->GetChildById(container_id);
343 }
344 
ShowLauncher()345 void RootWindowController::ShowLauncher() {
346   if (!shelf_->launcher())
347     return;
348   shelf_->launcher()->SetVisible(true);
349   shelf_->status_area_widget()->Show();
350 }
351 
OnLauncherCreated()352 void 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 
UpdateAfterLoginStatusChange(user::LoginStatus status)362 void 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 
HandleInitialDesktopBackgroundAnimationStarted()370 void 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 
OnWallpaperAnimationFinished(views::Widget * widget)383 void 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 
CloseChildWindows()407 void RootWindowController::CloseChildWindows() {
408   mouse_event_target_.reset();
409 
410   // |solo_window_tracker_| must be shut down before windows are destroyed.
411   if (solo_window_tracker_) {
412     if (docked_layout_manager_)
413       docked_layout_manager_->RemoveObserver(solo_window_tracker_.get());
414     solo_window_tracker_.reset();
415   }
416 
417   // Deactivate keyboard container before closing child windows and shutting
418   // down associated layout managers.
419   DeactivateKeyboard(Shell::GetInstance()->keyboard_controller());
420 
421   // panel_layout_manager_ needs to be shut down before windows are destroyed.
422   if (panel_layout_manager_) {
423     panel_layout_manager_->Shutdown();
424     panel_layout_manager_ = NULL;
425   }
426   // docked_layout_manager_ needs to be shut down before windows are destroyed.
427   if (docked_layout_manager_) {
428     if (shelf_ && shelf_->shelf_layout_manager())
429       docked_layout_manager_->RemoveObserver(shelf_->shelf_layout_manager());
430     docked_layout_manager_->Shutdown();
431     docked_layout_manager_ = NULL;
432   }
433 
434   aura::client::SetDragDropClient(root_window(), NULL);
435 
436   // TODO(harrym): Remove when Status Area Widget is a child view.
437   if (shelf_) {
438     shelf_->ShutdownStatusAreaWidget();
439 
440     if (shelf_->shelf_layout_manager())
441       shelf_->shelf_layout_manager()->PrepareForShutdown();
442   }
443 
444   // Close background widget first as it depends on tooltip.
445   wallpaper_controller_.reset();
446   animating_wallpaper_controller_.reset();
447 
448   workspace_controller_.reset();
449   aura::client::SetTooltipClient(root_window(), NULL);
450 
451   // Explicitly destroy top level windows. We do this as during part of
452   // destruction such windows may query the RootWindow for state.
453   std::queue<aura::Window*> non_toplevel_windows;
454   non_toplevel_windows.push(root_window());
455   while (!non_toplevel_windows.empty()) {
456     aura::Window* non_toplevel_window = non_toplevel_windows.front();
457     non_toplevel_windows.pop();
458     aura::WindowTracker toplevel_windows;
459     for (size_t i = 0; i < non_toplevel_window->children().size(); ++i) {
460       aura::Window* child = non_toplevel_window->children()[i];
461       if (!child->owned_by_parent())
462         continue;
463       if (child->delegate())
464         toplevel_windows.Add(child);
465       else
466         non_toplevel_windows.push(child);
467     }
468     while (!toplevel_windows.windows().empty())
469       delete *toplevel_windows.windows().begin();
470   }
471   // And then remove the containers.
472   while (!root_window()->children().empty()) {
473     aura::Window* window = root_window()->children()[0];
474     if (window->owned_by_parent()) {
475       delete window;
476     } else {
477       root_window()->RemoveChild(window);
478     }
479   }
480 
481   shelf_.reset();
482 }
483 
MoveWindowsTo(aura::Window * dst)484 void RootWindowController::MoveWindowsTo(aura::Window* dst) {
485   // Forget the shelf early so that shelf don't update itself using wrong
486   // display info.
487   workspace_controller_->SetShelf(NULL);
488   ReparentAllWindows(root_window(), dst);
489 }
490 
GetShelfLayoutManager()491 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
492   return shelf_->shelf_layout_manager();
493 }
494 
GetSystemTray()495 SystemTray* RootWindowController::GetSystemTray() {
496   // We assume in throughout the code that this will not return NULL. If code
497   // triggers this for valid reasons, it should test status_area_widget first.
498   CHECK(shelf_->status_area_widget());
499   return shelf_->status_area_widget()->system_tray();
500 }
501 
ShowContextMenu(const gfx::Point & location_in_screen,ui::MenuSourceType source_type)502 void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen,
503                                            ui::MenuSourceType source_type) {
504   DCHECK(Shell::GetInstance()->delegate());
505   scoped_ptr<ui::MenuModel> menu_model(
506       Shell::GetInstance()->delegate()->CreateContextMenu(root_window()));
507   if (!menu_model)
508     return;
509 
510   // Background controller may not be set yet if user clicked on status are
511   // before initial animation completion. See crbug.com/222218
512   if (!wallpaper_controller_.get())
513     return;
514 
515   views::MenuRunner menu_runner(menu_model.get());
516   if (menu_runner.RunMenuAt(wallpaper_controller_->widget(),
517           NULL, gfx::Rect(location_in_screen, gfx::Size()),
518           views::MenuItemView::TOPLEFT, source_type,
519           views::MenuRunner::CONTEXT_MENU) ==
520       views::MenuRunner::MENU_DELETED) {
521     return;
522   }
523 
524   Shell::GetInstance()->UpdateShelfVisibility();
525 }
526 
UpdateShelfVisibility()527 void RootWindowController::UpdateShelfVisibility() {
528   shelf_->shelf_layout_manager()->UpdateVisibilityState();
529 }
530 
GetWindowForFullscreenMode() const531 const aura::Window* RootWindowController::GetWindowForFullscreenMode() const {
532   const aura::Window::Windows& windows =
533       GetContainer(kShellWindowId_DefaultContainer)->children();
534   const aura::Window* topmost_window = NULL;
535   for (aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
536        iter != windows.rend(); ++iter) {
537     if (((*iter)->type() == aura::client::WINDOW_TYPE_NORMAL ||
538          (*iter)->type() == aura::client::WINDOW_TYPE_PANEL) &&
539         (*iter)->layer()->GetTargetVisibility()) {
540       topmost_window = *iter;
541       break;
542     }
543   }
544   while (topmost_window) {
545     if (wm::GetWindowState(topmost_window)->IsFullscreen())
546       return topmost_window;
547     topmost_window = topmost_window->transient_parent();
548   }
549   return NULL;
550 }
551 
ActivateKeyboard(keyboard::KeyboardController * keyboard_controller)552 void RootWindowController::ActivateKeyboard(
553     keyboard::KeyboardController* keyboard_controller) {
554   if (!keyboard::IsKeyboardEnabled() ||
555       GetContainer(kShellWindowId_VirtualKeyboardContainer)) {
556     return;
557   }
558   DCHECK(keyboard_controller);
559   if (!keyboard::IsKeyboardUsabilityExperimentEnabled()) {
560     keyboard_controller->AddObserver(shelf()->shelf_layout_manager());
561     keyboard_controller->AddObserver(panel_layout_manager_);
562     keyboard_controller->AddObserver(docked_layout_manager_);
563   }
564   aura::Window* parent = root_window();
565   aura::Window* keyboard_container =
566       keyboard_controller->GetContainerWindow();
567   keyboard_container->set_id(kShellWindowId_VirtualKeyboardContainer);
568   parent->AddChild(keyboard_container);
569   // TODO(oshima): Bounds of keyboard container should be handled by
570   // RootWindowLayoutManager. Remove this after fixed RootWindowLayoutManager.
571   keyboard_container->SetBounds(parent->bounds());
572 }
573 
DeactivateKeyboard(keyboard::KeyboardController * keyboard_controller)574 void RootWindowController::DeactivateKeyboard(
575     keyboard::KeyboardController* keyboard_controller) {
576   if (!keyboard::IsKeyboardEnabled())
577     return;
578 
579   DCHECK(keyboard_controller);
580   aura::Window* keyboard_container =
581       keyboard_controller->GetContainerWindow();
582   if (keyboard_container->GetRootWindow() == root_window()) {
583     root_window()->RemoveChild(keyboard_container);
584     if (!keyboard::IsKeyboardUsabilityExperimentEnabled()) {
585       keyboard_controller->RemoveObserver(shelf()->shelf_layout_manager());
586       keyboard_controller->RemoveObserver(panel_layout_manager_);
587       keyboard_controller->RemoveObserver(docked_layout_manager_);
588     }
589   }
590 }
591 
592 ////////////////////////////////////////////////////////////////////////////////
593 // RootWindowController, private:
594 
RootWindowController(aura::RootWindow * root_window)595 RootWindowController::RootWindowController(aura::RootWindow* root_window)
596     : root_window_(root_window),
597       root_window_layout_(NULL),
598       docked_layout_manager_(NULL),
599       panel_layout_manager_(NULL),
600       touch_hud_debug_(NULL),
601       touch_hud_projection_(NULL) {
602   GetRootWindowSettings(root_window_->window())->controller = this;
603   screen_dimmer_.reset(new ScreenDimmer(root_window_->window()));
604 
605   stacking_controller_.reset(new StackingController);
606   aura::client::SetWindowTreeClient(root_window_->window(),
607                                     stacking_controller_.get());
608   capture_client_.reset(
609       new views::corewm::ScopedCaptureClient(root_window_->window()));
610 }
611 
Init(RootWindowType root_window_type,bool first_run_after_boot)612 void RootWindowController::Init(RootWindowType root_window_type,
613                                 bool first_run_after_boot) {
614   Shell* shell = Shell::GetInstance();
615   shell->InitRootWindow(root_window());
616 
617   root_window_->SetCursor(ui::kCursorPointer);
618   CreateContainersInRootWindow(root_window_->window());
619 
620   if (root_window_type == VIRTUAL_KEYBOARD) {
621     shell->InitKeyboard();
622     return;
623   }
624 
625   CreateSystemBackground(first_run_after_boot);
626 
627   InitLayoutManagers();
628   InitTouchHuds();
629 
630   if (Shell::GetPrimaryRootWindowController()->
631       GetSystemModalLayoutManager(NULL)->has_modal_background()) {
632     GetSystemModalLayoutManager(NULL)->CreateModalBackground();
633   }
634 
635   shell->AddShellObserver(this);
636 
637   if (root_window_type == PRIMARY) {
638     root_window_layout()->OnWindowResized();
639     if (!keyboard::IsKeyboardUsabilityExperimentEnabled())
640       shell->InitKeyboard();
641   } else {
642     root_window_layout()->OnWindowResized();
643     shell->desktop_background_controller()->OnRootWindowAdded(root_window());
644     shell->high_contrast_controller()->OnRootWindowAdded(
645         root_window_->window());
646     root_window_->host()->Show();
647 
648     // Create a launcher if a user is already logged in.
649     if (shell->session_state_delegate()->NumberOfLoggedInUsers())
650       shelf()->CreateLauncher();
651   }
652 
653   solo_window_tracker_.reset(new SoloWindowTracker(root_window_.get()));
654   if (docked_layout_manager_)
655     docked_layout_manager_->AddObserver(solo_window_tracker_.get());
656 }
657 
InitLayoutManagers()658 void RootWindowController::InitLayoutManagers() {
659   root_window_layout_ = new RootWindowLayoutManager(root_window());
660   root_window()->SetLayoutManager(root_window_layout_);
661 
662   aura::Window* default_container =
663       GetContainer(kShellWindowId_DefaultContainer);
664   // Workspace manager has its own layout managers.
665   workspace_controller_.reset(
666       new WorkspaceController(default_container));
667 
668   aura::Window* always_on_top_container =
669       GetContainer(kShellWindowId_AlwaysOnTopContainer);
670   always_on_top_container->SetLayoutManager(
671       new BaseLayoutManager(
672           always_on_top_container->GetRootWindow()));
673   always_on_top_controller_.reset(new internal::AlwaysOnTopController);
674   always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container);
675 
676   DCHECK(!shelf_.get());
677   aura::Window* shelf_container =
678       GetContainer(internal::kShellWindowId_ShelfContainer);
679   // TODO(harrym): Remove when status area is view.
680   aura::Window* status_container =
681       GetContainer(internal::kShellWindowId_StatusContainer);
682   shelf_.reset(new ShelfWidget(
683       shelf_container, status_container, workspace_controller()));
684 
685   if (!Shell::GetInstance()->session_state_delegate()->
686       IsActiveUserSessionStarted()) {
687     // This window exists only to be a event target on login screen.
688     // It does not have to handle events, nor be visible.
689     mouse_event_target_.reset(new aura::Window(new EmptyWindowDelegate));
690     mouse_event_target_->Init(ui::LAYER_NOT_DRAWN);
691 
692     aura::Window* lock_background_container =
693         GetContainer(internal::kShellWindowId_LockScreenBackgroundContainer);
694     lock_background_container->AddChild(mouse_event_target_.get());
695     mouse_event_target_->Show();
696   }
697 
698   // Create Docked windows layout manager
699   aura::Window* docked_container = GetContainer(
700       internal::kShellWindowId_DockedContainer);
701   docked_layout_manager_ =
702       new internal::DockedWindowLayoutManager(docked_container,
703                                               workspace_controller());
704   docked_container_handler_.reset(
705       new ToplevelWindowEventHandler(docked_container));
706   docked_container->SetLayoutManager(docked_layout_manager_);
707 
708   // Create Panel layout manager
709   aura::Window* panel_container = GetContainer(
710       internal::kShellWindowId_PanelContainer);
711   panel_layout_manager_ =
712       new internal::PanelLayoutManager(panel_container);
713   panel_container_handler_.reset(
714       new PanelWindowEventHandler(panel_container));
715   panel_container->SetLayoutManager(panel_layout_manager_);
716 }
717 
InitTouchHuds()718 void RootWindowController::InitTouchHuds() {
719   CommandLine* command_line = CommandLine::ForCurrentProcess();
720   if (command_line->HasSwitch(switches::kAshTouchHud))
721     set_touch_hud_debug(new TouchHudDebug(root_window()));
722   if (Shell::GetInstance()->is_touch_hud_projection_enabled())
723     EnableTouchHudProjection();
724 }
725 
CreateSystemBackground(bool is_first_run_after_boot)726 void RootWindowController::CreateSystemBackground(
727     bool is_first_run_after_boot) {
728   SkColor color = SK_ColorBLACK;
729 #if defined(OS_CHROMEOS)
730   if (is_first_run_after_boot)
731     color = kChromeOsBootColor;
732 #endif
733   system_background_.reset(
734     new SystemBackgroundController(root_window(), color));
735 
736 #if defined(OS_CHROMEOS)
737   // Make a copy of the system's boot splash screen so we can composite it
738   // onscreen until the desktop background is ready.
739   if (is_first_run_after_boot &&
740       (CommandLine::ForCurrentProcess()->HasSwitch(
741            switches::kAshCopyHostBackgroundAtBoot) ||
742        CommandLine::ForCurrentProcess()->HasSwitch(
743            switches::kAshAnimateFromBootSplashScreen)))
744     boot_splash_screen_.reset(new BootSplashScreen(root_window_.get()));
745 #endif
746 }
747 
CreateContainersInRootWindow(aura::Window * root_window)748 void RootWindowController::CreateContainersInRootWindow(
749     aura::Window* root_window) {
750   // These containers are just used by PowerButtonController to animate groups
751   // of containers simultaneously without messing up the current transformations
752   // on those containers. These are direct children of the root window; all of
753   // the other containers are their children.
754 
755   // The desktop background container is not part of the lock animation, so it
756   // is not included in those animate groups.
757   // When screen is locked desktop background is moved to lock screen background
758   // container (moved back on unlock). We want to make sure that there's an
759   // opaque layer occluding the non-lock-screen layers.
760   aura::Window* desktop_background_container = CreateContainer(
761       kShellWindowId_DesktopBackgroundContainer,
762       "DesktopBackgroundContainer",
763       root_window);
764   views::corewm::SetChildWindowVisibilityChangesAnimated(
765       desktop_background_container);
766 
767   aura::Window* non_lock_screen_containers = CreateContainer(
768       kShellWindowId_NonLockScreenContainersContainer,
769       "NonLockScreenContainersContainer",
770       root_window);
771 
772   aura::Window* lock_background_containers = CreateContainer(
773       kShellWindowId_LockScreenBackgroundContainer,
774       "LockScreenBackgroundContainer",
775       root_window);
776   views::corewm::SetChildWindowVisibilityChangesAnimated(
777       lock_background_containers);
778 
779   aura::Window* lock_screen_containers = CreateContainer(
780       kShellWindowId_LockScreenContainersContainer,
781       "LockScreenContainersContainer",
782       root_window);
783   aura::Window* lock_screen_related_containers = CreateContainer(
784       kShellWindowId_LockScreenRelatedContainersContainer,
785       "LockScreenRelatedContainersContainer",
786       root_window);
787 
788   CreateContainer(kShellWindowId_UnparentedControlContainer,
789                   "UnparentedControlContainer",
790                   non_lock_screen_containers);
791 
792   aura::Window* default_container = CreateContainer(
793       kShellWindowId_DefaultContainer,
794       "DefaultContainer",
795       non_lock_screen_containers);
796   views::corewm::SetChildWindowVisibilityChangesAnimated(default_container);
797   SetUsesScreenCoordinates(default_container);
798 
799   aura::Window* always_on_top_container = CreateContainer(
800       kShellWindowId_AlwaysOnTopContainer,
801       "AlwaysOnTopContainer",
802       non_lock_screen_containers);
803   always_on_top_container_handler_.reset(
804       new ToplevelWindowEventHandler(always_on_top_container));
805   views::corewm::SetChildWindowVisibilityChangesAnimated(
806       always_on_top_container);
807   SetUsesScreenCoordinates(always_on_top_container);
808 
809   aura::Window* docked_container = CreateContainer(
810       kShellWindowId_DockedContainer,
811       "DockedContainer",
812       non_lock_screen_containers);
813   views::corewm::SetChildWindowVisibilityChangesAnimated(docked_container);
814   SetUsesScreenCoordinates(docked_container);
815 
816   aura::Window* shelf_container =
817       CreateContainer(kShellWindowId_ShelfContainer,
818                       "ShelfContainer",
819                       non_lock_screen_containers);
820   SetUsesScreenCoordinates(shelf_container);
821   DescendantShouldStayInSameRootWindow(shelf_container);
822 
823   aura::Window* panel_container = CreateContainer(
824       kShellWindowId_PanelContainer,
825       "PanelContainer",
826       non_lock_screen_containers);
827   SetUsesScreenCoordinates(panel_container);
828 
829   aura::Window* shelf_bubble_container =
830       CreateContainer(kShellWindowId_ShelfBubbleContainer,
831                       "ShelfBubbleContainer",
832                       non_lock_screen_containers);
833   SetUsesScreenCoordinates(shelf_bubble_container);
834   DescendantShouldStayInSameRootWindow(shelf_bubble_container);
835 
836   aura::Window* app_list_container =
837       CreateContainer(kShellWindowId_AppListContainer,
838                       "AppListContainer",
839                       non_lock_screen_containers);
840   SetUsesScreenCoordinates(app_list_container);
841 
842   aura::Window* modal_container = CreateContainer(
843       kShellWindowId_SystemModalContainer,
844       "SystemModalContainer",
845       non_lock_screen_containers);
846   modal_container_handler_.reset(
847       new ToplevelWindowEventHandler(modal_container));
848   modal_container->SetLayoutManager(
849       new SystemModalContainerLayoutManager(modal_container));
850   views::corewm::SetChildWindowVisibilityChangesAnimated(modal_container);
851   SetUsesScreenCoordinates(modal_container);
852 
853   aura::Window* input_method_container = CreateContainer(
854       kShellWindowId_InputMethodContainer,
855       "InputMethodContainer",
856       non_lock_screen_containers);
857   views::corewm::SetChildWindowVisibilityChangesAnimated(
858       input_method_container);
859   SetUsesScreenCoordinates(input_method_container);
860 
861   // TODO(beng): Figure out if we can make this use
862   // SystemModalContainerEventFilter instead of stops_event_propagation.
863   aura::Window* lock_container = CreateContainer(
864       kShellWindowId_LockScreenContainer,
865       "LockScreenContainer",
866       lock_screen_containers);
867   lock_container->SetLayoutManager(
868       new BaseLayoutManager(root_window));
869   SetUsesScreenCoordinates(lock_container);
870   // TODO(beng): stopsevents
871 
872   aura::Window* lock_modal_container = CreateContainer(
873       kShellWindowId_LockSystemModalContainer,
874       "LockSystemModalContainer",
875       lock_screen_containers);
876   lock_modal_container_handler_.reset(
877       new ToplevelWindowEventHandler(lock_modal_container));
878   lock_modal_container->SetLayoutManager(
879       new SystemModalContainerLayoutManager(lock_modal_container));
880   views::corewm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
881   SetUsesScreenCoordinates(lock_modal_container);
882 
883   aura::Window* status_container =
884       CreateContainer(kShellWindowId_StatusContainer,
885                       "StatusContainer",
886                       lock_screen_related_containers);
887   SetUsesScreenCoordinates(status_container);
888   DescendantShouldStayInSameRootWindow(status_container);
889 
890   aura::Window* settings_bubble_container = CreateContainer(
891       kShellWindowId_SettingBubbleContainer,
892       "SettingBubbleContainer",
893       lock_screen_related_containers);
894   views::corewm::SetChildWindowVisibilityChangesAnimated(
895       settings_bubble_container);
896   SetUsesScreenCoordinates(settings_bubble_container);
897   DescendantShouldStayInSameRootWindow(settings_bubble_container);
898 
899   aura::Window* menu_container = CreateContainer(
900       kShellWindowId_MenuContainer,
901       "MenuContainer",
902       lock_screen_related_containers);
903   views::corewm::SetChildWindowVisibilityChangesAnimated(menu_container);
904   SetUsesScreenCoordinates(menu_container);
905 
906   aura::Window* drag_drop_container = CreateContainer(
907       kShellWindowId_DragImageAndTooltipContainer,
908       "DragImageAndTooltipContainer",
909       lock_screen_related_containers);
910   views::corewm::SetChildWindowVisibilityChangesAnimated(drag_drop_container);
911   SetUsesScreenCoordinates(drag_drop_container);
912 
913   aura::Window* overlay_container = CreateContainer(
914       kShellWindowId_OverlayContainer,
915       "OverlayContainer",
916       lock_screen_related_containers);
917   SetUsesScreenCoordinates(overlay_container);
918 
919   CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
920                   "PowerButtonAnimationContainer", root_window) ;
921 }
922 
EnableTouchHudProjection()923 void RootWindowController::EnableTouchHudProjection() {
924   if (touch_hud_projection_)
925     return;
926   set_touch_hud_projection(new TouchHudProjection(root_window()));
927 }
928 
DisableTouchHudProjection()929 void RootWindowController::DisableTouchHudProjection() {
930   if (!touch_hud_projection_)
931     return;
932   touch_hud_projection_->Remove();
933 }
934 
OnLoginStateChanged(user::LoginStatus status)935 void RootWindowController::OnLoginStateChanged(user::LoginStatus status) {
936   shelf_->shelf_layout_manager()->UpdateVisibilityState();
937 }
938 
OnTouchHudProjectionToggled(bool enabled)939 void RootWindowController::OnTouchHudProjectionToggled(bool enabled) {
940   if (enabled)
941     EnableTouchHudProjection();
942   else
943     DisableTouchHudProjection();
944 }
945 
GetRootWindowController(const aura::Window * root_window)946 RootWindowController* GetRootWindowController(
947     const aura::Window* root_window) {
948   return root_window ? GetRootWindowSettings(root_window)->controller : NULL;
949 }
950 
951 }  // namespace internal
952 }  // namespace ash
953