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