blob: 4958c419d7a819eec0d7c05d47730dbb14a6b645 [file] [log] [blame]
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +00001// 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
Torne (Richard Coles)a1401312014-03-18 10:20:56 +00007#include "base/debug/trace_event.h"
8#include "ui/aura/client/capture_client.h"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +00009#include "ui/aura/client/cursor_client.h"
10#include "ui/aura/env.h"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000011#include "ui/aura/root_window_transformer.h"
12#include "ui/aura/window.h"
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000013#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"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000017#include "ui/compositor/dip_util.h"
18#include "ui/compositor/layer.h"
19#include "ui/gfx/display.h"
20#include "ui/gfx/insets.h"
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000021#include "ui/gfx/point.h"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000022#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"
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000026
27namespace aura {
28
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000029const char kWindowTreeHostForAcceleratedWidget[] =
30 "__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__";
31
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000032float 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();
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +000037}
38
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000039class SimpleRootWindowTransformer : public RootWindowTransformer {
40 public:
41 SimpleRootWindowTransformer(const Window* root_window,
42 const gfx::Transform& transform)
43 : root_window_(root_window),
44 transform_(transform) {
45 }
46
47 // RootWindowTransformer overrides:
48 virtual gfx::Transform GetTransform() const OVERRIDE {
49 return transform_;
50 }
51
52 virtual gfx::Transform GetInverseTransform() const OVERRIDE {
53 gfx::Transform invert;
54 if (!transform_.GetInverse(&invert))
55 return transform_;
56 return invert;
57 }
58
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()));
65 }
66
67 virtual gfx::Insets GetHostInsets() const OVERRIDE {
68 return gfx::Insets();
69 }
70
71 private:
72 virtual ~SimpleRootWindowTransformer() {}
73
74 const Window* root_window_;
75 const gfx::Transform transform_;
76
77 DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer);
78};
79
80////////////////////////////////////////////////////////////////////////////////
81// WindowTreeHost, public:
82
83WindowTreeHost::~WindowTreeHost() {
84 DCHECK(!compositor_) << "compositor must be destroyed before root window";
85}
86
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000087#if defined(OS_ANDROID)
88// static
89WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
90 // This is only hit for tests and ash, right now these aren't an issue so
91 // adding the CHECK.
92 // TODO(sky): decide if we want a factory.
93 CHECK(false);
94 return NULL;
95}
96#endif
97
98// static
99WindowTreeHost* WindowTreeHost::GetForAcceleratedWidget(
100 gfx::AcceleratedWidget widget) {
101 return reinterpret_cast<WindowTreeHost*>(
102 ui::ViewProp::GetValue(widget, kWindowTreeHostForAcceleratedWidget));
103}
104
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000105void WindowTreeHost::InitHost() {
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000106 InitCompositor();
107 UpdateRootWindowSize(GetBounds().size());
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000108 Env::GetInstance()->NotifyHostInitialized(this);
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000109 window()->Show();
110}
111
112void WindowTreeHost::InitCompositor() {
113 compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
114 GetBounds().size());
115 compositor_->SetRootLayer(window()->layer());
116 transformer_.reset(
117 new SimpleRootWindowTransformer(window(), gfx::Transform()));
118}
119
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000120void WindowTreeHost::AddObserver(WindowTreeHostObserver* observer) {
121 observers_.AddObserver(observer);
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000122}
123
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000124void WindowTreeHost::RemoveObserver(WindowTreeHostObserver* observer) {
125 observers_.RemoveObserver(observer);
126}
127
128ui::EventProcessor* WindowTreeHost::event_processor() {
129 return dispatcher();
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000130}
131
132void 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
138 // size immediately.
139 if (!window()->layer()->GetAnimator()->is_animating())
140 UpdateRootWindowSize(GetBounds().size());
141}
142
143gfx::Transform WindowTreeHost::GetRootTransform() const {
144 float scale = ui::GetDeviceScaleFactor(window()->layer());
145 gfx::Transform transform;
146 transform.Scale(scale, scale);
147 transform *= transformer_->GetTransform();
148 return transform;
149}
150
151void WindowTreeHost::SetTransform(const gfx::Transform& transform) {
152 scoped_ptr<RootWindowTransformer> transformer(
153 new SimpleRootWindowTransformer(window(), transform));
154 SetRootWindowTransformer(transformer.Pass());
155}
156
157gfx::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;
162}
163
164void WindowTreeHost::UpdateRootWindowSize(const gfx::Size& host_size) {
165 window()->SetBounds(transformer_->GetRootWindowBounds(host_size));
166}
167
168void WindowTreeHost::ConvertPointToNativeScreen(gfx::Point* point) const {
169 ConvertPointToHost(point);
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000170 gfx::Point location = GetLocationOnNativeScreen();
171 point->Offset(location.x(), location.y());
172}
173
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000174void WindowTreeHost::ConvertPointFromNativeScreen(gfx::Point* point) const {
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000175 gfx::Point location = GetLocationOnNativeScreen();
176 point->Offset(-location.x(), -location.y());
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000177 ConvertPointFromHost(point);
178}
179
180void WindowTreeHost::ConvertPointToHost(gfx::Point* point) const {
181 gfx::Point3F point_3f(*point);
182 GetRootTransform().TransformPoint(&point_3f);
183 *point = gfx::ToFlooredPoint(point_3f.AsPointF());
184}
185
186void WindowTreeHost::ConvertPointFromHost(gfx::Point* point) const {
187 gfx::Point3F point_3f(*point);
188 GetInverseRootTransform().TransformPoint(&point_3f);
189 *point = gfx::ToFlooredPoint(point_3f.AsPointF());
190}
191
192void 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);
197}
198
199void 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.
204 if (!show) {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000205 dispatcher()->DispatchMouseExitAtPoint(
206 dispatcher()->GetLastMouseLocationInRoot());
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000207 }
208
209 OnCursorVisibilityChangedNative(show);
210}
211
212void 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);
216}
217
218void WindowTreeHost::MoveCursorToHostLocation(const gfx::Point& host_location) {
219 gfx::Point root_location(host_location);
220 ConvertPointFromHost(&root_location);
221 MoveCursorToInternal(root_location, host_location);
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000222}
223
224////////////////////////////////////////////////////////////////////////////////
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000225// WindowTreeHost, protected:
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000226
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000227WindowTreeHost::WindowTreeHost()
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000228 : window_(new Window(NULL)),
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000229 last_cursor_(ui::kCursorNull) {
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000230}
231
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000232void WindowTreeHost::DestroyCompositor() {
233 DCHECK(GetAcceleratedWidget());
234 compositor_.reset();
235}
236
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000237void WindowTreeHost::DestroyDispatcher() {
238 delete window_;
239 window_ = NULL;
240 dispatcher_.reset();
241
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();
250}
251
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000252void WindowTreeHost::CreateCompositor(
253 gfx::AcceleratedWidget accelerated_widget) {
254 compositor_.reset(new ui::Compositor(GetAcceleratedWidget()));
255 DCHECK(compositor_.get());
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000256 // TODO(beng): I think this setup should probably all move to a "accelerated
257 // widget available" function.
258 if (!dispatcher()) {
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,
266 this));
267 dispatcher_.reset(new WindowEventDispatcher(this));
268 }
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000269}
270
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000271void WindowTreeHost::OnHostMoved(const gfx::Point& new_location) {
272 TRACE_EVENT1("ui", "WindowTreeHost::OnHostMoved",
273 "origin", new_location.ToString());
274
275 FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_,
276 OnHostMoved(this, new_location));
277}
278
279void WindowTreeHost::OnHostResized(const gfx::Size& new_size) {
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000280 // 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()),
283 new_size);
284
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);
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000289 FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_, OnHostResized(this));
290 dispatcher()->OnHostResized(layer_size);
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000291}
292
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000293void WindowTreeHost::OnHostCloseRequested() {
294 FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_,
295 OnHostCloseRequested(this));
296}
297
298void WindowTreeHost::OnHostActivated() {
299 Env::GetInstance()->NotifyHostActivated(this);
300}
301
302void WindowTreeHost::OnHostLostWindowCapture() {
303 Window* capture_window = client::GetCaptureWindow(window());
304 if (capture_window && capture_window->GetRootWindow() == window())
305 capture_window->ReleaseCapture();
306}
307
308////////////////////////////////////////////////////////////////////////////////
309// WindowTreeHost, private:
310
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000311void WindowTreeHost::MoveCursorToInternal(const gfx::Point& root_location,
312 const gfx::Point& host_location) {
313 MoveCursorToNative(host_location);
314 client::CursorClient* cursor_client = client::GetCursorClient(window());
315 if (cursor_client) {
316 const gfx::Display& display =
317 gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
318 cursor_client->SetDisplay(display);
319 }
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000320 dispatcher()->OnCursorMovedToRootLocation(root_location);
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000321}
322
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000323} // namespace aura