blob: 6d5fb627771b00a7534a0422c56dff3b984f8eaf [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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 <vector>
8
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009#include "ash/ash_constants.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010#include "ash/ash_switches.h"
11#include "ash/desktop_background/desktop_background_widget_controller.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010012#include "ash/desktop_background/user_wallpaper_delegate.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000013#include "ash/display/display_manager.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000014#include "ash/focus_cycler.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010015#include "ash/session_state_delegate.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000016#include "ash/shelf/shelf_layout_manager.h"
17#include "ash/shelf/shelf_types.h"
18#include "ash/shelf/shelf_widget.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000019#include "ash/shell.h"
20#include "ash/shell_delegate.h"
21#include "ash/shell_factory.h"
22#include "ash/shell_window_ids.h"
23#include "ash/system/status_area_widget.h"
24#include "ash/system/tray/system_tray_delegate.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010025#include "ash/touch/touch_hud_debug.h"
26#include "ash/touch/touch_hud_projection.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010027#include "ash/touch/touch_observer_hud.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010028#include "ash/wm/always_on_top_controller.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000029#include "ash/wm/base_layout_manager.h"
30#include "ash/wm/boot_splash_screen.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010031#include "ash/wm/dock/docked_window_layout_manager.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000032#include "ash/wm/panels/panel_layout_manager.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010033#include "ash/wm/panels/panel_window_event_handler.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000034#include "ash/wm/property_util.h"
35#include "ash/wm/root_window_layout_manager.h"
36#include "ash/wm/screen_dimmer.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000037#include "ash/wm/stacking_controller.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000038#include "ash/wm/status_area_layout_manager.h"
39#include "ash/wm/system_background_controller.h"
40#include "ash/wm/system_modal_container_layout_manager.h"
41#include "ash/wm/toplevel_window_event_handler.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000042#include "ash/wm/window_properties.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010043#include "ash/wm/window_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000044#include "ash/wm/workspace_controller.h"
45#include "base/command_line.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010046#include "base/time/time.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000047#include "ui/aura/client/aura_constants.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000048#include "ui/aura/client/tooltip_client.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000049#include "ui/aura/root_window.h"
50#include "ui/aura/window.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010051#include "ui/aura/window_delegate.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000052#include "ui/aura/window_observer.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010053#include "ui/base/hit_test.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000054#include "ui/base/models/menu_model.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000055#include "ui/gfx/screen.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010056#include "ui/keyboard/keyboard_controller.h"
57#include "ui/keyboard/keyboard_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000058#include "ui/views/controls/menu/menu_runner.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000059#include "ui/views/corewm/visibility_controller.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000060#include "ui/views/view_model.h"
61#include "ui/views/view_model_utils.h"
62
63namespace ash {
64namespace {
65
Torne (Richard Coles)58218062012-11-14 11:43:16 +000066// Duration for the animation that hides the boot splash screen, in
67// milliseconds. This should be short enough in relation to
68// wm/window_animation.cc's brightness/grayscale fade animation that the login
69// background image animation isn't hidden by the splash screen animation.
70const int kBootSplashScreenHideDurationMs = 500;
71
72// Creates a new window for use as a container.
73aura::Window* CreateContainer(int window_id,
74 const char* name,
75 aura::Window* parent) {
76 aura::Window* container = new aura::Window(NULL);
77 container->set_id(window_id);
78 container->SetName(name);
79 container->Init(ui::LAYER_NOT_DRAWN);
80 parent->AddChild(container);
81 if (window_id != internal::kShellWindowId_UnparentedControlContainer)
82 container->Show();
83 return container;
84}
85
Torne (Richard Coles)58218062012-11-14 11:43:16 +000086// Reparents |window| to |new_parent|.
87void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
88 // Update the restore bounds to make it relative to the display.
89 gfx::Rect restore_bounds(GetRestoreBoundsInParent(window));
90 new_parent->AddChild(window);
91 if (!restore_bounds.IsEmpty())
92 SetRestoreBoundsInParent(window, restore_bounds);
93}
94
95// Reparents the appropriate set of windows from |src| to |dst|.
96void ReparentAllWindows(aura::RootWindow* src, aura::RootWindow* dst) {
97 // Set of windows to move.
98 const int kContainerIdsToMove[] = {
99 internal::kShellWindowId_DefaultContainer,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100100 internal::kShellWindowId_DockedContainer,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000101 internal::kShellWindowId_PanelContainer,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000102 internal::kShellWindowId_AlwaysOnTopContainer,
103 internal::kShellWindowId_SystemModalContainer,
104 internal::kShellWindowId_LockSystemModalContainer,
105 internal::kShellWindowId_InputMethodContainer,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000106 internal::kShellWindowId_UnparentedControlContainer,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000107 };
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000108 for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) {
109 int id = kContainerIdsToMove[i];
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000110 aura::Window* src_container = Shell::GetContainer(src, id);
111 aura::Window* dst_container = Shell::GetContainer(dst, id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000112 while (!src_container->children().empty()) {
113 // Restart iteration from the source container windows each time as they
114 // may change as a result of moving other windows.
115 aura::Window::Windows::const_iterator iter =
116 src_container->children().begin();
117 while (iter != src_container->children().end() &&
118 internal::SystemModalContainerLayoutManager::IsModalBackground(
119 *iter)) {
120 ++iter;
121 }
122 // If the entire window list is modal background windows then stop.
123 if (iter == src_container->children().end())
124 break;
125 ReparentWindow(*iter, dst_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000126 }
127 }
128}
129
130// Mark the container window so that a widget added to this container will
131// use the virtual screeen coordinates instead of parent.
132void SetUsesScreenCoordinates(aura::Window* container) {
133 container->SetProperty(internal::kUsesScreenCoordinatesKey, true);
134}
135
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100136// Mark the container window so that a widget added to this container will
137// say in the same root window regardless of the bounds specified.
138void DescendantShouldStayInSameRootWindow(aura::Window* container) {
139 container->SetProperty(internal::kStayInSameRootWindowKey, true);
140}
141
Ben Murdochbb1529c2013-08-08 10:24:53 +0100142// A window delegate which does nothing. Used to create a window that
143// is a event target, but do nothing.
144class EmptyWindowDelegate : public aura::WindowDelegate {
145 public:
146 EmptyWindowDelegate() {}
147 virtual ~EmptyWindowDelegate() {}
148
149 // aura::WindowDelegate overrides:
150 virtual gfx::Size GetMinimumSize() const OVERRIDE {
151 return gfx::Size();
152 }
153 virtual gfx::Size GetMaximumSize() const OVERRIDE {
154 return gfx::Size();
155 }
156 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
157 const gfx::Rect& new_bounds) OVERRIDE {
158 }
159 virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
160 return gfx::kNullCursor;
161 }
162 virtual int GetNonClientComponent(
163 const gfx::Point& point) const OVERRIDE {
164 return HTNOWHERE;
165 }
166 virtual bool ShouldDescendIntoChildForEventHandling(
167 aura::Window* child,
168 const gfx::Point& location) OVERRIDE {
169 return false;
170 }
171 virtual bool CanFocus() OVERRIDE {
172 return false;
173 }
174 virtual void OnCaptureLost() OVERRIDE {
175 }
176 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
177 }
178 virtual void OnDeviceScaleFactorChanged(
179 float device_scale_factor) OVERRIDE {
180 }
181 virtual void OnWindowDestroying() OVERRIDE {}
182 virtual void OnWindowDestroyed() OVERRIDE {
183 delete this;
184 }
185 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
186 }
187 virtual bool HasHitTestMask() const OVERRIDE {
188 return false;
189 }
190 virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
191 virtual scoped_refptr<ui::Texture> CopyTexture() OVERRIDE {
192 NOTREACHED();
193 return scoped_refptr<ui::Texture>();
194 }
195
196 private:
197 DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate);
198};
199
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000200} // namespace
201
202namespace internal {
203
204RootWindowController::RootWindowController(aura::RootWindow* root_window)
205 : root_window_(root_window),
206 root_window_layout_(NULL),
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100207 docked_layout_manager_(NULL),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100208 panel_layout_manager_(NULL),
Ben Murdocheb525c52013-07-10 11:40:50 +0100209 touch_hud_debug_(NULL),
210 touch_hud_projection_(NULL) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000211 SetRootWindowController(root_window, this);
212 screen_dimmer_.reset(new ScreenDimmer(root_window));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000213
Ben Murdocheb525c52013-07-10 11:40:50 +0100214 stacking_controller_.reset(new StackingController);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000215 aura::client::SetStackingClient(root_window, stacking_controller_.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000216}
217
218RootWindowController::~RootWindowController() {
219 Shutdown();
220 root_window_.reset();
221}
222
223// static
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000224RootWindowController* RootWindowController::ForLauncher(aura::Window* window) {
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100225 return GetRootWindowController(window->GetRootWindow());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000226}
227
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000228// static
229RootWindowController* RootWindowController::ForWindow(
230 const aura::Window* window) {
231 return GetRootWindowController(window->GetRootWindow());
232}
233
234// static
235RootWindowController* RootWindowController::ForActiveRootWindow() {
236 return GetRootWindowController(Shell::GetActiveRootWindow());
237}
238
Ben Murdocheb525c52013-07-10 11:40:50 +0100239void RootWindowController::SetWallpaperController(
240 DesktopBackgroundWidgetController* controller) {
241 wallpaper_controller_.reset(controller);
242}
243
244void RootWindowController::SetAnimatingWallpaperController(
245 AnimatingDesktopController* controller) {
246 if (animating_wallpaper_controller_.get())
247 animating_wallpaper_controller_->StopAnimating();
248 animating_wallpaper_controller_.reset(controller);
249}
250
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000251void RootWindowController::Shutdown() {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100252 Shell::GetInstance()->RemoveShellObserver(this);
253
Ben Murdocheb525c52013-07-10 11:40:50 +0100254 if (animating_wallpaper_controller_.get())
255 animating_wallpaper_controller_->StopAnimating();
256 wallpaper_controller_.reset();
257 animating_wallpaper_controller_.reset();
258
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000259 CloseChildWindows();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100260 if (Shell::GetActiveRootWindow() == root_window_) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000261 Shell::GetInstance()->set_active_root_window(
262 Shell::GetPrimaryRootWindow() == root_window_.get() ?
263 NULL : Shell::GetPrimaryRootWindow());
264 }
265 SetRootWindowController(root_window_.get(), NULL);
266 screen_dimmer_.reset();
267 workspace_controller_.reset();
268 // Forget with the display ID so that display lookup
269 // ends up with invalid display.
270 root_window_->ClearProperty(kDisplayIdKey);
271 // And this root window should no longer process events.
272 root_window_->PrepareForShutdown();
273
274 system_background_.reset();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000275}
276
277SystemModalContainerLayoutManager*
278RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
279 aura::Window* container = NULL;
280 if (window) {
281 if (window->parent() &&
282 window->parent()->id() >= kShellWindowId_LockScreenContainer) {
283 container = GetContainer(kShellWindowId_LockSystemModalContainer);
284 } else {
285 container = GetContainer(kShellWindowId_SystemModalContainer);
286 }
287 } else {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100288 int modal_window_id = Shell::GetInstance()->session_state_delegate()
289 ->IsUserSessionBlocked() ? kShellWindowId_LockSystemModalContainer :
290 kShellWindowId_SystemModalContainer;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000291 container = GetContainer(modal_window_id);
292 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100293 return container ? static_cast<SystemModalContainerLayoutManager*>(
294 container->layout_manager()) : NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000295}
296
297aura::Window* RootWindowController::GetContainer(int container_id) {
298 return root_window_->GetChildById(container_id);
299}
300
Ben Murdoch2385ea32013-08-06 11:01:04 +0100301const aura::Window* RootWindowController::GetContainer(int container_id) const {
302 return root_window_->GetChildById(container_id);
303}
304
Ben Murdocheb525c52013-07-10 11:40:50 +0100305void RootWindowController::Init(bool first_run_after_boot) {
306 root_window_->SetCursor(ui::kCursorPointer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000307 CreateContainersInRootWindow(root_window_.get());
Ben Murdocheb525c52013-07-10 11:40:50 +0100308 CreateSystemBackground(first_run_after_boot);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100309
Ben Murdocheb525c52013-07-10 11:40:50 +0100310 InitLayoutManagers();
311 InitKeyboard();
312 InitTouchHuds();
313
314 if (Shell::GetPrimaryRootWindowController()->
315 GetSystemModalLayoutManager(NULL)->has_modal_background()) {
316 GetSystemModalLayoutManager(NULL)->CreateModalBackground();
317 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100318
319 Shell::GetInstance()->AddShellObserver(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000320}
321
Ben Murdocheb525c52013-07-10 11:40:50 +0100322void RootWindowController::ShowLauncher() {
323 if (!shelf_->launcher())
324 return;
325 shelf_->launcher()->SetVisible(true);
326 shelf_->status_area_widget()->Show();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000327}
328
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000329void RootWindowController::OnLauncherCreated() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000330 if (panel_layout_manager_)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000331 panel_layout_manager_->SetLauncher(shelf_->launcher());
Ben Murdochca12bfa2013-07-23 11:17:05 +0100332 if (docked_layout_manager_) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100333 docked_layout_manager_->SetLauncher(shelf_->launcher());
Ben Murdochca12bfa2013-07-23 11:17:05 +0100334 if (shelf_->shelf_layout_manager())
335 docked_layout_manager_->AddObserver(shelf_->shelf_layout_manager());
336 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000337}
338
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000339void RootWindowController::UpdateAfterLoginStatusChange(
340 user::LoginStatus status) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100341 if (status != user::LOGGED_IN_NONE)
342 mouse_event_target_.reset();
Ben Murdocheb525c52013-07-10 11:40:50 +0100343 if (shelf_->status_area_widget())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000344 shelf_->status_area_widget()->UpdateAfterLoginStatusChange(status);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000345}
346
347void RootWindowController::HandleInitialDesktopBackgroundAnimationStarted() {
348 if (CommandLine::ForCurrentProcess()->HasSwitch(
349 switches::kAshAnimateFromBootSplashScreen) &&
350 boot_splash_screen_.get()) {
351 // Make the splash screen fade out so it doesn't obscure the desktop
352 // wallpaper's brightness/grayscale animation.
353 boot_splash_screen_->StartHideAnimation(
354 base::TimeDelta::FromMilliseconds(kBootSplashScreenHideDurationMs));
355 }
356}
357
Ben Murdocheb525c52013-07-10 11:40:50 +0100358void RootWindowController::OnWallpaperAnimationFinished(views::Widget* widget) {
359 // Make sure the wallpaper is visible.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000360 system_background_->SetColor(SK_ColorBLACK);
361 boot_splash_screen_.reset();
Ben Murdocheb525c52013-07-10 11:40:50 +0100362
363 Shell::GetInstance()->user_wallpaper_delegate()->
364 OnWallpaperAnimationFinished();
365 // Only removes old component when wallpaper animation finished. If we
366 // remove the old one before the new wallpaper is done fading in there will
367 // be a white flash during the animation.
368 if (animating_wallpaper_controller()) {
369 DesktopBackgroundWidgetController* controller =
370 animating_wallpaper_controller()->GetController(true);
371 // |desktop_widget_| should be the same animating widget we try to move
372 // to |kDesktopController|. Otherwise, we may close |desktop_widget_|
373 // before move it to |kDesktopController|.
374 DCHECK_EQ(controller->widget(), widget);
375 // Release the old controller and close its background widget.
376 SetWallpaperController(controller);
377 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000378}
379
380void RootWindowController::CloseChildWindows() {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100381 mouse_event_target_.reset();
382
Ben Murdocheb525c52013-07-10 11:40:50 +0100383 if (!shelf_.get())
384 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000385 // panel_layout_manager_ needs to be shut down before windows are destroyed.
386 if (panel_layout_manager_) {
387 panel_layout_manager_->Shutdown();
388 panel_layout_manager_ = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000389 }
Ben Murdochca12bfa2013-07-23 11:17:05 +0100390 // docked_layout_manager_ needs to be shut down before windows are destroyed.
391 if (docked_layout_manager_) {
392 if (shelf_->shelf_layout_manager())
393 docked_layout_manager_->RemoveObserver(shelf_->shelf_layout_manager());
394 docked_layout_manager_->Shutdown();
395 docked_layout_manager_ = NULL;
396 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000397
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000398 // TODO(harrym): Remove when Status Area Widget is a child view.
Ben Murdocheb525c52013-07-10 11:40:50 +0100399 shelf_->ShutdownStatusAreaWidget();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000400
Ben Murdocheb525c52013-07-10 11:40:50 +0100401 if (shelf_->shelf_layout_manager())
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100402 shelf_->shelf_layout_manager()->PrepareForShutdown();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000403
404 // Close background widget first as it depends on tooltip.
Ben Murdocheb525c52013-07-10 11:40:50 +0100405 wallpaper_controller_.reset();
406 animating_wallpaper_controller_.reset();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000407
408 workspace_controller_.reset();
409 aura::client::SetTooltipClient(root_window_.get(), NULL);
410
411 while (!root_window_->children().empty()) {
412 aura::Window* child = root_window_->children()[0];
413 delete child;
414 }
415
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000416 shelf_.reset(NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000417}
418
419void RootWindowController::MoveWindowsTo(aura::RootWindow* dst) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000420 // Forget the shelf early so that shelf don't update itself using wrong
421 // display info.
422 workspace_controller_->SetShelf(NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000423 ReparentAllWindows(root_window_.get(), dst);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000424}
425
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000426ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
Ben Murdocheb525c52013-07-10 11:40:50 +0100427 return shelf_->shelf_layout_manager();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000428}
429
430SystemTray* RootWindowController::GetSystemTray() {
431 // We assume in throughout the code that this will not return NULL. If code
432 // triggers this for valid reasons, it should test status_area_widget first.
Ben Murdocheb525c52013-07-10 11:40:50 +0100433 CHECK(shelf_->status_area_widget());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000434 return shelf_->status_area_widget()->system_tray();
435}
436
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100437void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen,
438 ui::MenuSourceType source_type) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000439 DCHECK(Shell::GetInstance()->delegate());
440 scoped_ptr<ui::MenuModel> menu_model(
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100441 Shell::GetInstance()->delegate()->CreateContextMenu(root_window()));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100442 if (!menu_model)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000443 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000444
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100445 // Background controller may not be set yet if user clicked on status are
446 // before initial animation completion. See crbug.com/222218
Ben Murdocheb525c52013-07-10 11:40:50 +0100447 if (!wallpaper_controller_.get())
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100448 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000449
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100450 views::MenuRunner menu_runner(menu_model.get());
Ben Murdocheb525c52013-07-10 11:40:50 +0100451 if (menu_runner.RunMenuAt(wallpaper_controller_->widget(),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100452 NULL, gfx::Rect(location_in_screen, gfx::Size()),
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100453 views::MenuItemView::TOPLEFT, source_type,
454 views::MenuRunner::CONTEXT_MENU) ==
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100455 views::MenuRunner::MENU_DELETED) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000456 return;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100457 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000458
459 Shell::GetInstance()->UpdateShelfVisibility();
460}
461
462void RootWindowController::UpdateShelfVisibility() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000463 shelf_->shelf_layout_manager()->UpdateVisibilityState();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000464}
465
Ben Murdoch2385ea32013-08-06 11:01:04 +0100466const aura::Window* RootWindowController::GetFullscreenWindow() const {
467 const aura::Window* container = GetContainer(kShellWindowId_DefaultContainer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000468 for (size_t i = 0; i < container->children().size(); ++i) {
469 aura::Window* child = container->children()[i];
Ben Murdocheb525c52013-07-10 11:40:50 +0100470 if (wm::IsWindowFullscreen(child))
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100471 return child;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000472 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100473 return NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000474}
475
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100476void RootWindowController::InitKeyboard() {
477 if (keyboard::IsKeyboardEnabled()) {
478 aura::Window* parent = root_window();
479
480 keyboard::KeyboardControllerProxy* proxy =
481 Shell::GetInstance()->delegate()->CreateKeyboardControllerProxy();
482 keyboard_controller_.reset(
483 new keyboard::KeyboardController(proxy));
484
485 keyboard_controller_->AddObserver(shelf()->shelf_layout_manager());
486 keyboard_controller_->AddObserver(panel_layout_manager_);
487
488 aura::Window* keyboard_container =
489 keyboard_controller_->GetContainerWindow();
490 parent->AddChild(keyboard_container);
491 keyboard_container->SetBounds(parent->bounds());
492 }
493}
494
495
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000496////////////////////////////////////////////////////////////////////////////////
497// RootWindowController, private:
498
Ben Murdocheb525c52013-07-10 11:40:50 +0100499void RootWindowController::InitLayoutManagers() {
500 root_window_layout_ =
501 new RootWindowLayoutManager(root_window_.get());
502 root_window_->SetLayoutManager(root_window_layout_);
503
504 aura::Window* default_container =
505 GetContainer(kShellWindowId_DefaultContainer);
506 // Workspace manager has its own layout managers.
507 workspace_controller_.reset(
508 new WorkspaceController(default_container));
509
510 aura::Window* always_on_top_container =
511 GetContainer(kShellWindowId_AlwaysOnTopContainer);
512 always_on_top_container->SetLayoutManager(
513 new BaseLayoutManager(
514 always_on_top_container->GetRootWindow()));
515 always_on_top_controller_.reset(new internal::AlwaysOnTopController);
516 always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container);
517
518 DCHECK(!shelf_.get());
519 aura::Window* shelf_container =
520 GetContainer(internal::kShellWindowId_ShelfContainer);
521 // TODO(harrym): Remove when status area is view.
522 aura::Window* status_container =
523 GetContainer(internal::kShellWindowId_StatusContainer);
524 shelf_.reset(new ShelfWidget(
525 shelf_container, status_container, workspace_controller()));
526
Ben Murdochbb1529c2013-08-08 10:24:53 +0100527 if (!Shell::GetInstance()->session_state_delegate()->
528 IsActiveUserSessionStarted()) {
529 // This window exists only to be a event target on login screen.
530 // It does not have to handle events, nor be visible.
531 mouse_event_target_.reset(new aura::Window(new EmptyWindowDelegate));
532 mouse_event_target_->Init(ui::LAYER_NOT_DRAWN);
533
534 aura::Window* lock_background_container =
535 GetContainer(internal::kShellWindowId_LockScreenBackgroundContainer);
536 lock_background_container->AddChild(mouse_event_target_.get());
537 mouse_event_target_->Show();
538 }
539
Ben Murdocheb525c52013-07-10 11:40:50 +0100540 // Create Docked windows layout manager
541 aura::Window* docked_container = GetContainer(
542 internal::kShellWindowId_DockedContainer);
543 docked_layout_manager_ =
544 new internal::DockedWindowLayoutManager(docked_container);
545 docked_container_handler_.reset(
546 new ToplevelWindowEventHandler(docked_container));
547 docked_container->SetLayoutManager(docked_layout_manager_);
548
549 // Create Panel layout manager
550 aura::Window* panel_container = GetContainer(
551 internal::kShellWindowId_PanelContainer);
552 panel_layout_manager_ =
553 new internal::PanelLayoutManager(panel_container);
554 panel_container_handler_.reset(
555 new PanelWindowEventHandler(panel_container));
556 panel_container->SetLayoutManager(panel_layout_manager_);
557}
558
559void RootWindowController::InitTouchHuds() {
560 CommandLine* command_line = CommandLine::ForCurrentProcess();
561 if (command_line->HasSwitch(switches::kAshTouchHud))
562 set_touch_hud_debug(new TouchHudDebug(root_window_.get()));
563 if (Shell::GetInstance()->is_touch_hud_projection_enabled())
564 EnableTouchHudProjection();
565}
566
567void RootWindowController::CreateSystemBackground(
568 bool is_first_run_after_boot) {
569 SkColor color = SK_ColorBLACK;
570#if defined(OS_CHROMEOS)
571 if (is_first_run_after_boot)
572 color = kChromeOsBootColor;
573#endif
574 system_background_.reset(
575 new SystemBackgroundController(root_window_.get(), color));
576
577#if defined(OS_CHROMEOS)
578 // Make a copy of the system's boot splash screen so we can composite it
579 // onscreen until the desktop background is ready.
580 if (is_first_run_after_boot &&
581 (CommandLine::ForCurrentProcess()->HasSwitch(
582 switches::kAshCopyHostBackgroundAtBoot) ||
583 CommandLine::ForCurrentProcess()->HasSwitch(
584 switches::kAshAnimateFromBootSplashScreen)))
585 boot_splash_screen_.reset(new BootSplashScreen(root_window_.get()));
586#endif
587}
588
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000589void RootWindowController::CreateContainersInRootWindow(
590 aura::RootWindow* root_window) {
591 // These containers are just used by PowerButtonController to animate groups
592 // of containers simultaneously without messing up the current transformations
593 // on those containers. These are direct children of the root window; all of
594 // the other containers are their children.
595
596 // The desktop background container is not part of the lock animation, so it
597 // is not included in those animate groups.
598 // When screen is locked desktop background is moved to lock screen background
599 // container (moved back on unlock). We want to make sure that there's an
600 // opaque layer occluding the non-lock-screen layers.
601 aura::Window* desktop_background_container = CreateContainer(
602 kShellWindowId_DesktopBackgroundContainer,
603 "DesktopBackgroundContainer",
604 root_window);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000605 views::corewm::SetChildWindowVisibilityChangesAnimated(
606 desktop_background_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000607
608 aura::Window* non_lock_screen_containers = CreateContainer(
609 kShellWindowId_NonLockScreenContainersContainer,
610 "NonLockScreenContainersContainer",
611 root_window);
612
613 aura::Window* lock_background_containers = CreateContainer(
614 kShellWindowId_LockScreenBackgroundContainer,
615 "LockScreenBackgroundContainer",
616 root_window);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000617 views::corewm::SetChildWindowVisibilityChangesAnimated(
618 lock_background_containers);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000619
620 aura::Window* lock_screen_containers = CreateContainer(
621 kShellWindowId_LockScreenContainersContainer,
622 "LockScreenContainersContainer",
623 root_window);
624 aura::Window* lock_screen_related_containers = CreateContainer(
625 kShellWindowId_LockScreenRelatedContainersContainer,
626 "LockScreenRelatedContainersContainer",
627 root_window);
628
629 CreateContainer(kShellWindowId_UnparentedControlContainer,
630 "UnparentedControlContainer",
631 non_lock_screen_containers);
632
633 aura::Window* default_container = CreateContainer(
634 kShellWindowId_DefaultContainer,
635 "DefaultContainer",
636 non_lock_screen_containers);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000637 views::corewm::SetChildWindowVisibilityChangesAnimated(default_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000638 SetUsesScreenCoordinates(default_container);
639
640 aura::Window* always_on_top_container = CreateContainer(
641 kShellWindowId_AlwaysOnTopContainer,
642 "AlwaysOnTopContainer",
643 non_lock_screen_containers);
644 always_on_top_container_handler_.reset(
645 new ToplevelWindowEventHandler(always_on_top_container));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000646 views::corewm::SetChildWindowVisibilityChangesAnimated(
647 always_on_top_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000648 SetUsesScreenCoordinates(always_on_top_container);
649
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100650 aura::Window* docked_container = CreateContainer(
651 kShellWindowId_DockedContainer,
652 "DockedContainer",
653 non_lock_screen_containers);
654 SetUsesScreenCoordinates(docked_container);
655
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000656 aura::Window* panel_container = CreateContainer(
657 kShellWindowId_PanelContainer,
658 "PanelContainer",
659 non_lock_screen_containers);
660 SetUsesScreenCoordinates(panel_container);
661
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100662 aura::Window* shelf_container =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000663 CreateContainer(kShellWindowId_ShelfContainer,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100664 "ShelfContainer",
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000665 non_lock_screen_containers);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100666 SetUsesScreenCoordinates(shelf_container);
667 DescendantShouldStayInSameRootWindow(shelf_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000668
669 aura::Window* app_list_container =
670 CreateContainer(kShellWindowId_AppListContainer,
671 "AppListContainer",
672 non_lock_screen_containers);
673 SetUsesScreenCoordinates(app_list_container);
674
675 aura::Window* modal_container = CreateContainer(
676 kShellWindowId_SystemModalContainer,
677 "SystemModalContainer",
678 non_lock_screen_containers);
679 modal_container_handler_.reset(
680 new ToplevelWindowEventHandler(modal_container));
681 modal_container->SetLayoutManager(
682 new SystemModalContainerLayoutManager(modal_container));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000683 views::corewm::SetChildWindowVisibilityChangesAnimated(modal_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000684 SetUsesScreenCoordinates(modal_container);
685
686 aura::Window* input_method_container = CreateContainer(
687 kShellWindowId_InputMethodContainer,
688 "InputMethodContainer",
689 non_lock_screen_containers);
690 SetUsesScreenCoordinates(input_method_container);
691
692 // TODO(beng): Figure out if we can make this use
693 // SystemModalContainerEventFilter instead of stops_event_propagation.
694 aura::Window* lock_container = CreateContainer(
695 kShellWindowId_LockScreenContainer,
696 "LockScreenContainer",
697 lock_screen_containers);
698 lock_container->SetLayoutManager(
699 new BaseLayoutManager(root_window));
700 SetUsesScreenCoordinates(lock_container);
701 // TODO(beng): stopsevents
702
703 aura::Window* lock_modal_container = CreateContainer(
704 kShellWindowId_LockSystemModalContainer,
705 "LockSystemModalContainer",
706 lock_screen_containers);
707 lock_modal_container_handler_.reset(
708 new ToplevelWindowEventHandler(lock_modal_container));
709 lock_modal_container->SetLayoutManager(
710 new SystemModalContainerLayoutManager(lock_modal_container));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000711 views::corewm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000712 SetUsesScreenCoordinates(lock_modal_container);
713
714 aura::Window* status_container =
715 CreateContainer(kShellWindowId_StatusContainer,
716 "StatusContainer",
717 lock_screen_related_containers);
718 SetUsesScreenCoordinates(status_container);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100719 DescendantShouldStayInSameRootWindow(status_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000720
721 aura::Window* settings_bubble_container = CreateContainer(
722 kShellWindowId_SettingBubbleContainer,
723 "SettingBubbleContainer",
724 lock_screen_related_containers);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000725 views::corewm::SetChildWindowVisibilityChangesAnimated(
726 settings_bubble_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000727 SetUsesScreenCoordinates(settings_bubble_container);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100728 DescendantShouldStayInSameRootWindow(settings_bubble_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000729
730 aura::Window* menu_container = CreateContainer(
731 kShellWindowId_MenuContainer,
732 "MenuContainer",
733 lock_screen_related_containers);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000734 views::corewm::SetChildWindowVisibilityChangesAnimated(menu_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000735 SetUsesScreenCoordinates(menu_container);
736
737 aura::Window* drag_drop_container = CreateContainer(
738 kShellWindowId_DragImageAndTooltipContainer,
739 "DragImageAndTooltipContainer",
740 lock_screen_related_containers);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000741 views::corewm::SetChildWindowVisibilityChangesAnimated(drag_drop_container);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000742 SetUsesScreenCoordinates(drag_drop_container);
743
744 aura::Window* overlay_container = CreateContainer(
745 kShellWindowId_OverlayContainer,
746 "OverlayContainer",
747 lock_screen_related_containers);
748 SetUsesScreenCoordinates(overlay_container);
749
750 CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
751 "PowerButtonAnimationContainer", root_window) ;
752}
753
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100754void RootWindowController::EnableTouchHudProjection() {
755 if (touch_hud_projection_)
756 return;
757 set_touch_hud_projection(new TouchHudProjection(root_window_.get()));
758}
759
760void RootWindowController::DisableTouchHudProjection() {
761 if (!touch_hud_projection_)
762 return;
763 touch_hud_projection_->Remove();
764}
765
766void RootWindowController::OnLoginStateChanged(user::LoginStatus status) {
767 shelf_->shelf_layout_manager()->UpdateVisibilityState();
768}
769
770void RootWindowController::OnTouchHudProjectionToggled(bool enabled) {
771 if (enabled)
772 EnableTouchHudProjection();
773 else
774 DisableTouchHudProjection();
775}
776
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000777} // namespace internal
778} // namespace ash