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.
5 #include "ui/aura/window_tree_host.h"
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/root_window_transformer.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"
29 const char kWindowTreeHostForAcceleratedWidget
[] =
30 "__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__";
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();
39 class SimpleRootWindowTransformer
: public RootWindowTransformer
{
41 SimpleRootWindowTransformer(const Window
* root_window
,
42 const gfx::Transform
& transform
)
43 : root_window_(root_window
),
44 transform_(transform
) {
47 // RootWindowTransformer overrides:
48 virtual gfx::Transform
GetTransform() const OVERRIDE
{
52 virtual gfx::Transform
GetInverseTransform() const OVERRIDE
{
53 gfx::Transform invert
;
54 if (!transform_
.GetInverse(&invert
))
59 virtual gfx::Rect
GetRootWindowBounds(
60 const gfx::Size
& host_size
) const OVERRIDE
{
61 gfx::Rect
bounds(host_size
);
62 gfx::RectF
new_bounds(ui::ConvertRectToDIP(root_window_
->layer(), bounds
));
63 transform_
.TransformRect(&new_bounds
);
64 return gfx::Rect(gfx::ToFlooredSize(new_bounds
.size()));
67 virtual gfx::Insets
GetHostInsets() const OVERRIDE
{
72 virtual ~SimpleRootWindowTransformer() {}
74 const Window
* root_window_
;
75 const gfx::Transform transform_
;
77 DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer
);
80 ////////////////////////////////////////////////////////////////////////////////
81 // WindowTreeHost, public:
83 WindowTreeHost::~WindowTreeHost() {
84 DCHECK(!compositor_
) << "compositor must be destroyed before root window";
87 #if defined(OS_ANDROID)
89 WindowTreeHost
* WindowTreeHost::Create(const gfx::Rect
& bounds
) {
90 // This is only hit for tests and ash, right now these aren't an issue so
92 // TODO(sky): decide if we want a factory.
99 WindowTreeHost
* WindowTreeHost::GetForAcceleratedWidget(
100 gfx::AcceleratedWidget widget
) {
101 return reinterpret_cast<WindowTreeHost
*>(
102 ui::ViewProp::GetValue(widget
, kWindowTreeHostForAcceleratedWidget
));
105 void WindowTreeHost::InitHost() {
107 UpdateRootWindowSize(GetBounds().size());
108 Env::GetInstance()->NotifyHostInitialized(this);
112 void WindowTreeHost::InitCompositor() {
113 compositor_
->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
115 compositor_
->SetRootLayer(window()->layer());
117 new SimpleRootWindowTransformer(window(), gfx::Transform()));
120 void WindowTreeHost::AddObserver(WindowTreeHostObserver
* observer
) {
121 observers_
.AddObserver(observer
);
124 void WindowTreeHost::RemoveObserver(WindowTreeHostObserver
* observer
) {
125 observers_
.RemoveObserver(observer
);
128 ui::EventProcessor
* WindowTreeHost::event_processor() {
132 void WindowTreeHost::SetRootWindowTransformer(
133 scoped_ptr
<RootWindowTransformer
> transformer
) {
134 transformer_
= transformer
.Pass();
135 SetInsets(transformer_
->GetHostInsets());
136 window()->SetTransform(transformer_
->GetTransform());
137 // If the layer is not animating, then we need to update the root window
139 if (!window()->layer()->GetAnimator()->is_animating())
140 UpdateRootWindowSize(GetBounds().size());
143 gfx::Transform
WindowTreeHost::GetRootTransform() const {
144 float scale
= ui::GetDeviceScaleFactor(window()->layer());
145 gfx::Transform transform
;
146 transform
.Scale(scale
, scale
);
147 transform
*= transformer_
->GetTransform();
151 void WindowTreeHost::SetTransform(const gfx::Transform
& transform
) {
152 scoped_ptr
<RootWindowTransformer
> transformer(
153 new SimpleRootWindowTransformer(window(), transform
));
154 SetRootWindowTransformer(transformer
.Pass());
157 gfx::Transform
WindowTreeHost::GetInverseRootTransform() const {
158 float scale
= ui::GetDeviceScaleFactor(window()->layer());
159 gfx::Transform transform
;
160 transform
.Scale(1.0f
/ scale
, 1.0f
/ scale
);
161 return transformer_
->GetInverseTransform() * transform
;
164 void WindowTreeHost::UpdateRootWindowSize(const gfx::Size
& host_size
) {
165 window()->SetBounds(transformer_
->GetRootWindowBounds(host_size
));
168 void WindowTreeHost::ConvertPointToNativeScreen(gfx::Point
* point
) const {
169 ConvertPointToHost(point
);
170 gfx::Point location
= GetLocationOnNativeScreen();
171 point
->Offset(location
.x(), location
.y());
174 void WindowTreeHost::ConvertPointFromNativeScreen(gfx::Point
* point
) const {
175 gfx::Point location
= GetLocationOnNativeScreen();
176 point
->Offset(-location
.x(), -location
.y());
177 ConvertPointFromHost(point
);
180 void WindowTreeHost::ConvertPointToHost(gfx::Point
* point
) const {
181 gfx::Point3F
point_3f(*point
);
182 GetRootTransform().TransformPoint(&point_3f
);
183 *point
= gfx::ToFlooredPoint(point_3f
.AsPointF());
186 void WindowTreeHost::ConvertPointFromHost(gfx::Point
* point
) const {
187 gfx::Point3F
point_3f(*point
);
188 GetInverseRootTransform().TransformPoint(&point_3f
);
189 *point
= gfx::ToFlooredPoint(point_3f
.AsPointF());
192 void WindowTreeHost::SetCursor(gfx::NativeCursor cursor
) {
193 last_cursor_
= cursor
;
194 // A lot of code seems to depend on NULL cursors actually showing an arrow,
195 // so just pass everything along to the host.
196 SetCursorNative(cursor
);
199 void WindowTreeHost::OnCursorVisibilityChanged(bool show
) {
200 // Clear any existing mouse hover effects when the cursor becomes invisible.
201 // Note we do not need to dispatch a mouse enter when the cursor becomes
202 // visible because that can only happen in response to a mouse event, which
203 // will trigger its own mouse enter.
205 dispatcher()->DispatchMouseExitAtPoint(
206 dispatcher()->GetLastMouseLocationInRoot());
209 OnCursorVisibilityChangedNative(show
);
212 void WindowTreeHost::MoveCursorTo(const gfx::Point
& location_in_dip
) {
213 gfx::Point
host_location(location_in_dip
);
214 ConvertPointToHost(&host_location
);
215 MoveCursorToInternal(location_in_dip
, host_location
);
218 void WindowTreeHost::MoveCursorToHostLocation(const gfx::Point
& host_location
) {
219 gfx::Point
root_location(host_location
);
220 ConvertPointFromHost(&root_location
);
221 MoveCursorToInternal(root_location
, host_location
);
224 ////////////////////////////////////////////////////////////////////////////////
225 // WindowTreeHost, protected:
227 WindowTreeHost::WindowTreeHost()
228 : window_(new Window(NULL
)),
229 last_cursor_(ui::kCursorNull
) {
232 void WindowTreeHost::DestroyCompositor() {
233 DCHECK(GetAcceleratedWidget());
237 void WindowTreeHost::DestroyDispatcher() {
242 // TODO(beng): this comment is no longer quite valid since this function
243 // isn't called from WED, and WED isn't a subclass of Window. So it seems
244 // like we could just rely on ~Window now.
245 // Destroy child windows while we're still valid. This is also done by
246 // ~Window, but by that time any calls to virtual methods overriden here (such
247 // as GetRootWindow()) result in Window's implementation. By destroying here
248 // we ensure GetRootWindow() still returns this.
249 //window()->RemoveOrDestroyChildren();
252 void WindowTreeHost::CreateCompositor(
253 gfx::AcceleratedWidget accelerated_widget
) {
254 compositor_
.reset(new ui::Compositor(GetAcceleratedWidget()));
255 DCHECK(compositor_
.get());
256 // TODO(beng): I think this setup should probably all move to a "accelerated
257 // widget available" function.
259 window()->Init(WINDOW_LAYER_NOT_DRAWN
);
260 window()->set_host(this);
261 window()->SetName("RootWindow");
262 window()->SetEventTargeter(
263 scoped_ptr
<ui::EventTargeter
>(new WindowTargeter()));
264 prop_
.reset(new ui::ViewProp(GetAcceleratedWidget(),
265 kWindowTreeHostForAcceleratedWidget
,
267 dispatcher_
.reset(new WindowEventDispatcher(this));
271 void WindowTreeHost::OnHostMoved(const gfx::Point
& new_location
) {
272 TRACE_EVENT1("ui", "WindowTreeHost::OnHostMoved",
273 "origin", new_location
.ToString());
275 FOR_EACH_OBSERVER(WindowTreeHostObserver
, observers_
,
276 OnHostMoved(this, new_location
));
279 void WindowTreeHost::OnHostResized(const gfx::Size
& new_size
) {
280 // The compositor should have the same size as the native root window host.
281 // Get the latest scale from display because it might have been changed.
282 compositor_
->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
285 gfx::Size layer_size
= GetBounds().size();
286 // The layer, and the observers should be notified of the
287 // transformed size of the root window.
288 UpdateRootWindowSize(layer_size
);
289 FOR_EACH_OBSERVER(WindowTreeHostObserver
, observers_
, OnHostResized(this));
292 void WindowTreeHost::OnHostCloseRequested() {
293 FOR_EACH_OBSERVER(WindowTreeHostObserver
, observers_
,
294 OnHostCloseRequested(this));
297 void WindowTreeHost::OnHostActivated() {
298 Env::GetInstance()->NotifyHostActivated(this);
301 void WindowTreeHost::OnHostLostWindowCapture() {
302 Window
* capture_window
= client::GetCaptureWindow(window());
303 if (capture_window
&& capture_window
->GetRootWindow() == window())
304 capture_window
->ReleaseCapture();
307 ////////////////////////////////////////////////////////////////////////////////
308 // WindowTreeHost, private:
310 void WindowTreeHost::MoveCursorToInternal(const gfx::Point
& root_location
,
311 const gfx::Point
& host_location
) {
312 MoveCursorToNative(host_location
);
313 client::CursorClient
* cursor_client
= client::GetCursorClient(window());
315 const gfx::Display
& display
=
316 gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
317 cursor_client
->SetDisplay(display
);
319 dispatcher()->OnCursorMovedToRootLocation(root_location
);