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/server_view.h"
9 #include "base/strings/stringprintf.h"
10 #include "components/view_manager/server_view_delegate.h"
11 #include "components/view_manager/server_view_observer.h"
12 #include "components/view_manager/surfaces/surfaces_state.h"
13 #include "mojo/converters/geometry/geometry_type_converters.h"
14 #include "mojo/converters/surfaces/surfaces_type_converters.h"
16 namespace view_manager
{
20 void CallCallback(const mojo::Closure
& callback
, cc::SurfaceDrawStatus status
) {
26 ServerView::ServerView(ServerViewDelegate
* delegate
, const ViewId
& id
)
27 : delegate_(delegate
),
32 pending_access_policy_(mojo::ViewTree::ACCESS_POLICY_DEFAULT
),
33 // Don't notify newly added observers during notification. This causes
34 // problems for code that adds an observer as part of an observer
35 // notification (such as ServerViewDrawTracker).
36 observers_(base::ObserverList
<ServerViewObserver
>::NOTIFY_EXISTING_ONLY
),
38 DCHECK(delegate
); // Must provide a delegate.
41 ServerView::~ServerView() {
42 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
, OnWillDestroyView(this));
44 while (!children_
.empty())
45 children_
.front()->parent()->Remove(children_
.front());
48 parent_
->Remove(this);
50 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
, OnViewDestroyed(this));
52 // SurfaceFactory's destructor will attempt to return resources which will
53 // call back into here and access |client_| so we should destroy
54 // |surface_factory_| early on.
55 surface_factory_
.reset();
58 void ServerView::AddObserver(ServerViewObserver
* observer
) {
59 observers_
.AddObserver(observer
);
62 void ServerView::RemoveObserver(ServerViewObserver
* observer
) {
63 observers_
.RemoveObserver(observer
);
66 void ServerView::Bind(mojo::InterfaceRequest
<Surface
> request
,
67 mojo::SurfaceClientPtr client
) {
68 if (binding_
.is_bound()) {
69 if (surface_factory_
) {
70 // Destroy frame surfaces submitted by the old client before replacing
71 // client_, so those surfaces will be returned to the old client.
72 surface_factory_
->DestroyAll();
73 SetSurfaceId(cc::SurfaceId());
78 binding_
.Bind(request
.Pass());
79 client_
= client
.Pass();
82 void ServerView::Add(ServerView
* child
) {
83 // We assume validation checks happened already.
85 DCHECK(child
!= this);
86 DCHECK(!child
->Contains(this));
87 if (child
->parent() == this) {
88 if (children_
.size() == 1)
89 return; // Already in the right position.
90 Reorder(child
, children_
.back(), mojo::ORDER_DIRECTION_ABOVE
);
94 ServerView
* old_parent
= child
->parent();
95 FOR_EACH_OBSERVER(ServerViewObserver
, child
->observers_
,
96 OnWillChangeViewHierarchy(child
, this, old_parent
));
99 child
->parent()->RemoveImpl(child
);
101 child
->parent_
= this;
102 children_
.push_back(child
);
103 FOR_EACH_OBSERVER(ServerViewObserver
, child
->observers_
,
104 OnViewHierarchyChanged(child
, this, old_parent
));
107 void ServerView::Remove(ServerView
* child
) {
108 // We assume validation checks happened else where.
110 DCHECK(child
!= this);
111 DCHECK(child
->parent() == this);
113 FOR_EACH_OBSERVER(ServerViewObserver
, child
->observers_
,
114 OnWillChangeViewHierarchy(child
, nullptr, this));
116 FOR_EACH_OBSERVER(ServerViewObserver
, child
->observers_
,
117 OnViewHierarchyChanged(child
, nullptr, this));
120 void ServerView::Reorder(ServerView
* child
,
121 ServerView
* relative
,
122 mojo::OrderDirection direction
) {
123 // We assume validation checks happened else where.
125 DCHECK(child
->parent() == this);
126 DCHECK_GT(children_
.size(), 1u);
127 children_
.erase(std::find(children_
.begin(), children_
.end(), child
));
128 Views::iterator i
= std::find(children_
.begin(), children_
.end(), relative
);
129 if (direction
== mojo::ORDER_DIRECTION_ABOVE
) {
130 DCHECK(i
!= children_
.end());
131 children_
.insert(++i
, child
);
132 } else if (direction
== mojo::ORDER_DIRECTION_BELOW
) {
133 DCHECK(i
!= children_
.end());
134 children_
.insert(i
, child
);
136 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
137 OnViewReordered(this, relative
, direction
));
140 void ServerView::SetBounds(const gfx::Rect
& bounds
) {
141 if (bounds_
== bounds
)
144 const gfx::Rect old_bounds
= bounds_
;
146 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
147 OnViewBoundsChanged(this, old_bounds
, bounds
));
150 const ServerView
* ServerView::GetRoot() const {
151 return delegate_
->GetRootView(this);
154 std::vector
<const ServerView
*> ServerView::GetChildren() const {
155 std::vector
<const ServerView
*> children
;
156 children
.reserve(children_
.size());
157 for (size_t i
= 0; i
< children_
.size(); ++i
)
158 children
.push_back(children_
[i
]);
162 std::vector
<ServerView
*> ServerView::GetChildren() {
163 // TODO(sky): rename to children() and fix return type.
167 bool ServerView::Contains(const ServerView
* view
) const {
168 for (const ServerView
* parent
= view
; parent
; parent
= parent
->parent_
) {
175 void ServerView::SetVisible(bool value
) {
176 if (visible_
== value
)
179 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
180 OnWillChangeViewVisibility(this));
182 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
183 OnViewVisibilityChanged(this));
186 void ServerView::SetOpacity(float value
) {
187 if (value
== opacity_
)
190 delegate_
->OnScheduleViewPaint(this);
193 void ServerView::SetTransform(const gfx::Transform
& transform
) {
194 if (transform_
== transform
)
197 transform_
= transform
;
198 delegate_
->OnScheduleViewPaint(this);
201 void ServerView::SetProperty(const std::string
& name
,
202 const std::vector
<uint8_t>* value
) {
203 auto it
= properties_
.find(name
);
204 if (it
!= properties_
.end()) {
205 if (value
&& it
->second
== *value
)
208 // This property isn't set in |properties_| and |value| is NULL, so there's
214 properties_
[name
] = *value
;
215 } else if (it
!= properties_
.end()) {
216 properties_
.erase(it
);
219 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
220 OnViewSharedPropertyChanged(this, name
, value
));
223 void ServerView::SetTextInputState(const ui::TextInputState
& state
) {
224 const bool changed
= !(text_input_state_
== state
);
226 text_input_state_
= state
;
227 // keyboard even if the state is not changed. So we have to notify
229 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
230 OnViewTextInputStateChanged(this, state
));
234 bool ServerView::IsDrawn() const {
235 const ServerView
* root
= delegate_
->GetRootView(this);
236 if (!root
|| !root
->visible())
238 const ServerView
* view
= this;
239 while (view
&& view
!= root
&& view
->visible())
240 view
= view
->parent();
244 void ServerView::SetSurfaceId(cc::SurfaceId surface_id
) {
245 surface_id_
= surface_id
;
246 delegate_
->OnScheduleViewPaint(this);
249 void ServerView::SubmitCompositorFrame(
250 mojo::CompositorFramePtr frame
,
251 const SubmitCompositorFrameCallback
& callback
) {
252 gfx::Size frame_size
= frame
->passes
[0]->output_rect
.To
<gfx::Rect
>().size();
253 // Create Surfaces state on demand.
254 if (!surface_factory_
) {
255 surface_factory_
.reset(
256 new cc::SurfaceFactory(delegate_
->GetSurfacesState()->manager(), this));
258 if (!surface_id_allocator_
) {
259 surface_id_allocator_
.reset(
260 new cc::SurfaceIdAllocator(
261 delegate_
->GetSurfacesState()->next_id_namespace()));
263 if (surface_id().is_null()) {
264 // Create a Surface ID for the first time for this view.
265 cc::SurfaceId
surface_id(surface_id_allocator_
->GenerateId());
266 surface_factory_
->Create(surface_id
);
267 SetSurfaceId(surface_id
);
269 // If the size of the CompostiorFrame has changed then destroy the existing
270 // Surface and create a new one of the appropriate size.
271 if (frame_size
!= last_submitted_frame_size()) {
272 surface_factory_
->Destroy(surface_id());
273 cc::SurfaceId
surface_id(surface_id_allocator_
->GenerateId());
274 surface_factory_
->Create(surface_id
);
275 SetSurfaceId(surface_id
);
278 surface_factory_
->SubmitCompositorFrame(
280 delegate_
->UpdateViewTreeFromCompositorFrame(frame
),
281 base::Bind(&CallCallback
, callback
));
282 delegate_
->GetSurfacesState()->scheduler()->SetNeedsDraw();
283 last_submitted_frame_size_
= frame_size
;
287 std::string
ServerView::GetDebugWindowHierarchy() const {
289 BuildDebugInfo(std::string(), &result
);
293 void ServerView::BuildDebugInfo(const std::string
& depth
,
294 std::string
* result
) const {
295 *result
+= base::StringPrintf(
296 "%sid=%d,%d visible=%s bounds=%d,%d %dx%d surface_id=%" PRIu64
"\n",
297 depth
.c_str(), static_cast<int>(id_
.connection_id
),
298 static_cast<int>(id_
.view_id
), visible_
? "true" : "false", bounds_
.x(),
299 bounds_
.y(), bounds_
.width(), bounds_
.height(), surface_id_
.id
);
300 for (const ServerView
* child
: children_
)
301 child
->BuildDebugInfo(depth
+ " ", result
);
305 void ServerView::ReturnResources(
306 const cc::ReturnedResourceArray
& resources
) {
309 client_
->ReturnResources(
310 mojo::Array
<mojo::ReturnedResourcePtr
>::From(resources
));
313 void ServerView::RemoveImpl(ServerView
* view
) {
314 view
->parent_
= NULL
;
315 children_
.erase(std::find(children_
.begin(), children_
.end(), view
));
318 } // namespace view_manager