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 "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"
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();
32 class SimpleRootWindowTransformer
: public RootWindowTransformer
{
34 SimpleRootWindowTransformer(const Window
* root_window
,
35 const gfx::Transform
& transform
)
36 : root_window_(root_window
),
37 transform_(transform
) {
40 // RootWindowTransformer overrides:
41 virtual gfx::Transform
GetTransform() const OVERRIDE
{
45 virtual gfx::Transform
GetInverseTransform() const OVERRIDE
{
46 gfx::Transform invert
;
47 if (!transform_
.GetInverse(&invert
))
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()));
60 virtual gfx::Insets
GetHostInsets() const OVERRIDE
{
65 virtual ~SimpleRootWindowTransformer() {}
67 const Window
* root_window_
;
68 const gfx::Transform transform_
;
70 DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer
);
73 ////////////////////////////////////////////////////////////////////////////////
74 // WindowTreeHost, public:
76 WindowTreeHost::~WindowTreeHost() {
77 DCHECK(!compositor_
) << "compositor must be destroyed before root window";
80 void WindowTreeHost::InitHost() {
81 window()->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
83 UpdateRootWindowSize(GetBounds().size());
84 Env::GetInstance()->NotifyRootWindowInitialized(delegate_
->AsRootWindow());
88 void WindowTreeHost::InitCompositor() {
89 compositor_
->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
91 compositor_
->SetRootLayer(window()->layer());
93 new SimpleRootWindowTransformer(window(), gfx::Transform()));
96 aura::Window
* WindowTreeHost::window() {
97 return const_cast<Window
*>(const_cast<const WindowTreeHost
*>(this)->window());
100 const aura::Window
* WindowTreeHost::window() const {
101 return delegate_
->AsRootWindow()->window();
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
111 if (!window()->layer()->GetAnimator()->is_animating())
112 UpdateRootWindowSize(GetBounds().size());
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();
123 void WindowTreeHost::SetTransform(const gfx::Transform
& transform
) {
124 scoped_ptr
<RootWindowTransformer
> transformer(
125 new SimpleRootWindowTransformer(window(), transform
));
126 SetRootWindowTransformer(transformer
.Pass());
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
;
136 void WindowTreeHost::UpdateRootWindowSize(const gfx::Size
& host_size
) {
137 window()->SetBounds(transformer_
->GetRootWindowBounds(host_size
));
140 void WindowTreeHost::ConvertPointToNativeScreen(gfx::Point
* point
) const {
141 ConvertPointToHost(point
);
142 gfx::Point location
= GetLocationOnNativeScreen();
143 point
->Offset(location
.x(), location
.y());
146 void WindowTreeHost::ConvertPointFromNativeScreen(gfx::Point
* point
) const {
147 gfx::Point location
= GetLocationOnNativeScreen();
148 point
->Offset(-location
.x(), -location
.y());
149 ConvertPointFromHost(point
);
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());
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());
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
);
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.
177 delegate_
->AsRootWindow()->DispatchMouseExitAtPoint(
178 delegate_
->AsRootWindow()->GetLastMouseLocationInRoot());
181 OnCursorVisibilityChangedNative(show
);
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
);
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
);
196 ////////////////////////////////////////////////////////////////////////////////
197 // WindowTreeHost, protected:
199 WindowTreeHost::WindowTreeHost()
201 last_cursor_(ui::kCursorNull
) {
204 void WindowTreeHost::DestroyCompositor() {
205 DCHECK(GetAcceleratedWidget());
209 void WindowTreeHost::CreateCompositor(
210 gfx::AcceleratedWidget accelerated_widget
) {
211 compositor_
.reset(new ui::Compositor(GetAcceleratedWidget()));
212 DCHECK(compositor_
.get());
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()),
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
);
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());
233 const gfx::Display
& display
=
234 gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
235 cursor_client
->SetDisplay(display
);
237 delegate_
->OnCursorMovedToRootLocation(root_location
);
240 #if defined(OS_ANDROID)
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
245 // TODO(sky): decide if we want a factory.