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.
5 #include "ash/root_window_controller.h"
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"
70 #if defined(OS_CHROMEOS)
71 #include "ash/wm/boot_splash_screen_chromeos.h"
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;
85 // Creates a new window for use as a container.
86 aura::Window* CreateContainer(int window_id,
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)
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);
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,
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(
139 // If the entire window list is modal background windows then stop.
140 if (iter == src_container->children().end())
142 ReparentWindow(*iter, dst_container);
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);
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);
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 {
163 EmptyWindowDelegate() {}
164 virtual ~EmptyWindowDelegate() {}
166 // aura::WindowDelegate overrides:
167 virtual gfx::Size GetMinimumSize() const OVERRIDE {
170 virtual gfx::Size GetMaximumSize() const OVERRIDE {
173 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
174 const gfx::Rect& new_bounds) OVERRIDE {
176 virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
177 return gfx::kNullCursor;
179 virtual int GetNonClientComponent(
180 const gfx::Point& point) const OVERRIDE {
183 virtual bool ShouldDescendIntoChildForEventHandling(
185 const gfx::Point& location) OVERRIDE {
188 virtual bool CanFocus() OVERRIDE {
191 virtual void OnCaptureLost() OVERRIDE {
193 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
195 virtual void OnDeviceScaleFactorChanged(
196 float device_scale_factor) OVERRIDE {
198 virtual void OnWindowDestroying() OVERRIDE {}
199 virtual void OnWindowDestroyed() OVERRIDE {
202 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
204 virtual bool HasHitTestMask() const OVERRIDE {
207 virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
208 virtual void DidRecreateLayer(ui::Layer* old_layer,
209 ui::Layer* new_layer) OVERRIDE {}
212 DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate);
219 void RootWindowController::CreateForPrimaryDisplay(
220 aura::RootWindow* root) {
221 RootWindowController* controller = new RootWindowController(root);
222 controller->Init(RootWindowController::PRIMARY,
223 Shell::GetInstance()->delegate()->IsFirstRunAfterBoot());
226 void RootWindowController::CreateForSecondaryDisplay(aura::RootWindow * root) {
227 RootWindowController* controller = new RootWindowController(root);
228 controller->Init(RootWindowController::SECONDARY, false /* first run */);
231 void RootWindowController::CreateForVirtualKeyboardDisplay(
232 aura::RootWindow * root) {
233 RootWindowController* controller = new RootWindowController(root);
234 controller->Init(RootWindowController::VIRTUAL_KEYBOARD,
235 false /* first run */);
239 RootWindowController* RootWindowController::ForLauncher(aura::Window* window) {
240 return GetRootWindowController(window->GetRootWindow());
244 RootWindowController* RootWindowController::ForWindow(
245 const aura::Window* window) {
246 return GetRootWindowController(window->GetRootWindow());
250 RootWindowController* RootWindowController::ForTargetRootWindow() {
251 return internal::GetRootWindowController(Shell::GetTargetRootWindow());
254 RootWindowController::~RootWindowController() {
256 root_window_.reset();
257 // The CaptureClient needs to be around for as long as the RootWindow is
259 capture_client_.reset();
262 void RootWindowController::SetWallpaperController(
263 DesktopBackgroundWidgetController* controller) {
264 wallpaper_controller_.reset(controller);
267 void RootWindowController::SetAnimatingWallpaperController(
268 AnimatingDesktopController* controller) {
269 if (animating_wallpaper_controller_.get())
270 animating_wallpaper_controller_->StopAnimating();
271 animating_wallpaper_controller_.reset(controller);
274 void RootWindowController::Shutdown() {
275 Shell::GetInstance()->RemoveShellObserver(this);
277 if (animating_wallpaper_controller_.get())
278 animating_wallpaper_controller_->StopAnimating();
279 wallpaper_controller_.reset();
280 animating_wallpaper_controller_.reset();
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());
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();
303 system_background_.reset();
306 SystemModalContainerLayoutManager*
307 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
308 aura::Window* container = NULL;
310 if (window->parent() &&
311 window->parent()->id() >= kShellWindowId_LockScreenContainer) {
312 container = GetContainer(kShellWindowId_LockSystemModalContainer);
314 container = GetContainer(kShellWindowId_SystemModalContainer);
317 int modal_window_id = Shell::GetInstance()->session_state_delegate()
318 ->IsUserSessionBlocked() ? kShellWindowId_LockSystemModalContainer :
319 kShellWindowId_SystemModalContainer;
320 container = GetContainer(modal_window_id);
322 return container ? static_cast<SystemModalContainerLayoutManager*>(
323 container->layout_manager()) : NULL;
326 aura::Window* RootWindowController::GetContainer(int container_id) {
327 return root_window_->GetChildById(container_id);
330 const aura::Window* RootWindowController::GetContainer(int container_id) const {
331 return root_window_->GetChildById(container_id);
334 void RootWindowController::ShowLauncher() {
335 if (!shelf_->launcher())
337 shelf_->launcher()->SetVisible(true);
338 shelf_->status_area_widget()->Show();
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());
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);
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));
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();
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);
396 void RootWindowController::CloseChildWindows() {
397 mouse_event_target_.reset();
399 // Deactivate keyboard container before closing child windows and shutting
400 // down associated layout managers.
401 DeactivateKeyboard(Shell::GetInstance()->keyboard_controller());
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;
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;
416 aura::client::SetDragDropClient(root_window_.get(), NULL);
418 // TODO(harrym): Remove when Status Area Widget is a child view.
420 shelf_->ShutdownStatusAreaWidget();
422 if (shelf_->shelf_layout_manager())
423 shelf_->shelf_layout_manager()->PrepareForShutdown();
426 // Close background widget first as it depends on tooltip.
427 wallpaper_controller_.reset();
428 animating_wallpaper_controller_.reset();
430 workspace_controller_.reset();
431 aura::client::SetTooltipClient(root_window_.get(), NULL);
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())
445 if (child->delegate())
446 toplevel_windows.Add(child);
448 non_toplevel_windows.push(child);
450 while (!toplevel_windows.windows().empty())
451 delete *toplevel_windows.windows().begin();
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()) {
459 root_window_->RemoveChild(window);
466 void RootWindowController::MoveWindowsTo(aura::Window* dst) {
467 // Forget the shelf early so that shelf don't update itself using wrong
469 workspace_controller_->SetShelf(NULL);
470 ReparentAllWindows(root_window_.get(), dst);
473 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
474 return shelf_->shelf_layout_manager();
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();
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()));
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())
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) {
506 Shell::GetInstance()->UpdateShelfVisibility();
509 void RootWindowController::UpdateShelfVisibility() {
510 shelf_->shelf_layout_manager()->UpdateVisibilityState();
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())
524 void RootWindowController::ActivateKeyboard(
525 keyboard::KeyboardController* keyboard_controller) {
526 if (!keyboard::IsKeyboardEnabled() ||
527 GetContainer(kShellWindowId_VirtualKeyboardContainer)) {
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());
544 void RootWindowController::DeactivateKeyboard(
545 keyboard::KeyboardController* keyboard_controller) {
546 if (!keyboard::IsKeyboardEnabled())
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_);
561 ////////////////////////////////////////////////////////////////////////////////
562 // RootWindowController, private:
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));
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));
579 void RootWindowController::Init(RootWindowType root_window_type,
580 bool first_run_after_boot) {
581 Shell::GetInstance()->InitRootWindow(root_window_.get());
583 root_window_->SetCursor(ui::kCursorPointer);
584 CreateContainersInRootWindow(root_window_.get());
586 if (root_window_type == VIRTUAL_KEYBOARD)
589 CreateSystemBackground(first_run_after_boot);
591 InitLayoutManagers();
594 if (Shell::GetPrimaryRootWindowController()->
595 GetSystemModalLayoutManager(NULL)->has_modal_background()) {
596 GetSystemModalLayoutManager(NULL)->CreateModalBackground();
599 Shell* shell = Shell::GetInstance();
600 shell->AddShellObserver(this);
602 if (root_window_type == PRIMARY) {
603 root_window_layout()->OnWindowResized();
604 shell->InitKeyboard(this);
606 root_window_layout()->OnWindowResized();
607 shell->desktop_background_controller()->OnRootWindowAdded(
609 shell->high_contrast_controller()->OnRootWindowAdded(root_window_.get());
610 root_window_->ShowRootWindow();
612 // Create a launcher if a user is already logged.
613 if (shell->session_state_delegate()->NumberOfLoggedInUsers())
614 shelf()->CreateLauncher();
618 void RootWindowController::InitLayoutManagers() {
619 root_window_layout_ =
620 new RootWindowLayoutManager(root_window_.get());
621 root_window_->SetLayoutManager(root_window_layout_);
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));
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);
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()));
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);
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();
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_);
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_);
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();
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;
694 system_background_.reset(
695 new SystemBackgroundController(root_window_.get(), color));
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()));
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.
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",
725 views::corewm::SetChildWindowVisibilityChangesAnimated(
726 desktop_background_container);
728 aura::Window* non_lock_screen_containers = CreateContainer(
729 kShellWindowId_NonLockScreenContainersContainer,
730 "NonLockScreenContainersContainer",
733 aura::Window* lock_background_containers = CreateContainer(
734 kShellWindowId_LockScreenBackgroundContainer,
735 "LockScreenBackgroundContainer",
737 views::corewm::SetChildWindowVisibilityChangesAnimated(
738 lock_background_containers);
740 aura::Window* lock_screen_containers = CreateContainer(
741 kShellWindowId_LockScreenContainersContainer,
742 "LockScreenContainersContainer",
744 aura::Window* lock_screen_related_containers = CreateContainer(
745 kShellWindowId_LockScreenRelatedContainersContainer,
746 "LockScreenRelatedContainersContainer",
749 CreateContainer(kShellWindowId_UnparentedControlContainer,
750 "UnparentedControlContainer",
751 non_lock_screen_containers);
753 aura::Window* default_container = CreateContainer(
754 kShellWindowId_DefaultContainer,
756 non_lock_screen_containers);
757 views::corewm::SetChildWindowVisibilityChangesAnimated(default_container);
758 SetUsesScreenCoordinates(default_container);
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);
770 aura::Window* docked_container = CreateContainer(
771 kShellWindowId_DockedContainer,
773 non_lock_screen_containers);
774 views::corewm::SetChildWindowVisibilityChangesAnimated(docked_container);
775 SetUsesScreenCoordinates(docked_container);
777 aura::Window* shelf_container =
778 CreateContainer(kShellWindowId_ShelfContainer,
780 non_lock_screen_containers);
781 SetUsesScreenCoordinates(shelf_container);
782 DescendantShouldStayInSameRootWindow(shelf_container);
784 aura::Window* panel_container = CreateContainer(
785 kShellWindowId_PanelContainer,
787 non_lock_screen_containers);
788 SetUsesScreenCoordinates(panel_container);
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);
797 aura::Window* app_list_container =
798 CreateContainer(kShellWindowId_AppListContainer,
800 non_lock_screen_containers);
801 SetUsesScreenCoordinates(app_list_container);
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);
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);
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
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);
844 aura::Window* status_container =
845 CreateContainer(kShellWindowId_StatusContainer,
847 lock_screen_related_containers);
848 SetUsesScreenCoordinates(status_container);
849 DescendantShouldStayInSameRootWindow(status_container);
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);
860 aura::Window* menu_container = CreateContainer(
861 kShellWindowId_MenuContainer,
863 lock_screen_related_containers);
864 views::corewm::SetChildWindowVisibilityChangesAnimated(menu_container);
865 SetUsesScreenCoordinates(menu_container);
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);
874 aura::Window* overlay_container = CreateContainer(
875 kShellWindowId_OverlayContainer,
877 lock_screen_related_containers);
878 SetUsesScreenCoordinates(overlay_container);
880 CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
881 "PowerButtonAnimationContainer", root_window) ;
884 void RootWindowController::EnableTouchHudProjection() {
885 if (touch_hud_projection_)
887 set_touch_hud_projection(new TouchHudProjection(root_window_.get()));
890 void RootWindowController::DisableTouchHudProjection() {
891 if (!touch_hud_projection_)
893 touch_hud_projection_->Remove();
896 void RootWindowController::OnLoginStateChanged(user::LoginStatus status) {
897 shelf_->shelf_layout_manager()->UpdateVisibilityState();
900 void RootWindowController::OnTouchHudProjectionToggled(bool enabled) {
902 EnableTouchHudProjection();
904 DisableTouchHudProjection();
907 RootWindowController* GetRootWindowController(
908 const aura::Window* root_window) {
909 return root_window ? GetRootWindowSettings(root_window)->controller : NULL;
912 } // namespace internal