| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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 "services/window_manager/window_manager_root.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/memory/scoped_ptr.h" | |
| 10 #include "base/memory/scoped_vector.h" | |
| 11 #include "base/message_loop/message_loop.h" | |
| 12 #include "base/stl_util.h" | |
| 13 #include "mojo/converters/geometry/geometry_type_converters.h" | |
| 14 #include "mojo/converters/input_events/input_events_type_converters.h" | |
| 15 #include "mojo/public/cpp/application/application_connection.h" | |
| 16 #include "mojo/public/cpp/application/application_impl.h" | |
| 17 #include "mojo/public/interfaces/application/shell.mojom.h" | |
| 18 #include "mojo/services/view_manager/cpp/view.h" | |
| 19 #include "mojo/services/view_manager/cpp/view_manager.h" | |
| 20 #include "services/window_manager/capture_controller.h" | |
| 21 #include "services/window_manager/focus_controller.h" | |
| 22 #include "services/window_manager/focus_rules.h" | |
| 23 #include "services/window_manager/hit_test.h" | |
| 24 #include "services/window_manager/view_event_dispatcher.h" | |
| 25 #include "services/window_manager/view_target.h" | |
| 26 #include "services/window_manager/view_targeter.h" | |
| 27 #include "services/window_manager/window_manager_delegate.h" | |
| 28 | |
| 29 using mojo::ApplicationConnection; | |
| 30 using mojo::Id; | |
| 31 using mojo::ServiceProvider; | |
| 32 using mojo::View; | |
| 33 using mojo::WindowManager; | |
| 34 | |
| 35 namespace window_manager { | |
| 36 | |
| 37 namespace { | |
| 38 | |
| 39 Id GetIdForView(View* view) { | |
| 40 return view ? view->id() : 0; | |
| 41 } | |
| 42 | |
| 43 } // namespace | |
| 44 | |
| 45 // Used for calls to Embed() that occur before we've connected to the | |
| 46 // ViewManager. | |
| 47 struct WindowManagerRoot::PendingEmbed { | |
| 48 mojo::String url; | |
| 49 mojo::InterfaceRequest<ServiceProvider> services; | |
| 50 mojo::ServiceProviderPtr exposed_services; | |
| 51 }; | |
| 52 | |
| 53 //////////////////////////////////////////////////////////////////////////////// | |
| 54 // WindowManagerRoot, public: | |
| 55 | |
| 56 WindowManagerRoot::WindowManagerRoot( | |
| 57 mojo::ApplicationImpl* application_impl, | |
| 58 mojo::ApplicationConnection* connection, | |
| 59 WindowManagerControllerFactory* controller_factory, | |
| 60 mojo::InterfaceRequest<mojo::WindowManager> request) | |
| 61 : application_impl_(application_impl), | |
| 62 connection_(connection), | |
| 63 root_(nullptr) { | |
| 64 window_manager_controller_ = | |
| 65 controller_factory->CreateWindowManagerController(connection, this); | |
| 66 LaunchViewManager(application_impl_); | |
| 67 | |
| 68 // We own WindowManagerImpl. When binding to the request, WindowManagerImpl | |
| 69 // registers an error callback to WindowManagerRoot::RemoveConnectedService, | |
| 70 // which will delete it. | |
| 71 AddConnectedService(make_scoped_ptr( | |
| 72 new WindowManagerImpl(this, request.PassMessagePipe(), false))); | |
| 73 } | |
| 74 | |
| 75 WindowManagerRoot::~WindowManagerRoot() { | |
| 76 // TODO(msw|sky): Should this destructor explicitly delete the ViewManager? | |
| 77 mojo::ViewManager* cached_view_manager = view_manager(); | |
| 78 for (RegisteredViewIdSet::const_iterator it = registered_view_id_set_.begin(); | |
| 79 cached_view_manager && it != registered_view_id_set_.end(); ++it) { | |
| 80 View* view = cached_view_manager->GetViewById(*it); | |
| 81 if (view && view == root_) | |
| 82 root_ = nullptr; | |
| 83 if (view) | |
| 84 view->RemoveObserver(this); | |
| 85 } | |
| 86 registered_view_id_set_.clear(); | |
| 87 DCHECK(!root_); | |
| 88 | |
| 89 // connected_services_ destructor will ensure we don't leak any | |
| 90 // WindowManagerImpl objects and close all connections. | |
| 91 } | |
| 92 | |
| 93 void WindowManagerRoot::AddConnectedService( | |
| 94 scoped_ptr<WindowManagerImpl> connection) { | |
| 95 connected_services_.push_back(connection.Pass()); | |
| 96 } | |
| 97 | |
| 98 void WindowManagerRoot::RemoveConnectedService(WindowManagerImpl* connection) { | |
| 99 ConnectedServices::iterator position = std::find( | |
| 100 connected_services_.begin(), connected_services_.end(), connection); | |
| 101 DCHECK(position != connected_services_.end()); | |
| 102 | |
| 103 connected_services_.erase(position); | |
| 104 | |
| 105 // Having no inbound connection is not a guarantee we are no longer used: we | |
| 106 // can be processing an embed request (App 1 asked for a WindowManager, calls | |
| 107 // Embed then immediately closes the connection, EmbeddedApp is not yet | |
| 108 // started). | |
| 109 } | |
| 110 | |
| 111 bool WindowManagerRoot::SetCapture(Id view_id) { | |
| 112 View* view = view_manager()->GetViewById(view_id); | |
| 113 return view && SetCaptureImpl(view); | |
| 114 } | |
| 115 | |
| 116 bool WindowManagerRoot::FocusWindow(Id view_id) { | |
| 117 View* view = view_manager()->GetViewById(view_id); | |
| 118 return view && FocusWindowImpl(view); | |
| 119 } | |
| 120 | |
| 121 bool WindowManagerRoot::ActivateWindow(Id view_id) { | |
| 122 View* view = view_manager()->GetViewById(view_id); | |
| 123 return view && ActivateWindowImpl(view); | |
| 124 } | |
| 125 | |
| 126 bool WindowManagerRoot::IsReady() const { | |
| 127 return root_; | |
| 128 } | |
| 129 | |
| 130 void WindowManagerRoot::InitFocus(scoped_ptr<FocusRules> rules) { | |
| 131 DCHECK(root_); | |
| 132 | |
| 133 focus_controller_.reset(new FocusController(rules.Pass())); | |
| 134 focus_controller_->AddObserver(this); | |
| 135 SetFocusController(root_, focus_controller_.get()); | |
| 136 | |
| 137 capture_controller_.reset(new CaptureController); | |
| 138 capture_controller_->AddObserver(this); | |
| 139 SetCaptureController(root_, capture_controller_.get()); | |
| 140 } | |
| 141 | |
| 142 void WindowManagerRoot::Embed( | |
| 143 const mojo::String& url, | |
| 144 mojo::InterfaceRequest<mojo::ServiceProvider> services, | |
| 145 mojo::ServiceProviderPtr exposed_services) { | |
| 146 if (view_manager()) { | |
| 147 window_manager_controller_->Embed(url, services.Pass(), | |
| 148 exposed_services.Pass()); | |
| 149 return; | |
| 150 } | |
| 151 scoped_ptr<PendingEmbed> pending_embed(new PendingEmbed); | |
| 152 pending_embed->url = url; | |
| 153 pending_embed->services = services.Pass(); | |
| 154 pending_embed->exposed_services = exposed_services.Pass(); | |
| 155 pending_embeds_.push_back(pending_embed.release()); | |
| 156 } | |
| 157 | |
| 158 //////////////////////////////////////////////////////////////////////////////// | |
| 159 // WindowManagerRoot, ViewManagerDelegate implementation: | |
| 160 | |
| 161 void WindowManagerRoot::OnEmbed( | |
| 162 View* root, | |
| 163 mojo::InterfaceRequest<mojo::ServiceProvider> services, | |
| 164 mojo::ServiceProviderPtr exposed_services) { | |
| 165 DCHECK(!root_); | |
| 166 root_ = root; | |
| 167 | |
| 168 view_event_dispatcher_.reset(new ViewEventDispatcher); | |
| 169 | |
| 170 RegisterSubtree(root_); | |
| 171 | |
| 172 if (window_manager_controller_.get()) { | |
| 173 window_manager_controller_->OnEmbed(root, services.Pass(), | |
| 174 exposed_services.Pass()); | |
| 175 } | |
| 176 | |
| 177 for (PendingEmbed* pending_embed : pending_embeds_) { | |
| 178 Embed(pending_embed->url, pending_embed->services.Pass(), | |
| 179 pending_embed->exposed_services.Pass()); | |
| 180 } | |
| 181 pending_embeds_.clear(); | |
| 182 } | |
| 183 | |
| 184 void WindowManagerRoot::OnViewManagerDisconnected( | |
| 185 mojo::ViewManager* view_manager) { | |
| 186 if (window_manager_controller_.get()) | |
| 187 window_manager_controller_->OnViewManagerDisconnected(view_manager); | |
| 188 delete this; | |
| 189 } | |
| 190 | |
| 191 bool WindowManagerRoot::OnPerformAction(mojo::View* view, | |
| 192 const std::string& action) { | |
| 193 if (!view) | |
| 194 return false; | |
| 195 if (action == "capture") | |
| 196 return SetCaptureImpl(view); | |
| 197 if (action == "focus") | |
| 198 return FocusWindowImpl(view); | |
| 199 else if (action == "activate") | |
| 200 return ActivateWindowImpl(view); | |
| 201 return false; | |
| 202 } | |
| 203 | |
| 204 //////////////////////////////////////////////////////////////////////////////// | |
| 205 // WindowManagerRoot, ViewObserver implementation: | |
| 206 | |
| 207 void WindowManagerRoot::OnTreeChanged( | |
| 208 const ViewObserver::TreeChangeParams& params) { | |
| 209 if (params.receiver != root_) | |
| 210 return; | |
| 211 DCHECK(params.old_parent || params.new_parent); | |
| 212 if (!params.target) | |
| 213 return; | |
| 214 | |
| 215 if (params.new_parent) { | |
| 216 if (registered_view_id_set_.find(params.target->id()) == | |
| 217 registered_view_id_set_.end()) { | |
| 218 RegisteredViewIdSet::const_iterator it = | |
| 219 registered_view_id_set_.find(params.new_parent->id()); | |
| 220 DCHECK(it != registered_view_id_set_.end()); | |
| 221 RegisterSubtree(params.target); | |
| 222 } | |
| 223 } else if (params.old_parent) { | |
| 224 UnregisterSubtree(params.target); | |
| 225 } | |
| 226 } | |
| 227 | |
| 228 void WindowManagerRoot::OnViewDestroying(View* view) { | |
| 229 Unregister(view); | |
| 230 if (view == root_) { | |
| 231 root_ = nullptr; | |
| 232 if (focus_controller_) | |
| 233 focus_controller_->RemoveObserver(this); | |
| 234 if (capture_controller_) | |
| 235 capture_controller_->RemoveObserver(this); | |
| 236 } | |
| 237 } | |
| 238 | |
| 239 //////////////////////////////////////////////////////////////////////////////// | |
| 240 // WindowManagerRoot, ui::EventHandler implementation: | |
| 241 | |
| 242 void WindowManagerRoot::OnEvent(ui::Event* event) { | |
| 243 if (!window_manager_client_) | |
| 244 return; | |
| 245 | |
| 246 View* view = static_cast<ViewTarget*>(event->target())->view(); | |
| 247 if (!view) | |
| 248 return; | |
| 249 | |
| 250 if (event->IsKeyEvent()) { | |
| 251 const ui::KeyEvent* key_event = static_cast<const ui::KeyEvent*>(event); | |
| 252 if (key_event->type() == ui::ET_KEY_PRESSED) { | |
| 253 ui::Accelerator accelerator = ConvertEventToAccelerator(key_event); | |
| 254 if (accelerator_manager_.Process(accelerator, view)) | |
| 255 return; | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 if (focus_controller_) | |
| 260 focus_controller_->OnEvent(event); | |
| 261 | |
| 262 window_manager_client_->DispatchInputEventToView(view->id(), | |
| 263 mojo::Event::From(*event)); | |
| 264 } | |
| 265 | |
| 266 //////////////////////////////////////////////////////////////////////////////// | |
| 267 // WindowManagerRoot, mojo::FocusControllerObserver implementation: | |
| 268 | |
| 269 void WindowManagerRoot::OnFocused(View* gained_focus) { | |
| 270 for (ConnectedServices::const_iterator it = connected_services_.begin(); | |
| 271 it != connected_services_.end(); ++it) { | |
| 272 (*it)->NotifyViewFocused(GetIdForView(gained_focus)); | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 void WindowManagerRoot::OnActivated(View* gained_active) { | |
| 277 for (ConnectedServices::const_iterator it = connected_services_.begin(); | |
| 278 it != connected_services_.end(); ++it) { | |
| 279 (*it)->NotifyWindowActivated(GetIdForView(gained_active)); | |
| 280 } | |
| 281 if (gained_active) | |
| 282 gained_active->MoveToFront(); | |
| 283 } | |
| 284 | |
| 285 //////////////////////////////////////////////////////////////////////////////// | |
| 286 // WindowManagerRoot, mojo::CaptureControllerObserver implementation: | |
| 287 | |
| 288 void WindowManagerRoot::OnCaptureChanged(View* gained_capture) { | |
| 289 for (ConnectedServices::const_iterator it = connected_services_.begin(); | |
| 290 it != connected_services_.end(); ++it) { | |
| 291 (*it)->NotifyCaptureChanged(GetIdForView(gained_capture)); | |
| 292 } | |
| 293 if (gained_capture) | |
| 294 gained_capture->MoveToFront(); | |
| 295 } | |
| 296 | |
| 297 //////////////////////////////////////////////////////////////////////////////// | |
| 298 // WindowManagerRoot, private: | |
| 299 | |
| 300 bool WindowManagerRoot::SetCaptureImpl(View* view) { | |
| 301 CHECK(view); | |
| 302 capture_controller_->SetCapture(view); | |
| 303 return capture_controller_->GetCapture() == view; | |
| 304 } | |
| 305 | |
| 306 bool WindowManagerRoot::FocusWindowImpl(View* view) { | |
| 307 CHECK(view); | |
| 308 focus_controller_->FocusView(view); | |
| 309 return focus_controller_->GetFocusedView() == view; | |
| 310 } | |
| 311 | |
| 312 bool WindowManagerRoot::ActivateWindowImpl(View* view) { | |
| 313 CHECK(view); | |
| 314 focus_controller_->ActivateView(view); | |
| 315 return focus_controller_->GetActiveView() == view; | |
| 316 } | |
| 317 | |
| 318 void WindowManagerRoot::RegisterSubtree(View* view) { | |
| 319 view->AddObserver(this); | |
| 320 DCHECK(registered_view_id_set_.find(view->id()) == | |
| 321 registered_view_id_set_.end()); | |
| 322 // All events pass through the root during dispatch, so we only need a handler | |
| 323 // installed there. | |
| 324 if (view == root_) { | |
| 325 ViewTarget* target = ViewTarget::TargetFromView(view); | |
| 326 target->SetEventTargeter(scoped_ptr<ViewTargeter>(new ViewTargeter())); | |
| 327 target->AddPreTargetHandler(this); | |
| 328 view_event_dispatcher_->SetRootViewTarget(target); | |
| 329 } | |
| 330 registered_view_id_set_.insert(view->id()); | |
| 331 View::Children::const_iterator it = view->children().begin(); | |
| 332 for (; it != view->children().end(); ++it) | |
| 333 RegisterSubtree(*it); | |
| 334 } | |
| 335 | |
| 336 void WindowManagerRoot::UnregisterSubtree(View* view) { | |
| 337 for (View* child : view->children()) | |
| 338 UnregisterSubtree(child); | |
| 339 Unregister(view); | |
| 340 } | |
| 341 | |
| 342 void WindowManagerRoot::Unregister(View* view) { | |
| 343 RegisteredViewIdSet::iterator it = registered_view_id_set_.find(view->id()); | |
| 344 if (it == registered_view_id_set_.end()) { | |
| 345 // Because we unregister in OnViewDestroying() we can still get a subsequent | |
| 346 // OnTreeChanged for the same view. Ignore this one. | |
| 347 return; | |
| 348 } | |
| 349 view->RemoveObserver(this); | |
| 350 DCHECK(it != registered_view_id_set_.end()); | |
| 351 registered_view_id_set_.erase(it); | |
| 352 } | |
| 353 | |
| 354 void WindowManagerRoot::DispatchInputEventToView(View* view, | |
| 355 mojo::EventPtr event) { | |
| 356 window_manager_client_->DispatchInputEventToView(view->id(), event.Pass()); | |
| 357 } | |
| 358 | |
| 359 void WindowManagerRoot::SetViewportSize(const gfx::Size& size) { | |
| 360 window_manager_client_->SetViewportSize(mojo::Size::From(size)); | |
| 361 } | |
| 362 | |
| 363 void WindowManagerRoot::LaunchViewManager(mojo::ApplicationImpl* app) { | |
| 364 // TODO(sky): figure out logic if this connection goes away. | |
| 365 view_manager_client_factory_.reset( | |
| 366 new mojo::ViewManagerClientFactory(application_impl_->shell(), this)); | |
| 367 | |
| 368 ApplicationConnection* view_manager_app = | |
| 369 app->ConnectToApplication("mojo:view_manager"); | |
| 370 view_manager_app->ConnectToService(&view_manager_service_); | |
| 371 | |
| 372 view_manager_app->AddService<WindowManagerInternal>(this); | |
| 373 view_manager_app->AddService<mojo::NativeViewportEventDispatcher>(this); | |
| 374 | |
| 375 view_manager_app->ConnectToService(&window_manager_client_); | |
| 376 } | |
| 377 | |
| 378 void WindowManagerRoot::Create( | |
| 379 ApplicationConnection* connection, | |
| 380 mojo::InterfaceRequest<WindowManagerInternal> request) { | |
| 381 if (wm_internal_binding_.get()) { | |
| 382 VLOG(1) | |
| 383 << "WindowManager allows only one WindowManagerInternal connection."; | |
| 384 return; | |
| 385 } | |
| 386 wm_internal_binding_.reset( | |
| 387 new mojo::Binding<WindowManagerInternal>(this, request.Pass())); | |
| 388 } | |
| 389 | |
| 390 void WindowManagerRoot::Create( | |
| 391 mojo::ApplicationConnection* connection, | |
| 392 mojo::InterfaceRequest<mojo::NativeViewportEventDispatcher> request) { | |
| 393 new NativeViewportEventDispatcherImpl(this, request.Pass()); | |
| 394 } | |
| 395 | |
| 396 void WindowManagerRoot::CreateWindowManagerForViewManagerClient( | |
| 397 uint16_t connection_id, | |
| 398 mojo::ScopedMessagePipeHandle window_manager_pipe) { | |
| 399 // TODO(sky): pass in |connection_id| for validation. | |
| 400 AddConnectedService(make_scoped_ptr( | |
| 401 new WindowManagerImpl(this, window_manager_pipe.Pass(), true))); | |
| 402 } | |
| 403 | |
| 404 void WindowManagerRoot::SetViewManagerClient( | |
| 405 mojo::ScopedMessagePipeHandle view_manager_client_request) { | |
| 406 view_manager_client_.reset( | |
| 407 mojo::ViewManagerClientFactory::WeakBindViewManagerToPipe( | |
| 408 mojo::MakeRequest<mojo::ViewManagerClient>( | |
| 409 view_manager_client_request.Pass()), | |
| 410 view_manager_service_.Pass(), application_impl_->shell(), this)); | |
| 411 } | |
| 412 | |
| 413 } // namespace window_manager | |
| OLD | NEW |