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 "cc/output/compositor_frame.h"
10 #include "cc/quads/shared_quad_state.h"
11 #include "components/view_manager/client_connection.h"
12 #include "components/view_manager/connection_manager_delegate.h"
13 #include "components/view_manager/focus_controller.h"
14 #include "components/view_manager/server_view.h"
15 #include "components/view_manager/view_coordinate_conversions.h"
16 #include "components/view_manager/view_tree_host_connection.h"
17 #include "components/view_manager/view_tree_impl.h"
18 #include "mojo/application/public/cpp/application_connection.h"
19 #include "mojo/converters/geometry/geometry_type_converters.h"
20 #include "mojo/converters/input_events/input_events_type_converters.h"
21 #include "mojo/converters/surfaces/surfaces_type_converters.h"
23 using mojo::ConnectionSpecificId
;
25 namespace view_manager
{
28 // Creates a copy of |view|. The copied view has |delegate| as its delegate.
29 // This does not recurse.
30 ServerView
* CloneView(const ServerView
* view
, ServerViewDelegate
* delegate
) {
31 ServerView
* clone
= new ServerView(delegate
, ClonedViewId());
32 clone
->SetBounds(view
->bounds());
33 clone
->SetSurfaceId(view
->surface_id());
34 clone
->SetOpacity(view
->opacity());
38 // Creates copies of all the visible children of |parent|. Newly cloned views
39 // are added to |cloned_parent| and have |delegate| as their delegate. The
40 // stacking order of the cloned views is preseved.
41 void CloneViewTree(const ServerView
* parent
,
42 ServerView
* cloned_parent
,
43 ServerViewDelegate
* delegate
) {
44 DCHECK(parent
->visible());
45 for (const ServerView
* to_clone
: parent
->GetChildren()) {
46 if (to_clone
->visible()) {
47 ServerView
* cloned
= CloneView(to_clone
, delegate
);
48 cloned_parent
->Add(cloned
);
49 CloneViewTree(to_clone
, cloned
, delegate
);
54 // Recurses through all the children of |view| moving any cloned views to
55 // |new_parent| stacked above |stack_above|. |stack_above| is updated as views
57 void ReparentClonedViews(ServerView
* new_parent
,
58 ServerView
** stack_above
,
60 if (view
->id() == ClonedViewId()) {
61 const gfx::Rect
new_bounds(ConvertRectBetweenViews(
62 view
, new_parent
, gfx::Rect(view
->bounds().size())));
63 new_parent
->Add(view
);
64 new_parent
->Reorder(view
, *stack_above
, mojo::ORDER_DIRECTION_ABOVE
);
65 view
->SetBounds(new_bounds
);
70 for (ServerView
* child
: view
->GetChildren())
71 ReparentClonedViews(new_parent
, stack_above
, child
);
74 // Deletes |view| and all its descendants.
75 void DeleteViewTree(ServerView
* view
) {
76 for (ServerView
* child
: view
->GetChildren())
77 DeleteViewTree(child
);
82 // TODO(sky): nuke, proof of concept.
83 bool DecrementAnimatingViewsOpacity(ServerView
* view
) {
84 if (view
->id() == ClonedViewId()) {
85 const float new_opacity
= view
->opacity() - .05f
;
89 view
->SetOpacity(new_opacity
);
92 bool ret_value
= false;
93 for (ServerView
* child
: view
->GetChildren()) {
94 if (DecrementAnimatingViewsOpacity(child
))
102 ConnectionManager::ScopedChange::ScopedChange(
103 ViewTreeImpl
* connection
,
104 ConnectionManager
* connection_manager
,
106 : connection_manager_(connection_manager
),
107 connection_id_(connection
->id()),
108 is_delete_view_(is_delete_view
) {
109 connection_manager_
->PrepareForChange(this);
112 ConnectionManager::ScopedChange::~ScopedChange() {
113 connection_manager_
->FinishChange();
116 ConnectionManager::ConnectionManager(
117 ConnectionManagerDelegate
* delegate
,
118 const scoped_refptr
<surfaces::SurfacesState
>& surfaces_state
)
119 : delegate_(delegate
),
120 surfaces_state_(surfaces_state
),
121 next_connection_id_(1),
123 event_dispatcher_(this),
124 current_change_(nullptr),
125 in_destructor_(false),
126 animation_runner_(base::TimeTicks::Now()),
127 focus_controller_(new FocusController(this)) {
130 ConnectionManager::~ConnectionManager() {
131 in_destructor_
= true;
133 // Deleting views will attempt to advance focus. When we're being destroyed
134 // that is not necessary. Additionally |focus_controller_| needs to be
135 // destroyed before |host_|.
136 focus_controller_
.reset();
138 // Copy the HostConnectionMap because it will be mutated as the connections
140 HostConnectionMap
host_connection_map(host_connection_map_
);
141 for (auto& pair
: host_connection_map
)
142 pair
.second
->CloseConnection();
144 STLDeleteValues(&connection_map_
);
145 // All the connections should have been destroyed.
146 DCHECK(host_connection_map_
.empty());
147 DCHECK(connection_map_
.empty());
150 void ConnectionManager::AddHost(
151 ViewTreeHostConnection
* host_connection
) {
152 DCHECK_EQ(0u, host_connection_map_
.count(host_connection
->view_tree_host()));
153 host_connection_map_
[host_connection
->view_tree_host()] = host_connection
;
156 ServerView
* ConnectionManager::CreateServerView(const ViewId
& id
) {
157 ServerView
* view
= new ServerView(this, id
);
158 view
->AddObserver(this);
162 ConnectionSpecificId
ConnectionManager::GetAndAdvanceNextConnectionId() {
163 const ConnectionSpecificId id
= next_connection_id_
++;
164 DCHECK_LT(id
, next_connection_id_
);
168 uint16_t ConnectionManager::GetAndAdvanceNextHostId() {
169 const uint16_t id
= next_host_id_
++;
170 DCHECK_LT(id
, next_host_id_
);
174 void ConnectionManager::OnConnectionError(ClientConnection
* connection
) {
175 // This will be null if the root has been destroyed.
176 const ViewId
* view_id
= connection
->service()->root();
178 view_id
? GetView(*connection
->service()->root()) : nullptr;
179 // If the ViewTree root is a viewport root, then we'll wait until
180 // the root connection goes away to cleanup.
181 if (view
&& (GetRootView(view
) == view
))
184 scoped_ptr
<ClientConnection
> connection_owner(connection
);
186 connection_map_
.erase(connection
->service()->id());
188 // TODO(sky): I may want to advance focus differently if focus is in
191 // Notify remaining connections so that they can cleanup.
192 for (auto& pair
: connection_map_
) {
193 pair
.second
->service()->OnWillDestroyViewTreeImpl(
194 connection
->service());
198 void ConnectionManager::OnHostConnectionClosed(
199 ViewTreeHostConnection
* connection
) {
200 auto it
= host_connection_map_
.find(connection
->view_tree_host());
201 DCHECK(it
!= host_connection_map_
.end());
203 // Clear focus if the focused view is in this viewport.
204 if (GetRootView(GetFocusedView()) == it
->first
->root_view())
205 SetFocusedView(nullptr);
207 // Get the ClientConnection by ViewTreeImpl ID.
208 ConnectionMap::iterator service_connection_it
=
209 connection_map_
.find(it
->first
->GetViewTree()->id());
210 DCHECK(service_connection_it
!= connection_map_
.end());
212 // Tear down the associated ViewTree connection.
213 // TODO(fsamuel): I don't think this is quite right, we should tear down all
214 // connections within the root's viewport. We should probably employ an
215 // observer pattern to do this. Each ViewTreeImpl should track its
216 // parent's lifetime.
217 host_connection_map_
.erase(it
);
218 OnConnectionError(service_connection_it
->second
);
220 // If we have no more roots left, let the app know so it can terminate.
221 if (!host_connection_map_
.size())
222 delegate_
->OnNoMoreRootConnections();
225 void ConnectionManager::EmbedAtView(mojo::ConnectionSpecificId creator_id
,
226 const ViewId
& view_id
,
227 mojo::URLRequestPtr request
) {
228 mojo::ViewTreePtr service_ptr
;
229 ClientConnection
* client_connection
=
230 delegate_
->CreateClientConnectionForEmbedAtView(
231 this, GetProxy(&service_ptr
), creator_id
, request
.Pass(), view_id
);
232 AddConnection(client_connection
);
233 client_connection
->service()->Init(client_connection
->client(),
235 OnConnectionMessagedClient(client_connection
->service()->id());
238 ViewTreeImpl
* ConnectionManager::EmbedAtView(
239 mojo::ConnectionSpecificId creator_id
,
240 const ViewId
& view_id
,
241 mojo::ViewTreeClientPtr client
) {
242 mojo::ViewTreePtr service_ptr
;
243 ClientConnection
* client_connection
=
244 delegate_
->CreateClientConnectionForEmbedAtView(
245 this, GetProxy(&service_ptr
), creator_id
, view_id
, client
.Pass());
246 AddConnection(client_connection
);
247 client_connection
->service()->Init(client_connection
->client(),
249 OnConnectionMessagedClient(client_connection
->service()->id());
251 return client_connection
->service();
254 void ConnectionManager::OnAccelerator(ServerView
* root
,
256 mojo::EventPtr event
) {
257 for (auto& pair
: host_connection_map_
) {
258 if (root
== pair
.first
->root_view()) {
259 pair
.first
->client()->OnAccelerator(id
, event
.Pass());
265 ViewTreeImpl
* ConnectionManager::GetConnection(
266 ConnectionSpecificId connection_id
) {
267 ConnectionMap::iterator i
= connection_map_
.find(connection_id
);
268 return i
== connection_map_
.end() ? nullptr : i
->second
->service();
271 ServerView
* ConnectionManager::GetView(const ViewId
& id
) {
272 for (auto& pair
: host_connection_map_
) {
273 if (pair
.first
->root_view()->id() == id
)
274 return pair
.first
->root_view();
276 ViewTreeImpl
* service
= GetConnection(id
.connection_id
);
277 return service
? service
->GetView(id
) : nullptr;
280 void ConnectionManager::SetFocusedView(ServerView
* view
) {
281 if (!focus_controller_
)
283 ServerView
* old_focused
= GetFocusedView();
284 if (old_focused
== view
)
286 focus_controller_
->SetFocusedView(view
);
287 OnFocusChanged(old_focused
, view
);
290 ServerView
* ConnectionManager::GetFocusedView() {
291 if (!focus_controller_
)
293 return focus_controller_
->GetFocusedView();
296 bool ConnectionManager::IsViewAttachedToRoot(const ServerView
* view
) const {
297 for (auto& pair
: host_connection_map_
) {
298 if (pair
.first
->IsViewAttachedToRoot(view
))
304 void ConnectionManager::SchedulePaint(const ServerView
* view
,
305 const gfx::Rect
& bounds
) {
306 for (auto& pair
: host_connection_map_
) {
307 if (pair
.first
->SchedulePaintIfInViewport(view
, bounds
))
312 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id
) {
314 current_change_
->MarkConnectionAsMessaged(id
);
317 bool ConnectionManager::DidConnectionMessageClient(
318 ConnectionSpecificId id
) const {
319 return current_change_
&& current_change_
->DidMessageConnection(id
);
322 mojo::ViewportMetricsPtr
ConnectionManager::GetViewportMetricsForView(
323 const ServerView
* view
) {
324 ViewTreeHostImpl
* host
= GetViewTreeHostByView(view
);
326 return host
->GetViewportMetrics().Clone();
328 if (!host_connection_map_
.empty())
329 return host_connection_map_
.begin()->first
->GetViewportMetrics().Clone();
331 mojo::ViewportMetricsPtr metrics
= mojo::ViewportMetrics::New();
332 metrics
->size_in_pixels
= mojo::Size::New();
333 return metrics
.Pass();
336 const ViewTreeImpl
* ConnectionManager::GetConnectionWithRoot(
337 const ViewId
& id
) const {
338 for (auto& pair
: connection_map_
) {
339 if (pair
.second
->service()->IsRoot(id
))
340 return pair
.second
->service();
345 ViewTreeImpl
* ConnectionManager::GetEmbedRoot(ViewTreeImpl
* service
) {
347 const ViewId
* root_id
= service
->root();
348 if (!root_id
|| root_id
->connection_id
== service
->id())
351 ViewTreeImpl
* parent_service
= GetConnection(root_id
->connection_id
);
352 service
= parent_service
;
353 if (service
&& service
->is_embed_root())
359 bool ConnectionManager::CloneAndAnimate(const ViewId
& view_id
) {
360 ServerView
* view
= GetView(view_id
);
361 if (!view
|| !view
->IsDrawn() || (view
->GetRoot() == view
))
363 if (!animation_timer_
.IsRunning()) {
364 animation_timer_
.Start(FROM_HERE
, base::TimeDelta::FromMilliseconds(100),
365 this, &ConnectionManager::DoAnimation
);
367 ServerView
* clone
= CloneView(view
, this);
368 CloneViewTree(view
, clone
, this);
369 view
->parent()->Add(clone
);
370 view
->parent()->Reorder(clone
, view
, mojo::ORDER_DIRECTION_ABOVE
);
374 void ConnectionManager::DispatchInputEventToView(const ServerView
* view
,
375 mojo::EventPtr event
) {
376 // If the view is an embed root, forward to the embedded view, not the owner.
377 ViewTreeImpl
* connection
= GetConnectionWithRoot(view
->id());
379 connection
= GetConnection(view
->id().connection_id
);
381 connection
->client()->OnViewInputEvent(ViewIdToTransportId(view
->id()),
383 base::Bind(&base::DoNothing
));
386 void ConnectionManager::OnEvent(ViewTreeHostImpl
* host
,
387 mojo::EventPtr event
) {
388 event_dispatcher_
.OnEvent(host
->root_view(), event
.Pass());
391 void ConnectionManager::AddAccelerator(ViewTreeHostImpl
* host
,
393 mojo::KeyboardCode keyboard_code
,
394 mojo::EventFlags flags
) {
395 event_dispatcher_
.AddAccelerator(id
, keyboard_code
, flags
);
398 void ConnectionManager::RemoveAccelerator(ViewTreeHostImpl
* host
, uint32_t id
) {
399 event_dispatcher_
.RemoveAccelerator(id
);
402 void ConnectionManager::SetImeVisibility(ServerView
* view
, bool visible
) {
403 // Do not need to show or hide IME for unfocused view.
404 if (focus_controller_
->GetFocusedView() != view
)
407 ViewTreeHostImpl
* host
= GetViewTreeHostByView(view
);
408 host
->SetImeVisibility(visible
);
411 void ConnectionManager::ProcessViewBoundsChanged(const ServerView
* view
,
412 const gfx::Rect
& old_bounds
,
413 const gfx::Rect
& new_bounds
) {
414 for (auto& pair
: connection_map_
) {
415 pair
.second
->service()->ProcessViewBoundsChanged(
416 view
, old_bounds
, new_bounds
, IsChangeSource(pair
.first
));
420 void ConnectionManager::ProcessWillChangeViewHierarchy(
421 const ServerView
* view
,
422 const ServerView
* new_parent
,
423 const ServerView
* old_parent
) {
424 for (auto& pair
: connection_map_
) {
425 pair
.second
->service()->ProcessWillChangeViewHierarchy(
426 view
, new_parent
, old_parent
, IsChangeSource(pair
.first
));
430 void ConnectionManager::ProcessViewHierarchyChanged(
431 const ServerView
* view
,
432 const ServerView
* new_parent
,
433 const ServerView
* old_parent
) {
434 for (auto& pair
: connection_map_
) {
435 pair
.second
->service()->ProcessViewHierarchyChanged(
436 view
, new_parent
, old_parent
, IsChangeSource(pair
.first
));
440 void ConnectionManager::ProcessViewReorder(
441 const ServerView
* view
,
442 const ServerView
* relative_view
,
443 const mojo::OrderDirection direction
) {
444 for (auto& pair
: connection_map_
) {
445 pair
.second
->service()->ProcessViewReorder(view
, relative_view
, direction
,
446 IsChangeSource(pair
.first
));
450 void ConnectionManager::ProcessViewDeleted(const ViewId
& view
) {
451 for (auto& pair
: connection_map_
) {
452 pair
.second
->service()->ProcessViewDeleted(view
,
453 IsChangeSource(pair
.first
));
457 void ConnectionManager::ProcessViewportMetricsChanged(
458 const mojo::ViewportMetrics
& old_metrics
,
459 const mojo::ViewportMetrics
& new_metrics
) {
460 for (auto& pair
: connection_map_
) {
461 pair
.second
->service()->ProcessViewportMetricsChanged(
462 old_metrics
, new_metrics
, IsChangeSource(pair
.first
));
466 void ConnectionManager::PrepareForChange(ScopedChange
* change
) {
467 // Should only ever have one change in flight.
468 CHECK(!current_change_
);
469 current_change_
= change
;
472 void ConnectionManager::FinishChange() {
473 // PrepareForChange/FinishChange should be balanced.
474 CHECK(current_change_
);
475 current_change_
= NULL
;
478 void ConnectionManager::DoAnimation() {
479 // TODO(fsamuel): This is probably not right. We probably want a per-root
481 bool animating
= false;
482 for (auto& pair
: host_connection_map_
)
483 animating
|= DecrementAnimatingViewsOpacity(pair
.first
->root_view());
485 animation_timer_
.Stop();
488 void ConnectionManager::AddConnection(ClientConnection
* connection
) {
489 DCHECK_EQ(0u, connection_map_
.count(connection
->service()->id()));
490 connection_map_
[connection
->service()->id()] = connection
;
493 ViewTreeHostImpl
* ConnectionManager::GetViewTreeHostByView(
494 const ServerView
* view
) const {
495 while (view
&& view
->parent())
496 view
= view
->parent();
497 for (auto& pair
: host_connection_map_
) {
498 if (view
== pair
.first
->root_view())
504 scoped_ptr
<cc::CompositorFrame
>
505 ConnectionManager::UpdateViewTreeFromCompositorFrame(
506 const mojo::CompositorFramePtr
& input
) {
507 return ConvertToCompositorFrame(input
, this);
510 surfaces::SurfacesState
* ConnectionManager::GetSurfacesState() {
511 return surfaces_state_
.get();
514 void ConnectionManager::PrepareToDestroyView(ServerView
* view
) {
515 if (!in_destructor_
&& IsViewAttachedToRoot(view
) &&
516 view
->id() != ClonedViewId()) {
517 // We're about to destroy a view. Any cloned views need to be reparented
518 // else the animation would no longer be visible. By moving to a visible
519 // view, view->parent(), we ensure the animation is still visible.
520 ServerView
* parent_above
= view
;
521 ReparentClonedViews(view
->parent(), &parent_above
, view
);
524 animation_runner_
.CancelAnimationForView(view
);
527 void ConnectionManager::PrepareToChangeViewHierarchy(ServerView
* view
,
528 ServerView
* new_parent
,
529 ServerView
* old_parent
) {
530 if (view
->id() == ClonedViewId() || in_destructor_
)
533 if (IsViewAttachedToRoot(view
)) {
534 // We're about to reparent a view. Any cloned views need to be reparented
535 // else the animation may be effected in unusual ways. For example, the view
536 // could move to a new location such that the animation is entirely clipped.
537 // By moving to view->parent() we ensure the animation is still visible.
538 ServerView
* parent_above
= view
;
539 ReparentClonedViews(view
->parent(), &parent_above
, view
);
542 animation_runner_
.CancelAnimationForView(view
);
545 void ConnectionManager::PrepareToChangeViewVisibility(ServerView
* view
) {
549 if (IsViewAttachedToRoot(view
) && view
->id() != ClonedViewId() &&
551 // We're about to hide |view|, this would implicitly make any cloned views
552 // hide too. Reparent so that animations are still visible.
553 ServerView
* parent_above
= view
;
554 ReparentClonedViews(view
->parent(), &parent_above
, view
);
557 const bool is_parent_drawn
= view
->parent() && view
->parent()->IsDrawn();
558 if (!is_parent_drawn
|| !view
->visible())
559 animation_runner_
.CancelAnimationForView(view
);
562 void ConnectionManager::OnScheduleViewPaint(const ServerView
* view
) {
564 SchedulePaint(view
, gfx::Rect(view
->bounds().size()));
567 const ServerView
* ConnectionManager::GetRootView(const ServerView
* view
) const {
568 ViewTreeHostImpl
* host
= GetViewTreeHostByView(view
);
569 return host
? host
->root_view() : nullptr;
572 void ConnectionManager::OnViewDestroyed(ServerView
* view
) {
574 ProcessViewDeleted(view
->id());
577 void ConnectionManager::OnWillChangeViewHierarchy(ServerView
* view
,
578 ServerView
* new_parent
,
579 ServerView
* old_parent
) {
580 if (view
->id() == ClonedViewId() || in_destructor_
)
583 ProcessWillChangeViewHierarchy(view
, new_parent
, old_parent
);
586 void ConnectionManager::OnViewHierarchyChanged(ServerView
* view
,
587 ServerView
* new_parent
,
588 ServerView
* old_parent
) {
592 ProcessViewHierarchyChanged(view
, new_parent
, old_parent
);
594 // TODO(beng): optimize.
596 SchedulePaint(old_parent
, gfx::Rect(old_parent
->bounds().size()));
598 SchedulePaint(new_parent
, gfx::Rect(new_parent
->bounds().size()));
601 void ConnectionManager::OnViewBoundsChanged(ServerView
* view
,
602 const gfx::Rect
& old_bounds
,
603 const gfx::Rect
& new_bounds
) {
607 ProcessViewBoundsChanged(view
, old_bounds
, new_bounds
);
611 // TODO(sky): optimize this.
612 SchedulePaint(view
->parent(), old_bounds
);
613 SchedulePaint(view
->parent(), new_bounds
);
616 void ConnectionManager::OnViewReordered(ServerView
* view
,
617 ServerView
* relative
,
618 mojo::OrderDirection direction
) {
620 SchedulePaint(view
, gfx::Rect(view
->bounds().size()));
623 void ConnectionManager::OnWillChangeViewVisibility(ServerView
* view
) {
627 // Need to repaint if the view was drawn (which means it's in the process of
628 // hiding) or the view is transitioning to drawn.
629 if (view
->parent() && (view
->IsDrawn() ||
630 (!view
->visible() && view
->parent()->IsDrawn()))) {
631 SchedulePaint(view
->parent(), view
->bounds());
634 for (auto& pair
: connection_map_
) {
635 pair
.second
->service()->ProcessWillChangeViewVisibility(
636 view
, IsChangeSource(pair
.first
));
640 void ConnectionManager::OnViewSharedPropertyChanged(
642 const std::string
& name
,
643 const std::vector
<uint8_t>* new_data
) {
644 for (auto& pair
: connection_map_
) {
645 pair
.second
->service()->ProcessViewPropertyChanged(
646 view
, name
, new_data
, IsChangeSource(pair
.first
));
650 void ConnectionManager::OnViewTextInputStateChanged(
652 const ui::TextInputState
& state
) {
653 // Do not need to update text input for unfocused views.
654 if (focus_controller_
->GetFocusedView() != view
)
657 ViewTreeHostImpl
* host
= GetViewTreeHostByView(view
);
658 host
->UpdateTextInputState(state
);
661 void ConnectionManager::CloneAndAnimate(mojo::Id transport_view_id
) {
662 CloneAndAnimate(ViewIdFromTransportId(transport_view_id
));
665 void ConnectionManager::OnFocusChanged(ServerView
* old_focused_view
,
666 ServerView
* new_focused_view
) {
667 // There are up to four connections that need to be notified:
668 // . the connection containing |old_focused_view|.
669 // . the connection with |old_focused_view| as its root.
670 // . the connection containing |new_focused_view|.
671 // . the connection with |new_focused_view| as its root.
672 // Some of these connections may be the same. The following takes care to
673 // notify each only once.
674 ViewTreeImpl
* owning_connection_old
= nullptr;
675 ViewTreeImpl
* embedded_connection_old
= nullptr;
677 if (old_focused_view
) {
678 owning_connection_old
= GetConnection(old_focused_view
->id().connection_id
);
679 if (owning_connection_old
) {
680 owning_connection_old
->ProcessFocusChanged(old_focused_view
,
683 embedded_connection_old
= GetConnectionWithRoot(old_focused_view
->id());
684 if (embedded_connection_old
) {
685 DCHECK_NE(owning_connection_old
, embedded_connection_old
);
686 embedded_connection_old
->ProcessFocusChanged(old_focused_view
,
690 ViewTreeImpl
* owning_connection_new
= nullptr;
691 ViewTreeImpl
* embedded_connection_new
= nullptr;
692 if (new_focused_view
) {
693 owning_connection_new
= GetConnection(new_focused_view
->id().connection_id
);
694 if (owning_connection_new
&&
695 owning_connection_new
!= owning_connection_old
&&
696 owning_connection_new
!= embedded_connection_old
) {
697 owning_connection_new
->ProcessFocusChanged(old_focused_view
,
700 embedded_connection_new
= GetConnectionWithRoot(new_focused_view
->id());
701 if (embedded_connection_new
&&
702 embedded_connection_new
!= owning_connection_old
&&
703 embedded_connection_new
!= embedded_connection_old
) {
704 DCHECK_NE(owning_connection_new
, embedded_connection_new
);
705 embedded_connection_new
->ProcessFocusChanged(old_focused_view
,
710 for (auto& pair
: host_connection_map_
) {
711 ViewTreeImpl
* service
= pair
.first
->GetViewTree();
712 if (service
!= owning_connection_old
&&
713 service
!= embedded_connection_old
&&
714 service
!= owning_connection_new
&&
715 service
!= embedded_connection_new
) {
716 service
->ProcessFocusChanged(old_focused_view
, new_focused_view
);
720 ViewTreeHostImpl
* old_host
=
721 old_focused_view
? GetViewTreeHostByView(old_focused_view
) : nullptr;
723 ViewTreeHostImpl
* new_host
=
724 new_focused_view
? GetViewTreeHostByView(new_focused_view
) : nullptr;
727 new_host
->UpdateTextInputState(new_focused_view
->text_input_state());
729 old_host
->UpdateTextInputState(ui::TextInputState());
732 bool ConnectionManager::ConvertSurfaceDrawQuad(const mojo::QuadPtr
& input
,
733 cc::SharedQuadState
* sqs
,
734 cc::RenderPass
* render_pass
) {
735 unsigned int id
= static_cast<unsigned int>(
736 input
->surface_quad_state
->surface
.To
<cc::SurfaceId
>().id
);
737 // TODO(fsamuel): Security check.
738 ServerView
* view
= GetView(ViewIdFromTransportId(id
));
739 // If a CompositorFrame message arrives late, say during a navigation, then
740 // it may contain view IDs that no longer exist.
743 gfx::Rect
bounds(input
->visible_rect
.To
<gfx::Rect
>());
745 sqs
->quad_to_target_transform
.TransformPoint(&p
);
746 bounds
.set_origin(p
);
747 view
->SetBounds(bounds
);
751 } // namespace view_manager