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