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