blob: d50bbe9cb3fb8d491a43e05e6ad1db34a9ea9080 [file] [log] [blame]
[email protected]d90b8392012-06-13 09:34:561// 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
[email protected]8d625fb2012-07-18 16:40:067#include <vector>
8
[email protected]e6e41d2f2012-10-29 19:22:199#include "ash/ash_switches.h"
[email protected]b4ddc7a2012-08-07 04:17:3210#include "ash/desktop_background/desktop_background_widget_controller.h"
[email protected]8d625fb2012-07-18 16:40:0611#include "ash/display/display_controller.h"
[email protected]6bdf7952012-11-14 10:10:5812#include "ash/display/display_manager.h"
[email protected]e74aaf0a2012-10-12 18:42:2813#include "ash/focus_cycler.h"
[email protected]ef80e4302012-12-04 19:37:3114#include "ash/shelf_types.h"
[email protected]d90b8392012-06-13 09:34:5615#include "ash/shell.h"
[email protected]e74aaf0a2012-10-12 18:42:2816#include "ash/shell_delegate.h"
[email protected]d90b8392012-06-13 09:34:5617#include "ash/shell_factory.h"
18#include "ash/shell_window_ids.h"
[email protected]e74aaf0a2012-10-12 18:42:2819#include "ash/system/status_area_widget.h"
[email protected]8674b312012-10-12 19:02:4420#include "ash/system/tray/system_tray_delegate.h"
[email protected]d90b8392012-06-13 09:34:5621#include "ash/wm/base_layout_manager.h"
[email protected]bca9a7e2012-11-10 06:25:4922#include "ash/wm/boot_splash_screen.h"
[email protected]e74aaf0a2012-10-12 18:42:2823#include "ash/wm/panel_layout_manager.h"
24#include "ash/wm/panel_window_event_filter.h"
[email protected]d90b8392012-06-13 09:34:5625#include "ash/wm/property_util.h"
26#include "ash/wm/root_window_layout_manager.h"
27#include "ash/wm/screen_dimmer.h"
[email protected]e74aaf0a2012-10-12 18:42:2828#include "ash/wm/shelf_layout_manager.h"
[email protected]2a2caa02013-01-22 20:50:3629#include "ash/wm/stacking_controller.h"
[email protected]e74aaf0a2012-10-12 18:42:2830#include "ash/wm/status_area_layout_manager.h"
[email protected]e6e41d2f2012-10-29 19:22:1931#include "ash/wm/system_background_controller.h"
[email protected]d90b8392012-06-13 09:34:5632#include "ash/wm/system_modal_container_layout_manager.h"
[email protected]5dc51db82012-09-11 03:39:0133#include "ash/wm/toplevel_window_event_handler.h"
[email protected]8d625fb2012-07-18 16:40:0634#include "ash/wm/window_properties.h"
[email protected]d90b8392012-06-13 09:34:5635#include "ash/wm/workspace_controller.h"
[email protected]e6e41d2f2012-10-29 19:22:1936#include "base/command_line.h"
[email protected]bca9a7e2012-11-10 06:25:4937#include "base/time.h"
[email protected]f1853122012-06-27 16:21:2638#include "ui/aura/client/activation_client.h"
39#include "ui/aura/client/aura_constants.h"
40#include "ui/aura/client/capture_client.h"
[email protected]8cfb6722012-11-28 03:28:4641#include "ui/aura/client/focus_client.h"
[email protected]d90b8392012-06-13 09:34:5642#include "ui/aura/client/tooltip_client.h"
43#include "ui/aura/root_window.h"
[email protected]f1853122012-06-27 16:21:2644#include "ui/aura/window.h"
45#include "ui/aura/window_observer.h"
[email protected]1d030242012-06-28 18:34:0846#include "ui/aura/window_tracker.h"
[email protected]431552c2012-10-23 00:38:3347#include "ui/base/models/menu_model.h"
[email protected]8d625fb2012-07-18 16:40:0648#include "ui/gfx/display.h"
49#include "ui/gfx/screen.h"
[email protected]431552c2012-10-23 00:38:3350#include "ui/views/controls/menu/menu_model_adapter.h"
51#include "ui/views/controls/menu/menu_runner.h"
[email protected]b5756e22012-11-30 01:32:0252#include "ui/views/corewm/visibility_controller.h"
[email protected]431552c2012-10-23 00:38:3353#include "ui/views/view_model.h"
54#include "ui/views/view_model_utils.h"
[email protected]d90b8392012-06-13 09:34:5655
56namespace ash {
57namespace {
58
[email protected]bca9a7e2012-11-10 06:25:4959#if defined(OS_CHROMEOS)
60// Background color used for the Chrome OS boot splash screen.
61const SkColor kChromeOsBootColor = SkColorSetARGB(0xff, 0xfe, 0xfe, 0xfe);
62#endif
63
64// Duration for the animation that hides the boot splash screen, in
65// milliseconds. This should be short enough in relation to
66// wm/window_animation.cc's brightness/grayscale fade animation that the login
67// background image animation isn't hidden by the splash screen animation.
68const int kBootSplashScreenHideDurationMs = 500;
69
[email protected]d90b8392012-06-13 09:34:5670// Creates a new window for use as a container.
71aura::Window* CreateContainer(int window_id,
72 const char* name,
73 aura::Window* parent) {
74 aura::Window* container = new aura::Window(NULL);
75 container->set_id(window_id);
76 container->SetName(name);
77 container->Init(ui::LAYER_NOT_DRAWN);
78 parent->AddChild(container);
79 if (window_id != internal::kShellWindowId_UnparentedControlContainer)
80 container->Show();
81 return container;
82}
83
[email protected]95058572012-08-20 14:57:2984// Returns all the children of the workspace windows, eg the standard top-level
85// windows.
86std::vector<aura::Window*> GetWorkspaceWindows(aura::RootWindow* root) {
87 using aura::Window;
88
89 std::vector<Window*> windows;
90 Window* container = Shell::GetContainer(
91 root, internal::kShellWindowId_DefaultContainer);
92 for (Window::Windows::const_reverse_iterator i =
93 container->children().rbegin();
94 i != container->children().rend(); ++i) {
95 Window* workspace_window = *i;
96 if (workspace_window->id() == internal::kShellWindowId_WorkspaceContainer) {
97 windows.insert(windows.end(), workspace_window->children().begin(),
98 workspace_window->children().end());
99 }
100 }
101 return windows;
102}
103
104// Reparents |window| to |new_parent|.
105void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
106 // Update the restore bounds to make it relative to the display.
107 gfx::Rect restore_bounds(GetRestoreBoundsInParent(window));
108 new_parent->AddChild(window);
109 if (!restore_bounds.IsEmpty())
110 SetRestoreBoundsInParent(window, restore_bounds);
111}
112
113// Reparents the appropriate set of windows from |src| to |dst|.
114void ReparentAllWindows(aura::RootWindow* src, aura::RootWindow* dst) {
115 // Set of windows to move.
[email protected]f1853122012-06-27 16:21:26116 const int kContainerIdsToMove[] = {
117 internal::kShellWindowId_DefaultContainer,
118 internal::kShellWindowId_AlwaysOnTopContainer,
119 internal::kShellWindowId_SystemModalContainer,
120 internal::kShellWindowId_LockSystemModalContainer,
[email protected]6274d312012-10-04 22:06:41121 internal::kShellWindowId_InputMethodContainer,
[email protected]a9754872013-01-25 07:44:00122 internal::kShellWindowId_UnparentedControlContainer,
[email protected]f1853122012-06-27 16:21:26123 };
[email protected]ef0e32cc2012-10-31 20:57:33124 // For workspace windows we need to manually reparent the windows. This way
125 // workspace can move the windows to the appropriate workspace.
[email protected]c96b9812012-10-17 16:04:04126 std::vector<aura::Window*> windows(GetWorkspaceWindows(src));
127 internal::WorkspaceController* workspace_controller =
128 GetRootWindowController(dst)->workspace_controller();
129 for (size_t i = 0; i < windows.size(); ++i) {
130 aura::Window* new_parent =
131 workspace_controller->GetParentForNewWindow(windows[i]);
132 ReparentWindow(windows[i], new_parent);
[email protected]95058572012-08-20 14:57:29133 }
[email protected]f1853122012-06-27 16:21:26134 for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) {
135 int id = kContainerIdsToMove[i];
[email protected]c96b9812012-10-17 16:04:04136 if (id == internal::kShellWindowId_DefaultContainer)
[email protected]95058572012-08-20 14:57:29137 continue;
138
[email protected]f1853122012-06-27 16:21:26139 aura::Window* src_container = Shell::GetContainer(src, id);
140 aura::Window* dst_container = Shell::GetContainer(dst, id);
141 aura::Window::Windows children = src_container->children();
142 for (aura::Window::Windows::iterator iter = children.begin();
143 iter != children.end(); ++iter) {
144 aura::Window* window = *iter;
145 // Don't move modal screen.
[email protected]c0ce80e2012-10-05 23:28:27146 if (internal::SystemModalContainerLayoutManager::IsModalBackground(
147 window))
[email protected]f1853122012-06-27 16:21:26148 continue;
[email protected]f059c6942012-07-21 14:27:57149
[email protected]95058572012-08-20 14:57:29150 ReparentWindow(window, dst_container);
[email protected]f1853122012-06-27 16:21:26151 }
152 }
153}
154
[email protected]8d625fb2012-07-18 16:40:06155// Mark the container window so that a widget added to this container will
156// use the virtual screeen coordinates instead of parent.
157void SetUsesScreenCoordinates(aura::Window* container) {
158 container->SetProperty(internal::kUsesScreenCoordinatesKey, true);
159}
160
[email protected]d90b8392012-06-13 09:34:56161} // namespace
162
163namespace internal {
164
165RootWindowController::RootWindowController(aura::RootWindow* root_window)
[email protected]e74aaf0a2012-10-12 18:42:28166 : root_window_(root_window),
167 root_window_layout_(NULL),
168 status_area_widget_(NULL),
169 shelf_(NULL),
170 panel_layout_manager_(NULL) {
[email protected]d90b8392012-06-13 09:34:56171 SetRootWindowController(root_window, this);
[email protected]c0ce80e2012-10-05 23:28:27172 screen_dimmer_.reset(new ScreenDimmer(root_window));
[email protected]2a2caa02013-01-22 20:50:36173
174 stacking_controller_.reset(new ash::StackingController);
175 aura::client::SetStackingClient(root_window, stacking_controller_.get());
[email protected]d90b8392012-06-13 09:34:56176}
177
178RootWindowController::~RootWindowController() {
[email protected]6675e1c2012-09-11 09:15:45179 Shutdown();
180 root_window_.reset();
181}
182
[email protected]88d71122012-10-18 07:11:01183// static
[email protected]a0afeb12012-12-10 22:57:09184RootWindowController* RootWindowController::ForLauncher(aura::Window* window) {
[email protected]88d71122012-10-18 07:11:01185 if (Shell::IsLauncherPerDisplayEnabled())
186 return GetRootWindowController(window->GetRootWindow());
187 else
188 return Shell::GetPrimaryRootWindowController();
189}
190
[email protected]a0afeb12012-12-10 22:57:09191// static
192RootWindowController* RootWindowController::ForWindow(aura::Window* window) {
193 return GetRootWindowController(window->GetRootWindow());
194}
195
196// static
197RootWindowController* RootWindowController::ForActiveRootWindow() {
198 return GetRootWindowController(Shell::GetActiveRootWindow());
199}
200
[email protected]6675e1c2012-09-11 09:15:45201void RootWindowController::Shutdown() {
202 CloseChildWindows();
[email protected]f634dd32012-07-23 22:49:07203 if (Shell::GetActiveRootWindow() == root_window_.get()) {
204 Shell::GetInstance()->set_active_root_window(
205 Shell::GetPrimaryRootWindow() == root_window_.get() ?
206 NULL : Shell::GetPrimaryRootWindow());
207 }
[email protected]d90b8392012-06-13 09:34:56208 SetRootWindowController(root_window_.get(), NULL);
[email protected]d90b8392012-06-13 09:34:56209 screen_dimmer_.reset();
210 workspace_controller_.reset();
[email protected]6675e1c2012-09-11 09:15:45211 // Forget with the display ID so that display lookup
212 // ends up with invalid display.
213 root_window_->ClearProperty(kDisplayIdKey);
214 // And this root window should no longer process events.
215 root_window_->PrepareForShutdown();
[email protected]e74aaf0a2012-10-12 18:42:28216
[email protected]956a6a42012-10-29 23:58:10217 system_background_.reset();
218
[email protected]e74aaf0a2012-10-12 18:42:28219 // Launcher widget has an InputMethodBridge that references to
220 // |input_method_filter_|'s |input_method_|. So explicitly release
221 // |launcher_| before |input_method_filter_|. And this needs to be
222 // after we delete all containers in case there are still live
223 // browser windows which access LauncherModel during close.
224 launcher_.reset();
[email protected]d90b8392012-06-13 09:34:56225}
226
[email protected]c0ce80e2012-10-05 23:28:27227SystemModalContainerLayoutManager*
[email protected]8674b312012-10-12 19:02:44228RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
229 aura::Window* container = NULL;
230 if (window) {
[email protected]3b162e12012-11-09 11:52:35231 if (window->parent() &&
232 window->parent()->id() >= kShellWindowId_LockScreenContainer) {
233 container = GetContainer(kShellWindowId_LockSystemModalContainer);
234 } else {
[email protected]8674b312012-10-12 19:02:44235 container = GetContainer(kShellWindowId_SystemModalContainer);
[email protected]3b162e12012-11-09 11:52:35236 }
[email protected]8674b312012-10-12 19:02:44237 } else {
[email protected]945f9cae2012-12-12 09:54:29238 user::LoginStatus login = Shell::GetInstance()->system_tray_delegate() ?
239 Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus() :
[email protected]8674b312012-10-12 19:02:44240 user::LOGGED_IN_NONE;
241 int modal_window_id = (login == user::LOGGED_IN_LOCKED ||
242 login == user::LOGGED_IN_NONE) ?
243 kShellWindowId_LockSystemModalContainer :
244 kShellWindowId_SystemModalContainer;
245 container = GetContainer(modal_window_id);
246 }
[email protected]c0ce80e2012-10-05 23:28:27247 return static_cast<SystemModalContainerLayoutManager*>(
[email protected]8674b312012-10-12 19:02:44248 container->layout_manager());
[email protected]c0ce80e2012-10-05 23:28:27249}
250
[email protected]d90b8392012-06-13 09:34:56251aura::Window* RootWindowController::GetContainer(int container_id) {
252 return root_window_->GetChildById(container_id);
253}
254
255void RootWindowController::InitLayoutManagers() {
256 root_window_layout_ =
[email protected]c0ce80e2012-10-05 23:28:27257 new RootWindowLayoutManager(root_window_.get());
[email protected]d90b8392012-06-13 09:34:56258 root_window_->SetLayoutManager(root_window_layout_);
259
260 aura::Window* default_container =
[email protected]c0ce80e2012-10-05 23:28:27261 GetContainer(kShellWindowId_DefaultContainer);
[email protected]d90b8392012-06-13 09:34:56262 // Workspace manager has its own layout managers.
263 workspace_controller_.reset(
[email protected]c0ce80e2012-10-05 23:28:27264 new WorkspaceController(default_container));
[email protected]d90b8392012-06-13 09:34:56265
266 aura::Window* always_on_top_container =
[email protected]c0ce80e2012-10-05 23:28:27267 GetContainer(kShellWindowId_AlwaysOnTopContainer);
[email protected]d90b8392012-06-13 09:34:56268 always_on_top_container->SetLayoutManager(
[email protected]c0ce80e2012-10-05 23:28:27269 new BaseLayoutManager(
[email protected]d90b8392012-06-13 09:34:56270 always_on_top_container->GetRootWindow()));
271}
272
[email protected]e74aaf0a2012-10-12 18:42:28273void RootWindowController::InitForPrimaryDisplay() {
274 DCHECK(!status_area_widget_);
[email protected]16059276d2012-10-22 18:59:50275 aura::Window* status_container =
276 GetContainer(ash::internal::kShellWindowId_StatusContainer);
[email protected]e74aaf0a2012-10-12 18:42:28277 // Initialize Primary RootWindow specific items.
[email protected]16059276d2012-10-22 18:59:50278 status_area_widget_ = new internal::StatusAreaWidget(status_container);
[email protected]51ed5992012-11-07 10:14:39279 status_area_widget_->CreateTrayViews();
[email protected]e74aaf0a2012-10-12 18:42:28280 // Login screen manages status area visibility by itself.
[email protected]51ed5992012-11-07 10:14:39281 ShellDelegate* shell_delegate = Shell::GetInstance()->delegate();
[email protected]02dbd1a2012-11-08 22:50:13282 if (shell_delegate->IsSessionStarted())
[email protected]e74aaf0a2012-10-12 18:42:28283 status_area_widget_->Show();
284
285 Shell::GetInstance()->focus_cycler()->AddWidget(status_area_widget_);
286
287 internal::ShelfLayoutManager* shelf_layout_manager =
288 new internal::ShelfLayoutManager(status_area_widget_);
289 GetContainer(internal::kShellWindowId_LauncherContainer)->
290 SetLayoutManager(shelf_layout_manager);
291 shelf_ = shelf_layout_manager;
292
293 internal::StatusAreaLayoutManager* status_area_layout_manager =
294 new internal::StatusAreaLayoutManager(shelf_layout_manager);
295 GetContainer(internal::kShellWindowId_StatusContainer)->
296 SetLayoutManager(status_area_layout_manager);
297
298 shelf_layout_manager->set_workspace_controller(
299 workspace_controller());
300
301 workspace_controller()->SetShelf(shelf_);
302
[email protected]e5a3deba2012-12-15 20:18:28303 // TODO(oshima): Disable panels on non primary display for now.
304 // crbug.com/166195.
305 if (root_window_ == Shell::GetPrimaryRootWindow()) {
306 // Create Panel layout manager
307 aura::Window* panel_container = GetContainer(
308 internal::kShellWindowId_PanelContainer);
309 panel_layout_manager_ =
310 new internal::PanelLayoutManager(panel_container);
311 panel_container->AddPreTargetHandler(
312 new internal::PanelWindowEventFilter(
313 panel_container, panel_layout_manager_));
314 panel_container->SetLayoutManager(panel_layout_manager_);
315 }
[email protected]e74aaf0a2012-10-12 18:42:28316
[email protected]02dbd1a2012-11-08 22:50:13317 if (shell_delegate->IsUserLoggedIn())
[email protected]e74aaf0a2012-10-12 18:42:28318 CreateLauncher();
319}
320
[email protected]d90b8392012-06-13 09:34:56321void RootWindowController::CreateContainers() {
322 CreateContainersInRootWindow(root_window_.get());
323}
324
[email protected]697f04c2012-10-03 01:15:10325void RootWindowController::CreateSystemBackground(
326 bool is_first_run_after_boot) {
[email protected]bca9a7e2012-11-10 06:25:49327 SkColor color = SK_ColorBLACK;
[email protected]697f04c2012-10-03 01:15:10328#if defined(OS_CHROMEOS)
[email protected]bca9a7e2012-11-10 06:25:49329 if (is_first_run_after_boot)
330 color = kChromeOsBootColor;
[email protected]697f04c2012-10-03 01:15:10331#endif
[email protected]e6e41d2f2012-10-29 19:22:19332 system_background_.reset(
[email protected]bca9a7e2012-11-10 06:25:49333 new SystemBackgroundController(root_window_.get(), color));
334
335#if defined(OS_CHROMEOS)
336 // Make a copy of the system's boot splash screen so we can composite it
337 // onscreen until the desktop background is ready.
338 if (is_first_run_after_boot &&
339 (CommandLine::ForCurrentProcess()->HasSwitch(
340 switches::kAshCopyHostBackgroundAtBoot) ||
341 CommandLine::ForCurrentProcess()->HasSwitch(
342 switches::kAshAnimateFromBootSplashScreen)))
343 boot_splash_screen_.reset(new BootSplashScreen(root_window_.get()));
344#endif
[email protected]697f04c2012-10-03 01:15:10345}
346
[email protected]e74aaf0a2012-10-12 18:42:28347void RootWindowController::CreateLauncher() {
348 if (launcher_.get())
349 return;
350
351 aura::Window* default_container =
352 GetContainer(internal::kShellWindowId_DefaultContainer);
[email protected]0af58042012-12-13 03:21:35353 // Get the delegate first to make sure the launcher model is created.
354 LauncherDelegate* launcher_delegate =
355 Shell::GetInstance()->GetLauncherDelegate();
356 launcher_.reset(new Launcher(Shell::GetInstance()->launcher_model(),
357 launcher_delegate,
358 default_container,
359 shelf_));
[email protected]e74aaf0a2012-10-12 18:42:28360
361 launcher_->SetFocusCycler(Shell::GetInstance()->focus_cycler());
362 shelf_->SetLauncher(launcher_.get());
363
364 if (panel_layout_manager_)
365 panel_layout_manager_->SetLauncher(launcher_.get());
366
367 ShellDelegate* delegate = Shell::GetInstance()->delegate();
368 if (delegate)
369 launcher_->SetVisible(delegate->IsSessionStarted());
370 launcher_->widget()->Show();
371}
372
373void RootWindowController::ShowLauncher() {
374 if (!launcher_.get())
375 return;
376 launcher_->SetVisible(true);
[email protected]cb47bcb32012-11-05 21:36:38377 status_area_widget_->Show();
[email protected]e74aaf0a2012-10-12 18:42:28378}
379
[email protected]16059276d2012-10-22 18:59:50380void RootWindowController::OnLoginStateChanged(user::LoginStatus status) {
381 // TODO(oshima): remove if when launcher per display is enabled by
382 // default.
383 if (shelf_)
384 shelf_->UpdateVisibilityState();
385}
386
387void RootWindowController::UpdateAfterLoginStatusChange(
388 user::LoginStatus status) {
389 if (status_area_widget_)
390 status_area_widget_->UpdateAfterLoginStatusChange(status);
391}
392
[email protected]bca9a7e2012-11-10 06:25:49393void RootWindowController::HandleInitialDesktopBackgroundAnimationStarted() {
394 if (CommandLine::ForCurrentProcess()->HasSwitch(
395 switches::kAshAnimateFromBootSplashScreen) &&
396 boot_splash_screen_.get()) {
397 // Make the splash screen fade out so it doesn't obscure the desktop
398 // wallpaper's brightness/grayscale animation.
399 boot_splash_screen_->StartHideAnimation(
400 base::TimeDelta::FromMilliseconds(kBootSplashScreenHideDurationMs));
401 }
402}
403
[email protected]697f04c2012-10-03 01:15:10404void RootWindowController::HandleDesktopBackgroundVisible() {
[email protected]bca9a7e2012-11-10 06:25:49405 system_background_->SetColor(SK_ColorBLACK);
406 boot_splash_screen_.reset();
[email protected]697f04c2012-10-03 01:15:10407}
408
[email protected]d90b8392012-06-13 09:34:56409void RootWindowController::CloseChildWindows() {
[email protected]e74aaf0a2012-10-12 18:42:28410 // The status area needs to be shut down before the windows are destroyed.
[email protected]8674b312012-10-12 19:02:44411 if (status_area_widget_) {
[email protected]e74aaf0a2012-10-12 18:42:28412 status_area_widget_->Shutdown();
[email protected]8674b312012-10-12 19:02:44413 status_area_widget_ = NULL;
414 }
[email protected]e74aaf0a2012-10-12 18:42:28415
[email protected]79a87b7e2013-01-25 05:08:22416 // panel_layout_manager_ needs to be shut down before windows are destroyed.
417 if (panel_layout_manager_) {
418 panel_layout_manager_->Shutdown();
419 panel_layout_manager_ = NULL;
420 }
421
[email protected]e74aaf0a2012-10-12 18:42:28422 // Closing the windows frees the workspace controller.
423 if (shelf_)
424 shelf_->set_workspace_controller(NULL);
425
[email protected]d90b8392012-06-13 09:34:56426 // Close background widget first as it depends on tooltip.
[email protected]d86de6b22012-10-05 19:32:58427 root_window_->SetProperty(kDesktopController,
[email protected]b4ddc7a2012-08-07 04:17:32428 static_cast<DesktopBackgroundWidgetController*>(NULL));
[email protected]d86de6b22012-10-05 19:32:58429 root_window_->SetProperty(kAnimatingDesktopController,
430 static_cast<AnimatingDesktopController*>(NULL));
[email protected]b4ddc7a2012-08-07 04:17:32431
[email protected]d90b8392012-06-13 09:34:56432 workspace_controller_.reset();
433 aura::client::SetTooltipClient(root_window_.get(), NULL);
434
435 while (!root_window_->children().empty()) {
436 aura::Window* child = root_window_->children()[0];
437 delete child;
438 }
[email protected]83482fbf2012-11-21 14:02:09439 launcher_.reset();
[email protected]e74aaf0a2012-10-12 18:42:28440 // All containers are deleted, so reset shelf_.
441 shelf_ = NULL;
[email protected]d90b8392012-06-13 09:34:56442}
443
[email protected]f1853122012-06-27 16:21:26444void RootWindowController::MoveWindowsTo(aura::RootWindow* dst) {
[email protected]8cfb6722012-11-28 03:28:46445 aura::Window* focused = aura::client::GetFocusClient(dst)->GetFocusedWindow();
[email protected]dbf835d82012-09-11 18:23:09446 aura::WindowTracker tracker;
447 if (focused)
448 tracker.Add(focused);
[email protected]f1853122012-06-27 16:21:26449 aura::client::ActivationClient* activation_client =
450 aura::client::GetActivationClient(dst);
451 aura::Window* active = activation_client->GetActiveWindow();
[email protected]dbf835d82012-09-11 18:23:09452 if (active && focused != active)
453 tracker.Add(active);
[email protected]f1853122012-06-27 16:21:26454 // Deactivate the window to close menu / bubble windows.
455 activation_client->DeactivateWindow(active);
456 // Release capture if any.
457 aura::client::GetCaptureClient(root_window_.get())->
458 SetCapture(NULL);
[email protected]dbf835d82012-09-11 18:23:09459 // Clear the focused window if any. This is necessary because a
460 // window may be deleted when losing focus (fullscreen flash for
461 // example). If the focused window is still alive after move, it'll
462 // be re-focused below.
[email protected]550543e2013-01-11 22:43:44463 aura::client::GetFocusClient(dst)->FocusWindow(NULL);
[email protected]f1853122012-06-27 16:21:26464
[email protected]8039e06c2013-01-17 23:34:50465 // Forget the shelf early so that shelf don't update itself using wrong
466 // display info.
467 workspace_controller_->SetShelf(NULL);
468
[email protected]95058572012-08-20 14:57:29469 ReparentAllWindows(root_window_.get(), dst);
[email protected]f1853122012-06-27 16:21:26470
471 // Restore focused or active window if it's still alive.
[email protected]1d030242012-06-28 18:34:08472 if (focused && tracker.Contains(focused) && dst->Contains(focused)) {
[email protected]550543e2013-01-11 22:43:44473 aura::client::GetFocusClient(dst)->FocusWindow(focused);
[email protected]1d030242012-06-28 18:34:08474 } else if (active && tracker.Contains(active) && dst->Contains(active)) {
[email protected]f1853122012-06-27 16:21:26475 activation_client->ActivateWindow(active);
476 }
477}
478
[email protected]a0afeb12012-12-10 22:57:09479SystemTray* RootWindowController::GetSystemTray() {
480 // We assume in throughout the code that this will not return NULL. If code
481 // triggers this for valid reasons, it should test status_area_widget first.
482 internal::StatusAreaWidget* status_area = status_area_widget();
483 CHECK(status_area);
484 return status_area->system_tray();
485}
486
[email protected]431552c2012-10-23 00:38:33487void RootWindowController::ShowContextMenu(
488 const gfx::Point& location_in_screen) {
489 aura::RootWindow* target = Shell::IsLauncherPerDisplayEnabled() ?
490 root_window() : Shell::GetPrimaryRootWindow();
491 DCHECK(Shell::GetInstance()->delegate());
492 scoped_ptr<ui::MenuModel> menu_model(
493 Shell::GetInstance()->delegate()->CreateContextMenu(target));
494
495 views::MenuModelAdapter menu_model_adapter(menu_model.get());
496 views::MenuRunner menu_runner(menu_model_adapter.CreateMenu());
497 views::Widget* widget =
498 root_window_->GetProperty(kDesktopController)->widget();
499
500 if (menu_runner.RunMenuAt(
501 widget, NULL, gfx::Rect(location_in_screen, gfx::Size()),
502 views::MenuItemView::TOPLEFT, views::MenuRunner::CONTEXT_MENU) ==
503 views::MenuRunner::MENU_DELETED)
504 return;
505
506 Shell::GetInstance()->UpdateShelfVisibility();
507}
508
[email protected]e74aaf0a2012-10-12 18:42:28509void RootWindowController::UpdateShelfVisibility() {
510 shelf_->UpdateVisibilityState();
511}
512
513void RootWindowController::SetShelfAutoHideBehavior(
514 ShelfAutoHideBehavior behavior) {
515 shelf_->SetAutoHideBehavior(behavior);
516}
517
518ShelfAutoHideBehavior RootWindowController::GetShelfAutoHideBehavior() const {
519 return shelf_->auto_hide_behavior();
520}
521
522bool RootWindowController::SetShelfAlignment(ShelfAlignment alignment) {
523 return shelf_->SetAlignment(alignment);
524}
525
526ShelfAlignment RootWindowController::GetShelfAlignment() {
[email protected]1fcfb992012-12-05 01:47:23527 return shelf_->GetAlignment();
[email protected]e74aaf0a2012-10-12 18:42:28528}
529
[email protected]2ee2f5d2013-01-10 23:37:16530bool RootWindowController::IsImmersiveMode() const {
531 aura::Window* container = workspace_controller_->GetActiveWorkspaceWindow();
532 for (size_t i = 0; i < container->children().size(); ++i) {
533 aura::Window* child = container->children()[i];
534 if (child->IsVisible() && child->GetProperty(kImmersiveModeKey))
535 return true;
536 }
537 return false;
538}
539
[email protected]a4cd6d32012-09-12 03:42:13540////////////////////////////////////////////////////////////////////////////////
541// RootWindowController, private:
542
543void RootWindowController::CreateContainersInRootWindow(
544 aura::RootWindow* root_window) {
545 // These containers are just used by PowerButtonController to animate groups
546 // of containers simultaneously without messing up the current transformations
547 // on those containers. These are direct children of the root window; all of
548 // the other containers are their children.
[email protected]e6e41d2f2012-10-29 19:22:19549
550 // The desktop background container is not part of the lock animation, so it
551 // is not included in those animate groups.
[email protected]a4cd6d32012-09-12 03:42:13552 // When screen is locked desktop background is moved to lock screen background
553 // container (moved back on unlock). We want to make sure that there's an
554 // opaque layer occluding the non-lock-screen layers.
[email protected]e6e41d2f2012-10-29 19:22:19555 aura::Window* desktop_background_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27556 kShellWindowId_DesktopBackgroundContainer,
[email protected]a4cd6d32012-09-12 03:42:13557 "DesktopBackgroundContainer",
558 root_window);
[email protected]b5756e22012-11-30 01:32:02559 views::corewm::SetChildWindowVisibilityChangesAnimated(
560 desktop_background_container);
[email protected]a4cd6d32012-09-12 03:42:13561
562 aura::Window* non_lock_screen_containers = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27563 kShellWindowId_NonLockScreenContainersContainer,
[email protected]a4cd6d32012-09-12 03:42:13564 "NonLockScreenContainersContainer",
565 root_window);
566
567 aura::Window* lock_background_containers = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27568 kShellWindowId_LockScreenBackgroundContainer,
[email protected]a4cd6d32012-09-12 03:42:13569 "LockScreenBackgroundContainer",
570 root_window);
[email protected]b5756e22012-11-30 01:32:02571 views::corewm::SetChildWindowVisibilityChangesAnimated(
572 lock_background_containers);
[email protected]a4cd6d32012-09-12 03:42:13573
574 aura::Window* lock_screen_containers = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27575 kShellWindowId_LockScreenContainersContainer,
[email protected]a4cd6d32012-09-12 03:42:13576 "LockScreenContainersContainer",
577 root_window);
578 aura::Window* lock_screen_related_containers = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27579 kShellWindowId_LockScreenRelatedContainersContainer,
[email protected]a4cd6d32012-09-12 03:42:13580 "LockScreenRelatedContainersContainer",
581 root_window);
582
[email protected]c0ce80e2012-10-05 23:28:27583 CreateContainer(kShellWindowId_UnparentedControlContainer,
[email protected]a4cd6d32012-09-12 03:42:13584 "UnparentedControlContainer",
585 non_lock_screen_containers);
586
587 aura::Window* default_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27588 kShellWindowId_DefaultContainer,
[email protected]a4cd6d32012-09-12 03:42:13589 "DefaultContainer",
590 non_lock_screen_containers);
[email protected]b5756e22012-11-30 01:32:02591 views::corewm::SetChildWindowVisibilityChangesAnimated(default_container);
[email protected]a4cd6d32012-09-12 03:42:13592 SetUsesScreenCoordinates(default_container);
593
594 aura::Window* always_on_top_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27595 kShellWindowId_AlwaysOnTopContainer,
[email protected]a4cd6d32012-09-12 03:42:13596 "AlwaysOnTopContainer",
597 non_lock_screen_containers);
598 always_on_top_container_handler_.reset(
599 new ToplevelWindowEventHandler(always_on_top_container));
[email protected]b5756e22012-11-30 01:32:02600 views::corewm::SetChildWindowVisibilityChangesAnimated(
601 always_on_top_container);
[email protected]a4cd6d32012-09-12 03:42:13602 SetUsesScreenCoordinates(always_on_top_container);
603
604 aura::Window* panel_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27605 kShellWindowId_PanelContainer,
[email protected]a4cd6d32012-09-12 03:42:13606 "PanelContainer",
607 non_lock_screen_containers);
608 SetUsesScreenCoordinates(panel_container);
609
610 aura::Window* launcher_container =
[email protected]c0ce80e2012-10-05 23:28:27611 CreateContainer(kShellWindowId_LauncherContainer,
[email protected]a4cd6d32012-09-12 03:42:13612 "LauncherContainer",
613 non_lock_screen_containers);
614 SetUsesScreenCoordinates(launcher_container);
615
[email protected]dc851a4e52012-10-03 00:05:55616 aura::Window* app_list_container =
[email protected]c0ce80e2012-10-05 23:28:27617 CreateContainer(kShellWindowId_AppListContainer,
[email protected]dc851a4e52012-10-03 00:05:55618 "AppListContainer",
619 non_lock_screen_containers);
620 SetUsesScreenCoordinates(app_list_container);
[email protected]a4cd6d32012-09-12 03:42:13621
622 aura::Window* modal_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27623 kShellWindowId_SystemModalContainer,
[email protected]a4cd6d32012-09-12 03:42:13624 "SystemModalContainer",
625 non_lock_screen_containers);
626 modal_container_handler_.reset(
627 new ToplevelWindowEventHandler(modal_container));
[email protected]a4cd6d32012-09-12 03:42:13628 modal_container->SetLayoutManager(
[email protected]c0ce80e2012-10-05 23:28:27629 new SystemModalContainerLayoutManager(modal_container));
[email protected]b5756e22012-11-30 01:32:02630 views::corewm::SetChildWindowVisibilityChangesAnimated(modal_container);
[email protected]a4cd6d32012-09-12 03:42:13631 SetUsesScreenCoordinates(modal_container);
632
633 aura::Window* input_method_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27634 kShellWindowId_InputMethodContainer,
[email protected]a4cd6d32012-09-12 03:42:13635 "InputMethodContainer",
636 non_lock_screen_containers);
637 SetUsesScreenCoordinates(input_method_container);
638
639 // TODO(beng): Figure out if we can make this use
640 // SystemModalContainerEventFilter instead of stops_event_propagation.
641 aura::Window* lock_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27642 kShellWindowId_LockScreenContainer,
[email protected]a4cd6d32012-09-12 03:42:13643 "LockScreenContainer",
644 lock_screen_containers);
645 lock_container->SetLayoutManager(
[email protected]c0ce80e2012-10-05 23:28:27646 new BaseLayoutManager(root_window));
[email protected]a4cd6d32012-09-12 03:42:13647 SetUsesScreenCoordinates(lock_container);
648 // TODO(beng): stopsevents
649
650 aura::Window* lock_modal_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27651 kShellWindowId_LockSystemModalContainer,
[email protected]a4cd6d32012-09-12 03:42:13652 "LockSystemModalContainer",
653 lock_screen_containers);
654 lock_modal_container_handler_.reset(
655 new ToplevelWindowEventHandler(lock_modal_container));
[email protected]a4cd6d32012-09-12 03:42:13656 lock_modal_container->SetLayoutManager(
[email protected]c0ce80e2012-10-05 23:28:27657 new SystemModalContainerLayoutManager(lock_modal_container));
[email protected]b5756e22012-11-30 01:32:02658 views::corewm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
[email protected]a4cd6d32012-09-12 03:42:13659 SetUsesScreenCoordinates(lock_modal_container);
660
661 aura::Window* status_container =
[email protected]c0ce80e2012-10-05 23:28:27662 CreateContainer(kShellWindowId_StatusContainer,
[email protected]a4cd6d32012-09-12 03:42:13663 "StatusContainer",
664 lock_screen_related_containers);
665 SetUsesScreenCoordinates(status_container);
666
667 aura::Window* settings_bubble_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27668 kShellWindowId_SettingBubbleContainer,
[email protected]a4cd6d32012-09-12 03:42:13669 "SettingBubbleContainer",
670 lock_screen_related_containers);
[email protected]b5756e22012-11-30 01:32:02671 views::corewm::SetChildWindowVisibilityChangesAnimated(
672 settings_bubble_container);
[email protected]a4cd6d32012-09-12 03:42:13673 SetUsesScreenCoordinates(settings_bubble_container);
674
675 aura::Window* menu_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27676 kShellWindowId_MenuContainer,
[email protected]a4cd6d32012-09-12 03:42:13677 "MenuContainer",
678 lock_screen_related_containers);
[email protected]b5756e22012-11-30 01:32:02679 views::corewm::SetChildWindowVisibilityChangesAnimated(menu_container);
[email protected]a4cd6d32012-09-12 03:42:13680 SetUsesScreenCoordinates(menu_container);
681
682 aura::Window* drag_drop_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27683 kShellWindowId_DragImageAndTooltipContainer,
[email protected]a4cd6d32012-09-12 03:42:13684 "DragImageAndTooltipContainer",
685 lock_screen_related_containers);
[email protected]b5756e22012-11-30 01:32:02686 views::corewm::SetChildWindowVisibilityChangesAnimated(drag_drop_container);
[email protected]a4cd6d32012-09-12 03:42:13687 SetUsesScreenCoordinates(drag_drop_container);
688
689 aura::Window* overlay_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27690 kShellWindowId_OverlayContainer,
[email protected]a4cd6d32012-09-12 03:42:13691 "OverlayContainer",
692 lock_screen_related_containers);
693 SetUsesScreenCoordinates(overlay_container);
[email protected]a07615f2012-10-24 08:23:08694
695 CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
696 "PowerButtonAnimationContainer", root_window) ;
[email protected]a4cd6d32012-09-12 03:42:13697}
698
[email protected]d90b8392012-06-13 09:34:56699} // namespace internal
700} // namespace ash