Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / athena / env / athena_env_impl.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 "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/events/devices/device_data_manager.h"
26 #include "ui/events/devices/input_device_event_observer.h"
27 #include "ui/events/devices/touchscreen_device.h"
28 #include "ui/gfx/screen.h"
29 #include "ui/wm/core/compound_event_filter.h"
30 #include "ui/wm/core/cursor_manager.h"
31 #include "ui/wm/core/input_method_event_filter.h"
32 #include "ui/wm/core/native_cursor_manager.h"
33 #include "ui/wm/core/native_cursor_manager_delegate.h"
34 #include "ui/wm/core/user_activity_detector.h"
35
36 namespace athena {
37
38 namespace {
39
40 AthenaEnv* instance = nullptr;
41
42 // Screen object used during shutdown.
43 gfx::Screen* screen_for_shutdown = nullptr;
44
45 gfx::Transform GetTouchTransform(const ui::DisplaySnapshot& display,
46                                  const ui::TouchscreenDevice& touchscreen,
47                                  const gfx::SizeF& framebuffer_size) {
48   if (!display.current_mode())
49     return gfx::Transform();
50
51   gfx::SizeF display_size = display.current_mode()->size();
52 #if defined(USE_X11)
53   gfx::SizeF touchscreen_size = framebuffer_size;
54 #elif defined(USE_OZONE)
55   gfx::SizeF touchscreen_size = touchscreen.size;
56 #endif
57
58   if (display_size.IsEmpty() || touchscreen_size.IsEmpty())
59     return gfx::Transform();
60
61   gfx::Transform transform;
62   transform.Scale(display_size.width() / touchscreen_size.width(),
63                   display_size.height() / touchscreen_size.height());
64
65   return transform;
66 }
67
68 double GetTouchRadiusScale(const ui::DisplaySnapshot& display,
69                            const ui::TouchscreenDevice& touchscreen,
70                            const gfx::SizeF& framebuffer_size) {
71   if (!display.current_mode())
72     return 1;
73
74   gfx::SizeF display_size = display.current_mode()->size();
75 #if defined(USE_X11)
76   gfx::SizeF touchscreen_size = framebuffer_size;
77 #elif defined(USE_OZONE)
78   gfx::SizeF touchscreen_size = touchscreen.size;
79 #endif
80
81   if (display_size.IsEmpty() || touchscreen_size.IsEmpty())
82     return 1;
83
84   return std::sqrt(display_size.GetArea() / touchscreen_size.GetArea());
85 }
86
87 // TODO(flackr:oshima): Remove this once athena switches to share
88 // ash::DisplayManager.
89 class ScreenForShutdown : public gfx::Screen {
90  public:
91   // Creates and sets the screen for shutdown. Deletes existing one if any.
92   static void Create(const gfx::Screen* screen) {
93     delete screen_for_shutdown;
94     screen_for_shutdown = new ScreenForShutdown(screen->GetPrimaryDisplay());
95     gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
96                                    screen_for_shutdown);
97   }
98
99  private:
100   explicit ScreenForShutdown(const gfx::Display& primary_display)
101       : primary_display_(primary_display) {}
102
103   // gfx::Screen overrides:
104   gfx::Point GetCursorScreenPoint() override { return gfx::Point(); }
105   gfx::NativeWindow GetWindowUnderCursor() override { return NULL; }
106   gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override {
107     return nullptr;
108   }
109   int GetNumDisplays() const override { return 1; }
110   std::vector<gfx::Display> GetAllDisplays() const override {
111     std::vector<gfx::Display> displays(1, primary_display_);
112     return displays;
113   }
114   gfx::Display GetDisplayNearestWindow(gfx::NativeView view) const override {
115     return primary_display_;
116   }
117   gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const override {
118     return primary_display_;
119   }
120   gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override {
121     return primary_display_;
122   }
123   gfx::Display GetPrimaryDisplay() const override { return primary_display_; }
124   void AddObserver(gfx::DisplayObserver* observer) override {
125     NOTREACHED() << "Observer should not be added during shutdown";
126   }
127   void RemoveObserver(gfx::DisplayObserver* observer) override {}
128
129   const gfx::Display primary_display_;
130
131   DISALLOW_COPY_AND_ASSIGN(ScreenForShutdown);
132 };
133
134 // A class that bridges the gap between CursorManager and Aura. It borrows
135 // heavily from AshNativeCursorManager.
136 class AthenaNativeCursorManager : public wm::NativeCursorManager {
137  public:
138   explicit AthenaNativeCursorManager(aura::WindowTreeHost* host)
139       : host_(host), image_cursors_(new ui::ImageCursors) {}
140   ~AthenaNativeCursorManager() override {}
141
142   // wm::NativeCursorManager overrides.
143   void SetDisplay(const gfx::Display& display,
144                   wm::NativeCursorManagerDelegate* delegate) override {
145     if (image_cursors_->SetDisplay(display, display.device_scale_factor()))
146       SetCursor(delegate->GetCursor(), delegate);
147   }
148
149   void SetCursor(gfx::NativeCursor cursor,
150                  wm::NativeCursorManagerDelegate* delegate) override {
151     image_cursors_->SetPlatformCursor(&cursor);
152     cursor.set_device_scale_factor(image_cursors_->GetScale());
153     delegate->CommitCursor(cursor);
154
155     if (delegate->IsCursorVisible())
156       ApplyCursor(cursor);
157   }
158
159   void SetVisibility(bool visible,
160                      wm::NativeCursorManagerDelegate* delegate) override {
161     delegate->CommitVisibility(visible);
162
163     if (visible) {
164       SetCursor(delegate->GetCursor(), delegate);
165     } else {
166       gfx::NativeCursor invisible_cursor(ui::kCursorNone);
167       image_cursors_->SetPlatformCursor(&invisible_cursor);
168       ApplyCursor(invisible_cursor);
169     }
170   }
171
172   void SetCursorSet(ui::CursorSetType cursor_set,
173                     wm::NativeCursorManagerDelegate* delegate) override {
174     image_cursors_->SetCursorSet(cursor_set);
175     delegate->CommitCursorSet(cursor_set);
176     if (delegate->IsCursorVisible())
177       SetCursor(delegate->GetCursor(), delegate);
178   }
179
180   void SetMouseEventsEnabled(
181       bool enabled,
182       wm::NativeCursorManagerDelegate* delegate) override {
183     delegate->CommitMouseEventsEnabled(enabled);
184     SetVisibility(delegate->IsCursorVisible(), delegate);
185   }
186
187  private:
188   // Sets |cursor| as the active cursor within Aura.
189   void ApplyCursor(gfx::NativeCursor cursor) { host_->SetCursor(cursor); }
190
191   aura::WindowTreeHost* host_;  // Not owned.
192
193   scoped_ptr<ui::ImageCursors> image_cursors_;
194
195   DISALLOW_COPY_AND_ASSIGN(AthenaNativeCursorManager);
196 };
197
198 class AthenaEnvImpl : public AthenaEnv,
199                       public aura::WindowTreeHostObserver,
200                       public ui::DisplayConfigurator::Observer,
201                       public ui::InputDeviceEventObserver {
202  public:
203   AthenaEnvImpl() : display_configurator_(new ui::DisplayConfigurator) {
204     display_configurator_->Init(false);
205     display_configurator_->ForceInitialConfigure(0);
206     display_configurator_->AddObserver(this);
207
208     ui::DeviceDataManager::GetInstance()->AddObserver(this);
209
210     gfx::Size screen_size = GetPrimaryDisplaySize();
211     if (screen_size.IsEmpty()) {
212       // TODO(oshima): Remove this hack.
213       if (base::SysInfo::IsRunningOnChromeOS())
214         screen_size.SetSize(2560, 1600);
215       else
216         screen_size.SetSize(1280, 720);
217     }
218     screen_.reset(aura::TestScreen::Create(screen_size));
219
220     gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
221     host_.reset(screen_->CreateHostForPrimaryDisplay());
222     host_->InitHost();
223
224     aura::Window* root_window = GetHost()->window();
225     input_method_filter_.reset(
226         new wm::InputMethodEventFilter(host_->GetAcceleratedWidget()));
227     input_method_filter_->SetInputMethodPropertyInRootWindow(root_window);
228
229     root_window_event_filter_.reset(new wm::CompoundEventFilter);
230     host_->window()->AddPreTargetHandler(root_window_event_filter_.get());
231
232     root_window_event_filter_->AddHandler(input_method_filter_.get());
233
234     capture_client_.reset(
235         new aura::client::DefaultCaptureClient(host_->window()));
236
237     // Ensure new windows fill the display.
238     root_window->SetLayoutManager(new FillLayoutManager(root_window));
239
240     cursor_manager_.reset(
241         new wm::CursorManager(scoped_ptr<wm::NativeCursorManager>(
242             new AthenaNativeCursorManager(host_.get()))));
243     cursor_manager_->SetDisplay(
244         gfx::Screen::GetNativeScreen()->GetPrimaryDisplay());
245     cursor_manager_->SetCursor(ui::kCursorPointer);
246     aura::client::SetCursorClient(host_->window(), cursor_manager_.get());
247
248     user_activity_detector_.reset(new wm::UserActivityDetector);
249     host_->event_processor()->GetRootTarget()->AddPreTargetHandler(
250         user_activity_detector_.get());
251     user_activity_notifier_.reset(new ui::UserActivityPowerManagerNotifier(
252         user_activity_detector_.get()));
253
254     host_->AddObserver(this);
255     host_->Show();
256
257     DCHECK(!instance);
258     instance = this;
259   }
260
261   ~AthenaEnvImpl() override {
262     instance = nullptr;
263
264     host_->RemoveObserver(this);
265     if (input_method_filter_)
266       root_window_event_filter_->RemoveHandler(input_method_filter_.get());
267     if (user_activity_detector_) {
268       host_->event_processor()->GetRootTarget()->RemovePreTargetHandler(
269           user_activity_detector_.get());
270     }
271     root_window_event_filter_.reset();
272     capture_client_.reset();
273     input_method_filter_.reset();
274     cursor_manager_.reset();
275     user_activity_notifier_.reset();
276     user_activity_detector_.reset();
277
278     input_method_filter_.reset();
279     host_.reset();
280
281     ScreenForShutdown::Create(screen_.get());
282     screen_.reset();
283     aura::Env::DeleteInstance();
284
285     ui::DeviceDataManager::GetInstance()->RemoveObserver(this);
286
287     display_configurator_->RemoveObserver(this);
288     display_configurator_.reset();
289   }
290
291  private:
292   struct Finder {
293     explicit Finder(const base::Closure& c) : closure(c) {}
294     bool operator()(const base::Closure& other) {
295       return closure.Equals(other);
296     }
297     base::Closure closure;
298   };
299
300   // AthenaEnv:
301   aura::WindowTreeHost* GetHost() override { return host_.get(); }
302
303   void SetDisplayWorkAreaInsets(const gfx::Insets& insets) override {
304     screen_->SetWorkAreaInsets(insets);
305   }
306
307   void AddTerminatingCallback(const base::Closure& closure) override {
308     if (closure.is_null())
309       return;
310     DCHECK(terminating_callbacks_.end() ==
311            std::find_if(terminating_callbacks_.begin(),
312                         terminating_callbacks_.end(),
313                         Finder(closure)));
314     terminating_callbacks_.push_back(closure);
315   }
316
317   void RemoveTerminatingCallback(const base::Closure& closure) override {
318     std::vector<base::Closure>::iterator iter =
319         std::find_if(terminating_callbacks_.begin(),
320                      terminating_callbacks_.end(),
321                      Finder(closure));
322     if (iter != terminating_callbacks_.end())
323       terminating_callbacks_.erase(iter);
324   }
325
326   void OnTerminating() override {
327     for (std::vector<base::Closure>::iterator iter =
328              terminating_callbacks_.begin();
329          iter != terminating_callbacks_.end();
330          ++iter) {
331       iter->Run();
332     }
333   }
334
335   // ui::DisplayConfigurator::Observer:
336   void OnDisplayModeChanged(
337       const std::vector<ui::DisplayConfigurator::DisplayState>& displays)
338       override {
339     MapTouchscreenToDisplay();
340
341     gfx::Size size = GetPrimaryDisplaySize();
342     if (!size.IsEmpty())
343       host_->UpdateRootWindowSize(size);
344   }
345
346   // ui::InputDeviceEventObserver:
347   void OnTouchscreenDeviceConfigurationChanged() override {
348     MapTouchscreenToDisplay();
349   }
350
351   void OnKeyboardDeviceConfigurationChanged() override {}
352
353   // aura::WindowTreeHostObserver:
354   void OnHostCloseRequested(const aura::WindowTreeHost* host) override {
355     base::MessageLoopForUI::current()->PostTask(
356         FROM_HERE, base::MessageLoop::QuitClosure());
357   }
358
359   gfx::Size GetPrimaryDisplaySize() const {
360     const std::vector<ui::DisplayConfigurator::DisplayState>& displays =
361         display_configurator_->cached_displays();
362     if (displays.empty())
363       return gfx::Size();
364     const ui::DisplayMode* mode = displays[0].display->current_mode();
365     return mode ? mode->size() : gfx::Size();
366   }
367
368   void MapTouchscreenToDisplay() const {
369     auto device_manager = ui::DeviceDataManager::GetInstance();
370     auto displays = display_configurator_->cached_displays();
371     auto touchscreens = device_manager->touchscreen_devices();
372
373     if (displays.empty() || touchscreens.empty())
374       return;
375
376     gfx::SizeF framebuffer_size = display_configurator_->framebuffer_size();
377     device_manager->ClearTouchTransformerRecord();
378     device_manager->UpdateTouchInfoForDisplay(
379         displays[0].display->display_id(),
380         touchscreens[0].id,
381         GetTouchTransform(*displays[0].display,
382                           touchscreens[0],
383                           framebuffer_size));
384     device_manager->UpdateTouchRadiusScale(
385         touchscreens[0].id,
386         GetTouchRadiusScale(*displays[0].display,
387                             touchscreens[0],
388                             framebuffer_size));
389   }
390
391   scoped_ptr<aura::TestScreen> screen_;
392   scoped_ptr<aura::WindowTreeHost> host_;
393
394   scoped_ptr<wm::InputMethodEventFilter> input_method_filter_;
395   scoped_ptr<wm::CompoundEventFilter> root_window_event_filter_;
396   scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
397   scoped_ptr<wm::CursorManager> cursor_manager_;
398   scoped_ptr<wm::UserActivityDetector> user_activity_detector_;
399   scoped_ptr<ui::DisplayConfigurator> display_configurator_;
400   scoped_ptr<ui::UserActivityPowerManagerNotifier> user_activity_notifier_;
401
402   std::vector<base::Closure> terminating_callbacks_;
403
404   DISALLOW_COPY_AND_ASSIGN(AthenaEnvImpl);
405 };
406
407 }  // namespace
408
409 // static
410 void AthenaEnv::Create() {
411   DCHECK(!instance);
412   new AthenaEnvImpl();
413 }
414
415 AthenaEnv* AthenaEnv::Get() {
416   DCHECK(instance);
417   return instance;
418 }
419
420 // static
421
422 // static
423 void AthenaEnv::Shutdown() {
424   DCHECK(instance);
425   delete instance;
426 }
427
428 }  // namespace athena