Automate more Better Session Restore tests: POST data and cookies.
[chromium-blink-merge.git] / ash / root_window_controller.cc
blobfae9a4b93d51c419709155c84c741f11f48b6153
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"
7 #include <vector>
9 #include "ash/ash_switches.h"
10 #include "ash/desktop_background/desktop_background_widget_controller.h"
11 #include "ash/display/display_controller.h"
12 #include "ash/display/multi_display_manager.h"
13 #include "ash/focus_cycler.h"
14 #include "ash/shell.h"
15 #include "ash/shell_delegate.h"
16 #include "ash/shell_factory.h"
17 #include "ash/shell_window_ids.h"
18 #include "ash/system/status_area_widget.h"
19 #include "ash/system/tray/system_tray_delegate.h"
20 #include "ash/wm/base_layout_manager.h"
21 #include "ash/wm/panel_layout_manager.h"
22 #include "ash/wm/panel_window_event_filter.h"
23 #include "ash/wm/property_util.h"
24 #include "ash/wm/root_window_layout_manager.h"
25 #include "ash/wm/screen_dimmer.h"
26 #include "ash/wm/shelf_layout_manager.h"
27 #include "ash/wm/shelf_types.h"
28 #include "ash/wm/status_area_layout_manager.h"
29 #include "ash/wm/system_background_controller.h"
30 #include "ash/wm/system_modal_container_layout_manager.h"
31 #include "ash/wm/toplevel_window_event_handler.h"
32 #include "ash/wm/visibility_controller.h"
33 #include "ash/wm/window_properties.h"
34 #include "ash/wm/workspace_controller.h"
35 #include "base/command_line.h"
36 #include "ui/aura/client/activation_client.h"
37 #include "ui/aura/client/aura_constants.h"
38 #include "ui/aura/client/capture_client.h"
39 #include "ui/aura/client/tooltip_client.h"
40 #include "ui/aura/focus_manager.h"
41 #include "ui/aura/root_window.h"
42 #include "ui/aura/window.h"
43 #include "ui/aura/window_observer.h"
44 #include "ui/aura/window_tracker.h"
45 #include "ui/base/models/menu_model.h"
46 #include "ui/gfx/display.h"
47 #include "ui/gfx/screen.h"
48 #include "ui/views/controls/menu/menu_model_adapter.h"
49 #include "ui/views/controls/menu/menu_runner.h"
50 #include "ui/views/view_model.h"
51 #include "ui/views/view_model_utils.h"
53 namespace ash {
54 namespace {
56 // Creates a new window for use as a container.
57 aura::Window* CreateContainer(int window_id,
58 const char* name,
59 aura::Window* parent) {
60 aura::Window* container = new aura::Window(NULL);
61 container->set_id(window_id);
62 container->SetName(name);
63 container->Init(ui::LAYER_NOT_DRAWN);
64 parent->AddChild(container);
65 if (window_id != internal::kShellWindowId_UnparentedControlContainer)
66 container->Show();
67 return container;
70 // Returns all the children of the workspace windows, eg the standard top-level
71 // windows.
72 std::vector<aura::Window*> GetWorkspaceWindows(aura::RootWindow* root) {
73 using aura::Window;
75 std::vector<Window*> windows;
76 Window* container = Shell::GetContainer(
77 root, internal::kShellWindowId_DefaultContainer);
78 for (Window::Windows::const_reverse_iterator i =
79 container->children().rbegin();
80 i != container->children().rend(); ++i) {
81 Window* workspace_window = *i;
82 if (workspace_window->id() == internal::kShellWindowId_WorkspaceContainer) {
83 windows.insert(windows.end(), workspace_window->children().begin(),
84 workspace_window->children().end());
87 return windows;
90 // Reparents |window| to |new_parent|.
91 void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
92 // Update the restore bounds to make it relative to the display.
93 gfx::Rect restore_bounds(GetRestoreBoundsInParent(window));
94 new_parent->AddChild(window);
95 if (!restore_bounds.IsEmpty())
96 SetRestoreBoundsInParent(window, restore_bounds);
99 // Reparents the appropriate set of windows from |src| to |dst|.
100 void ReparentAllWindows(aura::RootWindow* src, aura::RootWindow* dst) {
101 // Set of windows to move.
102 const int kContainerIdsToMove[] = {
103 internal::kShellWindowId_DefaultContainer,
104 internal::kShellWindowId_AlwaysOnTopContainer,
105 internal::kShellWindowId_SystemModalContainer,
106 internal::kShellWindowId_LockSystemModalContainer,
107 internal::kShellWindowId_InputMethodContainer,
109 // For workspace windows we need to manually reparent the windows. This way
110 // workspace can move the windows to the appropriate workspace.
111 std::vector<aura::Window*> windows(GetWorkspaceWindows(src));
112 internal::WorkspaceController* workspace_controller =
113 GetRootWindowController(dst)->workspace_controller();
114 for (size_t i = 0; i < windows.size(); ++i) {
115 aura::Window* new_parent =
116 workspace_controller->GetParentForNewWindow(windows[i]);
117 ReparentWindow(windows[i], new_parent);
119 for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) {
120 int id = kContainerIdsToMove[i];
121 if (id == internal::kShellWindowId_DefaultContainer)
122 continue;
124 aura::Window* src_container = Shell::GetContainer(src, id);
125 aura::Window* dst_container = Shell::GetContainer(dst, id);
126 aura::Window::Windows children = src_container->children();
127 for (aura::Window::Windows::iterator iter = children.begin();
128 iter != children.end(); ++iter) {
129 aura::Window* window = *iter;
130 // Don't move modal screen.
131 if (internal::SystemModalContainerLayoutManager::IsModalBackground(
132 window))
133 continue;
135 ReparentWindow(window, dst_container);
140 // Mark the container window so that a widget added to this container will
141 // use the virtual screeen coordinates instead of parent.
142 void SetUsesScreenCoordinates(aura::Window* container) {
143 container->SetProperty(internal::kUsesScreenCoordinatesKey, true);
146 } // namespace
148 namespace internal {
150 RootWindowController::RootWindowController(aura::RootWindow* root_window)
151 : root_window_(root_window),
152 root_window_layout_(NULL),
153 status_area_widget_(NULL),
154 shelf_(NULL),
155 panel_layout_manager_(NULL) {
156 SetRootWindowController(root_window, this);
157 screen_dimmer_.reset(new ScreenDimmer(root_window));
160 RootWindowController::~RootWindowController() {
161 Shutdown();
162 root_window_.reset();
165 // static
166 internal::RootWindowController*
167 RootWindowController::ForLauncher(aura::Window* window) {
168 if (Shell::IsLauncherPerDisplayEnabled())
169 return GetRootWindowController(window->GetRootWindow());
170 else
171 return Shell::GetPrimaryRootWindowController();
174 void RootWindowController::Shutdown() {
175 CloseChildWindows();
176 if (Shell::GetActiveRootWindow() == root_window_.get()) {
177 Shell::GetInstance()->set_active_root_window(
178 Shell::GetPrimaryRootWindow() == root_window_.get() ?
179 NULL : Shell::GetPrimaryRootWindow());
181 SetRootWindowController(root_window_.get(), NULL);
182 screen_dimmer_.reset();
183 workspace_controller_.reset();
184 // Forget with the display ID so that display lookup
185 // ends up with invalid display.
186 root_window_->ClearProperty(kDisplayIdKey);
187 // And this root window should no longer process events.
188 root_window_->PrepareForShutdown();
190 system_background_.reset();
192 // Launcher widget has an InputMethodBridge that references to
193 // |input_method_filter_|'s |input_method_|. So explicitly release
194 // |launcher_| before |input_method_filter_|. And this needs to be
195 // after we delete all containers in case there are still live
196 // browser windows which access LauncherModel during close.
197 launcher_.reset();
200 SystemModalContainerLayoutManager*
201 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
202 aura::Window* container = NULL;
203 if (window) {
204 if (window->parent() &&
205 window->parent()->id() >= kShellWindowId_LockScreenContainer) {
206 container = GetContainer(kShellWindowId_LockSystemModalContainer);
207 } else {
208 container = GetContainer(kShellWindowId_SystemModalContainer);
210 } else {
211 user::LoginStatus login = Shell::GetInstance()->status_area_widget() ?
212 Shell::GetInstance()->tray_delegate()->GetUserLoginStatus() :
213 user::LOGGED_IN_NONE;
214 int modal_window_id = (login == user::LOGGED_IN_LOCKED ||
215 login == user::LOGGED_IN_NONE) ?
216 kShellWindowId_LockSystemModalContainer :
217 kShellWindowId_SystemModalContainer;
218 container = GetContainer(modal_window_id);
220 return static_cast<SystemModalContainerLayoutManager*>(
221 container->layout_manager());
224 aura::Window* RootWindowController::GetContainer(int container_id) {
225 return root_window_->GetChildById(container_id);
228 void RootWindowController::InitLayoutManagers() {
229 root_window_layout_ =
230 new RootWindowLayoutManager(root_window_.get());
231 root_window_->SetLayoutManager(root_window_layout_);
233 aura::Window* default_container =
234 GetContainer(kShellWindowId_DefaultContainer);
235 // Workspace manager has its own layout managers.
236 workspace_controller_.reset(
237 new WorkspaceController(default_container));
239 aura::Window* always_on_top_container =
240 GetContainer(kShellWindowId_AlwaysOnTopContainer);
241 always_on_top_container->SetLayoutManager(
242 new BaseLayoutManager(
243 always_on_top_container->GetRootWindow()));
246 void RootWindowController::InitForPrimaryDisplay() {
247 DCHECK(!status_area_widget_);
248 aura::Window* status_container =
249 GetContainer(ash::internal::kShellWindowId_StatusContainer);
250 // Initialize Primary RootWindow specific items.
251 status_area_widget_ = new internal::StatusAreaWidget(status_container);
252 status_area_widget_->CreateTrayViews();
253 // Login screen manages status area visibility by itself.
254 ShellDelegate* shell_delegate = Shell::GetInstance()->delegate();
255 if (shell_delegate->IsSessionStarted())
256 status_area_widget_->Show();
258 Shell::GetInstance()->focus_cycler()->AddWidget(status_area_widget_);
260 internal::ShelfLayoutManager* shelf_layout_manager =
261 new internal::ShelfLayoutManager(status_area_widget_);
262 GetContainer(internal::kShellWindowId_LauncherContainer)->
263 SetLayoutManager(shelf_layout_manager);
264 shelf_ = shelf_layout_manager;
266 internal::StatusAreaLayoutManager* status_area_layout_manager =
267 new internal::StatusAreaLayoutManager(shelf_layout_manager);
268 GetContainer(internal::kShellWindowId_StatusContainer)->
269 SetLayoutManager(status_area_layout_manager);
271 shelf_layout_manager->set_workspace_controller(
272 workspace_controller());
274 workspace_controller()->SetShelf(shelf_);
276 // Create Panel layout manager
277 aura::Window* panel_container = GetContainer(
278 internal::kShellWindowId_PanelContainer);
279 panel_layout_manager_ =
280 new internal::PanelLayoutManager(panel_container);
281 panel_container->SetEventFilter(
282 new internal::PanelWindowEventFilter(
283 panel_container, panel_layout_manager_));
284 panel_container->SetLayoutManager(panel_layout_manager_);
286 if (shell_delegate->IsUserLoggedIn())
287 CreateLauncher();
290 void RootWindowController::CreateContainers() {
291 CreateContainersInRootWindow(root_window_.get());
294 void RootWindowController::CreateSystemBackground(
295 bool is_first_run_after_boot) {
296 SystemBackgroundController::Content initial_content =
297 SystemBackgroundController::CONTENT_BLACK;
298 #if defined(OS_CHROMEOS)
299 if (is_first_run_after_boot) {
300 if (CommandLine::ForCurrentProcess()->HasSwitch(
301 switches::kAshCopyHostBackgroundAtBoot)) {
302 initial_content = SystemBackgroundController::CONTENT_COPY_FROM_HOST;
303 } else {
304 initial_content =
305 SystemBackgroundController::CONTENT_CHROME_OS_BOOT_COLOR;
308 #endif
309 system_background_.reset(
310 new SystemBackgroundController(root_window_.get(), initial_content));
313 void RootWindowController::CreateLauncher() {
314 if (launcher_.get())
315 return;
317 aura::Window* default_container =
318 GetContainer(internal::kShellWindowId_DefaultContainer);
319 launcher_.reset(new Launcher(default_container, shelf_));
321 launcher_->SetFocusCycler(Shell::GetInstance()->focus_cycler());
322 shelf_->SetLauncher(launcher_.get());
324 if (panel_layout_manager_)
325 panel_layout_manager_->SetLauncher(launcher_.get());
327 ShellDelegate* delegate = Shell::GetInstance()->delegate();
328 if (delegate)
329 launcher_->SetVisible(delegate->IsSessionStarted());
330 launcher_->widget()->Show();
333 void RootWindowController::ShowLauncher() {
334 if (!launcher_.get())
335 return;
336 launcher_->SetVisible(true);
337 status_area_widget_->Show();
340 void RootWindowController::OnLoginStateChanged(user::LoginStatus status) {
341 // TODO(oshima): remove if when launcher per display is enabled by
342 // default.
343 if (shelf_)
344 shelf_->UpdateVisibilityState();
347 void RootWindowController::UpdateAfterLoginStatusChange(
348 user::LoginStatus status) {
349 if (status_area_widget_)
350 status_area_widget_->UpdateAfterLoginStatusChange(status);
353 void RootWindowController::HandleDesktopBackgroundVisible() {
354 system_background_->SetContent(SystemBackgroundController::CONTENT_BLACK);
357 void RootWindowController::CloseChildWindows() {
358 // The status area needs to be shut down before the windows are destroyed.
359 if (status_area_widget_) {
360 status_area_widget_->Shutdown();
361 status_area_widget_ = NULL;
364 // Closing the windows frees the workspace controller.
365 if (shelf_)
366 shelf_->set_workspace_controller(NULL);
368 // Close background widget first as it depends on tooltip.
369 root_window_->SetProperty(kDesktopController,
370 static_cast<DesktopBackgroundWidgetController*>(NULL));
371 root_window_->SetProperty(kAnimatingDesktopController,
372 static_cast<AnimatingDesktopController*>(NULL));
374 workspace_controller_.reset();
375 aura::client::SetTooltipClient(root_window_.get(), NULL);
377 while (!root_window_->children().empty()) {
378 aura::Window* child = root_window_->children()[0];
379 delete child;
382 // All containers are deleted, so reset shelf_.
383 shelf_ = NULL;
386 void RootWindowController::MoveWindowsTo(aura::RootWindow* dst) {
387 aura::Window* focused = dst->GetFocusManager()->GetFocusedWindow();
388 aura::WindowTracker tracker;
389 if (focused)
390 tracker.Add(focused);
391 aura::client::ActivationClient* activation_client =
392 aura::client::GetActivationClient(dst);
393 aura::Window* active = activation_client->GetActiveWindow();
394 if (active && focused != active)
395 tracker.Add(active);
396 // Deactivate the window to close menu / bubble windows.
397 activation_client->DeactivateWindow(active);
398 // Release capture if any.
399 aura::client::GetCaptureClient(root_window_.get())->
400 SetCapture(NULL);
401 // Clear the focused window if any. This is necessary because a
402 // window may be deleted when losing focus (fullscreen flash for
403 // example). If the focused window is still alive after move, it'll
404 // be re-focused below.
405 dst->GetFocusManager()->SetFocusedWindow(NULL, NULL);
407 ReparentAllWindows(root_window_.get(), dst);
409 // Restore focused or active window if it's still alive.
410 if (focused && tracker.Contains(focused) && dst->Contains(focused)) {
411 dst->GetFocusManager()->SetFocusedWindow(focused, NULL);
412 } else if (active && tracker.Contains(active) && dst->Contains(active)) {
413 activation_client->ActivateWindow(active);
417 void RootWindowController::ShowContextMenu(
418 const gfx::Point& location_in_screen) {
419 aura::RootWindow* target = Shell::IsLauncherPerDisplayEnabled() ?
420 root_window() : Shell::GetPrimaryRootWindow();
421 DCHECK(Shell::GetInstance()->delegate());
422 scoped_ptr<ui::MenuModel> menu_model(
423 Shell::GetInstance()->delegate()->CreateContextMenu(target));
425 views::MenuModelAdapter menu_model_adapter(menu_model.get());
426 views::MenuRunner menu_runner(menu_model_adapter.CreateMenu());
427 views::Widget* widget =
428 root_window_->GetProperty(kDesktopController)->widget();
430 if (menu_runner.RunMenuAt(
431 widget, NULL, gfx::Rect(location_in_screen, gfx::Size()),
432 views::MenuItemView::TOPLEFT, views::MenuRunner::CONTEXT_MENU) ==
433 views::MenuRunner::MENU_DELETED)
434 return;
436 Shell::GetInstance()->UpdateShelfVisibility();
439 void RootWindowController::UpdateShelfVisibility() {
440 shelf_->UpdateVisibilityState();
443 void RootWindowController::SetShelfAutoHideBehavior(
444 ShelfAutoHideBehavior behavior) {
445 shelf_->SetAutoHideBehavior(behavior);
448 ShelfAutoHideBehavior RootWindowController::GetShelfAutoHideBehavior() const {
449 return shelf_->auto_hide_behavior();
452 bool RootWindowController::SetShelfAlignment(ShelfAlignment alignment) {
453 return shelf_->SetAlignment(alignment);
456 ShelfAlignment RootWindowController::GetShelfAlignment() {
457 return shelf_->alignment();
460 bool RootWindowController::IsShelfAutoHideMenuHideChecked() {
461 return GetShelfAutoHideBehavior() == ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
464 ShelfAutoHideBehavior
465 RootWindowController::GetToggledShelfAutoHideBehavior() {
466 return IsShelfAutoHideMenuHideChecked() ?
467 ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER :
468 ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
471 ////////////////////////////////////////////////////////////////////////////////
472 // RootWindowController, private:
474 void RootWindowController::CreateContainersInRootWindow(
475 aura::RootWindow* root_window) {
476 // These containers are just used by PowerButtonController to animate groups
477 // of containers simultaneously without messing up the current transformations
478 // on those containers. These are direct children of the root window; all of
479 // the other containers are their children.
481 // The desktop background container is not part of the lock animation, so it
482 // is not included in those animate groups.
483 // When screen is locked desktop background is moved to lock screen background
484 // container (moved back on unlock). We want to make sure that there's an
485 // opaque layer occluding the non-lock-screen layers.
486 aura::Window* desktop_background_container = CreateContainer(
487 kShellWindowId_DesktopBackgroundContainer,
488 "DesktopBackgroundContainer",
489 root_window);
490 SetChildWindowVisibilityChangesAnimated(desktop_background_container);
492 aura::Window* non_lock_screen_containers = CreateContainer(
493 kShellWindowId_NonLockScreenContainersContainer,
494 "NonLockScreenContainersContainer",
495 root_window);
497 aura::Window* lock_background_containers = CreateContainer(
498 kShellWindowId_LockScreenBackgroundContainer,
499 "LockScreenBackgroundContainer",
500 root_window);
501 SetChildWindowVisibilityChangesAnimated(lock_background_containers);
503 aura::Window* lock_screen_containers = CreateContainer(
504 kShellWindowId_LockScreenContainersContainer,
505 "LockScreenContainersContainer",
506 root_window);
507 aura::Window* lock_screen_related_containers = CreateContainer(
508 kShellWindowId_LockScreenRelatedContainersContainer,
509 "LockScreenRelatedContainersContainer",
510 root_window);
512 CreateContainer(kShellWindowId_UnparentedControlContainer,
513 "UnparentedControlContainer",
514 non_lock_screen_containers);
516 aura::Window* default_container = CreateContainer(
517 kShellWindowId_DefaultContainer,
518 "DefaultContainer",
519 non_lock_screen_containers);
520 SetChildWindowVisibilityChangesAnimated(default_container);
521 SetUsesScreenCoordinates(default_container);
523 aura::Window* always_on_top_container = CreateContainer(
524 kShellWindowId_AlwaysOnTopContainer,
525 "AlwaysOnTopContainer",
526 non_lock_screen_containers);
527 always_on_top_container_handler_.reset(
528 new ToplevelWindowEventHandler(always_on_top_container));
529 SetChildWindowVisibilityChangesAnimated(always_on_top_container);
530 SetUsesScreenCoordinates(always_on_top_container);
532 aura::Window* panel_container = CreateContainer(
533 kShellWindowId_PanelContainer,
534 "PanelContainer",
535 non_lock_screen_containers);
536 SetUsesScreenCoordinates(panel_container);
538 aura::Window* launcher_container =
539 CreateContainer(kShellWindowId_LauncherContainer,
540 "LauncherContainer",
541 non_lock_screen_containers);
542 SetUsesScreenCoordinates(launcher_container);
544 aura::Window* app_list_container =
545 CreateContainer(kShellWindowId_AppListContainer,
546 "AppListContainer",
547 non_lock_screen_containers);
548 SetUsesScreenCoordinates(app_list_container);
550 aura::Window* modal_container = CreateContainer(
551 kShellWindowId_SystemModalContainer,
552 "SystemModalContainer",
553 non_lock_screen_containers);
554 modal_container_handler_.reset(
555 new ToplevelWindowEventHandler(modal_container));
556 modal_container->SetLayoutManager(
557 new SystemModalContainerLayoutManager(modal_container));
558 SetChildWindowVisibilityChangesAnimated(modal_container);
559 SetUsesScreenCoordinates(modal_container);
561 aura::Window* input_method_container = CreateContainer(
562 kShellWindowId_InputMethodContainer,
563 "InputMethodContainer",
564 non_lock_screen_containers);
565 SetUsesScreenCoordinates(input_method_container);
567 // TODO(beng): Figure out if we can make this use
568 // SystemModalContainerEventFilter instead of stops_event_propagation.
569 aura::Window* lock_container = CreateContainer(
570 kShellWindowId_LockScreenContainer,
571 "LockScreenContainer",
572 lock_screen_containers);
573 lock_container->SetLayoutManager(
574 new BaseLayoutManager(root_window));
575 SetUsesScreenCoordinates(lock_container);
576 // TODO(beng): stopsevents
578 aura::Window* lock_modal_container = CreateContainer(
579 kShellWindowId_LockSystemModalContainer,
580 "LockSystemModalContainer",
581 lock_screen_containers);
582 lock_modal_container_handler_.reset(
583 new ToplevelWindowEventHandler(lock_modal_container));
584 lock_modal_container->SetLayoutManager(
585 new SystemModalContainerLayoutManager(lock_modal_container));
586 SetChildWindowVisibilityChangesAnimated(lock_modal_container);
587 SetUsesScreenCoordinates(lock_modal_container);
589 aura::Window* status_container =
590 CreateContainer(kShellWindowId_StatusContainer,
591 "StatusContainer",
592 lock_screen_related_containers);
593 SetUsesScreenCoordinates(status_container);
595 aura::Window* settings_bubble_container = CreateContainer(
596 kShellWindowId_SettingBubbleContainer,
597 "SettingBubbleContainer",
598 lock_screen_related_containers);
599 SetChildWindowVisibilityChangesAnimated(settings_bubble_container);
600 SetUsesScreenCoordinates(settings_bubble_container);
602 aura::Window* menu_container = CreateContainer(
603 kShellWindowId_MenuContainer,
604 "MenuContainer",
605 lock_screen_related_containers);
606 SetChildWindowVisibilityChangesAnimated(menu_container);
607 SetUsesScreenCoordinates(menu_container);
609 aura::Window* drag_drop_container = CreateContainer(
610 kShellWindowId_DragImageAndTooltipContainer,
611 "DragImageAndTooltipContainer",
612 lock_screen_related_containers);
613 SetChildWindowVisibilityChangesAnimated(drag_drop_container);
614 SetUsesScreenCoordinates(drag_drop_container);
616 aura::Window* overlay_container = CreateContainer(
617 kShellWindowId_OverlayContainer,
618 "OverlayContainer",
619 lock_screen_related_containers);
620 SetUsesScreenCoordinates(overlay_container);
622 CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
623 "PowerButtonAnimationContainer", root_window) ;
626 } // namespace internal
627 } // namespace ash