Vectorize website settings icons in omnibox
[chromium-blink-merge.git] / components / view_manager / server_view.cc
blob3817c445f965d543b83cfb52b5494fd687980d25
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 delegate_->PrepareToDestroyView(this);
44 FOR_EACH_OBSERVER(ServerViewObserver, observers_, OnWillDestroyView(this));
46 while (!children_.empty())
47 children_.front()->parent()->Remove(children_.front());
49 if (parent_)
50 parent_->Remove(this);
52 FOR_EACH_OBSERVER(ServerViewObserver, observers_, OnViewDestroyed(this));
54 // SurfaceFactory's destructor will attempt to return resources which will
55 // call back into here and access |client_| so we should destroy
56 // |surface_factory_| early on.
57 surface_factory_.reset();
60 void ServerView::AddObserver(ServerViewObserver* observer) {
61 observers_.AddObserver(observer);
64 void ServerView::RemoveObserver(ServerViewObserver* observer) {
65 observers_.RemoveObserver(observer);
68 void ServerView::Bind(mojo::InterfaceRequest<Surface> request,
69 mojo::SurfaceClientPtr client) {
70 if (binding_.is_bound()) {
71 binding_.Close();
72 client_ = nullptr;
74 binding_.Bind(request.Pass());
75 client_ = client.Pass();
78 void ServerView::Add(ServerView* child) {
79 // We assume validation checks happened already.
80 DCHECK(child);
81 DCHECK(child != this);
82 DCHECK(!child->Contains(this));
83 if (child->parent() == this) {
84 if (children_.size() == 1)
85 return; // Already in the right position.
86 Reorder(child, children_.back(), mojo::ORDER_DIRECTION_ABOVE);
87 return;
90 ServerView* old_parent = child->parent();
91 child->delegate_->PrepareToChangeViewHierarchy(child, this, old_parent);
92 FOR_EACH_OBSERVER(ServerViewObserver, child->observers_,
93 OnWillChangeViewHierarchy(child, this, old_parent));
95 if (child->parent())
96 child->parent()->RemoveImpl(child);
98 child->parent_ = this;
99 children_.push_back(child);
100 FOR_EACH_OBSERVER(ServerViewObserver, child->observers_,
101 OnViewHierarchyChanged(child, this, old_parent));
104 void ServerView::Remove(ServerView* child) {
105 // We assume validation checks happened else where.
106 DCHECK(child);
107 DCHECK(child != this);
108 DCHECK(child->parent() == this);
110 child->delegate_->PrepareToChangeViewHierarchy(child, NULL, this);
111 FOR_EACH_OBSERVER(ServerViewObserver, child->observers_,
112 OnWillChangeViewHierarchy(child, nullptr, this));
113 RemoveImpl(child);
114 FOR_EACH_OBSERVER(ServerViewObserver, child->observers_,
115 OnViewHierarchyChanged(child, nullptr, this));
118 void ServerView::Reorder(ServerView* child,
119 ServerView* relative,
120 mojo::OrderDirection direction) {
121 // We assume validation checks happened else where.
122 DCHECK(child);
123 DCHECK(child->parent() == this);
124 DCHECK_GT(children_.size(), 1u);
125 children_.erase(std::find(children_.begin(), children_.end(), child));
126 Views::iterator i = std::find(children_.begin(), children_.end(), relative);
127 if (direction == mojo::ORDER_DIRECTION_ABOVE) {
128 DCHECK(i != children_.end());
129 children_.insert(++i, child);
130 } else if (direction == mojo::ORDER_DIRECTION_BELOW) {
131 DCHECK(i != children_.end());
132 children_.insert(i, child);
134 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
135 OnViewReordered(this, relative, direction));
138 void ServerView::SetBounds(const gfx::Rect& bounds) {
139 if (bounds_ == bounds)
140 return;
142 const gfx::Rect old_bounds = bounds_;
143 bounds_ = bounds;
144 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
145 OnViewBoundsChanged(this, old_bounds, bounds));
148 const ServerView* ServerView::GetRoot() const {
149 return delegate_->GetRootView(this);
152 std::vector<const ServerView*> ServerView::GetChildren() const {
153 std::vector<const ServerView*> children;
154 children.reserve(children_.size());
155 for (size_t i = 0; i < children_.size(); ++i)
156 children.push_back(children_[i]);
157 return children;
160 std::vector<ServerView*> ServerView::GetChildren() {
161 // TODO(sky): rename to children() and fix return type.
162 return children_;
165 bool ServerView::Contains(const ServerView* view) const {
166 for (const ServerView* parent = view; parent; parent = parent->parent_) {
167 if (parent == this)
168 return true;
170 return false;
173 void ServerView::SetVisible(bool value) {
174 if (visible_ == value)
175 return;
177 delegate_->PrepareToChangeViewVisibility(this);
178 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
179 OnWillChangeViewVisibility(this));
180 visible_ = value;
181 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
182 OnViewVisibilityChanged(this));
185 void ServerView::SetOpacity(float value) {
186 if (value == opacity_)
187 return;
188 opacity_ = value;
189 delegate_->OnScheduleViewPaint(this);
192 void ServerView::SetTransform(const gfx::Transform& transform) {
193 if (transform_ == transform)
194 return;
196 transform_ = transform;
197 delegate_->OnScheduleViewPaint(this);
200 void ServerView::SetProperty(const std::string& name,
201 const std::vector<uint8_t>* value) {
202 auto it = properties_.find(name);
203 if (it != properties_.end()) {
204 if (value && it->second == *value)
205 return;
206 } else if (!value) {
207 // This property isn't set in |properties_| and |value| is NULL, so there's
208 // no change.
209 return;
212 if (value) {
213 properties_[name] = *value;
214 } else if (it != properties_.end()) {
215 properties_.erase(it);
218 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
219 OnViewSharedPropertyChanged(this, name, value));
222 void ServerView::SetTextInputState(const ui::TextInputState& state) {
223 const bool changed = !(text_input_state_ == state);
224 if (changed) {
225 text_input_state_ = state;
226 // keyboard even if the state is not changed. So we have to notify
227 // |observers_|.
228 FOR_EACH_OBSERVER(ServerViewObserver, observers_,
229 OnViewTextInputStateChanged(this, state));
233 bool ServerView::IsDrawn() const {
234 const ServerView* root = delegate_->GetRootView(this);
235 if (!root || !root->visible())
236 return false;
237 const ServerView* view = this;
238 while (view && view != root && view->visible())
239 view = view->parent();
240 return root == view;
243 void ServerView::SetSurfaceId(cc::SurfaceId surface_id) {
244 surface_id_ = surface_id;
245 delegate_->OnScheduleViewPaint(this);
248 void ServerView::SubmitCompositorFrame(
249 mojo::CompositorFramePtr frame,
250 const SubmitCompositorFrameCallback& callback) {
251 gfx::Size frame_size = frame->passes[0]->output_rect.To<gfx::Rect>().size();
252 // Create Surfaces state on demand.
253 if (!surface_factory_) {
254 surface_factory_.reset(
255 new cc::SurfaceFactory(delegate_->GetSurfacesState()->manager(), this));
257 if (!surface_id_allocator_) {
258 surface_id_allocator_.reset(
259 new cc::SurfaceIdAllocator(
260 delegate_->GetSurfacesState()->next_id_namespace()));
262 if (surface_id().is_null()) {
263 // Create a Surface ID for the first time for this view.
264 cc::SurfaceId surface_id(surface_id_allocator_->GenerateId());
265 surface_factory_->Create(surface_id);
266 SetSurfaceId(surface_id);
267 } else {
268 // If the size of the CompostiorFrame has changed then destroy the existing
269 // Surface and create a new one of the appropriate size.
270 if (frame_size != last_submitted_frame_size()) {
271 surface_factory_->Destroy(surface_id());
272 cc::SurfaceId surface_id(surface_id_allocator_->GenerateId());
273 surface_factory_->Create(surface_id);
274 SetSurfaceId(surface_id);
277 surface_factory_->SubmitCompositorFrame(
278 surface_id(),
279 delegate_->UpdateViewTreeFromCompositorFrame(frame),
280 base::Bind(&CallCallback, callback));
281 delegate_->GetSurfacesState()->scheduler()->SetNeedsDraw();
282 last_submitted_frame_size_ = frame_size;
285 #if !defined(NDEBUG)
286 std::string ServerView::GetDebugWindowHierarchy() const {
287 std::string result;
288 BuildDebugInfo(std::string(), &result);
289 return result;
292 void ServerView::BuildDebugInfo(const std::string& depth,
293 std::string* result) const {
294 *result += base::StringPrintf(
295 "%sid=%d,%d visible=%s bounds=%d,%d %dx%d surface_id=%" PRIu64 "\n",
296 depth.c_str(), static_cast<int>(id_.connection_id),
297 static_cast<int>(id_.view_id), visible_ ? "true" : "false", bounds_.x(),
298 bounds_.y(), bounds_.width(), bounds_.height(), surface_id_.id);
299 for (const ServerView* child : children_)
300 child->BuildDebugInfo(depth + " ", result);
302 #endif
304 void ServerView::ReturnResources(
305 const cc::ReturnedResourceArray& resources) {
306 if (!client_)
307 return;
308 client_->ReturnResources(
309 mojo::Array<mojo::ReturnedResourcePtr>::From(resources));
312 void ServerView::RemoveImpl(ServerView* view) {
313 view->parent_ = NULL;
314 children_.erase(std::find(children_.begin(), children_.end(), view));
317 } // namespace view_manager