Upstream version 7.36.149.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 "base/debug/trace_event.h"
8 #include "ui/aura/client/capture_client.h"
9 #include "ui/aura/client/cursor_client.h"
10 #include "ui/aura/env.h"
11 #include "ui/aura/window.h"
12 #include "ui/aura/window_event_dispatcher.h"
13 #include "ui/aura/window_targeter.h"
14 #include "ui/aura/window_tree_host_observer.h"
15 #include "ui/base/view_prop.h"
16 #include "ui/compositor/dip_util.h"
17 #include "ui/compositor/layer.h"
18 #include "ui/gfx/display.h"
19 #include "ui/gfx/insets.h"
20 #include "ui/gfx/point.h"
21 #include "ui/gfx/point3_f.h"
22 #include "ui/gfx/point_conversions.h"
23 #include "ui/gfx/screen.h"
24 #include "ui/gfx/size_conversions.h"
25
26 namespace aura {
27
28 const char kWindowTreeHostForAcceleratedWidget[] =
29     "__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__";
30
31 float GetDeviceScaleFactorFromDisplay(Window* window) {
32   gfx::Display display = gfx::Screen::GetScreenFor(window)->
33       GetDisplayNearestWindow(window);
34   DCHECK(display.is_valid());
35   return display.device_scale_factor();
36 }
37
38 ////////////////////////////////////////////////////////////////////////////////
39 // WindowTreeHost, public:
40
41 WindowTreeHost::~WindowTreeHost() {
42   DCHECK(!compositor_) << "compositor must be destroyed before root window";
43 }
44
45 #if defined(OS_ANDROID)
46 // static
47 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
48   // This is only hit for tests and ash, right now these aren't an issue so
49   // adding the CHECK.
50   // TODO(sky): decide if we want a factory.
51   CHECK(false);
52   return NULL;
53 }
54 #endif
55
56 // static
57 WindowTreeHost* WindowTreeHost::GetForAcceleratedWidget(
58     gfx::AcceleratedWidget widget) {
59   return reinterpret_cast<WindowTreeHost*>(
60       ui::ViewProp::GetValue(widget, kWindowTreeHostForAcceleratedWidget));
61 }
62
63 void WindowTreeHost::InitHost() {
64   InitCompositor();
65   UpdateRootWindowSize(GetBounds().size());
66   Env::GetInstance()->NotifyHostInitialized(this);
67   window()->Show();
68 }
69
70 void WindowTreeHost::InitCompositor() {
71   compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
72                                GetBounds().size());
73   compositor_->SetRootLayer(window()->layer());
74 }
75
76 void WindowTreeHost::AddObserver(WindowTreeHostObserver* observer) {
77   observers_.AddObserver(observer);
78 }
79
80 void WindowTreeHost::RemoveObserver(WindowTreeHostObserver* observer) {
81   observers_.RemoveObserver(observer);
82 }
83
84 ui::EventProcessor* WindowTreeHost::event_processor() {
85   return dispatcher();
86 }
87
88 gfx::Transform WindowTreeHost::GetRootTransform() const {
89   float scale = ui::GetDeviceScaleFactor(window()->layer());
90   gfx::Transform transform;
91   transform.Scale(scale, scale);
92   transform *= window()->layer()->transform();
93   return transform;
94 }
95
96 void WindowTreeHost::SetRootTransform(const gfx::Transform& transform) {
97   window()->SetTransform(transform);
98   UpdateRootWindowSize(GetBounds().size());
99 }
100
101 gfx::Transform WindowTreeHost::GetInverseRootTransform() const {
102   gfx::Transform invert;
103   gfx::Transform transform = GetRootTransform();
104   if (!transform.GetInverse(&invert))
105     return transform;
106   return invert;
107 }
108
109 void WindowTreeHost::UpdateRootWindowSize(const gfx::Size& host_size) {
110   gfx::Rect bounds(host_size);
111   gfx::RectF new_bounds(ui::ConvertRectToDIP(window()->layer(), bounds));
112   window()->layer()->transform().TransformRect(&new_bounds);
113   window()->SetBounds(gfx::Rect(gfx::ToFlooredSize(new_bounds.size())));
114 }
115
116 void WindowTreeHost::ConvertPointToNativeScreen(gfx::Point* point) const {
117   ConvertPointToHost(point);
118   gfx::Point location = GetLocationOnNativeScreen();
119   point->Offset(location.x(), location.y());
120 }
121
122 void WindowTreeHost::ConvertPointFromNativeScreen(gfx::Point* point) const {
123   gfx::Point location = GetLocationOnNativeScreen();
124   point->Offset(-location.x(), -location.y());
125   ConvertPointFromHost(point);
126 }
127
128 void WindowTreeHost::ConvertPointToHost(gfx::Point* point) const {
129   gfx::Point3F point_3f(*point);
130   GetRootTransform().TransformPoint(&point_3f);
131   *point = gfx::ToFlooredPoint(point_3f.AsPointF());
132 }
133
134 void WindowTreeHost::ConvertPointFromHost(gfx::Point* point) const {
135   gfx::Point3F point_3f(*point);
136   GetInverseRootTransform().TransformPoint(&point_3f);
137   *point = gfx::ToFlooredPoint(point_3f.AsPointF());
138 }
139
140 void WindowTreeHost::SetCursor(gfx::NativeCursor cursor) {
141   last_cursor_ = cursor;
142   // A lot of code seems to depend on NULL cursors actually showing an arrow,
143   // so just pass everything along to the host.
144   SetCursorNative(cursor);
145 }
146
147 void WindowTreeHost::OnCursorVisibilityChanged(bool show) {
148   // Clear any existing mouse hover effects when the cursor becomes invisible.
149   // Note we do not need to dispatch a mouse enter when the cursor becomes
150   // visible because that can only happen in response to a mouse event, which
151   // will trigger its own mouse enter.
152   if (!show) {
153     dispatcher()->DispatchMouseExitAtPoint(
154         dispatcher()->GetLastMouseLocationInRoot());
155   }
156
157   OnCursorVisibilityChangedNative(show);
158 }
159
160 void WindowTreeHost::MoveCursorTo(const gfx::Point& location_in_dip) {
161   gfx::Point host_location(location_in_dip);
162   ConvertPointToHost(&host_location);
163   MoveCursorToInternal(location_in_dip, host_location);
164 }
165
166 void WindowTreeHost::MoveCursorToHostLocation(const gfx::Point& host_location) {
167   gfx::Point root_location(host_location);
168   ConvertPointFromHost(&root_location);
169   MoveCursorToInternal(root_location, host_location);
170 }
171
172 ////////////////////////////////////////////////////////////////////////////////
173 // WindowTreeHost, protected:
174
175 WindowTreeHost::WindowTreeHost()
176     : window_(new Window(NULL)),
177       last_cursor_(ui::kCursorNull) {
178 }
179
180 void WindowTreeHost::DestroyCompositor() {
181   compositor_.reset();
182 }
183
184 void WindowTreeHost::DestroyDispatcher() {
185   delete window_;
186   window_ = NULL;
187   dispatcher_.reset();
188
189   // TODO(beng): this comment is no longer quite valid since this function
190   // isn't called from WED, and WED isn't a subclass of Window. So it seems
191   // like we could just rely on ~Window now.
192   // Destroy child windows while we're still valid. This is also done by
193   // ~Window, but by that time any calls to virtual methods overriden here (such
194   // as GetRootWindow()) result in Window's implementation. By destroying here
195   // we ensure GetRootWindow() still returns this.
196   //window()->RemoveOrDestroyChildren();
197 }
198
199 void WindowTreeHost::CreateCompositor(
200     gfx::AcceleratedWidget accelerated_widget) {
201   compositor_.reset(new ui::Compositor(GetAcceleratedWidget()));
202   DCHECK(compositor_.get());
203   // TODO(beng): I think this setup should probably all move to a "accelerated
204   // widget available" function.
205   if (!dispatcher()) {
206     window()->Init(WINDOW_LAYER_NOT_DRAWN);
207     window()->set_host(this);
208     window()->SetName("RootWindow");
209     window()->SetEventTargeter(
210         scoped_ptr<ui::EventTargeter>(new WindowTargeter()));
211     prop_.reset(new ui::ViewProp(GetAcceleratedWidget(),
212                                  kWindowTreeHostForAcceleratedWidget,
213                                  this));
214     dispatcher_.reset(new WindowEventDispatcher(this));
215   }
216 }
217
218 void WindowTreeHost::OnHostMoved(const gfx::Point& new_location) {
219   TRACE_EVENT1("ui", "WindowTreeHost::OnHostMoved",
220                "origin", new_location.ToString());
221
222   FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_,
223                     OnHostMoved(this, new_location));
224 }
225
226 void WindowTreeHost::OnHostResized(const gfx::Size& new_size) {
227   // The compositor should have the same size as the native root window host.
228   // Get the latest scale from display because it might have been changed.
229   compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
230                                new_size);
231
232   gfx::Size layer_size = GetBounds().size();
233   // The layer, and the observers should be notified of the
234   // transformed size of the root window.
235   UpdateRootWindowSize(layer_size);
236   FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_, OnHostResized(this));
237 }
238
239 void WindowTreeHost::OnHostCloseRequested() {
240   FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_,
241                     OnHostCloseRequested(this));
242 }
243
244 void WindowTreeHost::OnHostActivated() {
245   Env::GetInstance()->NotifyHostActivated(this);
246 }
247
248 void WindowTreeHost::OnHostLostWindowCapture() {
249   Window* capture_window = client::GetCaptureWindow(window());
250   if (capture_window && capture_window->GetRootWindow() == window())
251     capture_window->ReleaseCapture();
252 }
253
254 ////////////////////////////////////////////////////////////////////////////////
255 // WindowTreeHost, private:
256
257 void WindowTreeHost::MoveCursorToInternal(const gfx::Point& root_location,
258                                           const gfx::Point& host_location) {
259   last_cursor_request_position_in_host_ = host_location;
260   MoveCursorToNative(host_location);
261   client::CursorClient* cursor_client = client::GetCursorClient(window());
262   if (cursor_client) {
263     const gfx::Display& display =
264         gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
265     cursor_client->SetDisplay(display);
266   }
267   dispatcher()->OnCursorMovedToRootLocation(root_location);
268 }
269
270 }  // namespace aura