| OLD | NEW |
| (Empty) |
| 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 "base/thread_task_runner_handle.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/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 | |
| 27 namespace aura { | |
| 28 | |
| 29 const char kWindowTreeHostForAcceleratedWidget[] = | |
| 30 "__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__"; | |
| 31 | |
| 32 float 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 | |
| 39 //////////////////////////////////////////////////////////////////////////////// | |
| 40 // WindowTreeHost, public: | |
| 41 | |
| 42 WindowTreeHost::~WindowTreeHost() { | |
| 43 DCHECK(!compositor_) << "compositor must be destroyed before root window"; | |
| 44 } | |
| 45 | |
| 46 #if defined(OS_ANDROID) | |
| 47 // static | |
| 48 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) { | |
| 49 // This is only hit for tests and ash, right now these aren't an issue so | |
| 50 // adding the CHECK. | |
| 51 // TODO(sky): decide if we want a factory. | |
| 52 CHECK(false); | |
| 53 return NULL; | |
| 54 } | |
| 55 #endif | |
| 56 | |
| 57 // static | |
| 58 WindowTreeHost* WindowTreeHost::GetForAcceleratedWidget( | |
| 59 gfx::AcceleratedWidget widget) { | |
| 60 return reinterpret_cast<WindowTreeHost*>( | |
| 61 ui::ViewProp::GetValue(widget, kWindowTreeHostForAcceleratedWidget)); | |
| 62 } | |
| 63 | |
| 64 void WindowTreeHost::InitHost() { | |
| 65 InitCompositor(); | |
| 66 UpdateRootWindowSize(GetBounds().size()); | |
| 67 Env::GetInstance()->NotifyHostInitialized(this); | |
| 68 window()->Show(); | |
| 69 } | |
| 70 | |
| 71 void WindowTreeHost::InitCompositor() { | |
| 72 compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), | |
| 73 GetBounds().size()); | |
| 74 compositor_->SetRootLayer(window()->layer()); | |
| 75 } | |
| 76 | |
| 77 void WindowTreeHost::AddObserver(WindowTreeHostObserver* observer) { | |
| 78 observers_.AddObserver(observer); | |
| 79 } | |
| 80 | |
| 81 void WindowTreeHost::RemoveObserver(WindowTreeHostObserver* observer) { | |
| 82 observers_.RemoveObserver(observer); | |
| 83 } | |
| 84 | |
| 85 ui::EventProcessor* WindowTreeHost::event_processor() { | |
| 86 return dispatcher(); | |
| 87 } | |
| 88 | |
| 89 gfx::Transform WindowTreeHost::GetRootTransform() const { | |
| 90 float scale = ui::GetDeviceScaleFactor(window()->layer()); | |
| 91 gfx::Transform transform; | |
| 92 transform.Scale(scale, scale); | |
| 93 transform *= window()->layer()->transform(); | |
| 94 return transform; | |
| 95 } | |
| 96 | |
| 97 void WindowTreeHost::SetRootTransform(const gfx::Transform& transform) { | |
| 98 window()->SetTransform(transform); | |
| 99 UpdateRootWindowSize(GetBounds().size()); | |
| 100 } | |
| 101 | |
| 102 gfx::Transform WindowTreeHost::GetInverseRootTransform() const { | |
| 103 gfx::Transform invert; | |
| 104 gfx::Transform transform = GetRootTransform(); | |
| 105 if (!transform.GetInverse(&invert)) | |
| 106 return transform; | |
| 107 return invert; | |
| 108 } | |
| 109 | |
| 110 void WindowTreeHost::UpdateRootWindowSize(const gfx::Size& host_size) { | |
| 111 gfx::Rect bounds(host_size); | |
| 112 gfx::RectF new_bounds(ui::ConvertRectToDIP(window()->layer(), bounds)); | |
| 113 window()->layer()->transform().TransformRect(&new_bounds); | |
| 114 window()->SetBounds(gfx::Rect(gfx::ToFlooredSize(new_bounds.size()))); | |
| 115 } | |
| 116 | |
| 117 void WindowTreeHost::ConvertPointToNativeScreen(gfx::Point* point) const { | |
| 118 ConvertPointToHost(point); | |
| 119 gfx::Point location = GetLocationOnNativeScreen(); | |
| 120 point->Offset(location.x(), location.y()); | |
| 121 } | |
| 122 | |
| 123 void WindowTreeHost::ConvertPointFromNativeScreen(gfx::Point* point) const { | |
| 124 gfx::Point location = GetLocationOnNativeScreen(); | |
| 125 point->Offset(-location.x(), -location.y()); | |
| 126 ConvertPointFromHost(point); | |
| 127 } | |
| 128 | |
| 129 void WindowTreeHost::ConvertPointToHost(gfx::Point* point) const { | |
| 130 gfx::Point3F point_3f(*point); | |
| 131 GetRootTransform().TransformPoint(&point_3f); | |
| 132 *point = gfx::ToFlooredPoint(point_3f.AsPointF()); | |
| 133 } | |
| 134 | |
| 135 void WindowTreeHost::ConvertPointFromHost(gfx::Point* point) const { | |
| 136 gfx::Point3F point_3f(*point); | |
| 137 GetInverseRootTransform().TransformPoint(&point_3f); | |
| 138 *point = gfx::ToFlooredPoint(point_3f.AsPointF()); | |
| 139 } | |
| 140 | |
| 141 void WindowTreeHost::SetCursor(gfx::NativeCursor cursor) { | |
| 142 last_cursor_ = cursor; | |
| 143 // A lot of code seems to depend on NULL cursors actually showing an arrow, | |
| 144 // so just pass everything along to the host. | |
| 145 SetCursorNative(cursor); | |
| 146 } | |
| 147 | |
| 148 void WindowTreeHost::OnCursorVisibilityChanged(bool show) { | |
| 149 // Clear any existing mouse hover effects when the cursor becomes invisible. | |
| 150 // Note we do not need to dispatch a mouse enter when the cursor becomes | |
| 151 // visible because that can only happen in response to a mouse event, which | |
| 152 // will trigger its own mouse enter. | |
| 153 if (!show) { | |
| 154 ui::EventDispatchDetails details = dispatcher()->DispatchMouseExitAtPoint( | |
| 155 dispatcher()->GetLastMouseLocationInRoot()); | |
| 156 if (details.dispatcher_destroyed) | |
| 157 return; | |
| 158 } | |
| 159 | |
| 160 OnCursorVisibilityChangedNative(show); | |
| 161 } | |
| 162 | |
| 163 void WindowTreeHost::MoveCursorTo(const gfx::Point& location_in_dip) { | |
| 164 gfx::Point host_location(location_in_dip); | |
| 165 ConvertPointToHost(&host_location); | |
| 166 MoveCursorToInternal(location_in_dip, host_location); | |
| 167 } | |
| 168 | |
| 169 void WindowTreeHost::MoveCursorToHostLocation(const gfx::Point& host_location) { | |
| 170 gfx::Point root_location(host_location); | |
| 171 ConvertPointFromHost(&root_location); | |
| 172 MoveCursorToInternal(root_location, host_location); | |
| 173 } | |
| 174 | |
| 175 //////////////////////////////////////////////////////////////////////////////// | |
| 176 // WindowTreeHost, protected: | |
| 177 | |
| 178 WindowTreeHost::WindowTreeHost() | |
| 179 : window_(new Window(NULL)), | |
| 180 last_cursor_(ui::kCursorNull) { | |
| 181 } | |
| 182 | |
| 183 void WindowTreeHost::DestroyCompositor() { | |
| 184 compositor_.reset(); | |
| 185 } | |
| 186 | |
| 187 void WindowTreeHost::DestroyDispatcher() { | |
| 188 delete window_; | |
| 189 window_ = NULL; | |
| 190 dispatcher_.reset(); | |
| 191 | |
| 192 // TODO(beng): this comment is no longer quite valid since this function | |
| 193 // isn't called from WED, and WED isn't a subclass of Window. So it seems | |
| 194 // like we could just rely on ~Window now. | |
| 195 // Destroy child windows while we're still valid. This is also done by | |
| 196 // ~Window, but by that time any calls to virtual methods overriden here (such | |
| 197 // as GetRootWindow()) result in Window's implementation. By destroying here | |
| 198 // we ensure GetRootWindow() still returns this. | |
| 199 //window()->RemoveOrDestroyChildren(); | |
| 200 } | |
| 201 | |
| 202 void WindowTreeHost::CreateCompositor( | |
| 203 gfx::AcceleratedWidget accelerated_widget) { | |
| 204 DCHECK(Env::GetInstance()); | |
| 205 ui::ContextFactory* context_factory = Env::GetInstance()->context_factory(); | |
| 206 DCHECK(context_factory); | |
| 207 compositor_.reset( | |
| 208 new ui::Compositor(GetAcceleratedWidget(), | |
| 209 context_factory, | |
| 210 base::ThreadTaskRunnerHandle::Get())); | |
| 211 // TODO(beng): I think this setup should probably all move to a "accelerated | |
| 212 // widget available" function. | |
| 213 if (!dispatcher()) { | |
| 214 window()->Init(WINDOW_LAYER_NOT_DRAWN); | |
| 215 window()->set_host(this); | |
| 216 window()->SetName("RootWindow"); | |
| 217 window()->SetEventTargeter( | |
| 218 scoped_ptr<ui::EventTargeter>(new WindowTargeter())); | |
| 219 prop_.reset(new ui::ViewProp(GetAcceleratedWidget(), | |
| 220 kWindowTreeHostForAcceleratedWidget, | |
| 221 this)); | |
| 222 dispatcher_.reset(new WindowEventDispatcher(this)); | |
| 223 } | |
| 224 } | |
| 225 | |
| 226 void WindowTreeHost::OnHostMoved(const gfx::Point& new_location) { | |
| 227 TRACE_EVENT1("ui", "WindowTreeHost::OnHostMoved", | |
| 228 "origin", new_location.ToString()); | |
| 229 | |
| 230 FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_, | |
| 231 OnHostMoved(this, new_location)); | |
| 232 } | |
| 233 | |
| 234 void WindowTreeHost::OnHostResized(const gfx::Size& new_size) { | |
| 235 // The compositor should have the same size as the native root window host. | |
| 236 // Get the latest scale from display because it might have been changed. | |
| 237 compositor_->SetScaleAndSize(GetDeviceScaleFactorFromDisplay(window()), | |
| 238 new_size); | |
| 239 | |
| 240 gfx::Size layer_size = GetBounds().size(); | |
| 241 // The layer, and the observers should be notified of the | |
| 242 // transformed size of the root window. | |
| 243 UpdateRootWindowSize(layer_size); | |
| 244 FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_, OnHostResized(this)); | |
| 245 } | |
| 246 | |
| 247 void WindowTreeHost::OnHostCloseRequested() { | |
| 248 FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_, | |
| 249 OnHostCloseRequested(this)); | |
| 250 } | |
| 251 | |
| 252 void WindowTreeHost::OnHostActivated() { | |
| 253 Env::GetInstance()->NotifyHostActivated(this); | |
| 254 } | |
| 255 | |
| 256 void WindowTreeHost::OnHostLostWindowCapture() { | |
| 257 Window* capture_window = client::GetCaptureWindow(window()); | |
| 258 if (capture_window && capture_window->GetRootWindow() == window()) | |
| 259 capture_window->ReleaseCapture(); | |
| 260 } | |
| 261 | |
| 262 //////////////////////////////////////////////////////////////////////////////// | |
| 263 // WindowTreeHost, private: | |
| 264 | |
| 265 void WindowTreeHost::MoveCursorToInternal(const gfx::Point& root_location, | |
| 266 const gfx::Point& host_location) { | |
| 267 last_cursor_request_position_in_host_ = host_location; | |
| 268 MoveCursorToNative(host_location); | |
| 269 client::CursorClient* cursor_client = client::GetCursorClient(window()); | |
| 270 if (cursor_client) { | |
| 271 const gfx::Display& display = | |
| 272 gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window()); | |
| 273 cursor_client->SetDisplay(display); | |
| 274 } | |
| 275 dispatcher()->OnCursorMovedToRootLocation(root_location); | |
| 276 } | |
| 277 | |
| 278 } // namespace aura | |
| OLD | NEW |