Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / components / view_manager / connection_manager.cc
blob3a468367e7ca9e912887322b8eb44322fcc8ae59
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/converters/geometry/geometry_type_converters.h"
18 #include "mojo/converters/input_events/input_events_type_converters.h"
20 using mojo::ConnectionSpecificId;
22 namespace view_manager {
23 namespace {
25 // Creates a copy of |view|. The copied view has |delegate| as its delegate.
26 // This does not recurse.
27 ServerView* CloneView(const ServerView* view, ServerViewDelegate* delegate) {
28 ServerView* clone = new ServerView(delegate, ClonedViewId());
29 clone->SetBounds(view->bounds());
30 clone->SetSurfaceId(view->surface_id());
31 clone->SetOpacity(view->opacity());
32 return clone;
35 // Creates copies of all the visible children of |parent|. Newly cloned views
36 // are added to |cloned_parent| and have |delegate| as their delegate. The
37 // stacking order of the cloned views is preseved.
38 void CloneViewTree(const ServerView* parent,
39 ServerView* cloned_parent,
40 ServerViewDelegate* delegate) {
41 DCHECK(parent->visible());
42 for (const ServerView* to_clone : parent->GetChildren()) {
43 if (to_clone->visible()) {
44 ServerView* cloned = CloneView(to_clone, delegate);
45 cloned_parent->Add(cloned);
46 CloneViewTree(to_clone, cloned, delegate);
51 // Recurses through all the children of |view| moving any cloned views to
52 // |new_parent| stacked above |stack_above|. |stack_above| is updated as views
53 // are moved.
54 void ReparentClonedViews(ServerView* new_parent,
55 ServerView** stack_above,
56 ServerView* view) {
57 if (view->id() == ClonedViewId()) {
58 const gfx::Rect new_bounds(ConvertRectBetweenViews(
59 view, new_parent, gfx::Rect(view->bounds().size())));
60 new_parent->Add(view);
61 new_parent->Reorder(view, *stack_above, mojo::ORDER_DIRECTION_ABOVE);
62 view->SetBounds(new_bounds);
63 *stack_above = view;
64 return;
67 for (ServerView* child : view->GetChildren())
68 ReparentClonedViews(new_parent, stack_above, child);
71 // Deletes |view| and all its descendants.
72 void DeleteViewTree(ServerView* view) {
73 for (ServerView* child : view->GetChildren())
74 DeleteViewTree(child);
76 delete view;
79 // TODO(sky): nuke, proof of concept.
80 bool DecrementAnimatingViewsOpacity(ServerView* view) {
81 if (view->id() == ClonedViewId()) {
82 const float new_opacity = view->opacity() - .05f;
83 if (new_opacity <= 0)
84 DeleteViewTree(view);
85 else
86 view->SetOpacity(new_opacity);
87 return true;
89 bool ret_value = false;
90 for (ServerView* child : view->GetChildren()) {
91 if (DecrementAnimatingViewsOpacity(child))
92 ret_value = true;
94 return ret_value;
97 } // namespace
99 ConnectionManager::ScopedChange::ScopedChange(
100 ViewManagerServiceImpl* connection,
101 ConnectionManager* connection_manager,
102 bool is_delete_view)
103 : connection_manager_(connection_manager),
104 connection_id_(connection->id()),
105 is_delete_view_(is_delete_view) {
106 connection_manager_->PrepareForChange(this);
109 ConnectionManager::ScopedChange::~ScopedChange() {
110 connection_manager_->FinishChange();
113 ConnectionManager::ConnectionManager(ConnectionManagerDelegate* delegate)
114 : delegate_(delegate),
115 next_connection_id_(1),
116 next_root_id_(0),
117 event_dispatcher_(this),
118 current_change_(nullptr),
119 in_destructor_(false),
120 animation_runner_(base::TimeTicks::Now()),
121 focus_controller_(new FocusController(this)) {
124 ConnectionManager::~ConnectionManager() {
125 in_destructor_ = true;
127 // Deleting views will attempt to advance focus. When we're being destroyed
128 // that is not necessary. Additionally |focus_controller_| needs to be
129 // destroyed before |root_|.
130 focus_controller_.reset();
132 // Copy the RootConnectionMap because it will be mutated as the connections
133 // are closed.
134 RootConnectionMap root_connection_map(root_connection_map_);
135 for (auto& pair : root_connection_map)
136 pair.second->CloseConnection();
138 STLDeleteValues(&connection_map_);
139 // All the connections should have been destroyed.
140 DCHECK(root_connection_map_.empty());
141 DCHECK(connection_map_.empty());
144 void ConnectionManager::AddRoot(
145 ViewManagerRootConnection* root_connection) {
146 DCHECK_EQ(0u, root_connection_map_.count(
147 root_connection->view_manager_root()));
148 root_connection_map_[root_connection->view_manager_root()] = root_connection;
151 ServerView* ConnectionManager::CreateServerView(const ViewId& id) {
152 ServerView* view = new ServerView(this, id);
153 view->AddObserver(this);
154 return view;
157 ConnectionSpecificId ConnectionManager::GetAndAdvanceNextConnectionId() {
158 const ConnectionSpecificId id = next_connection_id_++;
159 DCHECK_LT(id, next_connection_id_);
160 return id;
163 uint16_t ConnectionManager::GetAndAdvanceNextRootId() {
164 const uint16_t id = next_root_id_++;
165 DCHECK_LT(id, next_root_id_);
166 return id;
169 void ConnectionManager::OnConnectionError(ClientConnection* connection) {
170 // This will be null if the root has been destroyed.
171 const ViewId* view_id = connection->service()->root();
172 ServerView* view =
173 view_id ? GetView(*connection->service()->root()) : nullptr;
174 // If the ViewManagerService root is a viewport root, then we'll wait until
175 // the root connection goes away to cleanup.
176 if (view && (GetRootView(view) == view))
177 return;
179 scoped_ptr<ClientConnection> connection_owner(connection);
181 connection_map_.erase(connection->service()->id());
183 // TODO(sky): I may want to advance focus differently if focus is in
184 // |connection|.
186 // Notify remaining connections so that they can cleanup.
187 for (auto& pair : connection_map_) {
188 pair.second->service()->OnWillDestroyViewManagerServiceImpl(
189 connection->service());
193 void ConnectionManager::OnRootConnectionClosed(
194 ViewManagerRootConnection* connection) {
195 auto it = root_connection_map_.find(connection->view_manager_root());
196 DCHECK(it != root_connection_map_.end());
198 // Clear focus if the focused view is in this viewport.
199 if (GetRootView(GetFocusedView()) == it->first->root_view())
200 SetFocusedView(nullptr);
202 // Get the ClientConnection by ViewManagerServiceImpl ID.
203 ConnectionMap::iterator service_connection_it =
204 connection_map_.find(it->first->GetViewManagerService()->id());
205 DCHECK(service_connection_it != connection_map_.end());
207 // Tear down the associated ViewManagerService connection.
208 // TODO(fsamuel): I don't think this is quite right, we should tear down all
209 // connections within the root's viewport. We should probably employ an
210 // observer pattern to do this. Each ViewManagerServiceImpl should track its
211 // parent's lifetime.
212 root_connection_map_.erase(it);
213 OnConnectionError(service_connection_it->second);
215 // If we have no more roots left, let the app know so it can terminate.
216 if (!root_connection_map_.size())
217 delegate_->OnNoMoreRootConnections();
220 void ConnectionManager::EmbedAtView(mojo::ConnectionSpecificId creator_id,
221 const ViewId& view_id,
222 mojo::URLRequestPtr request) {
223 mojo::ViewManagerServicePtr service_ptr;
224 ClientConnection* client_connection =
225 delegate_->CreateClientConnectionForEmbedAtView(
226 this, GetProxy(&service_ptr), creator_id, request.Pass(), view_id);
227 AddConnection(client_connection);
228 client_connection->service()->Init(client_connection->client(),
229 service_ptr.Pass());
230 OnConnectionMessagedClient(client_connection->service()->id());
233 ViewManagerServiceImpl* ConnectionManager::EmbedAtView(
234 mojo::ConnectionSpecificId creator_id,
235 const ViewId& view_id,
236 mojo::ViewManagerClientPtr client) {
237 mojo::ViewManagerServicePtr service_ptr;
238 ClientConnection* client_connection =
239 delegate_->CreateClientConnectionForEmbedAtView(
240 this, GetProxy(&service_ptr), creator_id, view_id, client.Pass());
241 AddConnection(client_connection);
242 client_connection->service()->Init(client_connection->client(),
243 service_ptr.Pass());
244 OnConnectionMessagedClient(client_connection->service()->id());
246 return client_connection->service();
249 void ConnectionManager::OnAccelerator(ServerView* root, mojo::EventPtr event) {
250 for (auto& pair : root_connection_map_) {
251 if (root == pair.first->root_view()) {
252 pair.first->client()->OnAccelerator(event.Pass());
253 return;
258 ViewManagerServiceImpl* ConnectionManager::GetConnection(
259 ConnectionSpecificId connection_id) {
260 ConnectionMap::iterator i = connection_map_.find(connection_id);
261 return i == connection_map_.end() ? nullptr : i->second->service();
264 ServerView* ConnectionManager::GetView(const ViewId& id) {
265 for (auto& pair : root_connection_map_) {
266 if (pair.first->root_view()->id() == id)
267 return pair.first->root_view();
269 ViewManagerServiceImpl* service = GetConnection(id.connection_id);
270 return service ? service->GetView(id) : nullptr;
273 void ConnectionManager::SetFocusedView(ServerView* view) {
274 if (!focus_controller_)
275 return;
276 ServerView* old_focused = GetFocusedView();
277 if (old_focused == view)
278 return;
279 focus_controller_->SetFocusedView(view);
280 OnFocusChanged(old_focused, view);
283 ServerView* ConnectionManager::GetFocusedView() {
284 if (!focus_controller_)
285 return nullptr;
286 return focus_controller_->GetFocusedView();
289 bool ConnectionManager::IsViewAttachedToRoot(const ServerView* view) const {
290 for (auto& pair : root_connection_map_) {
291 if (pair.first->IsViewAttachedToRoot(view))
292 return true;
294 return false;
297 void ConnectionManager::SchedulePaint(const ServerView* view,
298 const gfx::Rect& bounds) {
299 for (auto& pair : root_connection_map_) {
300 if (pair.first->SchedulePaintIfInViewport(view, bounds))
301 return;
305 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
306 if (current_change_)
307 current_change_->MarkConnectionAsMessaged(id);
310 bool ConnectionManager::DidConnectionMessageClient(
311 ConnectionSpecificId id) const {
312 return current_change_ && current_change_->DidMessageConnection(id);
315 mojo::ViewportMetricsPtr ConnectionManager::GetViewportMetricsForView(
316 const ServerView* view) {
317 ViewManagerRootImpl* view_manager_root = GetViewManagerRootByView(view);
318 if (view_manager_root)
319 return view_manager_root->GetViewportMetrics().Clone();
321 if (!root_connection_map_.empty())
322 return root_connection_map_.begin()->first->GetViewportMetrics().Clone();
324 mojo::ViewportMetricsPtr metrics = mojo::ViewportMetrics::New();
325 metrics->size_in_pixels = mojo::Size::New();
326 return metrics.Pass();
329 const ViewManagerServiceImpl* ConnectionManager::GetConnectionWithRoot(
330 const ViewId& id) const {
331 for (auto& pair : connection_map_) {
332 if (pair.second->service()->IsRoot(id))
333 return pair.second->service();
335 return nullptr;
338 ViewManagerServiceImpl* ConnectionManager::GetEmbedRoot(
339 ViewManagerServiceImpl* service) {
340 while (service) {
341 const ViewId* root_id = service->root();
342 if (!root_id || root_id->connection_id == service->id())
343 return nullptr;
345 ViewManagerServiceImpl* parent_service =
346 GetConnection(root_id->connection_id);
347 service = parent_service;
348 if (service && service->is_embed_root())
349 return service;
351 return nullptr;
354 bool ConnectionManager::CloneAndAnimate(const ViewId& view_id) {
355 ServerView* view = GetView(view_id);
356 if (!view || !view->IsDrawn() || (view->GetRoot() == view))
357 return false;
358 if (!animation_timer_.IsRunning()) {
359 animation_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(100),
360 this, &ConnectionManager::DoAnimation);
362 ServerView* clone = CloneView(view, this);
363 CloneViewTree(view, clone, this);
364 view->parent()->Add(clone);
365 view->parent()->Reorder(clone, view, mojo::ORDER_DIRECTION_ABOVE);
366 return true;
369 void ConnectionManager::DispatchInputEventToView(const ServerView* view,
370 mojo::EventPtr event) {
371 // If the view is an embed root, forward to the embedded view, not the owner.
372 ViewManagerServiceImpl* connection = GetConnectionWithRoot(view->id());
373 if (!connection)
374 connection = GetConnection(view->id().connection_id);
375 CHECK(connection);
376 connection->client()->OnViewInputEvent(ViewIdToTransportId(view->id()),
377 event.Pass(),
378 base::Bind(&base::DoNothing));
381 void ConnectionManager::OnEvent(ViewManagerRootImpl* root,
382 mojo::EventPtr event) {
383 event_dispatcher_.OnEvent(root->root_view(), event.Pass());
386 void ConnectionManager::AddAccelerator(ViewManagerRootImpl* root,
387 mojo::KeyboardCode keyboard_code,
388 mojo::EventFlags flags) {
389 event_dispatcher_.AddAccelerator(keyboard_code, flags);
392 void ConnectionManager::RemoveAccelerator(ViewManagerRootImpl* root,
393 mojo::KeyboardCode keyboard_code,
394 mojo::EventFlags flags) {
395 event_dispatcher_.RemoveAccelerator(keyboard_code, flags);
398 void ConnectionManager::SetImeVisibility(ServerView* view, bool visible) {
399 // Do not need to show or hide IME for unfocused view.
400 if (focus_controller_->GetFocusedView() != view)
401 return;
403 ViewManagerRootImpl* view_manager_root = GetViewManagerRootByView(view);
404 view_manager_root->SetImeVisibility(visible);
407 void ConnectionManager::ProcessViewBoundsChanged(const ServerView* view,
408 const gfx::Rect& old_bounds,
409 const gfx::Rect& new_bounds) {
410 for (auto& pair : connection_map_) {
411 pair.second->service()->ProcessViewBoundsChanged(
412 view, old_bounds, new_bounds, IsChangeSource(pair.first));
416 void ConnectionManager::ProcessWillChangeViewHierarchy(
417 const ServerView* view,
418 const ServerView* new_parent,
419 const ServerView* old_parent) {
420 for (auto& pair : connection_map_) {
421 pair.second->service()->ProcessWillChangeViewHierarchy(
422 view, new_parent, old_parent, IsChangeSource(pair.first));
426 void ConnectionManager::ProcessViewHierarchyChanged(
427 const ServerView* view,
428 const ServerView* new_parent,
429 const ServerView* old_parent) {
430 for (auto& pair : connection_map_) {
431 pair.second->service()->ProcessViewHierarchyChanged(
432 view, new_parent, old_parent, IsChangeSource(pair.first));
436 void ConnectionManager::ProcessViewReorder(
437 const ServerView* view,
438 const ServerView* relative_view,
439 const mojo::OrderDirection direction) {
440 for (auto& pair : connection_map_) {
441 pair.second->service()->ProcessViewReorder(view, relative_view, direction,
442 IsChangeSource(pair.first));
446 void ConnectionManager::ProcessViewDeleted(const ViewId& view) {
447 for (auto& pair : connection_map_) {
448 pair.second->service()->ProcessViewDeleted(view,
449 IsChangeSource(pair.first));
453 void ConnectionManager::ProcessViewportMetricsChanged(
454 const mojo::ViewportMetrics& old_metrics,
455 const mojo::ViewportMetrics& new_metrics) {
456 for (auto& pair : connection_map_) {
457 pair.second->service()->ProcessViewportMetricsChanged(
458 old_metrics, new_metrics, IsChangeSource(pair.first));
462 void ConnectionManager::PrepareForChange(ScopedChange* change) {
463 // Should only ever have one change in flight.
464 CHECK(!current_change_);
465 current_change_ = change;
468 void ConnectionManager::FinishChange() {
469 // PrepareForChange/FinishChange should be balanced.
470 CHECK(current_change_);
471 current_change_ = NULL;
474 void ConnectionManager::DoAnimation() {
475 // TODO(fsamuel): This is probably not right. We probably want a per-root
476 // animation.
477 bool animating = false;
478 for (auto& pair : root_connection_map_)
479 animating |= DecrementAnimatingViewsOpacity(pair.first->root_view());
480 if (!animating)
481 animation_timer_.Stop();
484 void ConnectionManager::AddConnection(ClientConnection* connection) {
485 DCHECK_EQ(0u, connection_map_.count(connection->service()->id()));
486 connection_map_[connection->service()->id()] = connection;
489 ViewManagerRootImpl* ConnectionManager::GetViewManagerRootByView(
490 const ServerView* view) const {
491 while (view && view->parent())
492 view = view->parent();
493 for (auto& pair : root_connection_map_) {
494 if (view == pair.first->root_view())
495 return pair.first;
497 return nullptr;
500 void ConnectionManager::PrepareToDestroyView(ServerView* view) {
501 if (!in_destructor_ && IsViewAttachedToRoot(view) &&
502 view->id() != ClonedViewId()) {
503 // We're about to destroy a view. Any cloned views need to be reparented
504 // else the animation would no longer be visible. By moving to a visible
505 // view, view->parent(), we ensure the animation is still visible.
506 ServerView* parent_above = view;
507 ReparentClonedViews(view->parent(), &parent_above, view);
510 animation_runner_.CancelAnimationForView(view);
513 void ConnectionManager::PrepareToChangeViewHierarchy(ServerView* view,
514 ServerView* new_parent,
515 ServerView* old_parent) {
516 if (view->id() == ClonedViewId() || in_destructor_)
517 return;
519 if (IsViewAttachedToRoot(view)) {
520 // We're about to reparent a view. Any cloned views need to be reparented
521 // else the animation may be effected in unusual ways. For example, the view
522 // could move to a new location such that the animation is entirely clipped.
523 // By moving to view->parent() we ensure the animation is still visible.
524 ServerView* parent_above = view;
525 ReparentClonedViews(view->parent(), &parent_above, view);
528 animation_runner_.CancelAnimationForView(view);
531 void ConnectionManager::PrepareToChangeViewVisibility(ServerView* view) {
532 if (in_destructor_)
533 return;
535 if (IsViewAttachedToRoot(view) && view->id() != ClonedViewId() &&
536 view->IsDrawn()) {
537 // We're about to hide |view|, this would implicitly make any cloned views
538 // hide too. Reparent so that animations are still visible.
539 ServerView* parent_above = view;
540 ReparentClonedViews(view->parent(), &parent_above, view);
543 const bool is_parent_drawn = view->parent() && view->parent()->IsDrawn();
544 if (!is_parent_drawn || !view->visible())
545 animation_runner_.CancelAnimationForView(view);
548 void ConnectionManager::OnScheduleViewPaint(const ServerView* view) {
549 if (!in_destructor_)
550 SchedulePaint(view, gfx::Rect(view->bounds().size()));
553 const ServerView* ConnectionManager::GetRootView(const ServerView* view) const {
554 ViewManagerRootImpl* view_manager_root = GetViewManagerRootByView(view);
555 return view_manager_root ? view_manager_root->root_view() : nullptr;
558 void ConnectionManager::OnViewDestroyed(ServerView* view) {
559 if (!in_destructor_)
560 ProcessViewDeleted(view->id());
563 void ConnectionManager::OnWillChangeViewHierarchy(ServerView* view,
564 ServerView* new_parent,
565 ServerView* old_parent) {
566 if (view->id() == ClonedViewId() || in_destructor_)
567 return;
569 ProcessWillChangeViewHierarchy(view, new_parent, old_parent);
572 void ConnectionManager::OnViewHierarchyChanged(ServerView* view,
573 ServerView* new_parent,
574 ServerView* old_parent) {
575 if (in_destructor_)
576 return;
578 ProcessViewHierarchyChanged(view, new_parent, old_parent);
580 // TODO(beng): optimize.
581 if (old_parent)
582 SchedulePaint(old_parent, gfx::Rect(old_parent->bounds().size()));
583 if (new_parent)
584 SchedulePaint(new_parent, gfx::Rect(new_parent->bounds().size()));
587 void ConnectionManager::OnViewBoundsChanged(ServerView* view,
588 const gfx::Rect& old_bounds,
589 const gfx::Rect& new_bounds) {
590 if (in_destructor_)
591 return;
593 ProcessViewBoundsChanged(view, old_bounds, new_bounds);
594 if (!view->parent())
595 return;
597 // TODO(sky): optimize this.
598 SchedulePaint(view->parent(), old_bounds);
599 SchedulePaint(view->parent(), new_bounds);
602 void ConnectionManager::OnViewReordered(ServerView* view,
603 ServerView* relative,
604 mojo::OrderDirection direction) {
605 if (!in_destructor_)
606 SchedulePaint(view, gfx::Rect(view->bounds().size()));
609 void ConnectionManager::OnWillChangeViewVisibility(ServerView* view) {
610 if (in_destructor_)
611 return;
613 // Need to repaint if the view was drawn (which means it's in the process of
614 // hiding) or the view is transitioning to drawn.
615 if (view->parent() && (view->IsDrawn() ||
616 (!view->visible() && view->parent()->IsDrawn()))) {
617 SchedulePaint(view->parent(), view->bounds());
620 for (auto& pair : connection_map_) {
621 pair.second->service()->ProcessWillChangeViewVisibility(
622 view, IsChangeSource(pair.first));
626 void ConnectionManager::OnViewSharedPropertyChanged(
627 ServerView* view,
628 const std::string& name,
629 const std::vector<uint8_t>* new_data) {
630 for (auto& pair : connection_map_) {
631 pair.second->service()->ProcessViewPropertyChanged(
632 view, name, new_data, IsChangeSource(pair.first));
636 void ConnectionManager::OnViewTextInputStateChanged(
637 ServerView* view,
638 const ui::TextInputState& state) {
639 // Do not need to update text input for unfocused views.
640 if (focus_controller_->GetFocusedView() != view)
641 return;
643 ViewManagerRootImpl* view_manager_root = GetViewManagerRootByView(view);
644 view_manager_root->UpdateTextInputState(state);
647 void ConnectionManager::CloneAndAnimate(mojo::Id transport_view_id) {
648 CloneAndAnimate(ViewIdFromTransportId(transport_view_id));
651 void ConnectionManager::OnFocusChanged(ServerView* old_focused_view,
652 ServerView* new_focused_view) {
653 // There are up to four connections that need to be notified:
654 // . the connection containing |old_focused_view|.
655 // . the connection with |old_focused_view| as its root.
656 // . the connection containing |new_focused_view|.
657 // . the connection with |new_focused_view| as its root.
658 // Some of these connections may be the same. The following takes care to
659 // notify each only once.
660 ViewManagerServiceImpl* owning_connection_old = nullptr;
661 ViewManagerServiceImpl* embedded_connection_old = nullptr;
663 if (old_focused_view) {
664 owning_connection_old = GetConnection(old_focused_view->id().connection_id);
665 if (owning_connection_old) {
666 owning_connection_old->ProcessFocusChanged(old_focused_view,
667 new_focused_view);
669 embedded_connection_old = GetConnectionWithRoot(old_focused_view->id());
670 if (embedded_connection_old) {
671 DCHECK_NE(owning_connection_old, embedded_connection_old);
672 embedded_connection_old->ProcessFocusChanged(old_focused_view,
673 new_focused_view);
676 ViewManagerServiceImpl* owning_connection_new = nullptr;
677 ViewManagerServiceImpl* embedded_connection_new = nullptr;
678 if (new_focused_view) {
679 owning_connection_new = GetConnection(new_focused_view->id().connection_id);
680 if (owning_connection_new &&
681 owning_connection_new != owning_connection_old &&
682 owning_connection_new != embedded_connection_old) {
683 owning_connection_new->ProcessFocusChanged(old_focused_view,
684 new_focused_view);
686 embedded_connection_new = GetConnectionWithRoot(new_focused_view->id());
687 if (embedded_connection_new &&
688 embedded_connection_new != owning_connection_old &&
689 embedded_connection_new != embedded_connection_old) {
690 DCHECK_NE(owning_connection_new, embedded_connection_new);
691 embedded_connection_new->ProcessFocusChanged(old_focused_view,
692 new_focused_view);
696 for (auto& pair : root_connection_map_) {
697 ViewManagerServiceImpl* service = pair.first->GetViewManagerService();
698 if (service != owning_connection_old &&
699 service != embedded_connection_old &&
700 service != owning_connection_new &&
701 service != embedded_connection_new) {
702 service->ProcessFocusChanged(old_focused_view, new_focused_view);
706 ViewManagerRootImpl* old_view_manager_root =
707 old_focused_view ? GetViewManagerRootByView(old_focused_view) : nullptr;
709 ViewManagerRootImpl* new_view_manager_root =
710 new_focused_view ? GetViewManagerRootByView(new_focused_view) : nullptr;
712 if (new_view_manager_root) {
713 new_view_manager_root->UpdateTextInputState(
714 new_focused_view->text_input_state());
715 } else if (old_view_manager_root) {
716 old_view_manager_root->UpdateTextInputState(ui::TextInputState());
720 } // namespace view_manager