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
{
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());
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
55 void ReparentClonedViews(ServerView
* new_parent
,
56 ServerView
** stack_above
,
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
);
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
);
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
;
87 view
->SetOpacity(new_opacity
);
90 bool ret_value
= false;
91 for (ServerView
* child
: view
->GetChildren()) {
92 if (DecrementAnimatingViewsOpacity(child
))
100 ConnectionManager::ScopedChange::ScopedChange(
101 ViewManagerServiceImpl
* connection
,
102 ConnectionManager
* connection_manager
,
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),
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
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);
158 ConnectionSpecificId
ConnectionManager::GetAndAdvanceNextConnectionId() {
159 const ConnectionSpecificId id
= next_connection_id_
++;
160 DCHECK_LT(id
, next_connection_id_
);
164 uint16_t ConnectionManager::GetAndAdvanceNextRootId() {
165 const uint16_t id
= next_root_id_
++;
166 DCHECK_LT(id
, next_root_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();
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
))
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
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(),
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(),
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());
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_
)
277 ServerView
* old_focused
= GetFocusedView();
278 if (old_focused
== view
)
280 focus_controller_
->SetFocusedView(view
);
281 OnFocusChanged(old_focused
, view
);
284 ServerView
* ConnectionManager::GetFocusedView() {
285 if (!focus_controller_
)
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
))
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
))
306 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id
) {
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();
339 ViewManagerServiceImpl
* ConnectionManager::GetEmbedRoot(
340 ViewManagerServiceImpl
* service
) {
342 const ViewId
* root_id
= service
->root();
343 if (!root_id
|| root_id
->connection_id
== service
->id())
346 ViewManagerServiceImpl
* parent_service
=
347 GetConnection(root_id
->connection_id
);
348 service
= parent_service
;
349 if (service
&& service
->is_embed_root())
355 bool ConnectionManager::CloneAndAnimate(const ViewId
& view_id
) {
356 ServerView
* view
= GetView(view_id
);
357 if (!view
|| !view
->IsDrawn() || (view
->GetRoot() == view
))
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
);
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());
375 connection
= GetConnection(view
->id().connection_id
);
377 connection
->client()->OnViewInputEvent(ViewIdToTransportId(view
->id()),
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
)
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
478 bool animating
= false;
479 for (auto& pair
: root_connection_map_
)
480 animating
|= DecrementAnimatingViewsOpacity(pair
.first
->root_view());
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())
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_
)
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
) {
536 if (IsViewAttachedToRoot(view
) && view
->id() != ClonedViewId() &&
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
) {
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
) {
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_
)
570 ProcessWillChangeViewHierarchy(view
, new_parent
, old_parent
);
573 void ConnectionManager::OnViewHierarchyChanged(ServerView
* view
,
574 ServerView
* new_parent
,
575 ServerView
* old_parent
) {
579 ProcessViewHierarchyChanged(view
, new_parent
, old_parent
);
581 // TODO(beng): optimize.
583 SchedulePaint(old_parent
, gfx::Rect(old_parent
->bounds().size()));
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
) {
594 ProcessViewBoundsChanged(view
, old_bounds
, new_bounds
);
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
) {
607 SchedulePaint(view
, gfx::Rect(view
->bounds().size()));
610 void ConnectionManager::OnWillChangeViewVisibility(ServerView
* view
) {
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(
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(
639 const ui::TextInputState
& state
) {
640 // Do not need to update text input for unfocused views.
641 if (focus_controller_
->GetFocusedView() != view
)
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
,
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
,
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
,
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
,
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