window_tree_host.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "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" 22 23namespace aura { 24 25float 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(); 30} 31 32class SimpleRootWindowTransformer : public RootWindowTransformer { 33 public: 34 SimpleRootWindowTransformer(const Window* root_window, 35 const gfx::Transform& transform) 36 : root_window_(root_window), 37 transform_(transform) { 38 } 39 40 // RootWindowTransformer overrides: 41 virtual gfx::Transform GetTransform() const OVERRIDE { 42 return transform_; 43 } 44 45 virtual gfx::Transform GetInverseTransform() const OVERRIDE { 46 gfx::Transform invert; 47 if (!transform_.GetInverse(&invert)) 48 return transform_; 49 return invert; 50 } 51 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())); 58 } 59 60 virtual gfx::Insets GetHostInsets() const OVERRIDE { 61 return gfx::Insets(); 62 } 63 64 private: 65 virtual ~SimpleRootWindowTransformer() {} 66 67 const Window* root_window_; 68 const gfx::Transform transform_; 69 70 DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer); 71}; 72 73//////////////////////////////////////////////////////////////////////////////// 74// WindowTreeHost, public: 75 76WindowTreeHost::~WindowTreeHost() { 77 DCHECK(!compositor_) << "compositor must be destroyed before root window"; 78} 79 80void WindowTreeHost::InitHost() { 81 window()->Init(aura::WINDOW_LAYER_NOT_DRAWN); 82 InitCompositor(); 83 UpdateRootWindowSize(GetBounds().size()); 84 Env::GetInstance()->NotifyRootWindowInitialized(delegate_->AsRootWindow()); 85 window()->Show(); 86} 87 88void WindowTreeHost::InitCompositor() { 89 compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), 90 GetBounds().size()); 91 compositor_->SetRootLayer(window()->layer()); 92 transformer_.reset( 93 new SimpleRootWindowTransformer(window(), gfx::Transform())); 94} 95 96aura::Window* WindowTreeHost::window() { 97 return const_cast<Window*>(const_cast<const WindowTreeHost*>(this)->window()); 98} 99 100const aura::Window* WindowTreeHost::window() const { 101 return delegate_->AsRootWindow()->window(); 102} 103 104void 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 110 // size immediately. 111 if (!window()->layer()->GetAnimator()->is_animating()) 112 UpdateRootWindowSize(GetBounds().size()); 113} 114 115gfx::Transform WindowTreeHost::GetRootTransform() const { 116 float scale = ui::GetDeviceScaleFactor(window()->layer()); 117 gfx::Transform transform; 118 transform.Scale(scale, scale); 119 transform *= transformer_->GetTransform(); 120 return transform; 121} 122 123void WindowTreeHost::SetTransform(const gfx::Transform& transform) { 124 scoped_ptr<RootWindowTransformer> transformer( 125 new SimpleRootWindowTransformer(window(), transform)); 126 SetRootWindowTransformer(transformer.Pass()); 127} 128 129gfx::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; 134} 135 136void WindowTreeHost::UpdateRootWindowSize(const gfx::Size& host_size) { 137 window()->SetBounds(transformer_->GetRootWindowBounds(host_size)); 138} 139 140void WindowTreeHost::ConvertPointToNativeScreen(gfx::Point* point) const { 141 ConvertPointToHost(point); 142 gfx::Point location = GetLocationOnNativeScreen(); 143 point->Offset(location.x(), location.y()); 144} 145 146void WindowTreeHost::ConvertPointFromNativeScreen(gfx::Point* point) const { 147 gfx::Point location = GetLocationOnNativeScreen(); 148 point->Offset(-location.x(), -location.y()); 149 ConvertPointFromHost(point); 150} 151 152void WindowTreeHost::ConvertPointToHost(gfx::Point* point) const { 153 gfx::Point3F point_3f(*point); 154 GetRootTransform().TransformPoint(&point_3f); 155 *point = gfx::ToFlooredPoint(point_3f.AsPointF()); 156} 157 158void WindowTreeHost::ConvertPointFromHost(gfx::Point* point) const { 159 gfx::Point3F point_3f(*point); 160 GetInverseRootTransform().TransformPoint(&point_3f); 161 *point = gfx::ToFlooredPoint(point_3f.AsPointF()); 162} 163 164void 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); 169} 170 171void 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. 176 if (!show) { 177 delegate_->AsRootWindow()->DispatchMouseExitAtPoint( 178 delegate_->AsRootWindow()->GetLastMouseLocationInRoot()); 179 } 180 181 OnCursorVisibilityChangedNative(show); 182} 183 184void 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); 188} 189 190void WindowTreeHost::MoveCursorToHostLocation(const gfx::Point& host_location) { 191 gfx::Point root_location(host_location); 192 ConvertPointFromHost(&root_location); 193 MoveCursorToInternal(root_location, host_location); 194} 195 196//////////////////////////////////////////////////////////////////////////////// 197// WindowTreeHost, protected: 198 199WindowTreeHost::WindowTreeHost() 200 : delegate_(NULL), 201 last_cursor_(ui::kCursorNull) { 202} 203 204void WindowTreeHost::DestroyCompositor() { 205 DCHECK(GetAcceleratedWidget()); 206 compositor_.reset(); 207} 208 209void WindowTreeHost::CreateCompositor( 210 gfx::AcceleratedWidget accelerated_widget) { 211 compositor_.reset(new ui::Compositor(GetAcceleratedWidget())); 212 DCHECK(compositor_.get()); 213} 214 215void 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()), 219 new_size); 220 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); 226} 227 228void 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()); 232 if (cursor_client) { 233 const gfx::Display& display = 234 gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window()); 235 cursor_client->SetDisplay(display); 236 } 237 delegate_->OnCursorMovedToRootLocation(root_location); 238} 239 240#if defined(OS_ANDROID) 241// static 242WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) { 243 // This is only hit for tests and ash, right now these aren't an issue so 244 // adding the CHECK. 245 // TODO(sky): decide if we want a factory. 246 CHECK(false); 247 return NULL; 248} 249#endif 250 251} // namespace aura 252