1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "apps/shell/browser/shell_desktop_controller.h"
7 #include "apps/shell/browser/shell_app_window.h"
8 #include "ui/aura/client/cursor_client.h"
9 #include "ui/aura/env.h"
10 #include "ui/aura/layout_manager.h"
11 #include "ui/aura/test/test_screen.h"
12 #include "ui/aura/window.h"
13 #include "ui/aura/window_event_dispatcher.h"
14 #include "ui/aura/window_tree_host.h"
15 #include "ui/base/cursor/cursor.h"
16 #include "ui/base/cursor/image_cursors.h"
17 #include "ui/base/ime/input_method_initializer.h"
18 #include "ui/gfx/native_widget_types.h"
19 #include "ui/gfx/screen.h"
20 #include "ui/wm/core/cursor_manager.h"
21 #include "ui/wm/core/native_cursor_manager.h"
22 #include "ui/wm/core/native_cursor_manager_delegate.h"
23 #include "ui/wm/core/user_activity_detector.h"
24 #include "ui/wm/test/wm_test_helper.h"
26 #if defined(OS_CHROMEOS)
27 #include "ui/chromeos/user_activity_power_manager_notifier.h"
28 #include "ui/display/types/chromeos/display_mode.h"
29 #include "ui/display/types/chromeos/display_snapshot.h"
35 // A simple layout manager that makes each new window fill its parent.
36 class FillLayout : public aura::LayoutManager {
39 virtual ~FillLayout() {}
42 // aura::LayoutManager:
43 virtual void OnWindowResized() OVERRIDE {}
45 virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
49 // Create a rect at 0,0 with the size of the parent.
50 gfx::Size parent_size = child->parent()->bounds().size();
51 child->SetBounds(gfx::Rect(parent_size));
54 virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
56 virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
58 virtual void OnChildWindowVisibilityChanged(aura::Window* child,
59 bool visible) OVERRIDE {}
61 virtual void SetChildBounds(aura::Window* child,
62 const gfx::Rect& requested_bounds) OVERRIDE {
63 SetChildBoundsDirect(child, requested_bounds);
66 DISALLOW_COPY_AND_ASSIGN(FillLayout);
69 // A class that bridges the gap between CursorManager and Aura. It borrows
70 // heavily from AshNativeCursorManager.
71 class ShellNativeCursorManager : public wm::NativeCursorManager {
73 explicit ShellNativeCursorManager(aura::WindowTreeHost* host)
75 image_cursors_(new ui::ImageCursors) {}
76 virtual ~ShellNativeCursorManager() {}
78 // wm::NativeCursorManager overrides.
79 virtual void SetDisplay(
80 const gfx::Display& display,
81 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
82 if (image_cursors_->SetDisplay(display, display.device_scale_factor()))
83 SetCursor(delegate->GetCursor(), delegate);
86 virtual void SetCursor(
87 gfx::NativeCursor cursor,
88 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
89 image_cursors_->SetPlatformCursor(&cursor);
90 cursor.set_device_scale_factor(image_cursors_->GetScale());
91 delegate->CommitCursor(cursor);
93 if (delegate->IsCursorVisible())
97 virtual void SetVisibility(
99 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
100 delegate->CommitVisibility(visible);
103 SetCursor(delegate->GetCursor(), delegate);
105 gfx::NativeCursor invisible_cursor(ui::kCursorNone);
106 image_cursors_->SetPlatformCursor(&invisible_cursor);
107 ApplyCursor(invisible_cursor);
111 virtual void SetCursorSet(
112 ui::CursorSetType cursor_set,
113 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
114 image_cursors_->SetCursorSet(cursor_set);
115 delegate->CommitCursorSet(cursor_set);
116 if (delegate->IsCursorVisible())
117 SetCursor(delegate->GetCursor(), delegate);
120 virtual void SetMouseEventsEnabled(
122 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
123 delegate->CommitMouseEventsEnabled(enabled);
124 SetVisibility(delegate->IsCursorVisible(), delegate);
128 // Sets |cursor| as the active cursor within Aura.
129 void ApplyCursor(gfx::NativeCursor cursor) {
130 host_->SetCursor(cursor);
133 aura::WindowTreeHost* host_; // Not owned.
135 scoped_ptr<ui::ImageCursors> image_cursors_;
137 DISALLOW_COPY_AND_ASSIGN(ShellNativeCursorManager);
140 ShellDesktopController* g_instance = NULL;
144 ShellDesktopController::ShellDesktopController() {
145 #if defined(OS_CHROMEOS)
146 display_configurator_.reset(new ui::DisplayConfigurator);
147 display_configurator_->Init(false);
148 display_configurator_->ForceInitialConfigure(0);
149 display_configurator_->AddObserver(this);
153 cursor_manager_.reset(
154 new wm::CursorManager(scoped_ptr<wm::NativeCursorManager>(
155 new ShellNativeCursorManager(GetWindowTreeHost()))));
156 cursor_manager_->SetDisplay(
157 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay());
158 cursor_manager_->SetCursor(ui::kCursorPointer);
159 aura::client::SetCursorClient(
160 GetWindowTreeHost()->window(), cursor_manager_.get());
162 user_activity_detector_.reset(new wm::UserActivityDetector);
163 GetWindowTreeHost()->event_processor()->GetRootTarget()->AddPreTargetHandler(
164 user_activity_detector_.get());
165 #if defined(OS_CHROMEOS)
166 user_activity_notifier_.reset(
167 new ui::UserActivityPowerManagerNotifier(user_activity_detector_.get()));
173 ShellDesktopController::~ShellDesktopController() {
174 // The app window must be explicitly closed before desktop teardown.
175 DCHECK(!app_window_);
177 GetWindowTreeHost()->event_processor()->GetRootTarget()
178 ->RemovePreTargetHandler(user_activity_detector_.get());
180 aura::Env::DeleteInstance();
184 ShellDesktopController* ShellDesktopController::instance() {
188 ShellAppWindow* ShellDesktopController::CreateAppWindow(
189 content::BrowserContext* context) {
190 aura::Window* root_window = GetWindowTreeHost()->window();
192 app_window_.reset(new ShellAppWindow);
193 app_window_->Init(context, root_window->bounds().size());
195 // Attach the web contents view to our window hierarchy.
196 aura::Window* content = app_window_->GetNativeWindow();
197 root_window->AddChild(content);
200 return app_window_.get();
203 void ShellDesktopController::CloseAppWindow() { app_window_.reset(); }
205 aura::WindowTreeHost* ShellDesktopController::GetWindowTreeHost() {
206 return wm_test_helper_->host();
209 #if defined(OS_CHROMEOS)
210 void ShellDesktopController::OnDisplayModeChanged(
211 const std::vector<ui::DisplayConfigurator::DisplayState>& displays) {
212 gfx::Size size = GetPrimaryDisplaySize();
214 wm_test_helper_->host()->UpdateRootWindowSize(size);
218 void ShellDesktopController::CreateRootWindow() {
219 test_screen_.reset(aura::TestScreen::Create());
220 // TODO(jamescook): Replace this with a real Screen implementation.
221 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen_.get());
222 // TODO(jamescook): Initialize a real input method.
223 ui::InitializeInputMethodForTesting();
225 // Set up basic pieces of ui::wm.
226 gfx::Size size = GetPrimaryDisplaySize();
228 size = gfx::Size(800, 600);
229 wm_test_helper_.reset(new wm::WMTestHelper(size));
231 // Ensure new windows fill the display.
232 aura::WindowTreeHost* host = wm_test_helper_->host();
233 host->window()->SetLayoutManager(new FillLayout);
235 // Ensure the X window gets mapped.
239 void ShellDesktopController::DestroyRootWindow() {
240 wm_test_helper_.reset();
241 ui::ShutdownInputMethodForTesting();
244 gfx::Size ShellDesktopController::GetPrimaryDisplaySize() {
245 #if defined(OS_CHROMEOS)
246 const std::vector<ui::DisplayConfigurator::DisplayState>& displays =
247 display_configurator_->cached_displays();
248 if (displays.empty())
250 const ui::DisplayMode* mode = displays[0].display->current_mode();
251 return mode ? mode->size() : gfx::Size();