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/thread_task_runner_handle.h"
8 #include "base/trace_event/trace_event.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/ime/input_method.h"
17 #include "ui/base/ime/input_method_factory.h"
18 #include "ui/base/view_prop.h"
19 #include "ui/compositor/dip_util.h"
20 #include "ui/compositor/layer.h"
21 #include "ui/gfx/display.h"
22 #include "ui/gfx/geometry/insets.h"
23 #include "ui/gfx/geometry/point.h"
24 #include "ui/gfx/geometry/point3_f.h"
25 #include "ui/gfx/geometry/point_conversions.h"
26 #include "ui/gfx/geometry/size_conversions.h"
27 #include "ui/gfx/screen.h"
31 const char kWindowTreeHostForAcceleratedWidget
[] =
32 "__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__";
34 float GetDeviceScaleFactorFromDisplay(Window
* window
) {
35 gfx::Display display
= gfx::Screen::GetScreenFor(window
)->
36 GetDisplayNearestWindow(window
);
37 DCHECK(display
.is_valid());
38 return display
.device_scale_factor();
41 ////////////////////////////////////////////////////////////////////////////////
42 // WindowTreeHost, public:
44 WindowTreeHost::~WindowTreeHost() {
45 DCHECK(!compositor_
) << "compositor must be destroyed before root window";
46 if (owned_input_method_
) {
48 input_method_
= nullptr;
52 #if defined(OS_ANDROID)
54 WindowTreeHost
* WindowTreeHost::Create(const gfx::Rect
& bounds
) {
55 // This is only hit for tests and ash, right now these aren't an issue so
57 // TODO(sky): decide if we want a factory.
64 WindowTreeHost
* WindowTreeHost::GetForAcceleratedWidget(
65 gfx::AcceleratedWidget widget
) {
66 return reinterpret_cast<WindowTreeHost
*>(
67 ui::ViewProp::GetValue(widget
, kWindowTreeHostForAcceleratedWidget
));
70 void WindowTreeHost::InitHost() {
72 UpdateRootWindowSize(GetBounds().size());
73 Env::GetInstance()->NotifyHostInitialized(this);
77 void WindowTreeHost::InitCompositor() {
78 compositor_
->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
80 compositor_
->SetRootLayer(window()->layer());
83 void WindowTreeHost::AddObserver(WindowTreeHostObserver
* observer
) {
84 observers_
.AddObserver(observer
);
87 void WindowTreeHost::RemoveObserver(WindowTreeHostObserver
* observer
) {
88 observers_
.RemoveObserver(observer
);
91 ui::EventProcessor
* WindowTreeHost::event_processor() {
95 gfx::Transform
WindowTreeHost::GetRootTransform() const {
96 float scale
= ui::GetDeviceScaleFactor(window()->layer());
97 gfx::Transform transform
;
98 transform
.Scale(scale
, scale
);
99 transform
*= window()->layer()->transform();
103 void WindowTreeHost::SetRootTransform(const gfx::Transform
& transform
) {
104 window()->SetTransform(transform
);
105 UpdateRootWindowSize(GetBounds().size());
108 gfx::Transform
WindowTreeHost::GetInverseRootTransform() const {
109 gfx::Transform invert
;
110 gfx::Transform transform
= GetRootTransform();
111 if (!transform
.GetInverse(&invert
))
116 void WindowTreeHost::UpdateRootWindowSize(const gfx::Size
& host_size
) {
117 gfx::Rect
bounds(host_size
);
118 gfx::RectF
new_bounds(ui::ConvertRectToDIP(window()->layer(), bounds
));
119 window()->layer()->transform().TransformRect(&new_bounds
);
120 window()->SetBounds(gfx::Rect(gfx::ToFlooredSize(new_bounds
.size())));
123 void WindowTreeHost::ConvertPointToNativeScreen(gfx::Point
* point
) const {
124 ConvertPointToHost(point
);
125 gfx::Point location
= GetLocationOnNativeScreen();
126 point
->Offset(location
.x(), location
.y());
129 void WindowTreeHost::ConvertPointFromNativeScreen(gfx::Point
* point
) const {
130 gfx::Point location
= GetLocationOnNativeScreen();
131 point
->Offset(-location
.x(), -location
.y());
132 ConvertPointFromHost(point
);
135 void WindowTreeHost::ConvertPointToHost(gfx::Point
* point
) const {
136 gfx::Point3F
point_3f(*point
);
137 GetRootTransform().TransformPoint(&point_3f
);
138 *point
= gfx::ToFlooredPoint(point_3f
.AsPointF());
141 void WindowTreeHost::ConvertPointFromHost(gfx::Point
* point
) const {
142 gfx::Point3F
point_3f(*point
);
143 GetInverseRootTransform().TransformPoint(&point_3f
);
144 *point
= gfx::ToFlooredPoint(point_3f
.AsPointF());
147 void WindowTreeHost::SetCursor(gfx::NativeCursor cursor
) {
148 last_cursor_
= cursor
;
149 // A lot of code seems to depend on NULL cursors actually showing an arrow,
150 // so just pass everything along to the host.
151 SetCursorNative(cursor
);
154 void WindowTreeHost::OnCursorVisibilityChanged(bool show
) {
155 // Clear any existing mouse hover effects when the cursor becomes invisible.
156 // Note we do not need to dispatch a mouse enter when the cursor becomes
157 // visible because that can only happen in response to a mouse event, which
158 // will trigger its own mouse enter.
160 ui::EventDispatchDetails details
= dispatcher()->DispatchMouseExitAtPoint(
161 nullptr, dispatcher()->GetLastMouseLocationInRoot());
162 if (details
.dispatcher_destroyed
)
166 OnCursorVisibilityChangedNative(show
);
169 void WindowTreeHost::MoveCursorTo(const gfx::Point
& location_in_dip
) {
170 gfx::Point
host_location(location_in_dip
);
171 ConvertPointToHost(&host_location
);
172 MoveCursorToInternal(location_in_dip
, host_location
);
175 void WindowTreeHost::MoveCursorToHostLocation(const gfx::Point
& host_location
) {
176 gfx::Point
root_location(host_location
);
177 ConvertPointFromHost(&root_location
);
178 MoveCursorToInternal(root_location
, host_location
);
181 ui::InputMethod
* WindowTreeHost::GetInputMethod() {
182 if (!input_method_
) {
184 ui::CreateInputMethod(this, GetAcceleratedWidget()).release();
185 owned_input_method_
= true;
187 return input_method_
;
190 void WindowTreeHost::SetSharedInputMethod(ui::InputMethod
* input_method
) {
191 DCHECK(!input_method_
);
192 input_method_
= input_method
;
193 owned_input_method_
= false;
196 ui::EventDispatchDetails
WindowTreeHost::DispatchKeyEventPostIME(
197 ui::KeyEvent
* event
) {
198 return SendEventToProcessor(event
);
201 void WindowTreeHost::Show() {
203 compositor()->SetVisible(true);
207 void WindowTreeHost::Hide() {
210 compositor()->SetVisible(false);
213 ////////////////////////////////////////////////////////////////////////////////
214 // WindowTreeHost, protected:
216 WindowTreeHost::WindowTreeHost()
217 : window_(new Window(nullptr)),
218 last_cursor_(ui::kCursorNull
),
219 input_method_(nullptr),
220 owned_input_method_(false) {
223 void WindowTreeHost::DestroyCompositor() {
227 void WindowTreeHost::DestroyDispatcher() {
232 // TODO(beng): this comment is no longer quite valid since this function
233 // isn't called from WED, and WED isn't a subclass of Window. So it seems
234 // like we could just rely on ~Window now.
235 // Destroy child windows while we're still valid. This is also done by
236 // ~Window, but by that time any calls to virtual methods overriden here (such
237 // as GetRootWindow()) result in Window's implementation. By destroying here
238 // we ensure GetRootWindow() still returns this.
239 //window()->RemoveOrDestroyChildren();
242 void WindowTreeHost::CreateCompositor(
243 gfx::AcceleratedWidget accelerated_widget
) {
244 DCHECK(Env::GetInstance());
245 ui::ContextFactory
* context_factory
= Env::GetInstance()->context_factory();
246 DCHECK(context_factory
);
248 new ui::Compositor(GetAcceleratedWidget(),
250 base::ThreadTaskRunnerHandle::Get()));
251 // TODO(beng): I think this setup should probably all move to a "accelerated
252 // widget available" function.
254 window()->Init(ui::LAYER_NOT_DRAWN
);
255 window()->set_host(this);
256 window()->SetName("RootWindow");
257 window()->SetEventTargeter(
258 scoped_ptr
<ui::EventTargeter
>(new WindowTargeter()));
259 prop_
.reset(new ui::ViewProp(GetAcceleratedWidget(),
260 kWindowTreeHostForAcceleratedWidget
,
262 dispatcher_
.reset(new WindowEventDispatcher(this));
266 void WindowTreeHost::OnHostMoved(const gfx::Point
& new_location
) {
267 TRACE_EVENT1("ui", "WindowTreeHost::OnHostMoved",
268 "origin", new_location
.ToString());
270 FOR_EACH_OBSERVER(WindowTreeHostObserver
, observers_
,
271 OnHostMoved(this, new_location
));
274 void WindowTreeHost::OnHostResized(const gfx::Size
& new_size
) {
275 // The compositor should have the same size as the native root window host.
276 // Get the latest scale from display because it might have been changed.
277 compositor_
->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
280 gfx::Size layer_size
= GetBounds().size();
281 // The layer, and the observers should be notified of the
282 // transformed size of the root window.
283 UpdateRootWindowSize(layer_size
);
284 FOR_EACH_OBSERVER(WindowTreeHostObserver
, observers_
, OnHostResized(this));
287 void WindowTreeHost::OnHostCloseRequested() {
288 FOR_EACH_OBSERVER(WindowTreeHostObserver
, observers_
,
289 OnHostCloseRequested(this));
292 void WindowTreeHost::OnHostActivated() {
293 Env::GetInstance()->NotifyHostActivated(this);
296 void WindowTreeHost::OnHostLostWindowCapture() {
297 Window
* capture_window
= client::GetCaptureWindow(window());
298 if (capture_window
&& capture_window
->GetRootWindow() == window())
299 capture_window
->ReleaseCapture();
302 ui::EventProcessor
* WindowTreeHost::GetEventProcessor() {
303 return event_processor();
306 ////////////////////////////////////////////////////////////////////////////////
307 // WindowTreeHost, private:
309 void WindowTreeHost::MoveCursorToInternal(const gfx::Point
& root_location
,
310 const gfx::Point
& host_location
) {
311 last_cursor_request_position_in_host_
= 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
);