Update V8 to version 4.6.52.
[chromium-blink-merge.git] / components / view_manager / connection_manager.cc
blobce8d32bab9db183345300b588eb29bd6814dc9e5
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.
5 #include "components/view_manager/connection_manager.h"
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "components/view_manager/client_connection.h"
10 #include "components/view_manager/connection_manager_delegate.h"
11 #include "components/view_manager/focus_controller.h"
12 #include "components/view_manager/server_view.h"
13 #include "components/view_manager/view_coordinate_conversions.h"
14 #include "components/view_manager/view_manager_root_connection.h"
15 #include "components/view_manager/view_manager_service_impl.h"
16 #include "mojo/application/public/cpp/application_connection.h"
17 #include "mojo/application/public/interfaces/service_provider.mojom.h"
18 #include "mojo/converters/geometry/geometry_type_converters.h"
19 #include "mojo/converters/input_events/input_events_type_converters.h"
21 using mojo::ConnectionSpecificId;
23 namespace view_manager {
24 namespace {
26 // Creates a copy of |view|. The copied view has |delegate| as its delegate.
27 // This does not recurse.
28 ServerView* CloneView(const ServerView* view, ServerViewDelegate* delegate) {
29 ServerView* clone = new ServerView(delegate, ClonedViewId());
30 clone->SetBounds(view->bounds());
31 clone->SetSurfaceId(view->surface_id());
32 clone->SetOpacity(view->opacity());
33 return clone;
36 // Creates copies of all the visible children of |parent|. Newly cloned views
37 // are added to |cloned_parent| and have |delegate| as their delegate. The
38 // stacking order of the cloned views is preseved.
39 void CloneViewTree(const ServerView* parent,
40 ServerView* cloned_parent,
41 ServerViewDelegate* delegate) {
42 DCHECK(parent->visible());
43 for (const ServerView* to_clone : parent->GetChildren()) {
44 if (to_clone->visible()) {
45 ServerView* cloned = CloneView(to_clone, delegate);
46 cloned_parent->Add(cloned);
47 CloneViewTree(to_clone, cloned, delegate);
52 // Recurses through all the children of |view| moving any cloned views to
53 // |new_parent| stacked above |stack_above|. |stack_above| is updated as views
54 // are moved.
55 void ReparentClonedViews(ServerView* new_parent,
56 ServerView** stack_above,
57 ServerView* view) {
58 if (view->id() == ClonedViewId()) {
59 const gfx::Rect new_bounds(ConvertRectBetweenViews(
60 view, new_parent, gfx::Rect(view->bounds().size())));
61 new_parent->Add(view);
62 new_parent->Reorder(view, *stack_above, mojo::ORDER_DIRECTION_ABOVE);
63 view->SetBounds(new_bounds);
64 *stack_above = view;
65 return;
68 for (ServerView* child : view->GetChildren())
69 ReparentClonedViews(new_parent, stack_above, child);
72 // Deletes |view| and all its descendants.
73 void DeleteViewTree(ServerView* view) {
74 for (ServerView* child : view->GetChildren())
75 DeleteViewTree(child);
77 delete view;
80 // TODO(sky): nuke, proof of concept.
81 bool DecrementAnimatingViewsOpacity(ServerView* view) {
82 if (view->id() == ClonedViewId()) {
83 const float new_opacity = view->opacity() - .05f;
84 if (new_opacity <= 0)
85 DeleteViewTree(view);
86 else
87 view->SetOpacity(new_opacity);
88 return true;
90 bool ret_value = false;
91 for (ServerView* child : view->GetChildren()) {
92 if (DecrementAnimatingViewsOpacity(child))
93 ret_value = true;
95 return ret_value;
98 } // namespace
100 ConnectionManager::ScopedChange::ScopedChange(
101 ViewManagerServiceImpl* connection,
102 ConnectionManager* connection_manager,
103 bool is_delete_view)
104 : connection_manager_(connection_manager),
105 connection_id_(connection->id()),
106 is_delete_view_(is_delete_view) {
107 connection_manager_->PrepareForChange(this);
110 ConnectionManager::ScopedChange::~ScopedChange() {
111 connection_manager_->FinishChange();
114 ConnectionManager::ConnectionManager(ConnectionManagerDelegate* delegate)
115 : delegate_(delegate),
116 next_connection_id_(1),
117 next_root_id_(0),
118 event_dispatcher_(this),
119 current_change_(nullptr),
120 in_destructor_(false),
121 animation_runner_(base::TimeTicks::Now()),
122 focus_controller_(new FocusController(this)) {
125 ConnectionManager::~ConnectionManager() {
126 in_destructor_ = true;
128 // Deleting views will attempt to advance focus. When we're being destroyed
129 // that is not necessary. Additionally |focus_controller_| needs to be
130 // destroyed before |root_|.
131 focus_controller_.reset();
133 // Copy the RootConnectionMap because it will be mutated as the connections
134 // are closed.
135 RootConnectionMap root_connection_map(root_connection_map_);
136 for (auto& pair : root_connection_map)
137 pair.second->CloseConnection();
139 STLDeleteValues(&connection_map_);
140 // All the connections should have been destroyed.
141 DCHECK(root_connection_map_.empty());
142 DCHECK(connection_map_.empty());
145 void ConnectionManager::AddRoot(
146 ViewManagerRootConnection* root_connection) {
147 DCHECK_EQ(0u, root_connection_map_.count(
148 root_connection->view_manager_root()));
149 root_connection_map_[root_connection->view_manager_root()] = root_connection;
152 ServerView* ConnectionManager::CreateServerView(const ViewId& id) {
153 ServerView* view = new ServerView(this, id);
154 view->AddObserver(this);
155 return view;
158 ConnectionSpecificId ConnectionManager::GetAndAdvanceNextConnectionId() {
159 const ConnectionSpecificId id = next_connection_id_++;
160 DCHECK_LT(id, next_connection_id_);
161 return id;
164 uint16_t ConnectionManager::GetAndAdvanceNextRootId() {
165 const uint16_t id = next_root_id_++;
166 DCHECK_LT(id, next_root_id_);
167 return id;
170 void ConnectionManager::OnConnectionError(ClientConnection* connection) {
171 // This will be null if the root has been destroyed.
172 const ViewId* view_id = connection->service()->root();
173 ServerView* view =
174 view_id ? GetView(*connection->service()->root()) : nullptr;
175 // If the ViewManagerService root is a viewport root, then we'll wait until
176 // the root connection goes away to cleanup.
177 if (view && (GetRootView(view) == view))
178 return;
180 scoped_ptr<ClientConnection> connection_owner(connection);
182 connection_map_.erase(connection->service()->id());
184 // TODO(sky): I may want to advance focus differently if focus is in
185 // |connection|.
187 // Notify remaining connections so that they can cleanup.
188 for (auto& pair : connection_map_) {
189 pair.second->service()->OnWillDestroyViewManagerServiceImpl(
190 connection->service());
194 void ConnectionManager::OnRootConnectionClosed(
195 ViewManagerRootConnection* connection) {
196 auto it = root_connection_map_.find(connection->view_manager_root());
197 DCHECK(it != root_connection_map_.end());
199 // Clear focus if the focused view is in this viewport.
200 if (GetRootView(GetFocusedView()) == it->first->root_view())
201 SetFocusedView(nullptr);
203 // Get the ClientConnection by ViewManagerServiceImpl ID.
204 ConnectionMap::iterator service_connection_it =
205 connection_map_.find(it->first->GetViewManagerService()->id());
206 DCHECK(service_connection_it != connection_map_.end());
208 // Tear down the associated ViewManagerService connection.
209 // TODO(fsamuel): I don't think this is quite right, we should tear down all
210 // connections within the root's viewport. We should probably employ an
211 // observer pattern to do this. Each ViewManagerServiceImpl should track its
212 // parent's lifetime.
213 root_connection_map_.erase(it);
214 OnConnectionError(service_connection_it->second);
216 // If we have no more roots left, let the app know so it can terminate.
217 if (!root_connection_map_.size())
218 delegate_->OnNoMoreRootConnections();
221 void ConnectionManager::EmbedAtView(mojo::ConnectionSpecificId creator_id,
222 const ViewId& view_id,
223 mojo::URLRequestPtr request) {
224 mojo::ViewManagerServicePtr service_ptr;
225 ClientConnection* client_connection =
226 delegate_->CreateClientConnectionForEmbedAtView(
227 this, GetProxy(&service_ptr), creator_id, request.Pass(), view_id);
228 AddConnection(client_connection);
229 client_connection->service()->Init(client_connection->client(),
230 service_ptr.Pass());
231 OnConnectionMessagedClient(client_connection->service()->id());
234 ViewManagerServiceImpl* ConnectionManager::EmbedAtView(
235 mojo::ConnectionSpecificId creator_id,
236 const ViewId& view_id,
237 mojo::ViewManagerClientPtr client) {
238 mojo::ViewManagerServicePtr service_ptr;
239 ClientConnection* client_connection =
240 delegate_->CreateClientConnectionForEmbedAtView(
241 this, GetProxy(&service_ptr), creator_id, view_id, client.Pass());
242 AddConnection(client_connection);
243 client_connection->service()->Init(client_connection->client(),
244 service_ptr.Pass());
245 OnConnectionMessagedClient(client_connection->service()->id());
247 return client_connection->service();
250 void ConnectionManager::OnAccelerator(ServerView* root, mojo::EventPtr event) {
251 for (auto& pair : root_connection_map_) {
252 if (root == pair.first->root_view()) {
253 pair.first->client()->OnAccelerator(event.Pass());
254 return;
259 ViewManagerServiceImpl* ConnectionManager::GetConnection(
260 ConnectionSpecificId connection_id) {
261 ConnectionMap::iterator i = connection_map_.find(connection_id);
262 return i == connection_map_.end() ? nullptr : i->second->service();
265 ServerView* ConnectionManager::GetView(const ViewId& id) {
266 for (auto& pair : root_connection_map_) {
267 if (pair.first->root_view()->id() == id)
268 return pair.first->root_view();
270 ViewManagerServiceImpl* service = GetConnection(id.connection_id);
271 return service ? service->GetView(id) : nullptr;
274 void ConnectionManager::SetFocusedView(ServerView* view) {
275 if (!focus_controller_)
276 return;
277 ServerView* old_focused = GetFocusedView();
278 if (old_focused == view)
279 return;
280 focus_controller_->SetFocusedView(view);
281 OnFocusChanged(old_focused, view);
284 ServerView* ConnectionManager::GetFocusedView() {
285 if (!focus_controller_)
286 return nullptr;
287 return focus_controller_->GetFocusedView();
290 bool ConnectionManager::IsViewAttachedToRoot(const ServerView* view) const {
291 for (auto& pair : root_connection_map_) {
292 if (pair.first->IsViewAttachedToRoot(view))
293 return true;
295 return false;
298 void ConnectionManager::SchedulePaint(const ServerView* view,
299 const gfx::Rect& bounds) {
300 for (auto& pair : root_connection_map_) {
301 if (pair.first->SchedulePaintIfInViewport(view, bounds))
302 return;
306 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
307 if (current_change_)
308 current_change_->MarkConnectionAsMessaged(id);
311 bool ConnectionManager::DidConnectionMessageClient(
312 ConnectionSpecificId id) const {
313 return current_change_ && current_change_->DidMessageConnection(id);
316 mojo::ViewportMetricsPtr ConnectionManager::GetViewportMetricsForView(
317 const ServerView* view) {
318 ViewManagerRootImpl* view_manager_root = GetViewManagerRootByView(view);
319 if (view_manager_root)
320 return view_manager_root->GetViewportMetrics().Clone();
322 if (!root_connection_map_.empty())
323 return root_connection_map_.begin()->first->GetViewportMetrics().Clone();
325 mojo::ViewportMetricsPtr metrics = mojo::ViewportMetrics::New();
326 metrics->size_in_pixels = mojo::Size::New();
327 return metrics.Pass();
330 const ViewManagerServiceImpl* ConnectionManager::GetConnectionWithRoot(
331 const ViewId& id) const {
332 for (auto& pair : connection_map_) {
333 if (pair.second->service()->IsRoot(id))
334 return pair.second->service();
336 return nullptr;
339 ViewManagerServiceImpl* ConnectionManager::GetEmbedRoot(
340 ViewManagerServiceImpl* service) {
341 while (service) {
342 const ViewId* root_id = service->root();
343 if (!root_id || root_id->connection_id == service->id())
344 return nullptr;
346 ViewManagerServiceImpl* parent_service =
347 GetConnection(root_id->connection_id);
348 service = parent_service;
349 if (service && service->is_embed_root())
350 return service;
352 return nullptr;
355 bool ConnectionManager::CloneAndAnimate(const ViewId& view_id) {
356 ServerView* view = GetView(view_id);
357 if (!view || !view->IsDrawn() || (view->GetRoot() == view))
358 return false;
359 if (!animation_timer_.IsRunning()) {
360 animation_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(100),
361 this, &ConnectionManager::DoAnimation);
363 ServerView* clone = CloneView(view, this);
364 CloneViewTree(view, clone, this);
365 view->parent()->Add(clone);
366 view->parent()->Reorder(clone, view, mojo::ORDER_DIRECTION_ABOVE);
367 return true;
370 void ConnectionManager::DispatchInputEventToView(const ServerView* view,
371 mojo::EventPtr event) {
372 // If the view is an embed root, forward to the embedded view, not the owner.
373 ViewManagerServiceImpl* connection = GetConnectionWithRoot(view->id());
374 if (!connection)
375 connection = GetConnection(view->id().connection_id);
376 CHECK(connection);
377 connection->client()->OnViewInputEvent(ViewIdToTransportId(view->id()),
378 event.Pass(),
379 base::Bind(&base::DoNothing));
382 void ConnectionManager::OnEvent(ViewManagerRootImpl* root,
383 mojo::EventPtr event) {
384 event_dispatcher_.OnEvent(root->root_view(), event.Pass());
387 void ConnectionManager::AddAccelerator(ViewManagerRootImpl* root,
388 mojo::KeyboardCode keyboard_code,
389 mojo::EventFlags flags) {
390 event_dispatcher_.AddAccelerator(keyboard_code, flags);
393 void ConnectionManager::RemoveAccelerator(ViewManagerRootImpl* root,
394 mojo::KeyboardCode keyboard_code,
395 mojo::EventFlags flags) {
396 event_dispatcher_.RemoveAccelerator(keyboard_code, flags);
399 void ConnectionManager::SetImeVisibility(ServerView* view, bool visible) {
400 // Do not need to show or hide IME for unfocused view.
401 if (focus_controller_->GetFocusedView() != view)
402 return;
404 ViewManagerRootImpl* view_manager_root = GetViewManagerRootByView(view);
405 view_manager_root->SetImeVisibility(visible);
408 void ConnectionManager::ProcessViewBoundsChanged(const ServerView* view,
409 const gfx::Rect& old_bounds,
410 const gfx::Rect& new_bounds) {
411 for (auto& pair : connection_map_) {
412 pair.second->service()->ProcessViewBoundsChanged(
413 view, old_bounds, new_bounds, IsChangeSource(pair.first));
417 void ConnectionManager::ProcessWillChangeViewHierarchy(
418 const ServerView* view,
419 const ServerView* new_parent,
420 const ServerView* old_parent) {
421 for (auto& pair : connection_map_) {
422 pair.second->service()->ProcessWillChangeViewHierarchy(
423 view, new_parent, old_parent, IsChangeSource(pair.first));
427 void ConnectionManager::ProcessViewHierarchyChanged(
428 const ServerView* view,
429 const ServerView* new_parent,
430 const ServerView* old_parent) {
431 for (auto& pair : connection_map_) {
432 pair.second->service()->ProcessViewHierarchyChanged(
433 view, new_parent, old_parent, IsChangeSource(pair.first));
437 void ConnectionManager::ProcessViewReorder(
438 const ServerView* view,
439 const ServerView* relative_view,
440 const mojo::OrderDirection direction) {
441 for (auto& pair : connection_map_) {
442 pair.second->service()->ProcessViewReorder(view, relative_view, direction,
443 IsChangeSource(pair.first));
447 void ConnectionManager::ProcessViewDeleted(const ViewId& view) {
448 for (auto& pair : connection_map_) {
449 pair.second->service()->ProcessViewDeleted(view,
450 IsChangeSource(pair.first));
454 void ConnectionManager::ProcessViewportMetricsChanged(
455 const mojo::ViewportMetrics& old_metrics,
456 const mojo::ViewportMetrics& new_metrics) {
457 for (auto& pair : connection_map_) {
458 pair.second->service()->ProcessViewportMetricsChanged(
459 old_metrics, new_metrics, IsChangeSource(pair.first));
463 void ConnectionManager::PrepareForChange(ScopedChange* change) {
464 // Should only ever have one change in flight.
465 CHECK(!current_change_);
466 current_change_ = change;
469 void ConnectionManager::FinishChange() {
470 // PrepareForChange/FinishChange should be balanced.
471 CHECK(current_change_);
472 current_change_ = NULL;
475 void ConnectionManager::DoAnimation() {
476 // TODO(fsamuel): This is probably not right. We probably want a per-root
477 // animation.
478 bool animating = false;
479 for (auto& pair : root_connection_map_)
480 animating |= DecrementAnimatingViewsOpacity(pair.first->root_view());
481 if (!animating)
482 animation_timer_.Stop();
485 void ConnectionManager::AddConnection(ClientConnection* connection) {
486 DCHECK_EQ(0u, connection_map_.count(connection->service()->id()));
487 connection_map_[connection->service()->id()] = connection;
490 ViewManagerRootImpl* ConnectionManager::GetViewManagerRootByView(
491 const ServerView* view) const {
492 while (view && view->parent())
493 view = view->parent();
494 for (auto& pair : root_connection_map_) {
495 if (view == pair.first->root_view())
496 return pair.first;
498 return nullptr;
501 void ConnectionManager::PrepareToDestroyView(ServerView* view) {
502 if (!in_destructor_ && IsViewAttachedToRoot(view) &&
503 view->id() != ClonedViewId()) {
504 // We're about to destroy a view. Any cloned views need to be reparented
505 // else the animation would no longer be visible. By moving to a visible
506 // view, view->parent(), we ensure the animation is still visible.
507 ServerView* parent_above = view;
508 ReparentClonedViews(view->parent(), &parent_above, view);
511 animation_runner_.CancelAnimationForView(view);
514 void ConnectionManager::PrepareToChangeViewHierarchy(ServerView* view,
515 ServerView* new_parent,
516 ServerView* old_parent) {
517 if (view->id() == ClonedViewId() || in_destructor_)
518 return;
520 if (IsViewAttachedToRoot(view)) {
521 // We're about to reparent a view. Any cloned views need to be reparented
522 // else the animation may be effected in unusual ways. For example, the view
523 // could move to a new location such that the animation is entirely clipped.
524 // By moving to view->parent() we ensure the animation is still visible.
525 ServerView* parent_above = view;
526 ReparentClonedViews(view->parent(), &parent_above, view);
529 animation_runner_.CancelAnimationForView(view);
532 void ConnectionManager::PrepareToChangeViewVisibility(ServerView* view) {
533 if (in_destructor_)
534 return;
536 if (IsViewAttachedToRoot(view) && view->id() != ClonedViewId() &&
537 view->IsDrawn()) {
538 // We're about to hide |view|, this would implicitly make any cloned views
539 // hide too. Reparent so that animations are still visible.
540 ServerView* parent_above = view;
541 ReparentClonedViews(view->parent(), &parent_above, view);
544 const bool is_parent_drawn = view->parent() && view->parent()->IsDrawn();
545 if (!is_parent_drawn || !view->visible())
546 animation_runner_.CancelAnimationForView(view);
549 void ConnectionManager::OnScheduleViewPaint(const ServerView* view) {
550 if (!in_destructor_)
551 SchedulePaint(view, gfx::Rect(view->bounds().size()));
554 const ServerView* ConnectionManager::GetRootView(const ServerView* view) const {
555 ViewManagerRootImpl* view_manager_root = GetViewManagerRootByView(view);
556 return view_manager_root ? view_manager_root->root_view() : nullptr;
559 void ConnectionManager::OnViewDestroyed(ServerView* view) {
560 if (!in_destructor_)
561 ProcessViewDeleted(view->id());
564 void ConnectionManager::OnWillChangeViewHierarchy(ServerView* view,
565 ServerView* new_parent,
566 ServerView* old_parent) {
567 if (view->id() == ClonedViewId() || in_destructor_)
568 return;
570 ProcessWillChangeViewHierarchy(view, new_parent, old_parent);
573 void ConnectionManager::OnViewHierarchyChanged(ServerView* view,
574 ServerView* new_parent,
575 ServerView* old_parent) {
576 if (in_destructor_)
577 return;
579 ProcessViewHierarchyChanged(view, new_parent, old_parent);
581 // TODO(beng): optimize.
582 if (old_parent)
583 SchedulePaint(old_parent, gfx::Rect(old_parent->bounds().size()));
584 if (new_parent)
585 SchedulePaint(new_parent, gfx::Rect(new_parent->bounds().size()));
588 void ConnectionManager::OnViewBoundsChanged(ServerView* view,
589 const gfx::Rect& old_bounds,
590 const gfx::Rect& new_bounds) {
591 if (in_destructor_)
592 return;
594 ProcessViewBoundsChanged(view, old_bounds, new_bounds);
595 if (!view->parent())
596 return;
598 // TODO(sky): optimize this.
599 SchedulePaint(view->parent(), old_bounds);
600 SchedulePaint(view->parent(), new_bounds);
603 void ConnectionManager::OnViewReordered(ServerView* view,
604 ServerView* relative,
605 mojo::OrderDirection direction) {
606 if (!in_destructor_)
607 SchedulePaint(view, gfx::Rect(view->bounds().size()));
610 void ConnectionManager::OnWillChangeViewVisibility(ServerView* view) {
611 if (in_destructor_)
612 return;
614 // Need to repaint if the view was drawn (which means it's in the process of
615 // hiding) or the view is transitioning to drawn.
616 if (view->parent() && (view->IsDrawn() ||
617 (!view->visible() && view->parent()->IsDrawn()))) {
618 SchedulePaint(view->parent(), view->bounds());
621 for (auto& pair : connection_map_) {
622 pair.second->service()->ProcessWillChangeViewVisibility(
623 view, IsChangeSource(pair.first));
627 void ConnectionManager::OnViewSharedPropertyChanged(
628 ServerView* view,
629 const std::string& name,
630 const std::vector<uint8_t>* new_data) {
631 for (auto& pair : connection_map_) {
632 pair.second->service()->ProcessViewPropertyChanged(
633 view, name, new_data, IsChangeSource(pair.first));
637 void ConnectionManager::OnViewTextInputStateChanged(
638 ServerView* view,
639 const ui::TextInputState& state) {
640 // Do not need to update text input for unfocused views.
641 if (focus_controller_->GetFocusedView() != view)
642 return;
644 ViewManagerRootImpl* view_manager_root = GetViewManagerRootByView(view);
645 view_manager_root->UpdateTextInputState(state);
648 void ConnectionManager::CloneAndAnimate(mojo::Id transport_view_id) {
649 CloneAndAnimate(ViewIdFromTransportId(transport_view_id));
652 void ConnectionManager::OnFocusChanged(ServerView* old_focused_view,
653 ServerView* new_focused_view) {
654 // There are up to four connections that need to be notified:
655 // . the connection containing |old_focused_view|.
656 // . the connection with |old_focused_view| as its root.
657 // . the connection containing |new_focused_view|.
658 // . the connection with |new_focused_view| as its root.
659 // Some of these connections may be the same. The following takes care to
660 // notify each only once.
661 ViewManagerServiceImpl* owning_connection_old = nullptr;
662 ViewManagerServiceImpl* embedded_connection_old = nullptr;
664 if (old_focused_view) {
665 owning_connection_old = GetConnection(old_focused_view->id().connection_id);
666 if (owning_connection_old) {
667 owning_connection_old->ProcessFocusChanged(old_focused_view,
668 new_focused_view);
670 embedded_connection_old = GetConnectionWithRoot(old_focused_view->id());
671 if (embedded_connection_old) {
672 DCHECK_NE(owning_connection_old, embedded_connection_old);
673 embedded_connection_old->ProcessFocusChanged(old_focused_view,
674 new_focused_view);
677 ViewManagerServiceImpl* owning_connection_new = nullptr;
678 ViewManagerServiceImpl* embedded_connection_new = nullptr;
679 if (new_focused_view) {
680 owning_connection_new = GetConnection(new_focused_view->id().connection_id);
681 if (owning_connection_new &&
682 owning_connection_new != owning_connection_old &&
683 owning_connection_new != embedded_connection_old) {
684 owning_connection_new->ProcessFocusChanged(old_focused_view,
685 new_focused_view);
687 embedded_connection_new = GetConnectionWithRoot(new_focused_view->id());
688 if (embedded_connection_new &&
689 embedded_connection_new != owning_connection_old &&
690 embedded_connection_new != embedded_connection_old) {
691 DCHECK_NE(owning_connection_new, embedded_connection_new);
692 embedded_connection_new->ProcessFocusChanged(old_focused_view,
693 new_focused_view);
697 for (auto& pair : root_connection_map_) {
698 ViewManagerServiceImpl* service = pair.first->GetViewManagerService();
699 if (service != owning_connection_old &&
700 service != embedded_connection_old &&
701 service != owning_connection_new &&
702 service != embedded_connection_new) {
703 service->ProcessFocusChanged(old_focused_view, new_focused_view);
707 ViewManagerRootImpl* old_view_manager_root =
708 old_focused_view ? GetViewManagerRootByView(old_focused_view) : nullptr;
710 ViewManagerRootImpl* new_view_manager_root =
711 new_focused_view ? GetViewManagerRootByView(new_focused_view) : nullptr;
713 if (new_view_manager_root) {
714 new_view_manager_root->UpdateTextInputState(
715 new_focused_view->text_input_state());
716 } else if (old_view_manager_root) {
717 old_view_manager_root->UpdateTextInputState(ui::TextInputState());
721 } // namespace view_manager