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 "athena/env/public/athena_env.h"
6
7 #include <vector>
8
9 #include "athena/util/fill_layout_manager.h"
10 #include "base/sys_info.h"
11 #include "ui/aura/client/aura_constants.h"
12 #include "ui/aura/client/cursor_client.h"
13 #include "ui/aura/client/default_capture_client.h"
14 #include "ui/aura/env.h"
15 #include "ui/aura/test/test_screen.h"
16 #include "ui/aura/window_event_dispatcher.h"
17 #include "ui/aura/window_tree_host.h"
18 #include "ui/aura/window_tree_host_observer.h"
19 #include "ui/base/cursor/cursor.h"
20 #include "ui/base/cursor/image_cursors.h"
21 #include "ui/chromeos/user_activity_power_manager_notifier.h"
22 #include "ui/display/chromeos/display_configurator.h"
23 #include "ui/display/types/display_mode.h"
24 #include "ui/display/types/display_snapshot.h"
25 #include "ui/gfx/screen.h"
26 #include "ui/wm/core/compound_event_filter.h"
27 #include "ui/wm/core/cursor_manager.h"
28 #include "ui/wm/core/input_method_event_filter.h"
29 #include "ui/wm/core/native_cursor_manager.h"
30 #include "ui/wm/core/native_cursor_manager_delegate.h"
31 #include "ui/wm/core/user_activity_detector.h"
32
33 namespace athena {
34
35 namespace {
36
37 AthenaEnv* instance = NULL;
38
39 // Screen object used during shutdown.
40 gfx::Screen* screen_for_shutdown = NULL;
41
42 // TODO(flackr:oshima): Remove this once athena switches to share
43 // ash::DisplayManager.
44 class ScreenForShutdown : public gfx::Screen {
45 public:
46 // Creates and sets the screen for shutdown. Deletes existing one if any.
Create(const gfx::Screen * screen)47 static void Create(const gfx::Screen* screen) {
48 delete screen_for_shutdown;
49 screen_for_shutdown = new ScreenForShutdown(screen->GetPrimaryDisplay());
50 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
51 screen_for_shutdown);
52 }
53
54 private:
ScreenForShutdown(const gfx::Display & primary_display)55 explicit ScreenForShutdown(const gfx::Display& primary_display)
56 : primary_display_(primary_display) {}
57
58 // gfx::Screen overrides:
IsDIPEnabled()59 virtual bool IsDIPEnabled() OVERRIDE { return true; }
GetCursorScreenPoint()60 virtual gfx::Point GetCursorScreenPoint() OVERRIDE { return gfx::Point(); }
GetWindowUnderCursor()61 virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE { return NULL; }
GetWindowAtScreenPoint(const gfx::Point & point)62 virtual gfx::NativeWindow GetWindowAtScreenPoint(
63 const gfx::Point& point) OVERRIDE {
64 return NULL;
65 }
GetNumDisplays() const66 virtual int GetNumDisplays() const OVERRIDE { return 1; }
GetAllDisplays() const67 virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE {
68 std::vector<gfx::Display> displays(1, primary_display_);
69 return displays;
70 }
GetDisplayNearestWindow(gfx::NativeView view) const71 virtual gfx::Display GetDisplayNearestWindow(
72 gfx::NativeView view) const OVERRIDE {
73 return primary_display_;
74 }
GetDisplayNearestPoint(const gfx::Point & point) const75 virtual gfx::Display GetDisplayNearestPoint(
76 const gfx::Point& point) const OVERRIDE {
77 return primary_display_;
78 }
GetDisplayMatching(const gfx::Rect & match_rect) const79 virtual gfx::Display GetDisplayMatching(
80 const gfx::Rect& match_rect) const OVERRIDE {
81 return primary_display_;
82 }
GetPrimaryDisplay() const83 virtual gfx::Display GetPrimaryDisplay() const OVERRIDE {
84 return primary_display_;
85 }
AddObserver(gfx::DisplayObserver * observer)86 virtual void AddObserver(gfx::DisplayObserver* observer) OVERRIDE {
87 NOTREACHED() << "Observer should not be added during shutdown";
88 }
RemoveObserver(gfx::DisplayObserver * observer)89 virtual void RemoveObserver(gfx::DisplayObserver* observer) OVERRIDE {}
90
91 const gfx::Display primary_display_;
92
93 DISALLOW_COPY_AND_ASSIGN(ScreenForShutdown);
94 };
95
96 // A class that bridges the gap between CursorManager and Aura. It borrows
97 // heavily from AshNativeCursorManager.
98 class AthenaNativeCursorManager : public wm::NativeCursorManager {
99 public:
AthenaNativeCursorManager(aura::WindowTreeHost * host)100 explicit AthenaNativeCursorManager(aura::WindowTreeHost* host)
101 : host_(host), image_cursors_(new ui::ImageCursors) {}
~AthenaNativeCursorManager()102 virtual ~AthenaNativeCursorManager() {}
103
104 // wm::NativeCursorManager overrides.
SetDisplay(const gfx::Display & display,wm::NativeCursorManagerDelegate * delegate)105 virtual void SetDisplay(const gfx::Display& display,
106 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
107 if (image_cursors_->SetDisplay(display, display.device_scale_factor()))
108 SetCursor(delegate->GetCursor(), delegate);
109 }
110
SetCursor(gfx::NativeCursor cursor,wm::NativeCursorManagerDelegate * delegate)111 virtual void SetCursor(gfx::NativeCursor cursor,
112 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
113 image_cursors_->SetPlatformCursor(&cursor);
114 cursor.set_device_scale_factor(image_cursors_->GetScale());
115 delegate->CommitCursor(cursor);
116
117 if (delegate->IsCursorVisible())
118 ApplyCursor(cursor);
119 }
120
SetVisibility(bool visible,wm::NativeCursorManagerDelegate * delegate)121 virtual void SetVisibility(
122 bool visible,
123 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
124 delegate->CommitVisibility(visible);
125
126 if (visible) {
127 SetCursor(delegate->GetCursor(), delegate);
128 } else {
129 gfx::NativeCursor invisible_cursor(ui::kCursorNone);
130 image_cursors_->SetPlatformCursor(&invisible_cursor);
131 ApplyCursor(invisible_cursor);
132 }
133 }
134
SetCursorSet(ui::CursorSetType cursor_set,wm::NativeCursorManagerDelegate * delegate)135 virtual void SetCursorSet(
136 ui::CursorSetType cursor_set,
137 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
138 image_cursors_->SetCursorSet(cursor_set);
139 delegate->CommitCursorSet(cursor_set);
140 if (delegate->IsCursorVisible())
141 SetCursor(delegate->GetCursor(), delegate);
142 }
143
SetMouseEventsEnabled(bool enabled,wm::NativeCursorManagerDelegate * delegate)144 virtual void SetMouseEventsEnabled(
145 bool enabled,
146 wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
147 delegate->CommitMouseEventsEnabled(enabled);
148 SetVisibility(delegate->IsCursorVisible(), delegate);
149 }
150
151 private:
152 // Sets |cursor| as the active cursor within Aura.
ApplyCursor(gfx::NativeCursor cursor)153 void ApplyCursor(gfx::NativeCursor cursor) { host_->SetCursor(cursor); }
154
155 aura::WindowTreeHost* host_; // Not owned.
156
157 scoped_ptr<ui::ImageCursors> image_cursors_;
158
159 DISALLOW_COPY_AND_ASSIGN(AthenaNativeCursorManager);
160 };
161
162 class AthenaEnvImpl : public AthenaEnv,
163 public aura::WindowTreeHostObserver,
164 public ui::DisplayConfigurator::Observer {
165 public:
AthenaEnvImpl()166 AthenaEnvImpl() : display_configurator_(new ui::DisplayConfigurator) {
167 display_configurator_->Init(false);
168 display_configurator_->ForceInitialConfigure(0);
169 display_configurator_->AddObserver(this);
170
171 gfx::Size screen_size = GetPrimaryDisplaySize();
172 if (screen_size.IsEmpty()) {
173 // TODO(oshima): Remove this hack.
174 if (base::SysInfo::IsRunningOnChromeOS())
175 screen_size.SetSize(2560, 1600);
176 else
177 screen_size.SetSize(1280, 720);
178 }
179 screen_.reset(aura::TestScreen::Create(screen_size));
180
181 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
182 host_.reset(screen_->CreateHostForPrimaryDisplay());
183 host_->InitHost();
184
185 aura::Window* root_window = GetHost()->window();
186 input_method_filter_.reset(
187 new wm::InputMethodEventFilter(host_->GetAcceleratedWidget()));
188 input_method_filter_->SetInputMethodPropertyInRootWindow(root_window);
189
190 root_window_event_filter_.reset(new wm::CompoundEventFilter);
191 host_->window()->AddPreTargetHandler(root_window_event_filter_.get());
192
193 input_method_filter_.reset(
194 new wm::InputMethodEventFilter(host_->GetAcceleratedWidget()));
195 input_method_filter_->SetInputMethodPropertyInRootWindow(host_->window());
196 root_window_event_filter_->AddHandler(input_method_filter_.get());
197
198 capture_client_.reset(
199 new aura::client::DefaultCaptureClient(host_->window()));
200
201 // Ensure new windows fill the display.
202 root_window->SetLayoutManager(new FillLayoutManager(root_window));
203
204 cursor_manager_.reset(
205 new wm::CursorManager(scoped_ptr<wm::NativeCursorManager>(
206 new AthenaNativeCursorManager(host_.get()))));
207 cursor_manager_->SetDisplay(
208 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay());
209 cursor_manager_->SetCursor(ui::kCursorPointer);
210 aura::client::SetCursorClient(host_->window(), cursor_manager_.get());
211
212 user_activity_detector_.reset(new wm::UserActivityDetector);
213 host_->event_processor()->GetRootTarget()->AddPreTargetHandler(
214 user_activity_detector_.get());
215 user_activity_notifier_.reset(new ui::UserActivityPowerManagerNotifier(
216 user_activity_detector_.get()));
217
218 host_->AddObserver(this);
219 host_->Show();
220
221 DCHECK(!instance);
222 instance = this;
223 }
224
~AthenaEnvImpl()225 virtual ~AthenaEnvImpl() {
226 instance = NULL;
227
228 host_->RemoveObserver(this);
229 if (input_method_filter_)
230 root_window_event_filter_->RemoveHandler(input_method_filter_.get());
231 if (user_activity_detector_) {
232 host_->event_processor()->GetRootTarget()->RemovePreTargetHandler(
233 user_activity_detector_.get());
234 }
235 root_window_event_filter_.reset();
236 capture_client_.reset();
237 input_method_filter_.reset();
238 cursor_manager_.reset();
239 user_activity_notifier_.reset();
240 user_activity_detector_.reset();
241
242 input_method_filter_.reset();
243 host_.reset();
244
245 ScreenForShutdown::Create(screen_.get());
246 screen_.reset();
247 aura::Env::DeleteInstance();
248
249 display_configurator_->RemoveObserver(this);
250 display_configurator_.reset();
251 }
252
253 private:
254 struct Finder {
Finderathena::__anond479e5580111::AthenaEnvImpl::Finder255 explicit Finder(const base::Closure& c) : closure(c) {}
operator ()athena::__anond479e5580111::AthenaEnvImpl::Finder256 bool operator()(const base::Closure& other) {
257 return closure.Equals(other);
258 }
259 base::Closure closure;
260 };
261
262 // AthenaEnv:
GetHost()263 virtual aura::WindowTreeHost* GetHost() OVERRIDE { return host_.get(); }
264
SetDisplayWorkAreaInsets(const gfx::Insets & insets)265 virtual void SetDisplayWorkAreaInsets(const gfx::Insets& insets) OVERRIDE {
266 screen_->SetWorkAreaInsets(insets);
267 }
268
AddTerminatingCallback(const base::Closure & closure)269 virtual void AddTerminatingCallback(const base::Closure& closure) OVERRIDE {
270 if (closure.is_null())
271 return;
272 DCHECK(terminating_callbacks_.end() ==
273 std::find_if(terminating_callbacks_.begin(),
274 terminating_callbacks_.end(),
275 Finder(closure)));
276 terminating_callbacks_.push_back(closure);
277 }
278
RemoveTerminatingCallback(const base::Closure & closure)279 virtual void RemoveTerminatingCallback(
280 const base::Closure& closure) OVERRIDE {
281 std::vector<base::Closure>::iterator iter =
282 std::find_if(terminating_callbacks_.begin(),
283 terminating_callbacks_.end(),
284 Finder(closure));
285 if (iter != terminating_callbacks_.end())
286 terminating_callbacks_.erase(iter);
287 }
288
OnTerminating()289 virtual void OnTerminating() OVERRIDE {
290 for (std::vector<base::Closure>::iterator iter =
291 terminating_callbacks_.begin();
292 iter != terminating_callbacks_.end();
293 ++iter) {
294 iter->Run();
295 }
296 }
297
298 // ui::DisplayConfigurator::Observer:
OnDisplayModeChanged(const std::vector<ui::DisplayConfigurator::DisplayState> & displays)299 virtual void OnDisplayModeChanged(const std::vector<
300 ui::DisplayConfigurator::DisplayState>& displays) OVERRIDE {
301 gfx::Size size = GetPrimaryDisplaySize();
302 if (!size.IsEmpty())
303 host_->UpdateRootWindowSize(size);
304 }
305
306 // aura::WindowTreeHostObserver:
OnHostCloseRequested(const aura::WindowTreeHost * host)307 virtual void OnHostCloseRequested(const aura::WindowTreeHost* host) OVERRIDE {
308 base::MessageLoopForUI::current()->PostTask(
309 FROM_HERE, base::MessageLoop::QuitClosure());
310 }
311
GetPrimaryDisplaySize() const312 gfx::Size GetPrimaryDisplaySize() const {
313 const std::vector<ui::DisplayConfigurator::DisplayState>& displays =
314 display_configurator_->cached_displays();
315 if (displays.empty())
316 return gfx::Size();
317 const ui::DisplayMode* mode = displays[0].display->current_mode();
318 return mode ? mode->size() : gfx::Size();
319 }
320
321 scoped_ptr<aura::TestScreen> screen_;
322 scoped_ptr<aura::WindowTreeHost> host_;
323
324 scoped_ptr<wm::InputMethodEventFilter> input_method_filter_;
325 scoped_ptr<wm::CompoundEventFilter> root_window_event_filter_;
326 scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
327 scoped_ptr<wm::CursorManager> cursor_manager_;
328 scoped_ptr<wm::UserActivityDetector> user_activity_detector_;
329 scoped_ptr<ui::DisplayConfigurator> display_configurator_;
330 scoped_ptr<ui::UserActivityPowerManagerNotifier> user_activity_notifier_;
331
332 std::vector<base::Closure> terminating_callbacks_;
333
334 DISALLOW_COPY_AND_ASSIGN(AthenaEnvImpl);
335 };
336
337 } // namespace
338
339 // static
Create()340 void AthenaEnv::Create() {
341 DCHECK(!instance);
342 new AthenaEnvImpl();
343 }
344
Get()345 AthenaEnv* AthenaEnv::Get() {
346 DCHECK(instance);
347 return instance;
348 }
349
350 // static
351
352 // static
Shutdown()353 void AthenaEnv::Shutdown() {
354 DCHECK(instance);
355 delete instance;
356 }
357
358 } // namespace athena
359