• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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