Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ui / aura / window_tree_host.cc
1 // Copyright (c) 2013 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 "ui/aura/window_tree_host.h"
6
7 #include "ui/aura/client/cursor_client.h"
8 #include "ui/aura/env.h"
9 #include "ui/aura/root_window.h"
10 #include "ui/aura/root_window_transformer.h"
11 #include "ui/aura/window.h"
12 #include "ui/aura/window_tree_host_delegate.h"
13 #include "ui/compositor/dip_util.h"
14 #include "ui/compositor/layer.h"
15 #include "ui/gfx/display.h"
16 #include "ui/gfx/insets.h"
17 #include "ui/gfx/point.h"
18 #include "ui/gfx/point3_f.h"
19 #include "ui/gfx/point_conversions.h"
20 #include "ui/gfx/screen.h"
21 #include "ui/gfx/size_conversions.h"
22
23 namespace aura {
24
25 float GetDeviceScaleFactorFromDisplay(Window* window) {
26   gfx::Display display = gfx::Screen::GetScreenFor(window)->
27       GetDisplayNearestWindow(window);
28   DCHECK(display.is_valid());
29   return display.device_scale_factor();
30 }
31
32 class SimpleRootWindowTransformer : public RootWindowTransformer {
33  public:
34   SimpleRootWindowTransformer(const Window* root_window,
35                               const gfx::Transform& transform)
36       : root_window_(root_window),
37         transform_(transform) {
38   }
39
40   // RootWindowTransformer overrides:
41   virtual gfx::Transform GetTransform() const OVERRIDE {
42     return transform_;
43   }
44
45   virtual gfx::Transform GetInverseTransform() const OVERRIDE {
46     gfx::Transform invert;
47     if (!transform_.GetInverse(&invert))
48       return transform_;
49     return invert;
50   }
51
52   virtual gfx::Rect GetRootWindowBounds(
53       const gfx::Size& host_size) const OVERRIDE {
54     gfx::Rect bounds(host_size);
55     gfx::RectF new_bounds(ui::ConvertRectToDIP(root_window_->layer(), bounds));
56     transform_.TransformRect(&new_bounds);
57     return gfx::Rect(gfx::ToFlooredSize(new_bounds.size()));
58   }
59
60   virtual gfx::Insets GetHostInsets() const OVERRIDE {
61     return gfx::Insets();
62   }
63
64  private:
65   virtual ~SimpleRootWindowTransformer() {}
66
67   const Window* root_window_;
68   const gfx::Transform transform_;
69
70   DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer);
71 };
72
73 ////////////////////////////////////////////////////////////////////////////////
74 // WindowTreeHost, public:
75
76 WindowTreeHost::~WindowTreeHost() {
77   DCHECK(!compositor_) << "compositor must be destroyed before root window";
78 }
79
80 void WindowTreeHost::InitHost() {
81   window()->Init(aura::WINDOW_LAYER_NOT_DRAWN);
82   InitCompositor();
83   UpdateRootWindowSize(GetBounds().size());
84   Env::GetInstance()->NotifyRootWindowInitialized(delegate_->AsRootWindow());
85   window()->Show();
86 }
87
88 void WindowTreeHost::InitCompositor() {
89   compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
90                                GetBounds().size());
91   compositor_->SetRootLayer(window()->layer());
92   transformer_.reset(
93       new SimpleRootWindowTransformer(window(), gfx::Transform()));
94 }
95
96 aura::Window* WindowTreeHost::window() {
97   return const_cast<Window*>(const_cast<const WindowTreeHost*>(this)->window());
98 }
99
100 const aura::Window* WindowTreeHost::window() const {
101   return delegate_->AsRootWindow()->window();
102 }
103
104 void WindowTreeHost::SetRootWindowTransformer(
105     scoped_ptr<RootWindowTransformer> transformer) {
106   transformer_ = transformer.Pass();
107   SetInsets(transformer_->GetHostInsets());
108   window()->SetTransform(transformer_->GetTransform());
109   // If the layer is not animating, then we need to update the root window
110   // size immediately.
111   if (!window()->layer()->GetAnimator()->is_animating())
112     UpdateRootWindowSize(GetBounds().size());
113 }
114
115 gfx::Transform WindowTreeHost::GetRootTransform() const {
116   float scale = ui::GetDeviceScaleFactor(window()->layer());
117   gfx::Transform transform;
118   transform.Scale(scale, scale);
119   transform *= transformer_->GetTransform();
120   return transform;
121 }
122
123 void WindowTreeHost::SetTransform(const gfx::Transform& transform) {
124   scoped_ptr<RootWindowTransformer> transformer(
125       new SimpleRootWindowTransformer(window(), transform));
126   SetRootWindowTransformer(transformer.Pass());
127 }
128
129 gfx::Transform WindowTreeHost::GetInverseRootTransform() const {
130   float scale = ui::GetDeviceScaleFactor(window()->layer());
131   gfx::Transform transform;
132   transform.Scale(1.0f / scale, 1.0f / scale);
133   return transformer_->GetInverseTransform() * transform;
134 }
135
136 void WindowTreeHost::UpdateRootWindowSize(const gfx::Size& host_size) {
137   window()->SetBounds(transformer_->GetRootWindowBounds(host_size));
138 }
139
140 void WindowTreeHost::ConvertPointToNativeScreen(gfx::Point* point) const {
141   ConvertPointToHost(point);
142   gfx::Point location = GetLocationOnNativeScreen();
143   point->Offset(location.x(), location.y());
144 }
145
146 void WindowTreeHost::ConvertPointFromNativeScreen(gfx::Point* point) const {
147   gfx::Point location = GetLocationOnNativeScreen();
148   point->Offset(-location.x(), -location.y());
149   ConvertPointFromHost(point);
150 }
151
152 void WindowTreeHost::ConvertPointToHost(gfx::Point* point) const {
153   gfx::Point3F point_3f(*point);
154   GetRootTransform().TransformPoint(&point_3f);
155   *point = gfx::ToFlooredPoint(point_3f.AsPointF());
156 }
157
158 void WindowTreeHost::ConvertPointFromHost(gfx::Point* point) const {
159   gfx::Point3F point_3f(*point);
160   GetInverseRootTransform().TransformPoint(&point_3f);
161   *point = gfx::ToFlooredPoint(point_3f.AsPointF());
162 }
163
164 void WindowTreeHost::SetCursor(gfx::NativeCursor cursor) {
165   last_cursor_ = cursor;
166   // A lot of code seems to depend on NULL cursors actually showing an arrow,
167   // so just pass everything along to the host.
168   SetCursorNative(cursor);
169 }
170
171 void WindowTreeHost::OnCursorVisibilityChanged(bool show) {
172   // Clear any existing mouse hover effects when the cursor becomes invisible.
173   // Note we do not need to dispatch a mouse enter when the cursor becomes
174   // visible because that can only happen in response to a mouse event, which
175   // will trigger its own mouse enter.
176   if (!show) {
177     delegate_->AsRootWindow()->DispatchMouseExitAtPoint(
178         delegate_->AsRootWindow()->GetLastMouseLocationInRoot());
179   }
180
181   OnCursorVisibilityChangedNative(show);
182 }
183
184 void WindowTreeHost::MoveCursorTo(const gfx::Point& location_in_dip) {
185   gfx::Point host_location(location_in_dip);
186   ConvertPointToHost(&host_location);
187   MoveCursorToInternal(location_in_dip, host_location);
188 }
189
190 void WindowTreeHost::MoveCursorToHostLocation(const gfx::Point& host_location) {
191   gfx::Point root_location(host_location);
192   ConvertPointFromHost(&root_location);
193   MoveCursorToInternal(root_location, host_location);
194 }
195
196 ////////////////////////////////////////////////////////////////////////////////
197 // WindowTreeHost, protected:
198
199 WindowTreeHost::WindowTreeHost()
200     : delegate_(NULL),
201       last_cursor_(ui::kCursorNull) {
202 }
203
204 void WindowTreeHost::DestroyCompositor() {
205   DCHECK(GetAcceleratedWidget());
206   compositor_.reset();
207 }
208
209 void WindowTreeHost::CreateCompositor(
210     gfx::AcceleratedWidget accelerated_widget) {
211   compositor_.reset(new ui::Compositor(GetAcceleratedWidget()));
212   DCHECK(compositor_.get());
213 }
214
215 void WindowTreeHost::NotifyHostResized(const gfx::Size& new_size) {
216   // The compositor should have the same size as the native root window host.
217   // Get the latest scale from display because it might have been changed.
218   compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
219                                new_size);
220
221   gfx::Size layer_size = GetBounds().size();
222   // The layer, and the observers should be notified of the
223   // transformed size of the root window.
224   UpdateRootWindowSize(layer_size);
225   delegate_->OnHostResized(layer_size);
226 }
227
228 void WindowTreeHost::MoveCursorToInternal(const gfx::Point& root_location,
229                                           const gfx::Point& host_location) {
230   MoveCursorToNative(host_location);
231   client::CursorClient* cursor_client = client::GetCursorClient(window());
232   if (cursor_client) {
233     const gfx::Display& display =
234         gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
235     cursor_client->SetDisplay(display);
236   }
237   delegate_->OnCursorMovedToRootLocation(root_location);
238 }
239
240 #if defined(OS_ANDROID)
241 // static
242 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
243   // This is only hit for tests and ash, right now these aren't an issue so
244   // adding the CHECK.
245   // TODO(sky): decide if we want a factory.
246   CHECK(false);
247   return NULL;
248 }
249 #endif
250
251 }  // namespace aura