window_tree_host.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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. 4 5#include "ui/aura/window_tree_host.h" 6 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" 26 27namespace aura { 28 29const char kWindowTreeHostForAcceleratedWidget[] = 30 "__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__"; 31 32float 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(); 37} 38 39class 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 87#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 105void WindowTreeHost::InitHost() { 106 InitCompositor(); 107 UpdateRootWindowSize(GetBounds().size()); 108 Env::GetInstance()->NotifyHostInitialized(this); 109 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 120void WindowTreeHost::AddObserver(WindowTreeHostObserver* observer) { 121 observers_.AddObserver(observer); 122} 123 124void WindowTreeHost::RemoveObserver(WindowTreeHostObserver* observer) { 125 observers_.RemoveObserver(observer); 126} 127 128ui::EventProcessor* WindowTreeHost::event_processor() { 129 return dispatcher(); 130} 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); 170 gfx::Point location = GetLocationOnNativeScreen(); 171 point->Offset(location.x(), location.y()); 172} 173 174void WindowTreeHost::ConvertPointFromNativeScreen(gfx::Point* point) const { 175 gfx::Point location = GetLocationOnNativeScreen(); 176 point->Offset(-location.x(), -location.y()); 177 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) { 205 dispatcher()->DispatchMouseExitAtPoint( 206 dispatcher()->GetLastMouseLocationInRoot()); 207 } 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); 222} 223 224//////////////////////////////////////////////////////////////////////////////// 225// WindowTreeHost, protected: 226 227WindowTreeHost::WindowTreeHost() 228 : window_(new Window(NULL)), 229 last_cursor_(ui::kCursorNull) { 230} 231 232void WindowTreeHost::DestroyCompositor() { 233 DCHECK(GetAcceleratedWidget()); 234 compositor_.reset(); 235} 236 237void 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 252void 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. 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 } 269} 270 271void 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) { 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()), 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); 289 FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_, OnHostResized(this)); 290 dispatcher()->OnHostResized(layer_size); 291} 292 293void 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 311void 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 } 320 dispatcher()->OnCursorMovedToRootLocation(root_location); 321} 322 323} // namespace aura 324