blob: 7c7909aaadb113ebf7410a765416ace553622646 [file] [log] [blame]
[email protected]d90b8392012-06-13 09:34:561// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ash/root_window_controller.h"
6
[email protected]8b3e3d82013-08-20 14:36:307#include <queue>
[email protected]8d625fb2012-07-18 16:40:068#include <vector>
9
[email protected]44d444c2013-01-30 01:47:4410#include "ash/ash_constants.h"
[email protected]e6e41d2f2012-10-29 19:22:1911#include "ash/ash_switches.h"
[email protected]b4ddc7a2012-08-07 04:17:3212#include "ash/desktop_background/desktop_background_widget_controller.h"
[email protected]0bf61732013-07-02 04:35:1013#include "ash/desktop_background/user_wallpaper_delegate.h"
[email protected]6bdf7952012-11-14 10:10:5814#include "ash/display/display_manager.h"
[email protected]e74aaf0a2012-10-12 18:42:2815#include "ash/focus_cycler.h"
[email protected]f8e6aad2013-08-30 21:49:1116#include "ash/root_window_settings.h"
[email protected]fcb123d2013-04-17 15:58:4917#include "ash/session_state_delegate.h"
[email protected]478c6c32013-03-09 02:50:5818#include "ash/shelf/shelf_layout_manager.h"
19#include "ash/shelf/shelf_types.h"
20#include "ash/shelf/shelf_widget.h"
[email protected]d90b8392012-06-13 09:34:5621#include "ash/shell.h"
[email protected]e74aaf0a2012-10-12 18:42:2822#include "ash/shell_delegate.h"
[email protected]d90b8392012-06-13 09:34:5623#include "ash/shell_factory.h"
24#include "ash/shell_window_ids.h"
[email protected]e74aaf0a2012-10-12 18:42:2825#include "ash/system/status_area_widget.h"
[email protected]8674b312012-10-12 19:02:4426#include "ash/system/tray/system_tray_delegate.h"
[email protected]2b8a9bb2013-07-01 22:43:4027#include "ash/touch/touch_hud_debug.h"
28#include "ash/touch/touch_hud_projection.h"
[email protected]80549c152013-07-02 01:42:4729#include "ash/touch/touch_observer_hud.h"
30#include "ash/wm/always_on_top_controller.h"
[email protected]d90b8392012-06-13 09:34:5631#include "ash/wm/base_layout_manager.h"
[email protected]beb4e5c2013-06-18 15:37:0732#include "ash/wm/dock/docked_window_layout_manager.h"
[email protected]7095a652013-03-07 19:41:4933#include "ash/wm/panels/panel_layout_manager.h"
[email protected]100659412013-06-21 22:59:5534#include "ash/wm/panels/panel_window_event_handler.h"
[email protected]d90b8392012-06-13 09:34:5635#include "ash/wm/root_window_layout_manager.h"
36#include "ash/wm/screen_dimmer.h"
[email protected]2a2caa02013-01-22 20:50:3637#include "ash/wm/stacking_controller.h"
[email protected]e74aaf0a2012-10-12 18:42:2838#include "ash/wm/status_area_layout_manager.h"
[email protected]e6e41d2f2012-10-29 19:22:1939#include "ash/wm/system_background_controller.h"
[email protected]d90b8392012-06-13 09:34:5640#include "ash/wm/system_modal_container_layout_manager.h"
[email protected]5dc51db82012-09-11 03:39:0141#include "ash/wm/toplevel_window_event_handler.h"
[email protected]8d625fb2012-07-18 16:40:0642#include "ash/wm/window_properties.h"
[email protected]700849f2013-04-30 17:49:2043#include "ash/wm/window_util.h"
[email protected]d90b8392012-06-13 09:34:5644#include "ash/wm/workspace_controller.h"
[email protected]e6e41d2f2012-10-29 19:22:1945#include "base/command_line.h"
[email protected]1e84c632013-06-27 23:12:2146#include "base/time/time.h"
[email protected]f1853122012-06-27 16:21:2647#include "ui/aura/client/aura_constants.h"
[email protected]8b3e3d82013-08-20 14:36:3048#include "ui/aura/client/drag_drop_client.h"
[email protected]d90b8392012-06-13 09:34:5649#include "ui/aura/client/tooltip_client.h"
50#include "ui/aura/root_window.h"
[email protected]f1853122012-06-27 16:21:2651#include "ui/aura/window.h"
[email protected]cf6fea22013-08-07 14:24:0152#include "ui/aura/window_delegate.h"
[email protected]f1853122012-06-27 16:21:2653#include "ui/aura/window_observer.h"
[email protected]8b3e3d82013-08-20 14:36:3054#include "ui/aura/window_tracker.h"
[email protected]cf6fea22013-08-07 14:24:0155#include "ui/base/hit_test.h"
[email protected]431552c2012-10-23 00:38:3356#include "ui/base/models/menu_model.h"
[email protected]f8e6aad2013-08-30 21:49:1157#include "ui/gfx/display.h"
[email protected]8d625fb2012-07-18 16:40:0658#include "ui/gfx/screen.h"
[email protected]86459e2c2013-04-10 13:39:2459#include "ui/keyboard/keyboard_controller.h"
60#include "ui/keyboard/keyboard_util.h"
[email protected]431552c2012-10-23 00:38:3361#include "ui/views/controls/menu/menu_runner.h"
[email protected]23a2dc82013-08-22 15:04:2262#include "ui/views/corewm/capture_controller.h"
[email protected]b5756e22012-11-30 01:32:0263#include "ui/views/corewm/visibility_controller.h"
[email protected]431552c2012-10-23 00:38:3364#include "ui/views/view_model.h"
65#include "ui/views/view_model_utils.h"
[email protected]d90b8392012-06-13 09:34:5666
[email protected]252eb232013-08-14 22:09:2767#if defined(OS_CHROMEOS)
68#include "ash/wm/boot_splash_screen_chromeos.h"
69#endif
70
[email protected]d90b8392012-06-13 09:34:5671namespace ash {
72namespace {
73
[email protected]252eb232013-08-14 22:09:2774#if defined(OS_CHROMEOS)
[email protected]bca9a7e2012-11-10 06:25:4975// Duration for the animation that hides the boot splash screen, in
76// milliseconds. This should be short enough in relation to
77// wm/window_animation.cc's brightness/grayscale fade animation that the login
78// background image animation isn't hidden by the splash screen animation.
79const int kBootSplashScreenHideDurationMs = 500;
[email protected]252eb232013-08-14 22:09:2780#endif
[email protected]bca9a7e2012-11-10 06:25:4981
[email protected]d90b8392012-06-13 09:34:5682// Creates a new window for use as a container.
83aura::Window* CreateContainer(int window_id,
84 const char* name,
85 aura::Window* parent) {
86 aura::Window* container = new aura::Window(NULL);
87 container->set_id(window_id);
88 container->SetName(name);
89 container->Init(ui::LAYER_NOT_DRAWN);
90 parent->AddChild(container);
91 if (window_id != internal::kShellWindowId_UnparentedControlContainer)
92 container->Show();
93 return container;
94}
95
[email protected]95058572012-08-20 14:57:2996// Reparents |window| to |new_parent|.
97void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
98 // Update the restore bounds to make it relative to the display.
99 gfx::Rect restore_bounds(GetRestoreBoundsInParent(window));
100 new_parent->AddChild(window);
101 if (!restore_bounds.IsEmpty())
102 SetRestoreBoundsInParent(window, restore_bounds);
103}
104
105// Reparents the appropriate set of windows from |src| to |dst|.
106void ReparentAllWindows(aura::RootWindow* src, aura::RootWindow* dst) {
107 // Set of windows to move.
[email protected]f1853122012-06-27 16:21:26108 const int kContainerIdsToMove[] = {
109 internal::kShellWindowId_DefaultContainer,
[email protected]beb4e5c2013-06-18 15:37:07110 internal::kShellWindowId_DockedContainer,
[email protected]95db9c12013-01-31 11:47:44111 internal::kShellWindowId_PanelContainer,
[email protected]f1853122012-06-27 16:21:26112 internal::kShellWindowId_AlwaysOnTopContainer,
113 internal::kShellWindowId_SystemModalContainer,
114 internal::kShellWindowId_LockSystemModalContainer,
[email protected]6274d312012-10-04 22:06:41115 internal::kShellWindowId_InputMethodContainer,
[email protected]a9754872013-01-25 07:44:00116 internal::kShellWindowId_UnparentedControlContainer,
[email protected]f1853122012-06-27 16:21:26117 };
[email protected]f1853122012-06-27 16:21:26118 for (size_t i = 0; i < arraysize(kContainerIdsToMove); i++) {
119 int id = kContainerIdsToMove[i];
120 aura::Window* src_container = Shell::GetContainer(src, id);
121 aura::Window* dst_container = Shell::GetContainer(dst, id);
[email protected]5b6021902013-02-26 05:33:29122 while (!src_container->children().empty()) {
123 // Restart iteration from the source container windows each time as they
124 // may change as a result of moving other windows.
125 aura::Window::Windows::const_iterator iter =
126 src_container->children().begin();
127 while (iter != src_container->children().end() &&
128 internal::SystemModalContainerLayoutManager::IsModalBackground(
129 *iter)) {
130 ++iter;
131 }
132 // If the entire window list is modal background windows then stop.
133 if (iter == src_container->children().end())
134 break;
135 ReparentWindow(*iter, dst_container);
[email protected]f1853122012-06-27 16:21:26136 }
137 }
138}
139
[email protected]8d625fb2012-07-18 16:40:06140// Mark the container window so that a widget added to this container will
141// use the virtual screeen coordinates instead of parent.
142void SetUsesScreenCoordinates(aura::Window* container) {
143 container->SetProperty(internal::kUsesScreenCoordinatesKey, true);
144}
145
[email protected]e887c6c2013-07-08 19:35:53146// Mark the container window so that a widget added to this container will
147// say in the same root window regardless of the bounds specified.
148void DescendantShouldStayInSameRootWindow(aura::Window* container) {
149 container->SetProperty(internal::kStayInSameRootWindowKey, true);
150}
151
[email protected]cf6fea22013-08-07 14:24:01152// A window delegate which does nothing. Used to create a window that
153// is a event target, but do nothing.
154class EmptyWindowDelegate : public aura::WindowDelegate {
155 public:
156 EmptyWindowDelegate() {}
157 virtual ~EmptyWindowDelegate() {}
158
159 // aura::WindowDelegate overrides:
160 virtual gfx::Size GetMinimumSize() const OVERRIDE {
161 return gfx::Size();
162 }
163 virtual gfx::Size GetMaximumSize() const OVERRIDE {
164 return gfx::Size();
165 }
166 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
167 const gfx::Rect& new_bounds) OVERRIDE {
168 }
169 virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
170 return gfx::kNullCursor;
171 }
172 virtual int GetNonClientComponent(
173 const gfx::Point& point) const OVERRIDE {
174 return HTNOWHERE;
175 }
176 virtual bool ShouldDescendIntoChildForEventHandling(
177 aura::Window* child,
178 const gfx::Point& location) OVERRIDE {
179 return false;
180 }
181 virtual bool CanFocus() OVERRIDE {
182 return false;
183 }
184 virtual void OnCaptureLost() OVERRIDE {
185 }
186 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
187 }
188 virtual void OnDeviceScaleFactorChanged(
189 float device_scale_factor) OVERRIDE {
190 }
191 virtual void OnWindowDestroying() OVERRIDE {}
[email protected]febe1fd62013-08-07 16:07:24192 virtual void OnWindowDestroyed() OVERRIDE {
193 delete this;
194 }
[email protected]cf6fea22013-08-07 14:24:01195 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
196 }
197 virtual bool HasHitTestMask() const OVERRIDE {
198 return false;
199 }
200 virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
[email protected]1ddbe932013-09-12 06:23:16201 virtual void DidRecreateLayer(ui::Layer* old_layer,
202 ui::Layer* new_layer) OVERRIDE {}
[email protected]cf6fea22013-08-07 14:24:01203
204 private:
205 DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate);
206};
207
[email protected]d90b8392012-06-13 09:34:56208} // namespace
209
210namespace internal {
211
212RootWindowController::RootWindowController(aura::RootWindow* root_window)
[email protected]e74aaf0a2012-10-12 18:42:28213 : root_window_(root_window),
214 root_window_layout_(NULL),
[email protected]beb4e5c2013-06-18 15:37:07215 docked_layout_manager_(NULL),
[email protected]bff17552013-04-25 04:44:55216 panel_layout_manager_(NULL),
[email protected]2b8a9bb2013-07-01 22:43:40217 touch_hud_debug_(NULL),
218 touch_hud_projection_(NULL) {
[email protected]6b2d4a0b2013-09-06 06:29:54219 GetRootWindowSettings(root_window)->controller = this;
[email protected]c0ce80e2012-10-05 23:28:27220 screen_dimmer_.reset(new ScreenDimmer(root_window));
[email protected]2a2caa02013-01-22 20:50:36221
[email protected]0bf61732013-07-02 04:35:10222 stacking_controller_.reset(new StackingController);
[email protected]2a2caa02013-01-22 20:50:36223 aura::client::SetStackingClient(root_window, stacking_controller_.get());
[email protected]23a2dc82013-08-22 15:04:22224 capture_client_.reset(new views::corewm::ScopedCaptureClient(root_window));
[email protected]d90b8392012-06-13 09:34:56225}
226
227RootWindowController::~RootWindowController() {
[email protected]6675e1c2012-09-11 09:15:45228 Shutdown();
229 root_window_.reset();
[email protected]23a2dc82013-08-22 15:04:22230 // The CaptureClient needs to be around for as long as the RootWindow is
231 // valid.
232 capture_client_.reset();
[email protected]6675e1c2012-09-11 09:15:45233}
234
[email protected]88d71122012-10-18 07:11:01235// static
[email protected]a0afeb12012-12-10 22:57:09236RootWindowController* RootWindowController::ForLauncher(aura::Window* window) {
[email protected]8c0ec432013-05-10 04:33:39237 return GetRootWindowController(window->GetRootWindow());
[email protected]88d71122012-10-18 07:11:01238}
239
[email protected]a0afeb12012-12-10 22:57:09240// static
[email protected]ccff3d72013-02-06 04:26:28241RootWindowController* RootWindowController::ForWindow(
242 const aura::Window* window) {
[email protected]a0afeb12012-12-10 22:57:09243 return GetRootWindowController(window->GetRootWindow());
244}
245
246// static
[email protected]d17642d2013-09-12 23:44:38247RootWindowController* RootWindowController::ForTargetRootWindow() {
248 return internal::GetRootWindowController(Shell::GetTargetRootWindow());
[email protected]a0afeb12012-12-10 22:57:09249}
250
[email protected]0bf61732013-07-02 04:35:10251void RootWindowController::SetWallpaperController(
252 DesktopBackgroundWidgetController* controller) {
253 wallpaper_controller_.reset(controller);
254}
255
256void RootWindowController::SetAnimatingWallpaperController(
257 AnimatingDesktopController* controller) {
258 if (animating_wallpaper_controller_.get())
259 animating_wallpaper_controller_->StopAnimating();
260 animating_wallpaper_controller_.reset(controller);
261}
262
[email protected]6675e1c2012-09-11 09:15:45263void RootWindowController::Shutdown() {
[email protected]d141b922013-07-09 08:13:17264 Shell::GetInstance()->RemoveShellObserver(this);
265
[email protected]0bf61732013-07-02 04:35:10266 if (animating_wallpaper_controller_.get())
267 animating_wallpaper_controller_->StopAnimating();
268 wallpaper_controller_.reset();
269 animating_wallpaper_controller_.reset();
270
[email protected]d17642d2013-09-12 23:44:38271 // Change the target root window before closing child windows. If any child
[email protected]c98a4922013-09-05 20:01:42272 // being removed triggers a relayout of the shelf it will try to build a
[email protected]d17642d2013-09-12 23:44:38273 // window list adding windows from the target root window's containers which
[email protected]c98a4922013-09-05 20:01:42274 // may have already gone away.
[email protected]d17642d2013-09-12 23:44:38275 if (Shell::GetTargetRootWindow() == root_window_) {
276 Shell::GetInstance()->set_target_root_window(
[email protected]f634dd32012-07-23 22:49:07277 Shell::GetPrimaryRootWindow() == root_window_.get() ?
278 NULL : Shell::GetPrimaryRootWindow());
279 }
[email protected]c98a4922013-09-05 20:01:42280
281 CloseChildWindows();
[email protected]6b2d4a0b2013-09-06 06:29:54282 GetRootWindowSettings(root_window_.get())->controller = NULL;
[email protected]d90b8392012-06-13 09:34:56283 screen_dimmer_.reset();
284 workspace_controller_.reset();
[email protected]6675e1c2012-09-11 09:15:45285 // Forget with the display ID so that display lookup
286 // ends up with invalid display.
[email protected]f8e6aad2013-08-30 21:49:11287 internal::GetRootWindowSettings(root_window_.get())->display_id =
288 gfx::Display::kInvalidDisplayID;
[email protected]6675e1c2012-09-11 09:15:45289 // And this root window should no longer process events.
290 root_window_->PrepareForShutdown();
[email protected]e74aaf0a2012-10-12 18:42:28291
[email protected]956a6a42012-10-29 23:58:10292 system_background_.reset();
[email protected]d90b8392012-06-13 09:34:56293}
294
[email protected]c0ce80e2012-10-05 23:28:27295SystemModalContainerLayoutManager*
[email protected]8674b312012-10-12 19:02:44296RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
297 aura::Window* container = NULL;
298 if (window) {
[email protected]3b162e12012-11-09 11:52:35299 if (window->parent() &&
300 window->parent()->id() >= kShellWindowId_LockScreenContainer) {
301 container = GetContainer(kShellWindowId_LockSystemModalContainer);
302 } else {
[email protected]8674b312012-10-12 19:02:44303 container = GetContainer(kShellWindowId_SystemModalContainer);
[email protected]3b162e12012-11-09 11:52:35304 }
[email protected]8674b312012-10-12 19:02:44305 } else {
[email protected]a44afbbd2013-07-24 21:49:35306 int modal_window_id = Shell::GetInstance()->session_state_delegate()
307 ->IsUserSessionBlocked() ? kShellWindowId_LockSystemModalContainer :
308 kShellWindowId_SystemModalContainer;
[email protected]8674b312012-10-12 19:02:44309 container = GetContainer(modal_window_id);
310 }
[email protected]bb0c7cd42013-05-20 23:39:45311 return container ? static_cast<SystemModalContainerLayoutManager*>(
312 container->layout_manager()) : NULL;
[email protected]c0ce80e2012-10-05 23:28:27313}
314
[email protected]d90b8392012-06-13 09:34:56315aura::Window* RootWindowController::GetContainer(int container_id) {
316 return root_window_->GetChildById(container_id);
317}
318
[email protected]d8a24952013-08-05 20:05:05319const aura::Window* RootWindowController::GetContainer(int container_id) const {
320 return root_window_->GetChildById(container_id);
321}
322
[email protected]756bda12013-07-03 08:17:06323void RootWindowController::Init(bool first_run_after_boot) {
324 root_window_->SetCursor(ui::kCursorPointer);
[email protected]d90b8392012-06-13 09:34:56325 CreateContainersInRootWindow(root_window_.get());
[email protected]756bda12013-07-03 08:17:06326 CreateSystemBackground(first_run_after_boot);
[email protected]d90b8392012-06-13 09:34:56327
[email protected]756bda12013-07-03 08:17:06328 InitLayoutManagers();
329 InitKeyboard();
330 InitTouchHuds();
[email protected]bca9a7e2012-11-10 06:25:49331
[email protected]756bda12013-07-03 08:17:06332 if (Shell::GetPrimaryRootWindowController()->
333 GetSystemModalLayoutManager(NULL)->has_modal_background()) {
334 GetSystemModalLayoutManager(NULL)->CreateModalBackground();
335 }
[email protected]d141b922013-07-09 08:13:17336
337 Shell::GetInstance()->AddShellObserver(this);
[email protected]e74aaf0a2012-10-12 18:42:28338}
339
340void RootWindowController::ShowLauncher() {
[email protected]80549c152013-07-02 01:42:47341 if (!shelf_->launcher())
[email protected]e74aaf0a2012-10-12 18:42:28342 return;
[email protected]478c6c32013-03-09 02:50:58343 shelf_->launcher()->SetVisible(true);
344 shelf_->status_area_widget()->Show();
[email protected]e74aaf0a2012-10-12 18:42:28345}
346
[email protected]756bda12013-07-03 08:17:06347void RootWindowController::OnLauncherCreated() {
348 if (panel_layout_manager_)
349 panel_layout_manager_->SetLauncher(shelf_->launcher());
[email protected]7115bd32013-07-19 08:25:39350 if (docked_layout_manager_) {
[email protected]756bda12013-07-03 08:17:06351 docked_layout_manager_->SetLauncher(shelf_->launcher());
[email protected]7115bd32013-07-19 08:25:39352 if (shelf_->shelf_layout_manager())
353 docked_layout_manager_->AddObserver(shelf_->shelf_layout_manager());
354 }
[email protected]756bda12013-07-03 08:17:06355}
356
[email protected]16059276d2012-10-22 18:59:50357void RootWindowController::UpdateAfterLoginStatusChange(
358 user::LoginStatus status) {
[email protected]cf6fea22013-08-07 14:24:01359 if (status != user::LOGGED_IN_NONE)
360 mouse_event_target_.reset();
[email protected]80549c152013-07-02 01:42:47361 if (shelf_->status_area_widget())
[email protected]478c6c32013-03-09 02:50:58362 shelf_->status_area_widget()->UpdateAfterLoginStatusChange(status);
[email protected]16059276d2012-10-22 18:59:50363}
364
[email protected]bca9a7e2012-11-10 06:25:49365void RootWindowController::HandleInitialDesktopBackgroundAnimationStarted() {
[email protected]252eb232013-08-14 22:09:27366#if defined(OS_CHROMEOS)
[email protected]bca9a7e2012-11-10 06:25:49367 if (CommandLine::ForCurrentProcess()->HasSwitch(
368 switches::kAshAnimateFromBootSplashScreen) &&
369 boot_splash_screen_.get()) {
370 // Make the splash screen fade out so it doesn't obscure the desktop
371 // wallpaper's brightness/grayscale animation.
372 boot_splash_screen_->StartHideAnimation(
373 base::TimeDelta::FromMilliseconds(kBootSplashScreenHideDurationMs));
374 }
[email protected]252eb232013-08-14 22:09:27375#endif
[email protected]bca9a7e2012-11-10 06:25:49376}
377
[email protected]0bf61732013-07-02 04:35:10378void RootWindowController::OnWallpaperAnimationFinished(views::Widget* widget) {
379 // Make sure the wallpaper is visible.
[email protected]bca9a7e2012-11-10 06:25:49380 system_background_->SetColor(SK_ColorBLACK);
[email protected]252eb232013-08-14 22:09:27381#if defined(OS_CHROMEOS)
[email protected]bca9a7e2012-11-10 06:25:49382 boot_splash_screen_.reset();
[email protected]252eb232013-08-14 22:09:27383#endif
[email protected]0bf61732013-07-02 04:35:10384
385 Shell::GetInstance()->user_wallpaper_delegate()->
386 OnWallpaperAnimationFinished();
387 // Only removes old component when wallpaper animation finished. If we
388 // remove the old one before the new wallpaper is done fading in there will
389 // be a white flash during the animation.
390 if (animating_wallpaper_controller()) {
391 DesktopBackgroundWidgetController* controller =
392 animating_wallpaper_controller()->GetController(true);
393 // |desktop_widget_| should be the same animating widget we try to move
394 // to |kDesktopController|. Otherwise, we may close |desktop_widget_|
395 // before move it to |kDesktopController|.
396 DCHECK_EQ(controller->widget(), widget);
397 // Release the old controller and close its background widget.
398 SetWallpaperController(controller);
399 }
[email protected]697f04c2012-10-03 01:15:10400}
401
[email protected]d90b8392012-06-13 09:34:56402void RootWindowController::CloseChildWindows() {
[email protected]cf6fea22013-08-07 14:24:01403 mouse_event_target_.reset();
404
[email protected]80549c152013-07-02 01:42:47405 if (!shelf_.get())
406 return;
[email protected]79a87b7e2013-01-25 05:08:22407 // panel_layout_manager_ needs to be shut down before windows are destroyed.
408 if (panel_layout_manager_) {
409 panel_layout_manager_->Shutdown();
410 panel_layout_manager_ = NULL;
411 }
[email protected]7115bd32013-07-19 08:25:39412 // docked_layout_manager_ needs to be shut down before windows are destroyed.
413 if (docked_layout_manager_) {
414 if (shelf_->shelf_layout_manager())
415 docked_layout_manager_->RemoveObserver(shelf_->shelf_layout_manager());
416 docked_layout_manager_->Shutdown();
417 docked_layout_manager_ = NULL;
418 }
[email protected]79a87b7e2013-01-25 05:08:22419
[email protected]8b3e3d82013-08-20 14:36:30420 aura::client::SetDragDropClient(root_window_.get(), NULL);
421
[email protected]478c6c32013-03-09 02:50:58422 // TODO(harrym): Remove when Status Area Widget is a child view.
[email protected]80549c152013-07-02 01:42:47423 shelf_->ShutdownStatusAreaWidget();
[email protected]478c6c32013-03-09 02:50:58424
[email protected]80549c152013-07-02 01:42:47425 if (shelf_->shelf_layout_manager())
[email protected]a3e412712013-07-11 09:32:58426 shelf_->shelf_layout_manager()->PrepareForShutdown();
[email protected]e74aaf0a2012-10-12 18:42:28427
[email protected]d90b8392012-06-13 09:34:56428 // Close background widget first as it depends on tooltip.
[email protected]0bf61732013-07-02 04:35:10429 wallpaper_controller_.reset();
430 animating_wallpaper_controller_.reset();
[email protected]b4ddc7a2012-08-07 04:17:32431
[email protected]d90b8392012-06-13 09:34:56432 workspace_controller_.reset();
433 aura::client::SetTooltipClient(root_window_.get(), NULL);
434
[email protected]8b3e3d82013-08-20 14:36:30435 // Remove all toplevel windows first.
436 std::queue<aura::Window*> non_toplevel_windows;
437 non_toplevel_windows.push(root_window_.get());
438 while (!non_toplevel_windows.empty()) {
439 aura::Window* non_toplevel_window = non_toplevel_windows.front();
440 non_toplevel_windows.pop();
441 aura::WindowTracker toplevel_windows;
442 for (size_t i = 0; i < non_toplevel_window->children().size(); ++i) {
443 aura::Window* child = non_toplevel_window->children()[i];
444 if (child->delegate())
445 toplevel_windows.Add(child);
446 else
447 non_toplevel_windows.push(child);
448 }
449 while (!toplevel_windows.windows().empty())
450 delete *toplevel_windows.windows().begin();
[email protected]d90b8392012-06-13 09:34:56451 }
[email protected]8b3e3d82013-08-20 14:36:30452 // And then remove the containers.
453 while (!root_window_->children().empty())
454 delete root_window_->children()[0];
[email protected]478c6c32013-03-09 02:50:58455
456 shelf_.reset(NULL);
[email protected]d90b8392012-06-13 09:34:56457}
458
[email protected]f1853122012-06-27 16:21:26459void RootWindowController::MoveWindowsTo(aura::RootWindow* dst) {
[email protected]8039e06c2013-01-17 23:34:50460 // Forget the shelf early so that shelf don't update itself using wrong
461 // display info.
462 workspace_controller_->SetShelf(NULL);
[email protected]95058572012-08-20 14:57:29463 ReparentAllWindows(root_window_.get(), dst);
[email protected]f1853122012-06-27 16:21:26464}
465
[email protected]478c6c32013-03-09 02:50:58466ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
[email protected]80549c152013-07-02 01:42:47467 return shelf_->shelf_layout_manager();
[email protected]478c6c32013-03-09 02:50:58468}
469
[email protected]a0afeb12012-12-10 22:57:09470SystemTray* RootWindowController::GetSystemTray() {
471 // We assume in throughout the code that this will not return NULL. If code
472 // triggers this for valid reasons, it should test status_area_widget first.
[email protected]80549c152013-07-02 01:42:47473 CHECK(shelf_->status_area_widget());
[email protected]478c6c32013-03-09 02:50:58474 return shelf_->status_area_widget()->system_tray();
[email protected]a0afeb12012-12-10 22:57:09475}
476
[email protected]940fb1c2013-06-18 16:54:28477void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen,
478 ui::MenuSourceType source_type) {
[email protected]431552c2012-10-23 00:38:33479 DCHECK(Shell::GetInstance()->delegate());
480 scoped_ptr<ui::MenuModel> menu_model(
[email protected]8c0ec432013-05-10 04:33:39481 Shell::GetInstance()->delegate()->CreateContextMenu(root_window()));
[email protected]7f7f65c2013-04-17 16:47:13482 if (!menu_model)
[email protected]8e837ec2013-01-31 01:48:33483 return;
[email protected]431552c2012-10-23 00:38:33484
[email protected]6175fc42013-04-05 05:58:58485 // Background controller may not be set yet if user clicked on status are
486 // before initial animation completion. See crbug.com/222218
[email protected]0bf61732013-07-02 04:35:10487 if (!wallpaper_controller_.get())
[email protected]431552c2012-10-23 00:38:33488 return;
489
[email protected]6175fc42013-04-05 05:58:58490 views::MenuRunner menu_runner(menu_model.get());
[email protected]0bf61732013-07-02 04:35:10491 if (menu_runner.RunMenuAt(wallpaper_controller_->widget(),
[email protected]6175fc42013-04-05 05:58:58492 NULL, gfx::Rect(location_in_screen, gfx::Size()),
[email protected]940fb1c2013-06-18 16:54:28493 views::MenuItemView::TOPLEFT, source_type,
494 views::MenuRunner::CONTEXT_MENU) ==
[email protected]6175fc42013-04-05 05:58:58495 views::MenuRunner::MENU_DELETED) {
496 return;
497 }
498
[email protected]431552c2012-10-23 00:38:33499 Shell::GetInstance()->UpdateShelfVisibility();
500}
501
[email protected]e74aaf0a2012-10-12 18:42:28502void RootWindowController::UpdateShelfVisibility() {
[email protected]478c6c32013-03-09 02:50:58503 shelf_->shelf_layout_manager()->UpdateVisibilityState();
[email protected]e74aaf0a2012-10-12 18:42:28504}
505
[email protected]e3bc88e2013-09-06 06:22:06506const aura::Window* RootWindowController::GetTopmostFullscreenWindow() const {
507 const aura::Window::Windows& windows =
508 GetContainer(kShellWindowId_DefaultContainer)->children();
509 for (aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
510 iter != windows.rend(); ++iter) {
511 if (wm::IsWindowFullscreen(*iter))
512 return *iter;
[email protected]2ee2f5d2013-01-10 23:37:16513 }
[email protected]700849f2013-04-30 17:49:20514 return NULL;
[email protected]2ee2f5d2013-01-10 23:37:16515}
516
[email protected]86459e2c2013-04-10 13:39:24517void RootWindowController::InitKeyboard() {
518 if (keyboard::IsKeyboardEnabled()) {
519 aura::Window* parent = root_window();
520
521 keyboard::KeyboardControllerProxy* proxy =
522 Shell::GetInstance()->delegate()->CreateKeyboardControllerProxy();
523 keyboard_controller_.reset(
524 new keyboard::KeyboardController(proxy));
[email protected]5416f282013-04-29 20:52:48525
526 keyboard_controller_->AddObserver(shelf()->shelf_layout_manager());
527 keyboard_controller_->AddObserver(panel_layout_manager_);
528
[email protected]86459e2c2013-04-10 13:39:24529 aura::Window* keyboard_container =
530 keyboard_controller_->GetContainerWindow();
[email protected]eff4c7f2013-08-13 01:45:50531 keyboard_container->set_id(kShellWindowId_VirtualKeyboardContainer);
[email protected]86459e2c2013-04-10 13:39:24532 parent->AddChild(keyboard_container);
[email protected]e0f71132013-04-17 12:32:51533 keyboard_container->SetBounds(parent->bounds());
[email protected]86459e2c2013-04-10 13:39:24534 }
535}
536
537
[email protected]a4cd6d32012-09-12 03:42:13538////////////////////////////////////////////////////////////////////////////////
539// RootWindowController, private:
540
[email protected]756bda12013-07-03 08:17:06541void RootWindowController::InitLayoutManagers() {
542 root_window_layout_ =
543 new RootWindowLayoutManager(root_window_.get());
544 root_window_->SetLayoutManager(root_window_layout_);
545
546 aura::Window* default_container =
547 GetContainer(kShellWindowId_DefaultContainer);
548 // Workspace manager has its own layout managers.
549 workspace_controller_.reset(
550 new WorkspaceController(default_container));
551
552 aura::Window* always_on_top_container =
553 GetContainer(kShellWindowId_AlwaysOnTopContainer);
554 always_on_top_container->SetLayoutManager(
555 new BaseLayoutManager(
556 always_on_top_container->GetRootWindow()));
557 always_on_top_controller_.reset(new internal::AlwaysOnTopController);
558 always_on_top_controller_->SetAlwaysOnTopContainer(always_on_top_container);
559
560 DCHECK(!shelf_.get());
561 aura::Window* shelf_container =
562 GetContainer(internal::kShellWindowId_ShelfContainer);
563 // TODO(harrym): Remove when status area is view.
564 aura::Window* status_container =
565 GetContainer(internal::kShellWindowId_StatusContainer);
566 shelf_.reset(new ShelfWidget(
567 shelf_container, status_container, workspace_controller()));
568
[email protected]cf6fea22013-08-07 14:24:01569 if (!Shell::GetInstance()->session_state_delegate()->
570 IsActiveUserSessionStarted()) {
571 // This window exists only to be a event target on login screen.
572 // It does not have to handle events, nor be visible.
573 mouse_event_target_.reset(new aura::Window(new EmptyWindowDelegate));
574 mouse_event_target_->Init(ui::LAYER_NOT_DRAWN);
575
576 aura::Window* lock_background_container =
577 GetContainer(internal::kShellWindowId_LockScreenBackgroundContainer);
578 lock_background_container->AddChild(mouse_event_target_.get());
579 mouse_event_target_->Show();
580 }
581
[email protected]756bda12013-07-03 08:17:06582 // Create Docked windows layout manager
583 aura::Window* docked_container = GetContainer(
584 internal::kShellWindowId_DockedContainer);
585 docked_layout_manager_ =
586 new internal::DockedWindowLayoutManager(docked_container);
587 docked_container_handler_.reset(
588 new ToplevelWindowEventHandler(docked_container));
589 docked_container->SetLayoutManager(docked_layout_manager_);
590
591 // Create Panel layout manager
592 aura::Window* panel_container = GetContainer(
593 internal::kShellWindowId_PanelContainer);
594 panel_layout_manager_ =
595 new internal::PanelLayoutManager(panel_container);
596 panel_container_handler_.reset(
597 new PanelWindowEventHandler(panel_container));
598 panel_container->SetLayoutManager(panel_layout_manager_);
599}
600
601void RootWindowController::InitTouchHuds() {
602 CommandLine* command_line = CommandLine::ForCurrentProcess();
603 if (command_line->HasSwitch(switches::kAshTouchHud))
604 set_touch_hud_debug(new TouchHudDebug(root_window_.get()));
605 if (Shell::GetInstance()->is_touch_hud_projection_enabled())
606 EnableTouchHudProjection();
607}
608
609void RootWindowController::CreateSystemBackground(
610 bool is_first_run_after_boot) {
611 SkColor color = SK_ColorBLACK;
612#if defined(OS_CHROMEOS)
613 if (is_first_run_after_boot)
614 color = kChromeOsBootColor;
615#endif
616 system_background_.reset(
617 new SystemBackgroundController(root_window_.get(), color));
618
619#if defined(OS_CHROMEOS)
620 // Make a copy of the system's boot splash screen so we can composite it
621 // onscreen until the desktop background is ready.
622 if (is_first_run_after_boot &&
623 (CommandLine::ForCurrentProcess()->HasSwitch(
624 switches::kAshCopyHostBackgroundAtBoot) ||
625 CommandLine::ForCurrentProcess()->HasSwitch(
626 switches::kAshAnimateFromBootSplashScreen)))
627 boot_splash_screen_.reset(new BootSplashScreen(root_window_.get()));
628#endif
629}
630
[email protected]a4cd6d32012-09-12 03:42:13631void RootWindowController::CreateContainersInRootWindow(
632 aura::RootWindow* root_window) {
633 // These containers are just used by PowerButtonController to animate groups
634 // of containers simultaneously without messing up the current transformations
635 // on those containers. These are direct children of the root window; all of
636 // the other containers are their children.
[email protected]e6e41d2f2012-10-29 19:22:19637
638 // The desktop background container is not part of the lock animation, so it
639 // is not included in those animate groups.
[email protected]a4cd6d32012-09-12 03:42:13640 // When screen is locked desktop background is moved to lock screen background
641 // container (moved back on unlock). We want to make sure that there's an
642 // opaque layer occluding the non-lock-screen layers.
[email protected]e6e41d2f2012-10-29 19:22:19643 aura::Window* desktop_background_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27644 kShellWindowId_DesktopBackgroundContainer,
[email protected]a4cd6d32012-09-12 03:42:13645 "DesktopBackgroundContainer",
646 root_window);
[email protected]b5756e22012-11-30 01:32:02647 views::corewm::SetChildWindowVisibilityChangesAnimated(
648 desktop_background_container);
[email protected]a4cd6d32012-09-12 03:42:13649
650 aura::Window* non_lock_screen_containers = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27651 kShellWindowId_NonLockScreenContainersContainer,
[email protected]a4cd6d32012-09-12 03:42:13652 "NonLockScreenContainersContainer",
653 root_window);
654
655 aura::Window* lock_background_containers = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27656 kShellWindowId_LockScreenBackgroundContainer,
[email protected]a4cd6d32012-09-12 03:42:13657 "LockScreenBackgroundContainer",
658 root_window);
[email protected]b5756e22012-11-30 01:32:02659 views::corewm::SetChildWindowVisibilityChangesAnimated(
660 lock_background_containers);
[email protected]a4cd6d32012-09-12 03:42:13661
662 aura::Window* lock_screen_containers = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27663 kShellWindowId_LockScreenContainersContainer,
[email protected]a4cd6d32012-09-12 03:42:13664 "LockScreenContainersContainer",
665 root_window);
666 aura::Window* lock_screen_related_containers = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27667 kShellWindowId_LockScreenRelatedContainersContainer,
[email protected]a4cd6d32012-09-12 03:42:13668 "LockScreenRelatedContainersContainer",
669 root_window);
670
[email protected]c0ce80e2012-10-05 23:28:27671 CreateContainer(kShellWindowId_UnparentedControlContainer,
[email protected]a4cd6d32012-09-12 03:42:13672 "UnparentedControlContainer",
673 non_lock_screen_containers);
674
675 aura::Window* default_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27676 kShellWindowId_DefaultContainer,
[email protected]a4cd6d32012-09-12 03:42:13677 "DefaultContainer",
678 non_lock_screen_containers);
[email protected]b5756e22012-11-30 01:32:02679 views::corewm::SetChildWindowVisibilityChangesAnimated(default_container);
[email protected]a4cd6d32012-09-12 03:42:13680 SetUsesScreenCoordinates(default_container);
681
682 aura::Window* always_on_top_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27683 kShellWindowId_AlwaysOnTopContainer,
[email protected]a4cd6d32012-09-12 03:42:13684 "AlwaysOnTopContainer",
685 non_lock_screen_containers);
686 always_on_top_container_handler_.reset(
687 new ToplevelWindowEventHandler(always_on_top_container));
[email protected]b5756e22012-11-30 01:32:02688 views::corewm::SetChildWindowVisibilityChangesAnimated(
689 always_on_top_container);
[email protected]a4cd6d32012-09-12 03:42:13690 SetUsesScreenCoordinates(always_on_top_container);
691
[email protected]beb4e5c2013-06-18 15:37:07692 aura::Window* docked_container = CreateContainer(
693 kShellWindowId_DockedContainer,
694 "DockedContainer",
695 non_lock_screen_containers);
[email protected]5eab6e92013-09-19 19:09:27696 views::corewm::SetChildWindowVisibilityChangesAnimated(docked_container);
[email protected]beb4e5c2013-06-18 15:37:07697 SetUsesScreenCoordinates(docked_container);
698
[email protected]a4cd6d32012-09-12 03:42:13699 aura::Window* panel_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27700 kShellWindowId_PanelContainer,
[email protected]a4cd6d32012-09-12 03:42:13701 "PanelContainer",
702 non_lock_screen_containers);
703 SetUsesScreenCoordinates(panel_container);
704
[email protected]3f13cf12013-07-12 05:13:59705 aura::Window* shelf_container =
[email protected]478c6c32013-03-09 02:50:58706 CreateContainer(kShellWindowId_ShelfContainer,
[email protected]3f13cf12013-07-12 05:13:59707 "ShelfContainer",
[email protected]a4cd6d32012-09-12 03:42:13708 non_lock_screen_containers);
[email protected]3f13cf12013-07-12 05:13:59709 SetUsesScreenCoordinates(shelf_container);
710 DescendantShouldStayInSameRootWindow(shelf_container);
[email protected]a4cd6d32012-09-12 03:42:13711
[email protected]dc851a4e52012-10-03 00:05:55712 aura::Window* app_list_container =
[email protected]c0ce80e2012-10-05 23:28:27713 CreateContainer(kShellWindowId_AppListContainer,
[email protected]dc851a4e52012-10-03 00:05:55714 "AppListContainer",
715 non_lock_screen_containers);
716 SetUsesScreenCoordinates(app_list_container);
[email protected]a4cd6d32012-09-12 03:42:13717
718 aura::Window* modal_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27719 kShellWindowId_SystemModalContainer,
[email protected]a4cd6d32012-09-12 03:42:13720 "SystemModalContainer",
721 non_lock_screen_containers);
722 modal_container_handler_.reset(
723 new ToplevelWindowEventHandler(modal_container));
[email protected]a4cd6d32012-09-12 03:42:13724 modal_container->SetLayoutManager(
[email protected]c0ce80e2012-10-05 23:28:27725 new SystemModalContainerLayoutManager(modal_container));
[email protected]b5756e22012-11-30 01:32:02726 views::corewm::SetChildWindowVisibilityChangesAnimated(modal_container);
[email protected]a4cd6d32012-09-12 03:42:13727 SetUsesScreenCoordinates(modal_container);
728
729 aura::Window* input_method_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27730 kShellWindowId_InputMethodContainer,
[email protected]a4cd6d32012-09-12 03:42:13731 "InputMethodContainer",
732 non_lock_screen_containers);
733 SetUsesScreenCoordinates(input_method_container);
734
735 // TODO(beng): Figure out if we can make this use
736 // SystemModalContainerEventFilter instead of stops_event_propagation.
737 aura::Window* lock_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27738 kShellWindowId_LockScreenContainer,
[email protected]a4cd6d32012-09-12 03:42:13739 "LockScreenContainer",
740 lock_screen_containers);
741 lock_container->SetLayoutManager(
[email protected]c0ce80e2012-10-05 23:28:27742 new BaseLayoutManager(root_window));
[email protected]a4cd6d32012-09-12 03:42:13743 SetUsesScreenCoordinates(lock_container);
744 // TODO(beng): stopsevents
745
746 aura::Window* lock_modal_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27747 kShellWindowId_LockSystemModalContainer,
[email protected]a4cd6d32012-09-12 03:42:13748 "LockSystemModalContainer",
749 lock_screen_containers);
750 lock_modal_container_handler_.reset(
751 new ToplevelWindowEventHandler(lock_modal_container));
[email protected]a4cd6d32012-09-12 03:42:13752 lock_modal_container->SetLayoutManager(
[email protected]c0ce80e2012-10-05 23:28:27753 new SystemModalContainerLayoutManager(lock_modal_container));
[email protected]b5756e22012-11-30 01:32:02754 views::corewm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
[email protected]a4cd6d32012-09-12 03:42:13755 SetUsesScreenCoordinates(lock_modal_container);
756
757 aura::Window* status_container =
[email protected]c0ce80e2012-10-05 23:28:27758 CreateContainer(kShellWindowId_StatusContainer,
[email protected]a4cd6d32012-09-12 03:42:13759 "StatusContainer",
760 lock_screen_related_containers);
761 SetUsesScreenCoordinates(status_container);
[email protected]e887c6c2013-07-08 19:35:53762 DescendantShouldStayInSameRootWindow(status_container);
[email protected]a4cd6d32012-09-12 03:42:13763
764 aura::Window* settings_bubble_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27765 kShellWindowId_SettingBubbleContainer,
[email protected]a4cd6d32012-09-12 03:42:13766 "SettingBubbleContainer",
767 lock_screen_related_containers);
[email protected]b5756e22012-11-30 01:32:02768 views::corewm::SetChildWindowVisibilityChangesAnimated(
769 settings_bubble_container);
[email protected]a4cd6d32012-09-12 03:42:13770 SetUsesScreenCoordinates(settings_bubble_container);
[email protected]e887c6c2013-07-08 19:35:53771 DescendantShouldStayInSameRootWindow(settings_bubble_container);
[email protected]a4cd6d32012-09-12 03:42:13772
773 aura::Window* menu_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27774 kShellWindowId_MenuContainer,
[email protected]a4cd6d32012-09-12 03:42:13775 "MenuContainer",
776 lock_screen_related_containers);
[email protected]b5756e22012-11-30 01:32:02777 views::corewm::SetChildWindowVisibilityChangesAnimated(menu_container);
[email protected]a4cd6d32012-09-12 03:42:13778 SetUsesScreenCoordinates(menu_container);
779
780 aura::Window* drag_drop_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27781 kShellWindowId_DragImageAndTooltipContainer,
[email protected]a4cd6d32012-09-12 03:42:13782 "DragImageAndTooltipContainer",
783 lock_screen_related_containers);
[email protected]b5756e22012-11-30 01:32:02784 views::corewm::SetChildWindowVisibilityChangesAnimated(drag_drop_container);
[email protected]a4cd6d32012-09-12 03:42:13785 SetUsesScreenCoordinates(drag_drop_container);
786
787 aura::Window* overlay_container = CreateContainer(
[email protected]c0ce80e2012-10-05 23:28:27788 kShellWindowId_OverlayContainer,
[email protected]a4cd6d32012-09-12 03:42:13789 "OverlayContainer",
790 lock_screen_related_containers);
791 SetUsesScreenCoordinates(overlay_container);
[email protected]a07615f2012-10-24 08:23:08792
793 CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
794 "PowerButtonAnimationContainer", root_window) ;
[email protected]a4cd6d32012-09-12 03:42:13795}
796
[email protected]d141b922013-07-09 08:13:17797void RootWindowController::EnableTouchHudProjection() {
798 if (touch_hud_projection_)
799 return;
800 set_touch_hud_projection(new TouchHudProjection(root_window_.get()));
801}
802
803void RootWindowController::DisableTouchHudProjection() {
804 if (!touch_hud_projection_)
805 return;
806 touch_hud_projection_->Remove();
807}
808
809void RootWindowController::OnLoginStateChanged(user::LoginStatus status) {
810 shelf_->shelf_layout_manager()->UpdateVisibilityState();
811}
812
813void RootWindowController::OnTouchHudProjectionToggled(bool enabled) {
814 if (enabled)
815 EnableTouchHudProjection();
816 else
817 DisableTouchHudProjection();
818}
819
[email protected]6b2d4a0b2013-09-06 06:29:54820RootWindowController* GetRootWindowController(
821 const aura::RootWindow* root_window) {
822 return root_window ? GetRootWindowSettings(root_window)->controller : NULL;
823}
824
[email protected]d90b8392012-06-13 09:34:56825} // namespace internal
826} // namespace ash