Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / components / view_manager / server_view.cc
blobfe90ac9db9194262f1dafe2a26dae39a745bd485
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"
7 #include <inttypes.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 {
18 namespace {
20 void CallCallback(const mojo::Closure& callback, cc::SurfaceDrawStatus status) {
21 callback.Run();
24 } // namespace
26 ServerView::ServerView(ServerViewDelegate* delegate,
27 const ViewId& id)
28 : delegate_(delegate),
29 id_(id),
30 parent_(nullptr),
31 visible_(false),
32 opacity_(1),
33 allows_reembed_(false),
34 // Don't notify newly added observers during notification. This causes
35 // problems for code that adds an observer as part of an observer
36 // notification (such as ServerViewDrawTracker).
37 observers_(base::ObserverList<ServerViewObserver>::NOTIFY_EXISTING_ONLY),
38 binding_(this) {
39 DCHECK(delegate); // Must provide a delegate.
42 ServerView::~ServerView() {
43 FOR_EACH_OBSERVER(ServerViewObserver, observers_, OnWillDestroyView(this));
45 while (!children_.empty())
46 children_.front()->parent()->Remove(children_.front());
48 if (parent_)
49 parent_->Remove(this);
51 FOR_EACH_OBSERVER(ServerViewObserver, observers_, OnViewDestroyed(this));
53 // SurfaceFactory's destructor will attempt to return resources which will
54 // call back into here and access |client_| so we should destroy
55 // |surface_factory_| early on.
56 surface_factory_.reset();
59 void ServerView::AddObserver(ServerViewObserver* observer) {
60 observers_.AddObserver(observer);
63 void ServerView::RemoveObserver(ServerViewObserver* observer) {
64 observers_.RemoveObserver(observer);
67 void ServerView::Bind(mojo::InterfaceRequest<Surface> request,
68 mojo::SurfaceClientPtr client) {
69 if (binding_.is_bound()) {
70 if (surface_factory_) {
71 // Destroy frame surfaces submitted by the old client before replacing
72 // client_, so those surfaces will be returned to the old client.
73 surface_factory_->DestroyAll();
74 SetSurfaceId(cc::SurfaceId());
76 binding_.Close();
77 client_ = nullptr;
79 binding_.Bind(request.Pass());
80 client_ = client.Pass();
83 void ServerView::Add(ServerView* child) {
84 // We assume validation checks happened already.
85 DCHECK(child);
86 DCHECK(child != this);
87 DCHECK(!child->Contains(this));
88 if (child->parent() == this) {
89 if (children_.size() == 1)
90 return; // Already in the right position.
91 Reorder(child, children_.back(), mojo::ORDER_DIRECTION_ABOVE);
92 return;
95 ServerView* old_parent = child->parent();
96 FOR_EACH_OBSERVER(ServerViewObserver, child->observers_,
97 OnWillChangeViewHierarchy(child, this, old_parent));
99 if (child->parent())
100 child->parent()->RemoveImpl(child);
102 child->parent_ = this;
103 children_.push_back(child);
104 FOR_EACH_OBSERVER(ServerViewObserver, child->observers_,
105 OnViewHierarchyChanged(child, this, old_parent));
108 void ServerView::Remove(ServerView* child) {
109 // We assume validation checks happened else where.
110 DCHECK(child);
111 DCHECK(child != this);
112 DCHECK(child->parent() == this);
114 FOR_EACH_OBSERVER(ServerViewObserver, child->observers_,
115 OnWillChangeViewHierarchy(child, nullptr, this));
116 RemoveImpl(child);
117 FOR_EACH_OBSERVER(ServerViewObserver, child->observers_,
118 OnViewHierarchyChanged(child, nullptr, this));
121 void ServerView::Reorder(ServerView* child,
122 ServerView* relative,
123 mojo::OrderDirection direction) {
124 // We assume validation checks happened else where.
125 DCHECK(child);
126 DCHECK(child->parent() == this);
127 DCHECK_GT(children_.size(), 1u);
128 children_.erase(std::find(children_.begin(), children_.end(), child));
129 Views::iterator i = std::find(children_.begin(), children_.end(), relative);
130 if (direction == mojo::ORDER_DIRECTION_ABOVE) {
131 DCHECK(i != children_.end());
132 children_.insert(++i, child);
133 } else if (direction == mojo::ORDER_DIRECTION_BELOW) {
134 DCHECK(i != children_.end());
135 children_.insert(i, child);
137 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
138 OnViewReordered(this, relative, direction));
141 void ServerView::SetBounds(const gfx::Rect& bounds) {
142 if (bounds_ == bounds)
143 return;
145 const gfx::Rect old_bounds = bounds_;
146 bounds_ = bounds;
147 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
148 OnViewBoundsChanged(this, old_bounds, bounds));
151 const ServerView* ServerView::GetRoot() const {
152 return delegate_->GetRootView(this);
155 std::vector<const ServerView*> ServerView::GetChildren() const {
156 std::vector<const ServerView*> children;
157 children.reserve(children_.size());
158 for (size_t i = 0; i < children_.size(); ++i)
159 children.push_back(children_[i]);
160 return children;
163 std::vector<ServerView*> ServerView::GetChildren() {
164 // TODO(sky): rename to children() and fix return type.
165 return children_;
168 bool ServerView::Contains(const ServerView* view) const {
169 for (const ServerView* parent = view; parent; parent = parent->parent_) {
170 if (parent == this)
171 return true;
173 return false;
176 void ServerView::SetVisible(bool value) {
177 if (visible_ == value)
178 return;
180 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
181 OnWillChangeViewVisibility(this));
182 visible_ = value;
183 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
184 OnViewVisibilityChanged(this));
187 void ServerView::SetOpacity(float value) {
188 if (value == opacity_)
189 return;
190 opacity_ = value;
191 delegate_->OnScheduleViewPaint(this);
194 void ServerView::SetTransform(const gfx::Transform& transform) {
195 if (transform_ == transform)
196 return;
198 transform_ = transform;
199 delegate_->OnScheduleViewPaint(this);
202 void ServerView::SetProperty(const std::string& name,
203 const std::vector<uint8_t>* value) {
204 auto it = properties_.find(name);
205 if (it != properties_.end()) {
206 if (value && it->second == *value)
207 return;
208 } else if (!value) {
209 // This property isn't set in |properties_| and |value| is NULL, so there's
210 // no change.
211 return;
214 if (value) {
215 properties_[name] = *value;
216 } else if (it != properties_.end()) {
217 properties_.erase(it);
220 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
221 OnViewSharedPropertyChanged(this, name, value));
224 void ServerView::SetTextInputState(const ui::TextInputState& state) {
225 const bool changed = !(text_input_state_ == state);
226 if (changed) {
227 text_input_state_ = state;
228 // keyboard even if the state is not changed. So we have to notify
229 // |observers_|.
230 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
231 OnViewTextInputStateChanged(this, state));
235 bool ServerView::IsDrawn() const {
236 const ServerView* root = delegate_->GetRootView(this);
237 if (!root || !root->visible())
238 return false;
239 const ServerView* view = this;
240 while (view && view != root && view->visible())
241 view = view->parent();
242 return root == view;
245 void ServerView::SetSurfaceId(cc::SurfaceId surface_id) {
246 surface_id_ = surface_id;
247 delegate_->OnScheduleViewPaint(this);
250 void ServerView::SubmitCompositorFrame(
251 mojo::CompositorFramePtr frame,
252 const SubmitCompositorFrameCallback& callback) {
253 gfx::Size frame_size = frame->passes[0]->output_rect.To<gfx::Rect>().size();
254 // Create Surfaces state on demand.
255 if (!surface_factory_) {
256 surface_factory_.reset(
257 new cc::SurfaceFactory(delegate_->GetSurfacesState()->manager(), this));
259 if (!surface_id_allocator_) {
260 surface_id_allocator_.reset(
261 new cc::SurfaceIdAllocator(
262 delegate_->GetSurfacesState()->next_id_namespace()));
264 if (surface_id().is_null()) {
265 // Create a Surface ID for the first time for this view.
266 cc::SurfaceId surface_id(surface_id_allocator_->GenerateId());
267 surface_factory_->Create(surface_id);
268 SetSurfaceId(surface_id);
269 } else {
270 // If the size of the CompostiorFrame has changed then destroy the existing
271 // Surface and create a new one of the appropriate size.
272 if (frame_size != last_submitted_frame_size()) {
273 surface_factory_->Destroy(surface_id());
274 cc::SurfaceId surface_id(surface_id_allocator_->GenerateId());
275 surface_factory_->Create(surface_id);
276 SetSurfaceId(surface_id);
279 surface_factory_->SubmitCompositorFrame(
280 surface_id(),
281 delegate_->UpdateViewTreeFromCompositorFrame(frame),
282 base::Bind(&CallCallback, callback));
283 delegate_->GetSurfacesState()->scheduler()->SetNeedsDraw();
284 last_submitted_frame_size_ = frame_size;
287 #if !defined(NDEBUG)
288 std::string ServerView::GetDebugWindowHierarchy() const {
289 std::string result;
290 BuildDebugInfo(std::string(), &result);
291 return result;
294 void ServerView::BuildDebugInfo(const std::string& depth,
295 std::string* result) const {
296 *result += base::StringPrintf(
297 "%sid=%d,%d visible=%s bounds=%d,%d %dx%d surface_id=%" PRIu64 "\n",
298 depth.c_str(), static_cast<int>(id_.connection_id),
299 static_cast<int>(id_.view_id), visible_ ? "true" : "false", bounds_.x(),
300 bounds_.y(), bounds_.width(), bounds_.height(), surface_id_.id);
301 for (const ServerView* child : children_)
302 child->BuildDebugInfo(depth + " ", result);
304 #endif
306 void ServerView::ReturnResources(
307 const cc::ReturnedResourceArray& resources) {
308 if (!client_)
309 return;
310 client_->ReturnResources(
311 mojo::Array<mojo::ReturnedResourcePtr>::From(resources));
314 void ServerView::RemoveImpl(ServerView* view) {
315 view->parent_ = NULL;
316 children_.erase(std::find(children_.begin(), children_.end(), view));
319 } // namespace view_manager