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 |