Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ash / root_window_controller.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/root_window_controller.h"
6
7 #include <queue>
8 #include <vector>
9
10 #include "ash/ash_constants.h"
11 #include "ash/ash_switches.h"
12 #include "ash/desktop_background/desktop_background_controller.h"
13 #include "ash/desktop_background/desktop_background_widget_controller.h"
14 #include "ash/desktop_background/user_wallpaper_delegate.h"
15 #include "ash/display/display_manager.h"
16 #include "ash/focus_cycler.h"
17 #include "ash/high_contrast/high_contrast_controller.h"
18 #include "ash/host/ash_window_tree_host.h"
19 #include "ash/root_window_settings.h"
20 #include "ash/session/session_state_delegate.h"
21 #include "ash/shelf/shelf_layout_manager.h"
22 #include "ash/shelf/shelf_types.h"
23 #include "ash/shelf/shelf_widget.h"
24 #include "ash/shell.h"
25 #include "ash/shell_delegate.h"
26 #include "ash/shell_factory.h"
27 #include "ash/shell_window_ids.h"
28 #include "ash/switchable_windows.h"
29 #include "ash/system/status_area_widget.h"
30 #include "ash/system/tray/system_tray_delegate.h"
31 #include "ash/system/tray/system_tray_notifier.h"
32 #include "ash/touch/touch_hud_debug.h"
33 #include "ash/touch/touch_hud_projection.h"
34 #include "ash/touch/touch_observer_hud.h"
35 #include "ash/wm/always_on_top_controller.h"
36 #include "ash/wm/dock/docked_window_layout_manager.h"
37 #include "ash/wm/lock_layout_manager.h"
38 #include "ash/wm/panels/attached_panel_window_targeter.h"
39 #include "ash/wm/panels/panel_layout_manager.h"
40 #include "ash/wm/panels/panel_window_event_handler.h"
41 #include "ash/wm/root_window_layout_manager.h"
42 #include "ash/wm/screen_dimmer.h"
43 #include "ash/wm/stacking_controller.h"
44 #include "ash/wm/status_area_layout_manager.h"
45 #include "ash/wm/system_background_controller.h"
46 #include "ash/wm/system_modal_container_layout_manager.h"
47 #include "ash/wm/virtual_keyboard_container_layout_manager.h"
48 #include "ash/wm/window_properties.h"
49 #include "ash/wm/window_state.h"
50 #include "ash/wm/window_util.h"
51 #include "ash/wm/workspace/workspace_layout_manager.h"
52 #include "ash/wm/workspace_controller.h"
53 #include "base/command_line.h"
54 #include "base/time/time.h"
55 #include "ui/aura/client/aura_constants.h"
56 #include "ui/aura/client/screen_position_client.h"
57 #include "ui/aura/window.h"
58 #include "ui/aura/window_delegate.h"
59 #include "ui/aura/window_event_dispatcher.h"
60 #include "ui/aura/window_observer.h"
61 #include "ui/aura/window_tracker.h"
62 #include "ui/base/hit_test.h"
63 #include "ui/base/models/menu_model.h"
64 #include "ui/gfx/display.h"
65 #include "ui/gfx/screen.h"
66 #include "ui/keyboard/keyboard_controller.h"
67 #include "ui/keyboard/keyboard_util.h"
68 #include "ui/views/controls/menu/menu_runner.h"
69 #include "ui/views/view_model.h"
70 #include "ui/views/view_model_utils.h"
71 #include "ui/wm/core/capture_controller.h"
72 #include "ui/wm/core/easy_resize_window_targeter.h"
73 #include "ui/wm/core/visibility_controller.h"
74 #include "ui/wm/core/window_util.h"
75 #include "ui/wm/public/drag_drop_client.h"
76 #include "ui/wm/public/tooltip_client.h"
77 #include "ui/wm/public/window_types.h"
78
79 #if defined(OS_CHROMEOS)
80 #include "ash/ash_touch_exploration_manager_chromeos.h"
81 #include "ash/wm/boot_splash_screen_chromeos.h"
82 #include "ui/chromeos/touch_exploration_controller.h"
83 #endif
84
85 namespace ash {
86 namespace {
87
88 #if defined(OS_CHROMEOS)
89 // Duration for the animation that hides the boot splash screen, in
90 // milliseconds.  This should be short enough in relation to
91 // wm/window_animation.cc's brightness/grayscale fade animation that the login
92 // background image animation isn't hidden by the splash screen animation.
93 const int kBootSplashScreenHideDurationMs = 500;
94 #endif
95
96 // Creates a new window for use as a container.
97 aura::Window* CreateContainer(int window_id,
98                               const char* name,
99                               aura::Window* parent) {
100   aura::Window* container = new aura::Window(NULL);
101   container->set_id(window_id);
102   container->SetName(name);
103   container->Init(aura::WINDOW_LAYER_NOT_DRAWN);
104   parent->AddChild(container);
105   if (window_id != kShellWindowId_UnparentedControlContainer)
106     container->Show();
107   return container;
108 }
109
110 float ToRelativeValue(int value, int src, int dst) {
111   return static_cast<float>(value) / static_cast<float>(src) * dst;
112 }
113
114 void MoveOriginRelativeToSize(const gfx::Size& src_size,
115                                 const gfx::Size& dst_size,
116                                 gfx::Rect* bounds_in_out) {
117   gfx::Point origin = bounds_in_out->origin();
118   bounds_in_out->set_origin(gfx::Point(
119       ToRelativeValue(origin.x(), src_size.width(), dst_size.width()),
120       ToRelativeValue(origin.y(), src_size.height(), dst_size.height())));
121 }
122
123 // Reparents |window| to |new_parent|.
124 void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
125   const gfx::Size src_size = window->parent()->bounds().size();
126   const gfx::Size dst_size = new_parent->bounds().size();
127   // Update the restore bounds to make it relative to the display.
128   wm::WindowState* state = wm::GetWindowState(window);
129   gfx::Rect restore_bounds;
130   bool has_restore_bounds = state->HasRestoreBounds();
131
132   bool update_bounds = (state->IsNormalOrSnapped() || state->IsMinimized()) &&
133                        new_parent->id() != kShellWindowId_DockedContainer;
134   gfx::Rect local_bounds;
135   if (update_bounds) {
136     local_bounds = state->window()->bounds();
137     MoveOriginRelativeToSize(src_size, dst_size, &local_bounds);
138   }
139
140   if (has_restore_bounds) {
141     restore_bounds = state->GetRestoreBoundsInParent();
142     MoveOriginRelativeToSize(src_size, dst_size, &restore_bounds);
143   }
144
145   new_parent->AddChild(window);
146
147   // Docked windows have bounds handled by the layout manager in AddChild().
148   if (update_bounds)
149     window->SetBounds(local_bounds);
150
151   if (has_restore_bounds)
152     state->SetRestoreBoundsInParent(restore_bounds);
153 }
154
155 // Reparents the appropriate set of windows from |src| to |dst|.
156 void ReparentAllWindows(aura::Window* src, aura::Window* dst) {
157   // Set of windows to move.
158   const int kContainerIdsToMove[] = {
159       kShellWindowId_DefaultContainer,
160       kShellWindowId_DockedContainer,
161       kShellWindowId_PanelContainer,
162       kShellWindowId_AlwaysOnTopContainer,
163       kShellWindowId_SystemModalContainer,
164       kShellWindowId_LockSystemModalContainer,
165       kShellWindowId_UnparentedControlContainer, };
166   for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) {
167     int id = kContainerIdsToMove[i];
168     aura::Window* src_container = Shell::GetContainer(src, id);
169     aura::Window* dst_container = Shell::GetContainer(dst, id);
170     while (!src_container->children().empty()) {
171       // Restart iteration from the source container windows each time as they
172       // may change as a result of moving other windows.
173       aura::Window::Windows::const_iterator iter =
174           src_container->children().begin();
175       while (iter != src_container->children().end() &&
176              SystemModalContainerLayoutManager::IsModalBackground(*iter)) {
177         ++iter;
178       }
179       // If the entire window list is modal background windows then stop.
180       if (iter == src_container->children().end())
181         break;
182       ReparentWindow(*iter, dst_container);
183     }
184   }
185 }
186
187 // Mark the container window so that a widget added to this container will
188 // use the virtual screeen coordinates instead of parent.
189 void SetUsesScreenCoordinates(aura::Window* container) {
190   container->SetProperty(kUsesScreenCoordinatesKey, true);
191 }
192
193 // Mark the container window so that a widget added to this container will
194 // say in the same root window regardless of the bounds specified.
195 void DescendantShouldStayInSameRootWindow(aura::Window* container) {
196   container->SetProperty(kStayInSameRootWindowKey, true);
197 }
198
199 void SetUsesEasyResizeTargeter(aura::Window* container) {
200   gfx::Insets mouse_extend(-kResizeOutsideBoundsSize,
201                            -kResizeOutsideBoundsSize,
202                            -kResizeOutsideBoundsSize,
203                            -kResizeOutsideBoundsSize);
204   gfx::Insets touch_extend = mouse_extend.Scale(
205       kResizeOutsideBoundsScaleForTouch);
206   container->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
207       new ::wm::EasyResizeWindowTargeter(container, mouse_extend,
208                                          touch_extend)));
209 }
210
211 // A window delegate which does nothing. Used to create a window that
212 // is a event target, but do nothing.
213 class EmptyWindowDelegate : public aura::WindowDelegate {
214  public:
215   EmptyWindowDelegate() {}
216   ~EmptyWindowDelegate() override {}
217
218   // aura::WindowDelegate overrides:
219   gfx::Size GetMinimumSize() const override { return gfx::Size(); }
220   gfx::Size GetMaximumSize() const override { return gfx::Size(); }
221   void OnBoundsChanged(const gfx::Rect& old_bounds,
222                        const gfx::Rect& new_bounds) override {}
223   gfx::NativeCursor GetCursor(const gfx::Point& point) override {
224     return gfx::kNullCursor;
225   }
226   int GetNonClientComponent(const gfx::Point& point) const override {
227     return HTNOWHERE;
228   }
229   bool ShouldDescendIntoChildForEventHandling(
230       aura::Window* child,
231       const gfx::Point& location) override {
232     return false;
233   }
234   bool CanFocus() override { return false; }
235   void OnCaptureLost() override {}
236   void OnPaint(gfx::Canvas* canvas) override {}
237   void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
238   void OnWindowDestroying(aura::Window* window) override {}
239   void OnWindowDestroyed(aura::Window* window) override { delete this; }
240   void OnWindowTargetVisibilityChanged(bool visible) override {}
241   bool HasHitTestMask() const override { return false; }
242   void GetHitTestMask(gfx::Path* mask) const override {}
243
244  private:
245   DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate);
246 };
247
248 }  // namespace
249
250 void RootWindowController::CreateForPrimaryDisplay(AshWindowTreeHost* host) {
251   RootWindowController* controller = new RootWindowController(host);
252   controller->Init(RootWindowController::PRIMARY,
253                    Shell::GetInstance()->delegate()->IsFirstRunAfterBoot());
254 }
255
256 void RootWindowController::CreateForSecondaryDisplay(AshWindowTreeHost* host) {
257   RootWindowController* controller = new RootWindowController(host);
258   controller->Init(RootWindowController::SECONDARY, false /* first run */);
259 }
260
261 // static
262 RootWindowController* RootWindowController::ForShelf(
263     const aura::Window* window) {
264   CHECK(Shell::HasInstance());
265   return GetRootWindowController(window->GetRootWindow());
266 }
267
268 // static
269 RootWindowController* RootWindowController::ForWindow(
270     const aura::Window* window) {
271   CHECK(Shell::HasInstance());
272   return GetRootWindowController(window->GetRootWindow());
273 }
274
275 // static
276 RootWindowController* RootWindowController::ForTargetRootWindow() {
277   CHECK(Shell::HasInstance());
278   return GetRootWindowController(Shell::GetTargetRootWindow());
279 }
280
281 // static
282 aura::Window* RootWindowController::GetContainerForWindow(
283     aura::Window* window) {
284   aura::Window* container = window->parent();
285   while (container && container->type() != ui::wm::WINDOW_TYPE_UNKNOWN)
286     container = container->parent();
287   return container;
288 }
289
290 RootWindowController::~RootWindowController() {
291   Shutdown();
292   ash_host_.reset();
293   // The CaptureClient needs to be around for as long as the RootWindow is
294   // valid.
295   capture_client_.reset();
296 }
297
298 aura::WindowTreeHost* RootWindowController::GetHost() {
299   return ash_host_->AsWindowTreeHost();
300 }
301
302 const aura::WindowTreeHost* RootWindowController::GetHost() const {
303   return ash_host_->AsWindowTreeHost();
304 }
305
306 aura::Window* RootWindowController::GetRootWindow() {
307   return GetHost()->window();
308 }
309
310 const aura::Window* RootWindowController::GetRootWindow() const {
311   return GetHost()->window();
312 }
313
314 void RootWindowController::SetWallpaperController(
315     DesktopBackgroundWidgetController* controller) {
316   wallpaper_controller_.reset(controller);
317 }
318
319 void RootWindowController::SetAnimatingWallpaperController(
320     AnimatingDesktopController* controller) {
321   if (animating_wallpaper_controller_.get())
322     animating_wallpaper_controller_->StopAnimating();
323   animating_wallpaper_controller_.reset(controller);
324 }
325
326 void RootWindowController::Shutdown() {
327   Shell* shell = Shell::GetInstance();
328   shell->RemoveShellObserver(this);
329
330 #if defined(OS_CHROMEOS)
331   if (touch_exploration_manager_) {
332     touch_exploration_manager_.reset();
333   }
334 #endif
335
336   if (animating_wallpaper_controller_.get())
337     animating_wallpaper_controller_->StopAnimating();
338   wallpaper_controller_.reset();
339   animating_wallpaper_controller_.reset();
340   aura::Window* root_window = GetRootWindow();
341   // Change the target root window before closing child windows. If any child
342   // being removed triggers a relayout of the shelf it will try to build a
343   // window list adding windows from the target root window's containers which
344   // may have already gone away.
345   if (Shell::GetTargetRootWindow() == root_window) {
346     shell->set_target_root_window(
347         Shell::GetPrimaryRootWindow() == root_window
348             ? NULL
349             : Shell::GetPrimaryRootWindow());
350   }
351
352   CloseChildWindows();
353   GetRootWindowSettings(root_window)->controller = NULL;
354   screen_dimmer_.reset();
355   workspace_controller_.reset();
356   // Forget with the display ID so that display lookup
357   // ends up with invalid display.
358   GetRootWindowSettings(root_window)->display_id =
359       gfx::Display::kInvalidDisplayID;
360   ash_host_->PrepareForShutdown();
361
362   system_background_.reset();
363   aura::client::SetScreenPositionClient(root_window, NULL);
364 }
365
366 SystemModalContainerLayoutManager*
367 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
368   aura::Window* modal_container = NULL;
369   if (window) {
370     aura::Window* window_container = GetContainerForWindow(window);
371     if (window_container &&
372         window_container->id() >= kShellWindowId_LockScreenContainer) {
373       modal_container = GetContainer(kShellWindowId_LockSystemModalContainer);
374     } else {
375       modal_container = GetContainer(kShellWindowId_SystemModalContainer);
376     }
377   } else {
378     int modal_window_id = Shell::GetInstance()->session_state_delegate()
379         ->IsUserSessionBlocked() ? kShellWindowId_LockSystemModalContainer :
380                                    kShellWindowId_SystemModalContainer;
381     modal_container = GetContainer(modal_window_id);
382   }
383   return modal_container ? static_cast<SystemModalContainerLayoutManager*>(
384       modal_container->layout_manager()) : NULL;
385 }
386
387 aura::Window* RootWindowController::GetContainer(int container_id) {
388   return GetRootWindow()->GetChildById(container_id);
389 }
390
391 const aura::Window* RootWindowController::GetContainer(int container_id) const {
392   return ash_host_->AsWindowTreeHost()->window()->GetChildById(container_id);
393 }
394
395 void RootWindowController::ShowShelf() {
396   if (!shelf_->shelf())
397     return;
398   shelf_->shelf()->SetVisible(true);
399   shelf_->status_area_widget()->Show();
400 }
401
402 void RootWindowController::OnShelfCreated() {
403   if (panel_layout_manager_)
404     panel_layout_manager_->SetShelf(shelf_->shelf());
405   if (docked_layout_manager_) {
406     docked_layout_manager_->SetShelf(shelf_->shelf());
407     if (shelf_->shelf_layout_manager())
408       docked_layout_manager_->AddObserver(shelf_->shelf_layout_manager());
409   }
410
411   // Notify shell observers that the shelf has been created.
412   Shell::GetInstance()->OnShelfCreatedForRootWindow(GetRootWindow());
413 }
414
415 void RootWindowController::UpdateAfterLoginStatusChange(
416     user::LoginStatus status) {
417   if (status != user::LOGGED_IN_NONE)
418     mouse_event_target_.reset();
419   if (shelf_->status_area_widget())
420     shelf_->status_area_widget()->UpdateAfterLoginStatusChange(status);
421 }
422
423 void RootWindowController::HandleInitialDesktopBackgroundAnimationStarted() {
424 #if defined(OS_CHROMEOS)
425   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
426           switches::kAshAnimateFromBootSplashScreen) &&
427       boot_splash_screen_.get()) {
428     // Make the splash screen fade out so it doesn't obscure the desktop
429     // wallpaper's brightness/grayscale animation.
430     boot_splash_screen_->StartHideAnimation(
431         base::TimeDelta::FromMilliseconds(kBootSplashScreenHideDurationMs));
432   }
433 #endif
434 }
435
436 void RootWindowController::OnWallpaperAnimationFinished(views::Widget* widget) {
437   // Make sure the wallpaper is visible.
438   system_background_->SetColor(SK_ColorBLACK);
439 #if defined(OS_CHROMEOS)
440   boot_splash_screen_.reset();
441 #endif
442
443   Shell::GetInstance()->user_wallpaper_delegate()->
444       OnWallpaperAnimationFinished();
445   // Only removes old component when wallpaper animation finished. If we
446   // remove the old one before the new wallpaper is done fading in there will
447   // be a white flash during the animation.
448   if (animating_wallpaper_controller()) {
449     DesktopBackgroundWidgetController* controller =
450         animating_wallpaper_controller()->GetController(true);
451     // |desktop_widget_| should be the same animating widget we try to move
452     // to |kDesktopController|. Otherwise, we may close |desktop_widget_|
453     // before move it to |kDesktopController|.
454     DCHECK_EQ(controller->widget(), widget);
455     // Release the old controller and close its background widget.
456     SetWallpaperController(controller);
457   }
458 }
459
460 void RootWindowController::CloseChildWindows() {
461   mouse_event_target_.reset();
462
463   // Remove observer as deactivating keyboard causes |docked_layout_manager_|
464   // to fire notifications.
465   if (docked_layout_manager_ && shelf_ && shelf_->shelf_layout_manager())
466     docked_layout_manager_->RemoveObserver(shelf_->shelf_layout_manager());
467
468   // Deactivate keyboard container before closing child windows and shutting
469   // down associated layout managers.
470   DeactivateKeyboard(keyboard::KeyboardController::GetInstance());
471
472   // panel_layout_manager_ needs to be shut down before windows are destroyed.
473   if (panel_layout_manager_) {
474     panel_layout_manager_->Shutdown();
475     panel_layout_manager_ = NULL;
476   }
477   // docked_layout_manager_ needs to be shut down before windows are destroyed.
478   if (docked_layout_manager_) {
479     docked_layout_manager_->Shutdown();
480     docked_layout_manager_ = NULL;
481   }
482   aura::Window* root_window = GetRootWindow();
483   aura::client::SetDragDropClient(root_window, NULL);
484
485   // TODO(harrym): Remove when Status Area Widget is a child view.
486   if (shelf_) {
487     shelf_->ShutdownStatusAreaWidget();
488
489     if (shelf_->shelf_layout_manager())
490       shelf_->shelf_layout_manager()->PrepareForShutdown();
491   }
492
493   // Close background widget first as it depends on tooltip.
494   wallpaper_controller_.reset();
495   animating_wallpaper_controller_.reset();
496
497   workspace_controller_.reset();
498   aura::client::SetTooltipClient(root_window, NULL);
499
500   // Explicitly destroy top level windows. We do this as during part of
501   // destruction such windows may query the RootWindow for state.
502   std::queue<aura::Window*> non_toplevel_windows;
503   non_toplevel_windows.push(root_window);
504   while (!non_toplevel_windows.empty()) {
505     aura::Window* non_toplevel_window = non_toplevel_windows.front();
506     non_toplevel_windows.pop();
507     aura::WindowTracker toplevel_windows;
508     for (size_t i = 0; i < non_toplevel_window->children().size(); ++i) {
509       aura::Window* child = non_toplevel_window->children()[i];
510       if (!child->owned_by_parent())
511         continue;
512       if (child->delegate())
513         toplevel_windows.Add(child);
514       else
515         non_toplevel_windows.push(child);
516     }
517     while (!toplevel_windows.windows().empty())
518       delete *toplevel_windows.windows().begin();
519   }
520   // And then remove the containers.
521   while (!root_window->children().empty()) {
522     aura::Window* window = root_window->children()[0];
523     if (window->owned_by_parent()) {
524       delete window;
525     } else {
526       root_window->RemoveChild(window);
527     }
528   }
529
530   shelf_.reset();
531 }
532
533 void RootWindowController::MoveWindowsTo(aura::Window* dst) {
534   // Forget the shelf early so that shelf don't update itself using wrong
535   // display info.
536   workspace_controller_->SetShelf(NULL);
537   ReparentAllWindows(GetRootWindow(), dst);
538 }
539
540 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
541   return shelf_->shelf_layout_manager();
542 }
543
544 SystemTray* RootWindowController::GetSystemTray() {
545   // We assume in throughout the code that this will not return NULL. If code
546   // triggers this for valid reasons, it should test status_area_widget first.
547   CHECK(shelf_->status_area_widget());
548   return shelf_->status_area_widget()->system_tray();
549 }
550
551 void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen,
552                                            ui::MenuSourceType source_type) {
553   DCHECK(Shell::GetInstance()->delegate());
554   scoped_ptr<ui::MenuModel> menu_model(
555       Shell::GetInstance()->delegate()->CreateContextMenu(
556           GetRootWindow(), NULL, NULL));
557   if (!menu_model)
558     return;
559
560   // Background controller may not be set yet if user clicked on status are
561   // before initial animation completion. See crbug.com/222218
562   if (!wallpaper_controller_.get())
563     return;
564
565   views::MenuRunner menu_runner(menu_model.get(),
566                                 views::MenuRunner::CONTEXT_MENU);
567   if (menu_runner.RunMenuAt(wallpaper_controller_->widget(),
568                             NULL,
569                             gfx::Rect(location_in_screen, gfx::Size()),
570                             views::MENU_ANCHOR_TOPLEFT,
571                             source_type) == views::MenuRunner::MENU_DELETED) {
572     return;
573   }
574
575   Shell::GetInstance()->UpdateShelfVisibility();
576 }
577
578 void RootWindowController::UpdateShelfVisibility() {
579   shelf_->shelf_layout_manager()->UpdateVisibilityState();
580 }
581
582 const aura::Window* RootWindowController::GetWindowForFullscreenMode() const {
583   const aura::Window* topmost_window = NULL;
584   const aura::Window* active_window = wm::GetActiveWindow();
585   if (active_window && active_window->GetRootWindow() == GetRootWindow() &&
586       IsSwitchableContainer(active_window->parent())) {
587     // Use the active window when it is on the current root window to determine
588     // the fullscreen state to allow temporarily using a panel or docked window
589     // (which are always above the default container) while a fullscreen
590     // window is open. We only use the active window when in a switchable
591     // container as the launcher should not exit fullscreen mode.
592     topmost_window = active_window;
593   } else {
594     // Otherwise, use the topmost window on the root window's default container
595     // when there is no active window on this root window.
596     const aura::Window::Windows& windows =
597         GetContainer(kShellWindowId_DefaultContainer)->children();
598     for (aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
599          iter != windows.rend(); ++iter) {
600       if (((*iter)->type() == ui::wm::WINDOW_TYPE_NORMAL ||
601            (*iter)->type() == ui::wm::WINDOW_TYPE_PANEL) &&
602           (*iter)->layer()->GetTargetVisibility()) {
603         topmost_window = *iter;
604         break;
605       }
606     }
607   }
608   while (topmost_window) {
609     if (wm::GetWindowState(topmost_window)->IsFullscreen())
610       return topmost_window;
611     topmost_window = ::wm::GetTransientParent(topmost_window);
612   }
613   return NULL;
614 }
615
616 void RootWindowController::ActivateKeyboard(
617     keyboard::KeyboardController* keyboard_controller) {
618   if (!keyboard::IsKeyboardEnabled() ||
619       GetContainer(kShellWindowId_VirtualKeyboardContainer)) {
620     return;
621   }
622   DCHECK(keyboard_controller);
623   keyboard_controller->AddObserver(shelf()->shelf_layout_manager());
624   keyboard_controller->AddObserver(panel_layout_manager_);
625   keyboard_controller->AddObserver(docked_layout_manager_);
626   keyboard_controller->AddObserver(workspace_controller_->layout_manager());
627   Shell::GetInstance()->delegate()->VirtualKeyboardActivated(true);
628   aura::Window* parent = GetContainer(kShellWindowId_ImeWindowParentContainer);
629   DCHECK(parent);
630   aura::Window* keyboard_container =
631       keyboard_controller->GetContainerWindow();
632   keyboard_container->set_id(kShellWindowId_VirtualKeyboardContainer);
633   parent->AddChild(keyboard_container);
634   // TODO(oshima): Bounds of keyboard container should be handled by
635   // RootWindowLayoutManager. Remove this after fixed RootWindowLayoutManager.
636   keyboard_container->SetBounds(parent->bounds());
637 }
638
639 void RootWindowController::DeactivateKeyboard(
640     keyboard::KeyboardController* keyboard_controller) {
641   if (!keyboard_controller ||
642       !keyboard_controller->keyboard_container_initialized()) {
643     return;
644   }
645   aura::Window* keyboard_container =
646       keyboard_controller->GetContainerWindow();
647   if (keyboard_container->GetRootWindow() == GetRootWindow()) {
648     aura::Window* parent =
649         GetContainer(kShellWindowId_ImeWindowParentContainer);
650     DCHECK(parent);
651     parent->RemoveChild(keyboard_container);
652     // Virtual keyboard may be deactivated while still showing, notify all
653     // observers that keyboard bounds changed to 0 before remove them.
654     keyboard_controller->NotifyKeyboardBoundsChanging(gfx::Rect());
655     keyboard_controller->RemoveObserver(shelf()->shelf_layout_manager());
656     keyboard_controller->RemoveObserver(panel_layout_manager_);
657     keyboard_controller->RemoveObserver(docked_layout_manager_);
658     keyboard_controller->RemoveObserver(
659         workspace_controller_->layout_manager());
660     Shell::GetInstance()->delegate()->VirtualKeyboardActivated(false);
661   }
662 }
663
664 bool RootWindowController::IsVirtualKeyboardWindow(aura::Window* window) {
665   aura::Window* parent = GetContainer(kShellWindowId_ImeWindowParentContainer);
666   return parent ? parent->Contains(window) : false;
667 }
668
669 ////////////////////////////////////////////////////////////////////////////////
670 // RootWindowController, private:
671
672 RootWindowController::RootWindowController(AshWindowTreeHost* ash_host)
673     : ash_host_(ash_host),
674       root_window_layout_(NULL),
675       docked_layout_manager_(NULL),
676       panel_layout_manager_(NULL),
677       touch_hud_debug_(NULL),
678       touch_hud_projection_(NULL) {
679   aura::Window* root_window = GetRootWindow();
680   GetRootWindowSettings(root_window)->controller = this;
681   screen_dimmer_.reset(new ScreenDimmer(root_window));
682
683   stacking_controller_.reset(new StackingController);
684   aura::client::SetWindowTreeClient(root_window, stacking_controller_.get());
685   capture_client_.reset(new ::wm::ScopedCaptureClient(root_window));
686 }
687
688 void RootWindowController::Init(RootWindowType root_window_type,
689                                 bool first_run_after_boot) {
690   aura::Window* root_window = GetRootWindow();
691   Shell* shell = Shell::GetInstance();
692   shell->InitRootWindow(root_window);
693
694   ash_host_->AsWindowTreeHost()->SetCursor(ui::kCursorPointer);
695   CreateContainersInRootWindow(root_window);
696
697   CreateSystemBackground(first_run_after_boot);
698
699   InitLayoutManagers();
700   InitTouchHuds();
701
702   if (Shell::GetPrimaryRootWindowController()->
703       GetSystemModalLayoutManager(NULL)->has_modal_background()) {
704     GetSystemModalLayoutManager(NULL)->CreateModalBackground();
705   }
706
707   shell->AddShellObserver(this);
708
709   if (root_window_type == PRIMARY) {
710     root_window_layout()->OnWindowResized();
711     shell->InitKeyboard();
712   } else {
713     root_window_layout()->OnWindowResized();
714     ash_host_->AsWindowTreeHost()->Show();
715
716     // Create a shelf if a user is already logged in.
717     if (shell->session_state_delegate()->NumberOfLoggedInUsers())
718       shelf()->CreateShelf();
719
720     // Notify shell observers about new root window.
721     shell->OnRootWindowAdded(root_window);
722   }
723
724 #if defined(OS_CHROMEOS)
725   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
726           switches::kAshDisableTouchExplorationMode)) {
727     touch_exploration_manager_.reset(new AshTouchExplorationManager(this));
728   }
729 #endif
730 }
731
732 void RootWindowController::InitLayoutManagers() {
733   aura::Window* root_window = GetRootWindow();
734   root_window_layout_ = new RootWindowLayoutManager(root_window);
735   root_window->SetLayoutManager(root_window_layout_);
736
737   aura::Window* default_container =
738       GetContainer(kShellWindowId_DefaultContainer);
739   // Workspace manager has its own layout managers.
740   workspace_controller_.reset(
741       new WorkspaceController(default_container));
742
743   aura::Window* always_on_top_container =
744       GetContainer(kShellWindowId_AlwaysOnTopContainer);
745   always_on_top_container->SetLayoutManager(
746       new WorkspaceLayoutManager(always_on_top_container));
747   always_on_top_controller_.reset(new AlwaysOnTopController);
748   always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container);
749
750   DCHECK(!shelf_.get());
751   aura::Window* shelf_container = GetContainer(kShellWindowId_ShelfContainer);
752   // TODO(harrym): Remove when status area is view.
753   aura::Window* status_container = GetContainer(kShellWindowId_StatusContainer);
754   shelf_.reset(new ShelfWidget(
755       shelf_container, status_container, workspace_controller()));
756
757   if (!Shell::GetInstance()->session_state_delegate()->
758       IsActiveUserSessionStarted()) {
759     // This window exists only to be a event target on login screen.
760     // It does not have to handle events, nor be visible.
761     mouse_event_target_.reset(new aura::Window(new EmptyWindowDelegate));
762     mouse_event_target_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
763
764     aura::Window* lock_background_container =
765         GetContainer(kShellWindowId_LockScreenBackgroundContainer);
766     lock_background_container->AddChild(mouse_event_target_.get());
767     mouse_event_target_->Show();
768   }
769
770   // Create Docked windows layout manager
771   aura::Window* docked_container = GetContainer(kShellWindowId_DockedContainer);
772   docked_layout_manager_ =
773       new DockedWindowLayoutManager(docked_container, workspace_controller());
774   docked_container->SetLayoutManager(docked_layout_manager_);
775
776   // Installs SnapLayoutManager to containers who set the
777   // |kSnapsChildrenToPhysicalPixelBoundary| property.
778   wm::InstallSnapLayoutManagerToContainers(root_window);
779
780   // Create Panel layout manager
781   aura::Window* panel_container = GetContainer(kShellWindowId_PanelContainer);
782   panel_layout_manager_ = new PanelLayoutManager(panel_container);
783   panel_container->SetLayoutManager(panel_layout_manager_);
784   panel_container_handler_.reset(new PanelWindowEventHandler);
785   panel_container->AddPreTargetHandler(panel_container_handler_.get());
786
787   // Install an AttachedPanelWindowTargeter on the panel container to make it
788   // easier to correctly target shelf buttons with touch.
789   gfx::Insets mouse_extend(-kResizeOutsideBoundsSize,
790                            -kResizeOutsideBoundsSize,
791                            -kResizeOutsideBoundsSize,
792                            -kResizeOutsideBoundsSize);
793   gfx::Insets touch_extend = mouse_extend.Scale(
794       kResizeOutsideBoundsScaleForTouch);
795   panel_container->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
796       new AttachedPanelWindowTargeter(panel_container,
797                                       mouse_extend,
798                                       touch_extend,
799                                       panel_layout_manager_)));
800 }
801
802 void RootWindowController::InitTouchHuds() {
803   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
804   if (command_line->HasSwitch(switches::kAshTouchHud))
805     set_touch_hud_debug(new TouchHudDebug(GetRootWindow()));
806   if (Shell::GetInstance()->is_touch_hud_projection_enabled())
807     EnableTouchHudProjection();
808 }
809
810 void RootWindowController::CreateSystemBackground(
811     bool is_first_run_after_boot) {
812   SkColor color = SK_ColorBLACK;
813 #if defined(OS_CHROMEOS)
814   if (is_first_run_after_boot)
815     color = kChromeOsBootColor;
816 #endif
817   system_background_.reset(
818       new SystemBackgroundController(GetRootWindow(), color));
819
820 #if defined(OS_CHROMEOS)
821   // Make a copy of the system's boot splash screen so we can composite it
822   // onscreen until the desktop background is ready.
823   if (is_first_run_after_boot &&
824       (base::CommandLine::ForCurrentProcess()->HasSwitch(
825            switches::kAshCopyHostBackgroundAtBoot) ||
826        base::CommandLine::ForCurrentProcess()->HasSwitch(
827            switches::kAshAnimateFromBootSplashScreen)))
828     boot_splash_screen_.reset(new BootSplashScreen(GetHost()));
829 #endif
830 }
831
832 void RootWindowController::CreateContainersInRootWindow(
833     aura::Window* root_window) {
834   // These containers are just used by PowerButtonController to animate groups
835   // of containers simultaneously without messing up the current transformations
836   // on those containers. These are direct children of the root window; all of
837   // the other containers are their children.
838
839   // The desktop background container is not part of the lock animation, so it
840   // is not included in those animate groups.
841   // When screen is locked desktop background is moved to lock screen background
842   // container (moved back on unlock). We want to make sure that there's an
843   // opaque layer occluding the non-lock-screen layers.
844   aura::Window* desktop_background_container = CreateContainer(
845       kShellWindowId_DesktopBackgroundContainer,
846       "DesktopBackgroundContainer",
847       root_window);
848   ::wm::SetChildWindowVisibilityChangesAnimated(desktop_background_container);
849
850   aura::Window* non_lock_screen_containers = CreateContainer(
851       kShellWindowId_NonLockScreenContainersContainer,
852       "NonLockScreenContainersContainer",
853       root_window);
854
855   aura::Window* lock_background_containers = CreateContainer(
856       kShellWindowId_LockScreenBackgroundContainer,
857       "LockScreenBackgroundContainer",
858       root_window);
859   ::wm::SetChildWindowVisibilityChangesAnimated(lock_background_containers);
860
861   aura::Window* lock_screen_containers = CreateContainer(
862       kShellWindowId_LockScreenContainersContainer,
863       "LockScreenContainersContainer",
864       root_window);
865   aura::Window* lock_screen_related_containers = CreateContainer(
866       kShellWindowId_LockScreenRelatedContainersContainer,
867       "LockScreenRelatedContainersContainer",
868       root_window);
869
870   CreateContainer(kShellWindowId_UnparentedControlContainer,
871                   "UnparentedControlContainer",
872                   non_lock_screen_containers);
873
874   aura::Window* default_container = CreateContainer(
875       kShellWindowId_DefaultContainer,
876       "DefaultContainer",
877       non_lock_screen_containers);
878   ::wm::SetChildWindowVisibilityChangesAnimated(default_container);
879   wm::SetSnapsChildrenToPhysicalPixelBoundary(default_container);
880   SetUsesScreenCoordinates(default_container);
881   SetUsesEasyResizeTargeter(default_container);
882
883   aura::Window* always_on_top_container = CreateContainer(
884       kShellWindowId_AlwaysOnTopContainer,
885       "AlwaysOnTopContainer",
886       non_lock_screen_containers);
887   ::wm::SetChildWindowVisibilityChangesAnimated(always_on_top_container);
888   wm::SetSnapsChildrenToPhysicalPixelBoundary(always_on_top_container);
889   SetUsesScreenCoordinates(always_on_top_container);
890
891   aura::Window* docked_container = CreateContainer(
892       kShellWindowId_DockedContainer,
893       "DockedContainer",
894       non_lock_screen_containers);
895   ::wm::SetChildWindowVisibilityChangesAnimated(docked_container);
896   wm::SetSnapsChildrenToPhysicalPixelBoundary(docked_container);
897   SetUsesScreenCoordinates(docked_container);
898   SetUsesEasyResizeTargeter(docked_container);
899
900   aura::Window* shelf_container =
901       CreateContainer(kShellWindowId_ShelfContainer,
902                       "ShelfContainer",
903                       non_lock_screen_containers);
904   wm::SetSnapsChildrenToPhysicalPixelBoundary(shelf_container);
905   SetUsesScreenCoordinates(shelf_container);
906   DescendantShouldStayInSameRootWindow(shelf_container);
907
908   aura::Window* panel_container = CreateContainer(
909       kShellWindowId_PanelContainer,
910       "PanelContainer",
911       non_lock_screen_containers);
912   wm::SetSnapsChildrenToPhysicalPixelBoundary(panel_container);
913   SetUsesScreenCoordinates(panel_container);
914
915   aura::Window* shelf_bubble_container =
916       CreateContainer(kShellWindowId_ShelfBubbleContainer,
917                       "ShelfBubbleContainer",
918                       non_lock_screen_containers);
919   wm::SetSnapsChildrenToPhysicalPixelBoundary(shelf_bubble_container);
920   SetUsesScreenCoordinates(shelf_bubble_container);
921   DescendantShouldStayInSameRootWindow(shelf_bubble_container);
922
923   aura::Window* app_list_container =
924       CreateContainer(kShellWindowId_AppListContainer,
925                       "AppListContainer",
926                       non_lock_screen_containers);
927   wm::SetSnapsChildrenToPhysicalPixelBoundary(app_list_container);
928   SetUsesScreenCoordinates(app_list_container);
929
930   aura::Window* modal_container = CreateContainer(
931       kShellWindowId_SystemModalContainer,
932       "SystemModalContainer",
933       non_lock_screen_containers);
934   wm::SetSnapsChildrenToPhysicalPixelBoundary(modal_container);
935   modal_container->SetLayoutManager(
936       new SystemModalContainerLayoutManager(modal_container));
937   ::wm::SetChildWindowVisibilityChangesAnimated(modal_container);
938   SetUsesScreenCoordinates(modal_container);
939   SetUsesEasyResizeTargeter(modal_container);
940
941   // TODO(beng): Figure out if we can make this use
942   // SystemModalContainerEventFilter instead of stops_event_propagation.
943   aura::Window* lock_container = CreateContainer(
944       kShellWindowId_LockScreenContainer,
945       "LockScreenContainer",
946       lock_screen_containers);
947   wm::SetSnapsChildrenToPhysicalPixelBoundary(lock_container);
948   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
949           switches::kAshDisableLockLayoutManager)) {
950     lock_container->SetLayoutManager(
951             new WorkspaceLayoutManager(lock_container));
952   } else {
953     lock_container->SetLayoutManager(new LockLayoutManager(lock_container));
954   }
955   SetUsesScreenCoordinates(lock_container);
956   // TODO(beng): stopsevents
957
958   aura::Window* lock_modal_container = CreateContainer(
959       kShellWindowId_LockSystemModalContainer,
960       "LockSystemModalContainer",
961       lock_screen_containers);
962   wm::SetSnapsChildrenToPhysicalPixelBoundary(lock_modal_container);
963   lock_modal_container->SetLayoutManager(
964       new SystemModalContainerLayoutManager(lock_modal_container));
965   ::wm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
966   SetUsesScreenCoordinates(lock_modal_container);
967   SetUsesEasyResizeTargeter(lock_modal_container);
968
969   aura::Window* status_container =
970       CreateContainer(kShellWindowId_StatusContainer,
971                       "StatusContainer",
972                       lock_screen_related_containers);
973   wm::SetSnapsChildrenToPhysicalPixelBoundary(status_container);
974   SetUsesScreenCoordinates(status_container);
975   DescendantShouldStayInSameRootWindow(status_container);
976
977   aura::Window* settings_bubble_container = CreateContainer(
978       kShellWindowId_SettingBubbleContainer,
979       "SettingBubbleContainer",
980       lock_screen_related_containers);
981   ::wm::SetChildWindowVisibilityChangesAnimated(settings_bubble_container);
982   wm::SetSnapsChildrenToPhysicalPixelBoundary(settings_bubble_container);
983   SetUsesScreenCoordinates(settings_bubble_container);
984   DescendantShouldStayInSameRootWindow(settings_bubble_container);
985
986   aura::Window* virtual_keyboard_parent_container =
987       CreateContainer(kShellWindowId_ImeWindowParentContainer,
988                       "VirtualKeyboardParentContainer",
989                       lock_screen_related_containers);
990   wm::SetSnapsChildrenToPhysicalPixelBoundary(
991       virtual_keyboard_parent_container);
992   virtual_keyboard_parent_container->SetLayoutManager(
993       new VirtualKeyboardContainerLayoutManager(
994           virtual_keyboard_parent_container));
995   SetUsesScreenCoordinates(virtual_keyboard_parent_container);
996
997   aura::Window* menu_container = CreateContainer(
998       kShellWindowId_MenuContainer,
999       "MenuContainer",
1000       lock_screen_related_containers);
1001   ::wm::SetChildWindowVisibilityChangesAnimated(menu_container);
1002   wm::SetSnapsChildrenToPhysicalPixelBoundary(menu_container);
1003   SetUsesScreenCoordinates(menu_container);
1004
1005   aura::Window* drag_drop_container = CreateContainer(
1006       kShellWindowId_DragImageAndTooltipContainer,
1007       "DragImageAndTooltipContainer",
1008       lock_screen_related_containers);
1009   ::wm::SetChildWindowVisibilityChangesAnimated(drag_drop_container);
1010   wm::SetSnapsChildrenToPhysicalPixelBoundary(drag_drop_container);
1011   SetUsesScreenCoordinates(drag_drop_container);
1012
1013   aura::Window* overlay_container = CreateContainer(
1014       kShellWindowId_OverlayContainer,
1015       "OverlayContainer",
1016       lock_screen_related_containers);
1017   wm::SetSnapsChildrenToPhysicalPixelBoundary(overlay_container);
1018   SetUsesScreenCoordinates(overlay_container);
1019
1020 #if defined(OS_CHROMEOS)
1021   aura::Window* mouse_cursor_container = CreateContainer(
1022       kShellWindowId_MouseCursorContainer,
1023       "MouseCursorContainer",
1024       root_window);
1025   SetUsesScreenCoordinates(mouse_cursor_container);
1026 #endif
1027
1028   CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
1029                   "PowerButtonAnimationContainer", root_window);
1030 }
1031
1032 void RootWindowController::EnableTouchHudProjection() {
1033   if (touch_hud_projection_)
1034     return;
1035   set_touch_hud_projection(new TouchHudProjection(GetRootWindow()));
1036 }
1037
1038 void RootWindowController::DisableTouchHudProjection() {
1039   if (!touch_hud_projection_)
1040     return;
1041   touch_hud_projection_->Remove();
1042 }
1043
1044 void RootWindowController::OnLoginStateChanged(user::LoginStatus status) {
1045   shelf_->shelf_layout_manager()->UpdateVisibilityState();
1046 }
1047
1048 void RootWindowController::OnTouchHudProjectionToggled(bool enabled) {
1049   if (enabled)
1050     EnableTouchHudProjection();
1051   else
1052     DisableTouchHudProjection();
1053 }
1054
1055 RootWindowController* GetRootWindowController(
1056     const aura::Window* root_window) {
1057   return root_window ? GetRootWindowSettings(root_window)->controller : NULL;
1058 }
1059
1060 }  // namespace ash