Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / apps / shell / browser / shell_desktop_controller.cc
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.
4
5 #include "apps/shell/browser/shell_desktop_controller.h"
6
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"
25
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"
30 #endif
31
32 namespace apps {
33 namespace {
34
35 // A simple layout manager that makes each new window fill its parent.
36 class FillLayout : public aura::LayoutManager {
37  public:
38   FillLayout() {}
39   virtual ~FillLayout() {}
40
41  private:
42   // aura::LayoutManager:
43   virtual void OnWindowResized() OVERRIDE {}
44
45   virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
46     if (!child->parent())
47       return;
48
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));
52   }
53
54   virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
55
56   virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
57
58   virtual void OnChildWindowVisibilityChanged(aura::Window* child,
59                                               bool visible) OVERRIDE {}
60
61   virtual void SetChildBounds(aura::Window* child,
62                               const gfx::Rect& requested_bounds) OVERRIDE {
63     SetChildBoundsDirect(child, requested_bounds);
64   }
65
66   DISALLOW_COPY_AND_ASSIGN(FillLayout);
67 };
68
69 // A class that bridges the gap between CursorManager and Aura. It borrows
70 // heavily from AshNativeCursorManager.
71 class ShellNativeCursorManager : public wm::NativeCursorManager {
72  public:
73   explicit ShellNativeCursorManager(aura::WindowTreeHost* host)
74       : host_(host),
75         image_cursors_(new ui::ImageCursors) {}
76   virtual ~ShellNativeCursorManager() {}
77
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);
84   }
85
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);
92
93     if (delegate->IsCursorVisible())
94       ApplyCursor(cursor);
95   }
96
97   virtual void SetVisibility(
98       bool visible,
99       wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
100     delegate->CommitVisibility(visible);
101
102     if (visible) {
103       SetCursor(delegate->GetCursor(), delegate);
104     } else {
105       gfx::NativeCursor invisible_cursor(ui::kCursorNone);
106       image_cursors_->SetPlatformCursor(&invisible_cursor);
107       ApplyCursor(invisible_cursor);
108     }
109   }
110
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);
118   }
119
120   virtual void SetMouseEventsEnabled(
121       bool enabled,
122       wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
123     delegate->CommitMouseEventsEnabled(enabled);
124     SetVisibility(delegate->IsCursorVisible(), delegate);
125   }
126
127  private:
128   // Sets |cursor| as the active cursor within Aura.
129   void ApplyCursor(gfx::NativeCursor cursor) {
130     host_->SetCursor(cursor);
131   }
132
133   aura::WindowTreeHost* host_;  // Not owned.
134
135   scoped_ptr<ui::ImageCursors> image_cursors_;
136
137   DISALLOW_COPY_AND_ASSIGN(ShellNativeCursorManager);
138 };
139
140 ShellDesktopController* g_instance = NULL;
141
142 }  // namespace
143
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);
150 #endif
151   CreateRootWindow();
152
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());
161
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()));
168 #endif
169
170   g_instance = this;
171 }
172
173 ShellDesktopController::~ShellDesktopController() {
174   // The app window must be explicitly closed before desktop teardown.
175   DCHECK(!app_window_);
176   g_instance = NULL;
177   GetWindowTreeHost()->event_processor()->GetRootTarget()
178       ->RemovePreTargetHandler(user_activity_detector_.get());
179   DestroyRootWindow();
180   aura::Env::DeleteInstance();
181 }
182
183 // static
184 ShellDesktopController* ShellDesktopController::instance() {
185   return g_instance;
186 }
187
188 ShellAppWindow* ShellDesktopController::CreateAppWindow(
189     content::BrowserContext* context) {
190   aura::Window* root_window = GetWindowTreeHost()->window();
191
192   app_window_.reset(new ShellAppWindow);
193   app_window_->Init(context, root_window->bounds().size());
194
195   // Attach the web contents view to our window hierarchy.
196   aura::Window* content = app_window_->GetNativeWindow();
197   root_window->AddChild(content);
198   content->Show();
199
200   return app_window_.get();
201 }
202
203 void ShellDesktopController::CloseAppWindow() { app_window_.reset(); }
204
205 aura::WindowTreeHost* ShellDesktopController::GetWindowTreeHost() {
206   return wm_test_helper_->host();
207 }
208
209 #if defined(OS_CHROMEOS)
210 void ShellDesktopController::OnDisplayModeChanged(
211     const std::vector<ui::DisplayConfigurator::DisplayState>& displays) {
212   gfx::Size size = GetPrimaryDisplaySize();
213   if (!size.IsEmpty())
214     wm_test_helper_->host()->UpdateRootWindowSize(size);
215 }
216 #endif
217
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();
224
225   // Set up basic pieces of ui::wm.
226   gfx::Size size = GetPrimaryDisplaySize();
227   if (size.IsEmpty())
228     size = gfx::Size(800, 600);
229   wm_test_helper_.reset(new wm::WMTestHelper(size));
230
231   // Ensure new windows fill the display.
232   aura::WindowTreeHost* host = wm_test_helper_->host();
233   host->window()->SetLayoutManager(new FillLayout);
234
235   // Ensure the X window gets mapped.
236   host->Show();
237 }
238
239 void ShellDesktopController::DestroyRootWindow() {
240   wm_test_helper_.reset();
241   ui::ShutdownInputMethodForTesting();
242 }
243
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())
249     return gfx::Size();
250   const ui::DisplayMode* mode = displays[0].display->current_mode();
251   return mode ? mode->size() : gfx::Size();
252 #else
253   return gfx::Size();
254 #endif
255 }
256
257 }  // namespace apps