Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / aura / window_tree_host.cc
blobc65c9271f4bc3bbdf7a0f6ffc03ec1d7ea6d6297
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"
29 namespace aura {
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_) {
47 delete input_method_;
48 input_method_ = nullptr;
52 #if defined(OS_ANDROID)
53 // static
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
56 // adding the CHECK.
57 // TODO(sky): decide if we want a factory.
58 CHECK(false);
59 return nullptr;
61 #endif
63 // static
64 WindowTreeHost* WindowTreeHost::GetForAcceleratedWidget(
65 gfx::AcceleratedWidget widget) {
66 return reinterpret_cast<WindowTreeHost*>(
67 ui::ViewProp::GetValue(widget, kWindowTreeHostForAcceleratedWidget));
70 void WindowTreeHost::InitHost() {
71 InitCompositor();
72 UpdateRootWindowSize(GetBounds().size());
73 Env::GetInstance()->NotifyHostInitialized(this);
74 window()->Show();
77 void WindowTreeHost::InitCompositor() {
78 compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
79 GetBounds().size());
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() {
92 return dispatcher();
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();
100 return 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))
112 return transform;
113 return 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.
159 if (!show) {
160 ui::EventDispatchDetails details = dispatcher()->DispatchMouseExitAtPoint(
161 nullptr, dispatcher()->GetLastMouseLocationInRoot());
162 if (details.dispatcher_destroyed)
163 return;
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_) {
183 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 bool WindowTreeHost::DispatchKeyEventPostIME(const ui::KeyEvent& event) {
197 ui::KeyEvent copied_event(event);
198 ui::EventDispatchDetails details = SendEventToProcessor(&copied_event);
199 DCHECK(!details.dispatcher_destroyed);
200 return copied_event.stopped_propagation();
203 void WindowTreeHost::Show() {
204 if (compositor())
205 compositor()->SetVisible(true);
206 ShowImpl();
209 void WindowTreeHost::Hide() {
210 HideImpl();
211 if (compositor())
212 compositor()->SetVisible(false);
215 ////////////////////////////////////////////////////////////////////////////////
216 // WindowTreeHost, protected:
218 WindowTreeHost::WindowTreeHost()
219 : window_(new Window(nullptr)),
220 last_cursor_(ui::kCursorNull),
221 input_method_(nullptr),
222 owned_input_method_(false) {
225 void WindowTreeHost::DestroyCompositor() {
226 compositor_.reset();
229 void WindowTreeHost::DestroyDispatcher() {
230 delete window_;
231 window_ = nullptr;
232 dispatcher_.reset();
234 // TODO(beng): this comment is no longer quite valid since this function
235 // isn't called from WED, and WED isn't a subclass of Window. So it seems
236 // like we could just rely on ~Window now.
237 // Destroy child windows while we're still valid. This is also done by
238 // ~Window, but by that time any calls to virtual methods overriden here (such
239 // as GetRootWindow()) result in Window's implementation. By destroying here
240 // we ensure GetRootWindow() still returns this.
241 //window()->RemoveOrDestroyChildren();
244 void WindowTreeHost::CreateCompositor(
245 gfx::AcceleratedWidget accelerated_widget) {
246 DCHECK(Env::GetInstance());
247 ui::ContextFactory* context_factory = Env::GetInstance()->context_factory();
248 DCHECK(context_factory);
249 compositor_.reset(
250 new ui::Compositor(GetAcceleratedWidget(),
251 context_factory,
252 base::ThreadTaskRunnerHandle::Get()));
253 // TODO(beng): I think this setup should probably all move to a "accelerated
254 // widget available" function.
255 if (!dispatcher()) {
256 window()->Init(ui::LAYER_NOT_DRAWN);
257 window()->set_host(this);
258 window()->SetName("RootWindow");
259 window()->SetEventTargeter(
260 scoped_ptr<ui::EventTargeter>(new WindowTargeter()));
261 prop_.reset(new ui::ViewProp(GetAcceleratedWidget(),
262 kWindowTreeHostForAcceleratedWidget,
263 this));
264 dispatcher_.reset(new WindowEventDispatcher(this));
268 void WindowTreeHost::OnHostMoved(const gfx::Point& new_location) {
269 TRACE_EVENT1("ui", "WindowTreeHost::OnHostMoved",
270 "origin", new_location.ToString());
272 FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_,
273 OnHostMoved(this, new_location));
276 void WindowTreeHost::OnHostResized(const gfx::Size& new_size) {
277 // The compositor should have the same size as the native root window host.
278 // Get the latest scale from display because it might have been changed.
279 compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()),
280 new_size);
282 gfx::Size layer_size = GetBounds().size();
283 // The layer, and the observers should be notified of the
284 // transformed size of the root window.
285 UpdateRootWindowSize(layer_size);
286 FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_, OnHostResized(this));
289 void WindowTreeHost::OnHostCloseRequested() {
290 FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_,
291 OnHostCloseRequested(this));
294 void WindowTreeHost::OnHostActivated() {
295 Env::GetInstance()->NotifyHostActivated(this);
298 void WindowTreeHost::OnHostLostWindowCapture() {
299 Window* capture_window = client::GetCaptureWindow(window());
300 if (capture_window && capture_window->GetRootWindow() == window())
301 capture_window->ReleaseCapture();
304 ui::EventProcessor* WindowTreeHost::GetEventProcessor() {
305 return event_processor();
308 ////////////////////////////////////////////////////////////////////////////////
309 // WindowTreeHost, private:
311 void WindowTreeHost::MoveCursorToInternal(const gfx::Point& root_location,
312 const gfx::Point& host_location) {
313 last_cursor_request_position_in_host_ = host_location;
314 MoveCursorToNative(host_location);
315 client::CursorClient* cursor_client = client::GetCursorClient(window());
316 if (cursor_client) {
317 const gfx::Display& display =
318 gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
319 cursor_client->SetDisplay(display);
321 dispatcher()->OnCursorMovedToRootLocation(root_location);
324 } // namespace aura