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. 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|. 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|. 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. 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. 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: 164 EmptyWindowDelegate() {} 165 virtual ~EmptyWindowDelegate() {} 166 167 // aura::WindowDelegate overrides: 168 virtual gfx::Size GetMinimumSize() const OVERRIDE { 169 return gfx::Size(); 170 } 171 virtual gfx::Size GetMaximumSize() const OVERRIDE { 172 return gfx::Size(); 173 } 174 virtual void OnBoundsChanged(const gfx::Rect& old_bounds, 175 const gfx::Rect& new_bounds) OVERRIDE { 176 } 177 virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE { 178 return gfx::kNullCursor; 179 } 180 virtual int GetNonClientComponent( 181 const gfx::Point& point) const OVERRIDE { 182 return HTNOWHERE; 183 } 184 virtual bool ShouldDescendIntoChildForEventHandling( 185 aura::Window* child, 186 const gfx::Point& location) OVERRIDE { 187 return false; 188 } 189 virtual bool CanFocus() OVERRIDE { 190 return false; 191 } 192 virtual void OnCaptureLost() OVERRIDE { 193 } 194 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { 195 } 196 virtual void OnDeviceScaleFactorChanged( 197 float device_scale_factor) OVERRIDE { 198 } 199 virtual void OnWindowDestroying() OVERRIDE {} 200 virtual void OnWindowDestroyed() OVERRIDE { 201 delete this; 202 } 203 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE { 204 } 205 virtual bool HasHitTestMask() const OVERRIDE { 206 return false; 207 } 208 virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {} 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 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 227 void RootWindowController::CreateForSecondaryDisplay(aura::RootWindow * root) { 228 RootWindowController* controller = new RootWindowController(root); 229 controller->Init(RootWindowController::SECONDARY, false /* first run */); 230 } 231 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 240 RootWindowController* RootWindowController::ForLauncher(aura::Window* window) { 241 return GetRootWindowController(window->GetRootWindow()); 242 } 243 244 // static 245 RootWindowController* RootWindowController::ForWindow( 246 const aura::Window* window) { 247 return GetRootWindowController(window->GetRootWindow()); 248 } 249 250 // static 251 RootWindowController* RootWindowController::ForTargetRootWindow() { 252 return internal::GetRootWindowController(Shell::GetTargetRootWindow()); 253 } 254 255 // static 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 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 272 void RootWindowController::SetWallpaperController( 273 DesktopBackgroundWidgetController* controller) { 274 wallpaper_controller_.reset(controller); 275 } 276 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 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* 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 337 aura::Window* RootWindowController::GetContainer(int container_id) { 338 return root_window()->GetChildById(container_id); 339 } 340 341 const aura::Window* RootWindowController::GetContainer(int container_id) const { 342 return root_window_->window()->GetChildById(container_id); 343 } 344 345 void RootWindowController::ShowLauncher() { 346 if (!shelf_->launcher()) 347 return; 348 shelf_->launcher()->SetVisible(true); 349 shelf_->status_area_widget()->Show(); 350 } 351 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 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 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 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 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 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 491 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() { 492 return shelf_->shelf_layout_manager(); 493 } 494 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 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 527 void RootWindowController::UpdateShelfVisibility() { 528 shelf_->shelf_layout_manager()->UpdateVisibilityState(); 529 } 530 531 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 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 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 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 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 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 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 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 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 923 void RootWindowController::EnableTouchHudProjection() { 924 if (touch_hud_projection_) 925 return; 926 set_touch_hud_projection(new TouchHudProjection(root_window())); 927 } 928 929 void RootWindowController::DisableTouchHudProjection() { 930 if (!touch_hud_projection_) 931 return; 932 touch_hud_projection_->Remove(); 933 } 934 935 void RootWindowController::OnLoginStateChanged(user::LoginStatus status) { 936 shelf_->shelf_layout_manager()->UpdateVisibilityState(); 937 } 938 939 void RootWindowController::OnTouchHudProjectionToggled(bool enabled) { 940 if (enabled) 941 EnableTouchHudProjection(); 942 else 943 DisableTouchHudProjection(); 944 } 945 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