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"
13 namespace view_manager
{
15 ServerView::ServerView(ServerViewDelegate
* delegate
, const ViewId
& id
)
16 : delegate_(delegate
),
21 allows_reembed_(false),
22 // Don't notify newly added observers during notification. This causes
23 // problems for code that adds an observer as part of an observer
24 // notification (such as ServerViewDrawTracker).
25 observers_(base::ObserverList
<ServerViewObserver
>::NOTIFY_EXISTING_ONLY
) {
26 DCHECK(delegate
); // Must provide a delegate.
29 ServerView::~ServerView() {
30 delegate_
->PrepareToDestroyView(this);
31 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
, OnWillDestroyView(this));
33 while (!children_
.empty())
34 children_
.front()->parent()->Remove(children_
.front());
37 parent_
->Remove(this);
39 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
, OnViewDestroyed(this));
42 void ServerView::AddObserver(ServerViewObserver
* observer
) {
43 observers_
.AddObserver(observer
);
46 void ServerView::RemoveObserver(ServerViewObserver
* observer
) {
47 observers_
.RemoveObserver(observer
);
50 void ServerView::Add(ServerView
* child
) {
51 // We assume validation checks happened already.
53 DCHECK(child
!= this);
54 DCHECK(!child
->Contains(this));
55 if (child
->parent() == this) {
56 if (children_
.size() == 1)
57 return; // Already in the right position.
58 Reorder(child
, children_
.back(), mojo::ORDER_DIRECTION_ABOVE
);
62 ServerView
* old_parent
= child
->parent();
63 child
->delegate_
->PrepareToChangeViewHierarchy(child
, this, old_parent
);
64 FOR_EACH_OBSERVER(ServerViewObserver
, child
->observers_
,
65 OnWillChangeViewHierarchy(child
, this, old_parent
));
68 child
->parent()->RemoveImpl(child
);
70 child
->parent_
= this;
71 children_
.push_back(child
);
72 FOR_EACH_OBSERVER(ServerViewObserver
, child
->observers_
,
73 OnViewHierarchyChanged(child
, this, old_parent
));
76 void ServerView::Remove(ServerView
* child
) {
77 // We assume validation checks happened else where.
79 DCHECK(child
!= this);
80 DCHECK(child
->parent() == this);
82 child
->delegate_
->PrepareToChangeViewHierarchy(child
, NULL
, this);
83 FOR_EACH_OBSERVER(ServerViewObserver
, child
->observers_
,
84 OnWillChangeViewHierarchy(child
, nullptr, this));
86 FOR_EACH_OBSERVER(ServerViewObserver
, child
->observers_
,
87 OnViewHierarchyChanged(child
, nullptr, this));
90 void ServerView::Reorder(ServerView
* child
,
92 mojo::OrderDirection direction
) {
93 // We assume validation checks happened else where.
95 DCHECK(child
->parent() == this);
96 DCHECK_GT(children_
.size(), 1u);
97 children_
.erase(std::find(children_
.begin(), children_
.end(), child
));
98 Views::iterator i
= std::find(children_
.begin(), children_
.end(), relative
);
99 if (direction
== mojo::ORDER_DIRECTION_ABOVE
) {
100 DCHECK(i
!= children_
.end());
101 children_
.insert(++i
, child
);
102 } else if (direction
== mojo::ORDER_DIRECTION_BELOW
) {
103 DCHECK(i
!= children_
.end());
104 children_
.insert(i
, child
);
106 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
107 OnViewReordered(this, relative
, direction
));
110 void ServerView::SetBounds(const gfx::Rect
& bounds
) {
111 if (bounds_
== bounds
)
114 const gfx::Rect old_bounds
= bounds_
;
116 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
117 OnViewBoundsChanged(this, old_bounds
, bounds
));
120 const ServerView
* ServerView::GetRoot() const {
121 return delegate_
->GetRootView(this);
124 std::vector
<const ServerView
*> ServerView::GetChildren() const {
125 std::vector
<const ServerView
*> children
;
126 children
.reserve(children_
.size());
127 for (size_t i
= 0; i
< children_
.size(); ++i
)
128 children
.push_back(children_
[i
]);
132 std::vector
<ServerView
*> ServerView::GetChildren() {
133 // TODO(sky): rename to children() and fix return type.
137 bool ServerView::Contains(const ServerView
* view
) const {
138 for (const ServerView
* parent
= view
; parent
; parent
= parent
->parent_
) {
145 void ServerView::SetVisible(bool value
) {
146 if (visible_
== value
)
149 delegate_
->PrepareToChangeViewVisibility(this);
150 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
151 OnWillChangeViewVisibility(this));
153 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
154 OnViewVisibilityChanged(this));
157 void ServerView::SetOpacity(float value
) {
158 if (value
== opacity_
)
161 delegate_
->OnScheduleViewPaint(this);
164 void ServerView::SetTransform(const gfx::Transform
& transform
) {
165 if (transform_
== transform
)
168 transform_
= transform
;
169 delegate_
->OnScheduleViewPaint(this);
172 void ServerView::SetProperty(const std::string
& name
,
173 const std::vector
<uint8_t>* value
) {
174 auto it
= properties_
.find(name
);
175 if (it
!= properties_
.end()) {
176 if (value
&& it
->second
== *value
)
179 // This property isn't set in |properties_| and |value| is NULL, so there's
185 properties_
[name
] = *value
;
186 } else if (it
!= properties_
.end()) {
187 properties_
.erase(it
);
190 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
191 OnViewSharedPropertyChanged(this, name
, value
));
194 void ServerView::SetTextInputState(const ui::TextInputState
& state
) {
195 const bool changed
= !(text_input_state_
== state
);
197 text_input_state_
= state
;
198 // keyboard even if the state is not changed. So we have to notify
200 FOR_EACH_OBSERVER(ServerViewObserver
, observers_
,
201 OnViewTextInputStateChanged(this, state
));
205 bool ServerView::IsDrawn() const {
206 const ServerView
* root
= delegate_
->GetRootView(this);
207 if (!root
|| !root
->visible())
209 const ServerView
* view
= this;
210 while (view
&& view
!= root
&& view
->visible())
211 view
= view
->parent();
215 void ServerView::SetSurfaceId(cc::SurfaceId surface_id
) {
216 surface_id_
= surface_id
;
217 delegate_
->OnScheduleViewPaint(this);
221 std::string
ServerView::GetDebugWindowHierarchy() const {
223 BuildDebugInfo(std::string(), &result
);
227 void ServerView::BuildDebugInfo(const std::string
& depth
,
228 std::string
* result
) const {
229 *result
+= base::StringPrintf(
230 "%sid=%d,%d visible=%s bounds=%d,%d %dx%d surface_id=%" PRIu64
"\n",
231 depth
.c_str(), static_cast<int>(id_
.connection_id
),
232 static_cast<int>(id_
.view_id
), visible_
? "true" : "false", bounds_
.x(),
233 bounds_
.y(), bounds_
.width(), bounds_
.height(), surface_id_
.id
);
234 for (const ServerView
* child
: children_
)
235 child
->BuildDebugInfo(depth
+ " ", result
);
239 void ServerView::RemoveImpl(ServerView
* view
) {
240 view
->parent_
= NULL
;
241 children_
.erase(std::find(children_
.begin(), children_
.end(), view
));
244 } // namespace view_manager