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
{
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());
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
54 void ReparentClonedViews(ServerView
* new_parent
,
55 ServerView
** stack_above
,
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
);
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
);
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
;
86 view
->SetOpacity(new_opacity
);
89 bool ret_value
= false;
90 for (ServerView
* child
: view
->GetChildren()) {
91 if (DecrementAnimatingViewsOpacity(child
))
99 ConnectionManager::ScopedChange::ScopedChange(
100 ViewManagerServiceImpl
* connection
,
101 ConnectionManager
* connection_manager
,
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),
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
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);
157 ConnectionSpecificId
ConnectionManager::GetAndAdvanceNextConnectionId() {
158 const ConnectionSpecificId id
= next_connection_id_
++;
159 DCHECK_LT(id
, next_connection_id_
);
163 uint16_t ConnectionManager::GetAndAdvanceNextRootId() {
164 const uint16_t id
= next_root_id_
++;
165 DCHECK_LT(id
, next_root_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();
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
))
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
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(),
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(),
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());
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_
)
276 ServerView
* old_focused
= GetFocusedView();
277 if (old_focused
== view
)
279 focus_controller_
->SetFocusedView(view
);
280 OnFocusChanged(old_focused
, view
);
283 ServerView
* ConnectionManager::GetFocusedView() {
284 if (!focus_controller_
)
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
))
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
))
305 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id
) {
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();
338 ViewManagerServiceImpl
* ConnectionManager::GetEmbedRoot(
339 ViewManagerServiceImpl
* service
) {
341 const ViewId
* root_id
= service
->root();
342 if (!root_id
|| root_id
->connection_id
== service
->id())
345 ViewManagerServiceImpl
* parent_service
=
346 GetConnection(root_id
->connection_id
);
347 service
= parent_service
;
348 if (service
&& service
->is_embed_root())
354 bool ConnectionManager::CloneAndAnimate(const ViewId
& view_id
) {
355 ServerView
* view
= GetView(view_id
);
356 if (!view
|| !view
->IsDrawn() || (view
->GetRoot() == view
))
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
);
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());
374 connection
= GetConnection(view
->id().connection_id
);
376 connection
->client()->OnViewInputEvent(ViewIdToTransportId(view
->id()),
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
)
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
477 bool animating
= false;
478 for (auto& pair
: root_connection_map_
)
479 animating
|= DecrementAnimatingViewsOpacity(pair
.first
->root_view());
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())
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_
)
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
) {
535 if (IsViewAttachedToRoot(view
) && view
->id() != ClonedViewId() &&
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
) {
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
) {
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_
)
569 ProcessWillChangeViewHierarchy(view
, new_parent
, old_parent
);
572 void ConnectionManager::OnViewHierarchyChanged(ServerView
* view
,
573 ServerView
* new_parent
,
574 ServerView
* old_parent
) {
578 ProcessViewHierarchyChanged(view
, new_parent
, old_parent
);
580 // TODO(beng): optimize.
582 SchedulePaint(old_parent
, gfx::Rect(old_parent
->bounds().size()));
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
) {
593 ProcessViewBoundsChanged(view
, old_bounds
, new_bounds
);
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
) {
606 SchedulePaint(view
, gfx::Rect(view
->bounds().size()));
609 void ConnectionManager::OnWillChangeViewVisibility(ServerView
* view
) {
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(
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(
638 const ui::TextInputState
& state
) {
639 // Do not need to update text input for unfocused views.
640 if (focus_controller_
->GetFocusedView() != view
)
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
,
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
,
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
,
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
,
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