| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "services/ui/view_manager/view_registry.h" |
| 6 |
| 5 #include <algorithm> | 7 #include <algorithm> |
| 6 #include <utility> | 8 #include <utility> |
| 7 | 9 |
| 8 #include "base/bind.h" | 10 #include "base/bind.h" |
| 9 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 10 #include "services/ui/view_manager/surface_manager.h" | 12 #include "mojo/services/ui/views/cpp/logging.h" |
| 11 #include "services/ui/view_manager/view_host_impl.h" | 13 #include "services/ui/view_manager/view_host_impl.h" |
| 12 #include "services/ui/view_manager/view_registry.h" | |
| 13 #include "services/ui/view_manager/view_tree_host_impl.h" | 14 #include "services/ui/view_manager/view_tree_host_impl.h" |
| 14 | 15 |
| 15 namespace view_manager { | 16 namespace view_manager { |
| 16 | 17 |
| 17 static bool AreViewLayoutParamsValid(const mojo::ui::ViewLayoutParams* params) { | 18 static bool AreViewLayoutParamsValid(const mojo::ui::ViewLayoutParams* params) { |
| 18 return params && params->constraints && params->constraints->min_width >= 0 && | 19 return params && params->constraints && params->constraints->min_width >= 0 && |
| 19 params->constraints->max_width >= params->constraints->min_width && | 20 params->constraints->max_width >= params->constraints->min_width && |
| 20 params->constraints->min_height >= 0 && | 21 params->constraints->min_height >= 0 && |
| 21 params->constraints->max_height >= params->constraints->min_height && | 22 params->constraints->max_height >= params->constraints->min_height && |
| 22 params->device_pixel_ratio > 0; | 23 params->device_pixel_ratio > 0; |
| 23 } | 24 } |
| 24 | 25 |
| 25 static std::ostream& operator<<(std::ostream& os, const mojo::Size* size) { | 26 ViewRegistry::ViewRegistry(mojo::gfx::composition::CompositorPtr compositor) |
| 26 return size | 27 : compositor_(compositor.Pass()) {} |
| 27 ? os << "{width=" << size->width << ", height=" << size->height | |
| 28 << "}" | |
| 29 : os << "{null}"; | |
| 30 } | |
| 31 | |
| 32 static std::ostream& operator<<(std::ostream& os, | |
| 33 const mojo::SurfaceId* surface_id) { | |
| 34 return surface_id | |
| 35 ? os << "{id_namespace=" << surface_id->id_namespace | |
| 36 << ", local=" << surface_id->local << "}" | |
| 37 : os << "{null}"; | |
| 38 } | |
| 39 | |
| 40 static std::ostream& operator<<(std::ostream& os, | |
| 41 const mojo::ui::ViewToken* token) { | |
| 42 return token ? os << "{token=" << token->value << "}" : os << "{null}"; | |
| 43 } | |
| 44 | |
| 45 static std::ostream& operator<<(std::ostream& os, const ViewState* view_state) { | |
| 46 return view_state ? os << "{token=" << view_state->view_token_value() << "}" | |
| 47 : os << "{null}"; | |
| 48 } | |
| 49 | |
| 50 static std::ostream& operator<<(std::ostream& os, | |
| 51 const mojo::ui::BoxConstraints* constraints) { | |
| 52 return constraints | |
| 53 ? os << "{min_width=" << constraints->min_width | |
| 54 << ", max_width=" << constraints->max_width | |
| 55 << ", min_height=" << constraints->min_height | |
| 56 << ", max_height=" << constraints->max_height << "}" | |
| 57 : os << "{null}"; | |
| 58 }; | |
| 59 | |
| 60 static std::ostream& operator<<(std::ostream& os, | |
| 61 const mojo::ui::ViewLayoutParams* params) { | |
| 62 return params | |
| 63 ? os << "{constraints=" << params->constraints.get() | |
| 64 << ", device_pixel_ratio=" << params->device_pixel_ratio | |
| 65 << "}" | |
| 66 : os << "{null}"; | |
| 67 } | |
| 68 | |
| 69 static std::ostream& operator<<(std::ostream& os, | |
| 70 const mojo::ui::ViewLayoutInfo* info) { | |
| 71 return info | |
| 72 ? os << "{size=" << info->size.get() | |
| 73 << ", surface_id=" << info->surface_id.get() << "}" | |
| 74 : os << "{null}"; | |
| 75 } | |
| 76 | |
| 77 ViewRegistry::ViewRegistry(SurfaceManager* surface_manager) | |
| 78 : surface_manager_(surface_manager), next_view_token_value_(1u) {} | |
| 79 | 28 |
| 80 ViewRegistry::~ViewRegistry() {} | 29 ViewRegistry::~ViewRegistry() {} |
| 81 | 30 |
| 31 void ViewRegistry::ConnectAssociates( |
| 32 mojo::ApplicationImpl* app_impl, |
| 33 const std::vector<std::string>& urls, |
| 34 const AssociateConnectionErrorCallback& connection_error_callback) { |
| 35 associate_table_.ConnectAssociates(app_impl, this, urls, |
| 36 connection_error_callback); |
| 37 } |
| 38 |
| 82 mojo::ui::ViewTokenPtr ViewRegistry::RegisterView( | 39 mojo::ui::ViewTokenPtr ViewRegistry::RegisterView( |
| 83 mojo::ui::ViewPtr view, | 40 mojo::ui::ViewPtr view, |
| 84 mojo::InterfaceRequest<mojo::ui::ViewHost> view_host_request) { | 41 mojo::InterfaceRequest<mojo::ui::ViewHost> view_host_request, |
| 42 const mojo::String& label) { |
| 85 DCHECK(view); | 43 DCHECK(view); |
| 86 uint32_t view_token_value = next_view_token_value_++; | 44 |
| 87 DCHECK(!FindView(view_token_value)); | 45 auto view_token = mojo::ui::ViewToken::New(); |
| 46 view_token->value = next_view_token_value_++; |
| 47 CHECK(view_token->value); |
| 48 CHECK(!FindView(view_token->value)); |
| 88 | 49 |
| 89 // Create the state and bind host to it. | 50 // Create the state and bind host to it. |
| 90 ViewState* view_state = new ViewState(view.Pass(), view_token_value); | 51 std::string sanitized_label = |
| 52 label.get().substr(0, mojo::ui::kLabelMaxLength); |
| 53 ViewState* view_state = |
| 54 new ViewState(view.Pass(), view_token.Pass(), sanitized_label); |
| 91 ViewHostImpl* view_host = | 55 ViewHostImpl* view_host = |
| 92 new ViewHostImpl(this, view_state, view_host_request.Pass()); | 56 new ViewHostImpl(this, view_state, view_host_request.Pass()); |
| 93 view_state->set_view_host(view_host); | 57 view_state->set_view_host(view_host); |
| 94 view_state->set_view_connection_error_handler( | 58 view_state->set_view_connection_error_handler( |
| 95 base::Bind(&ViewRegistry::OnViewConnectionError, base::Unretained(this), | 59 base::Bind(&ViewRegistry::OnViewConnectionError, base::Unretained(this), |
| 96 view_state)); | 60 view_state)); |
| 97 view_host->set_view_host_connection_error_handler( | 61 view_host->set_view_host_connection_error_handler( |
| 98 base::Bind(&ViewRegistry::OnViewConnectionError, base::Unretained(this), | 62 base::Bind(&ViewRegistry::OnViewConnectionError, base::Unretained(this), |
| 99 view_state)); | 63 view_state)); |
| 100 | 64 |
| 101 // Add to registry and return token. | 65 // Add to registry and return token. |
| 102 views_by_token_.insert({view_token_value, view_state}); | 66 views_by_token_.insert({view_state->view_token()->value, view_state}); |
| 103 mojo::ui::ViewTokenPtr token = mojo::ui::ViewToken::New(); | |
| 104 token->value = view_state->view_token_value(); | |
| 105 DVLOG(1) << "RegisterView: view=" << view_state; | 67 DVLOG(1) << "RegisterView: view=" << view_state; |
| 106 return token; | 68 return view_state->view_token()->Clone(); |
| 107 } | 69 } |
| 108 | 70 |
| 109 void ViewRegistry::OnViewConnectionError(ViewState* view_state) { | 71 void ViewRegistry::OnViewConnectionError(ViewState* view_state) { |
| 110 DCHECK(IsViewStateRegisteredDebug(view_state)); | 72 DCHECK(IsViewStateRegisteredDebug(view_state)); |
| 111 DVLOG(1) << "OnViewConnectionError: view=" << view_state; | 73 DVLOG(1) << "OnViewConnectionError: view=" << view_state; |
| 112 | 74 |
| 113 UnregisterView(view_state); | 75 UnregisterView(view_state); |
| 114 } | 76 } |
| 115 | 77 |
| 116 void ViewRegistry::UnregisterView(ViewState* view_state) { | 78 void ViewRegistry::UnregisterView(ViewState* view_state) { |
| 117 DCHECK(IsViewStateRegisteredDebug(view_state)); | 79 DCHECK(IsViewStateRegisteredDebug(view_state)); |
| 118 DVLOG(1) << "UnregisterView: view=" << view_state; | 80 DVLOG(1) << "UnregisterView: view=" << view_state; |
| 119 | 81 |
| 120 // Remove from parent or roots. | 82 // Remove from parent or roots. |
| 121 HijackView(view_state); | 83 HijackView(view_state); |
| 122 | 84 |
| 123 // Remove from registry. | 85 // Remove from registry. |
| 124 views_by_token_.erase(view_state->view_token_value()); | 86 views_by_token_.erase(view_state->view_token()->value); |
| 125 delete view_state; | 87 delete view_state; |
| 126 } | 88 } |
| 127 | 89 |
| 128 void ViewRegistry::RegisterViewTree( | 90 mojo::ui::ViewTreeTokenPtr ViewRegistry::RegisterViewTree( |
| 129 mojo::ui::ViewTreePtr view_tree, | 91 mojo::ui::ViewTreePtr view_tree, |
| 130 mojo::InterfaceRequest<mojo::ui::ViewTreeHost> view_tree_host_request) { | 92 mojo::InterfaceRequest<mojo::ui::ViewTreeHost> view_tree_host_request, |
| 93 const mojo::String& label) { |
| 131 DCHECK(view_tree); | 94 DCHECK(view_tree); |
| 132 | 95 |
| 96 auto view_tree_token = mojo::ui::ViewTreeToken::New(); |
| 97 view_tree_token->value = next_view_tree_token_value_++; |
| 98 CHECK(view_tree_token->value); |
| 99 CHECK(!FindViewTree(view_tree_token->value)); |
| 100 |
| 133 // Create the state and bind host to it. | 101 // Create the state and bind host to it. |
| 134 ViewTreeState* tree_state = new ViewTreeState(view_tree.Pass()); | 102 std::string sanitized_label = |
| 103 label.get().substr(0, mojo::ui::kLabelMaxLength); |
| 104 ViewTreeState* tree_state = new ViewTreeState( |
| 105 view_tree.Pass(), view_tree_token.Pass(), sanitized_label); |
| 135 ViewTreeHostImpl* tree_host = | 106 ViewTreeHostImpl* tree_host = |
| 136 new ViewTreeHostImpl(this, tree_state, view_tree_host_request.Pass()); | 107 new ViewTreeHostImpl(this, tree_state, view_tree_host_request.Pass()); |
| 137 tree_state->set_view_tree_host(tree_host); | 108 tree_state->set_view_tree_host(tree_host); |
| 138 tree_state->set_view_tree_connection_error_handler( | 109 tree_state->set_view_tree_connection_error_handler( |
| 139 base::Bind(&ViewRegistry::OnViewTreeConnectionError, | 110 base::Bind(&ViewRegistry::OnViewTreeConnectionError, |
| 140 base::Unretained(this), tree_state)); | 111 base::Unretained(this), tree_state)); |
| 141 tree_host->set_view_tree_host_connection_error_handler( | 112 tree_host->set_view_tree_host_connection_error_handler( |
| 142 base::Bind(&ViewRegistry::OnViewTreeConnectionError, | 113 base::Bind(&ViewRegistry::OnViewTreeConnectionError, |
| 143 base::Unretained(this), tree_state)); | 114 base::Unretained(this), tree_state)); |
| 144 | 115 |
| 145 // Add to registry. | 116 // Add to registry. |
| 146 view_trees_.push_back(tree_state); | 117 view_trees_by_token_.insert( |
| 118 {tree_state->view_tree_token()->value, tree_state}); |
| 147 DVLOG(1) << "RegisterViewTree: tree=" << tree_state; | 119 DVLOG(1) << "RegisterViewTree: tree=" << tree_state; |
| 120 return tree_state->view_tree_token()->Clone(); |
| 148 } | 121 } |
| 149 | 122 |
| 150 void ViewRegistry::OnViewTreeConnectionError(ViewTreeState* tree_state) { | 123 void ViewRegistry::OnViewTreeConnectionError(ViewTreeState* tree_state) { |
| 151 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); | 124 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); |
| 152 DVLOG(1) << "OnViewTreeConnectionError: tree=" << tree_state; | 125 DVLOG(1) << "OnViewTreeConnectionError: tree=" << tree_state; |
| 153 | 126 |
| 154 UnregisterViewTree(tree_state); | 127 UnregisterViewTree(tree_state); |
| 155 } | 128 } |
| 156 | 129 |
| 157 void ViewRegistry::UnregisterViewTree(ViewTreeState* tree_state) { | 130 void ViewRegistry::UnregisterViewTree(ViewTreeState* tree_state) { |
| 158 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); | 131 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); |
| 159 DVLOG(1) << "UnregisterViewTree: tree=" << tree_state; | 132 DVLOG(1) << "UnregisterViewTree: tree=" << tree_state; |
| 160 | 133 |
| 161 // Unlink the root if needed. | 134 // Unlink the root if needed. |
| 162 if (tree_state->root()) | 135 if (tree_state->root()) |
| 163 UnlinkRoot(tree_state); | 136 UnlinkRoot(tree_state); |
| 164 | 137 |
| 165 // Remove from registry. | 138 // Remove from registry. |
| 166 view_trees_.erase(std::find_if( | 139 view_trees_by_token_.erase(tree_state->view_tree_token()->value); |
| 167 view_trees_.begin(), view_trees_.end(), | |
| 168 [tree_state](ViewTreeState* other) { return tree_state == other; })); | |
| 169 delete tree_state; | 140 delete tree_state; |
| 170 } | 141 } |
| 171 | 142 |
| 143 void ViewRegistry::CreateScene( |
| 144 ViewState* view_state, |
| 145 mojo::InterfaceRequest<mojo::gfx::composition::Scene> scene) { |
| 146 DCHECK(IsViewStateRegisteredDebug(view_state)); |
| 147 DVLOG(1) << "CreateScene: view=" << view_state; |
| 148 |
| 149 compositor_->CreateScene( |
| 150 scene.Pass(), view_state->label(), |
| 151 base::Bind(&ViewRegistry::OnSceneCreated, base::Unretained(this), |
| 152 view_state->GetWeakPtr())); |
| 153 } |
| 154 |
| 155 void ViewRegistry::OnSceneCreated( |
| 156 base::WeakPtr<ViewState> view_state_weak, |
| 157 mojo::gfx::composition::SceneTokenPtr scene_token) { |
| 158 DCHECK(scene_token); |
| 159 ViewState* view_state = view_state_weak.get(); |
| 160 if (view_state) { |
| 161 DVLOG(1) << "OnSceneCreated: scene_token=" << scene_token; |
| 162 |
| 163 view_state->set_scene_token(scene_token.Pass()); |
| 164 view_state->set_scene_changed_since_last_report(true); |
| 165 InvalidateLayout(view_state); |
| 166 } |
| 167 } |
| 168 |
| 172 void ViewRegistry::RequestLayout(ViewState* view_state) { | 169 void ViewRegistry::RequestLayout(ViewState* view_state) { |
| 173 DCHECK(IsViewStateRegisteredDebug(view_state)); | 170 DCHECK(IsViewStateRegisteredDebug(view_state)); |
| 174 DVLOG(1) << "RequestLayout: view=" << view_state; | 171 DVLOG(1) << "RequestLayout: view=" << view_state; |
| 175 | 172 |
| 176 InvalidateLayout(view_state); | 173 InvalidateLayout(view_state); |
| 177 } | 174 } |
| 178 | 175 |
| 179 void ViewRegistry::AddChild(ViewState* parent_state, | 176 void ViewRegistry::AddChild(ViewState* parent_state, |
| 180 uint32_t child_key, | 177 uint32_t child_key, |
| 181 mojo::ui::ViewTokenPtr child_view_token) { | 178 mojo::ui::ViewTokenPtr child_view_token) { |
| 182 DCHECK(IsViewStateRegisteredDebug(parent_state)); | 179 DCHECK(IsViewStateRegisteredDebug(parent_state)); |
| 183 DCHECK(child_view_token); | 180 DCHECK(child_view_token); |
| 184 DVLOG(1) << "AddChild: parent=" << parent_state << ", child_key=" << child_key | 181 DVLOG(1) << "AddChild: parent=" << parent_state << ", child_key=" << child_key |
| 185 << ", child=" << child_view_token.get(); | 182 << ", child=" << child_view_token; |
| 186 | 183 |
| 187 // Check for duplicate children. | 184 // Check for duplicate children. |
| 188 if (parent_state->children().find(child_key) != | 185 if (parent_state->children().find(child_key) != |
| 189 parent_state->children().end()) { | 186 parent_state->children().end()) { |
| 190 LOG(ERROR) << "View attempted to add a child with a duplicate key: " | 187 LOG(ERROR) << "View attempted to add a child with a duplicate key: " |
| 191 << "parent=" << parent_state << ", child_key=" << child_key | 188 << "parent=" << parent_state << ", child_key=" << child_key |
| 192 << ", child=" << child_view_token.get(); | 189 << ", child=" << child_view_token; |
| 193 UnregisterView(parent_state); | 190 UnregisterView(parent_state); |
| 194 return; | 191 return; |
| 195 } | 192 } |
| 196 | 193 |
| 197 // Check whether the desired child view still exists. | 194 // Check whether the desired child view still exists. |
| 198 // Adding a non-existent child still succeeds but the view manager will | 195 // Adding a non-existent child still succeeds but the view manager will |
| 199 // immediately report it as being unavailable. | 196 // immediately report it as being unavailable. |
| 200 ViewState* child_state = FindView(child_view_token->value); | 197 ViewState* child_state = FindView(child_view_token->value); |
| 201 if (!child_state) { | 198 if (!child_state) { |
| 202 LinkChildAsUnavailable(parent_state, child_key); | 199 LinkChildAsUnavailable(parent_state, child_key); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 233 void ViewRegistry::LayoutChild( | 230 void ViewRegistry::LayoutChild( |
| 234 ViewState* parent_state, | 231 ViewState* parent_state, |
| 235 uint32_t child_key, | 232 uint32_t child_key, |
| 236 mojo::ui::ViewLayoutParamsPtr child_layout_params, | 233 mojo::ui::ViewLayoutParamsPtr child_layout_params, |
| 237 const ViewLayoutCallback& callback) { | 234 const ViewLayoutCallback& callback) { |
| 238 DCHECK(IsViewStateRegisteredDebug(parent_state)); | 235 DCHECK(IsViewStateRegisteredDebug(parent_state)); |
| 239 DCHECK(child_layout_params); | 236 DCHECK(child_layout_params); |
| 240 DCHECK(child_layout_params->constraints); | 237 DCHECK(child_layout_params->constraints); |
| 241 DVLOG(1) << "LayoutChild: parent=" << parent_state | 238 DVLOG(1) << "LayoutChild: parent=" << parent_state |
| 242 << ", child_key=" << child_key | 239 << ", child_key=" << child_key |
| 243 << ", child_layout_params=" << child_layout_params.get(); | 240 << ", child_layout_params=" << child_layout_params; |
| 244 | 241 |
| 245 // Check whether the layout parameters are well-formed. | 242 // Check whether the layout parameters are well-formed. |
| 246 if (!AreViewLayoutParamsValid(child_layout_params.get())) { | 243 if (!AreViewLayoutParamsValid(child_layout_params.get())) { |
| 247 LOG(ERROR) << "View provided invalid child layout parameters: " | 244 LOG(ERROR) << "View provided invalid child layout parameters: " |
| 248 << "parent=" << parent_state << ", child_key=" << child_key | 245 << "parent=" << parent_state << ", child_key=" << child_key |
| 249 << ", child_layout_params=" << child_layout_params.get(); | 246 << ", child_layout_params=" << child_layout_params; |
| 250 UnregisterView(parent_state); | 247 UnregisterView(parent_state); |
| 251 callback.Run(nullptr); | 248 callback.Run(nullptr); |
| 252 return; | 249 return; |
| 253 } | 250 } |
| 254 | 251 |
| 255 // Check whether the child key exists in the parent. | 252 // Check whether the child key exists in the parent. |
| 256 auto child_it = parent_state->children().find(child_key); | 253 auto child_it = parent_state->children().find(child_key); |
| 257 if (child_it == parent_state->children().end()) { | 254 if (child_it == parent_state->children().end()) { |
| 258 LOG(ERROR) << "View attempted to layout a child with an invalid key: " | 255 LOG(ERROR) << "View attempted to layout a child with an invalid key: " |
| 259 << "parent=" << parent_state << ", child_key=" << child_key | 256 << "parent=" << parent_state << ", child_key=" << child_key |
| 260 << ", child_layout_params=" << child_layout_params.get(); | 257 << ", child_layout_params=" << child_layout_params; |
| 261 UnregisterView(parent_state); | 258 UnregisterView(parent_state); |
| 262 callback.Run(nullptr); | 259 callback.Run(nullptr); |
| 263 return; | 260 return; |
| 264 } | 261 } |
| 265 | 262 |
| 266 SetLayout(child_it->second, child_layout_params.Pass(), callback); | 263 SetLayout(child_it->second, child_layout_params.Pass(), callback); |
| 267 } | 264 } |
| 268 | 265 |
| 266 void ViewRegistry::ConnectToViewService( |
| 267 ViewState* view_state, |
| 268 const mojo::String& service_name, |
| 269 mojo::ScopedMessagePipeHandle client_handle) { |
| 270 DCHECK(IsViewStateRegisteredDebug(view_state)); |
| 271 |
| 272 associate_table_.ConnectToViewService(view_state->view_token()->Clone(), |
| 273 service_name, client_handle.Pass()); |
| 274 } |
| 275 |
| 269 void ViewRegistry::RequestLayout(ViewTreeState* tree_state) { | 276 void ViewRegistry::RequestLayout(ViewTreeState* tree_state) { |
| 270 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); | 277 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); |
| 271 DVLOG(1) << "RequestLayout: tree=" << tree_state; | 278 DVLOG(1) << "RequestLayout: tree=" << tree_state; |
| 272 | 279 |
| 273 InvalidateLayoutForRoot(tree_state); | 280 InvalidateLayoutForRoot(tree_state); |
| 274 } | 281 } |
| 275 | 282 |
| 276 void ViewRegistry::SetRoot(ViewTreeState* tree_state, | 283 void ViewRegistry::SetRoot(ViewTreeState* tree_state, |
| 277 uint32_t root_key, | 284 uint32_t root_key, |
| 278 mojo::ui::ViewTokenPtr root_view_token) { | 285 mojo::ui::ViewTokenPtr root_view_token) { |
| 279 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); | 286 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); |
| 280 DCHECK(root_view_token); | 287 DCHECK(root_view_token); |
| 281 DVLOG(1) << "SetRoot: tree=" << tree_state << ", root_key=" << root_key | 288 DVLOG(1) << "SetRoot: tree=" << tree_state << ", root_key=" << root_key |
| 282 << ", root=" << root_view_token.get(); | 289 << ", root=" << root_view_token; |
| 283 | 290 |
| 284 // Check whether the desired root view still exists. | 291 // Check whether the desired root view still exists. |
| 285 // Using a non-existent root view still succeeds but the view manager will | 292 // Using a non-existent root view still succeeds but the view manager will |
| 286 // immediately report it as being unavailable. | 293 // immediately report it as being unavailable. |
| 287 ViewState* root_state = FindView(root_view_token->value); | 294 ViewState* root_state = FindView(root_view_token->value); |
| 288 if (root_state) { | 295 if (root_state) { |
| 289 HijackView(root_state); | 296 HijackView(root_state); |
| 290 LinkRoot(tree_state, root_state, root_key); | 297 LinkRoot(tree_state, root_state, root_key); |
| 291 } else { | 298 } else { |
| 292 SendRootUnavailable(tree_state, root_key); | 299 SendRootUnavailable(tree_state, root_key); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 303 tree_state->set_explicit_root(false); | 310 tree_state->set_explicit_root(false); |
| 304 } | 311 } |
| 305 | 312 |
| 306 void ViewRegistry::LayoutRoot(ViewTreeState* tree_state, | 313 void ViewRegistry::LayoutRoot(ViewTreeState* tree_state, |
| 307 mojo::ui::ViewLayoutParamsPtr root_layout_params, | 314 mojo::ui::ViewLayoutParamsPtr root_layout_params, |
| 308 const ViewLayoutCallback& callback) { | 315 const ViewLayoutCallback& callback) { |
| 309 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); | 316 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); |
| 310 DCHECK(root_layout_params); | 317 DCHECK(root_layout_params); |
| 311 DCHECK(root_layout_params->constraints); | 318 DCHECK(root_layout_params->constraints); |
| 312 DVLOG(1) << "LayoutRoot: tree=" << tree_state | 319 DVLOG(1) << "LayoutRoot: tree=" << tree_state |
| 313 << ", root_layout_params=" << root_layout_params.get(); | 320 << ", root_layout_params=" << root_layout_params; |
| 314 | 321 |
| 315 // Check whether the layout parameters are well-formed. | 322 // Check whether the layout parameters are well-formed. |
| 316 if (!AreViewLayoutParamsValid(root_layout_params.get())) { | 323 if (!AreViewLayoutParamsValid(root_layout_params.get())) { |
| 317 LOG(ERROR) << "View tree provided invalid root layout parameters: " | 324 LOG(ERROR) << "View tree provided invalid root layout parameters: " |
| 318 << "tree=" << tree_state | 325 << "tree=" << tree_state |
| 319 << ", root_layout_params=" << root_layout_params.get(); | 326 << ", root_layout_params=" << root_layout_params; |
| 320 UnregisterViewTree(tree_state); | 327 UnregisterViewTree(tree_state); |
| 321 callback.Run(nullptr); | 328 callback.Run(nullptr); |
| 322 return; | 329 return; |
| 323 } | 330 } |
| 324 | 331 |
| 325 // Check whether the client called LayoutRoot without first having actually | 332 // Check whether the client called LayoutRoot without first having actually |
| 326 // set a root. | 333 // set a root. |
| 327 if (!tree_state->explicit_root()) { | 334 if (!tree_state->explicit_root()) { |
| 328 LOG(ERROR) << "View tree attempted to layout the rout without having " | 335 LOG(ERROR) << "View tree attempted to layout the rout without having " |
| 329 "set one first: tree=" | 336 "set one first: tree=" |
| 330 << tree_state | 337 << tree_state << ", root_layout_params=" << root_layout_params; |
| 331 << ", root_layout_params=" << root_layout_params.get(); | |
| 332 UnregisterViewTree(tree_state); | 338 UnregisterViewTree(tree_state); |
| 333 callback.Run(nullptr); | 339 callback.Run(nullptr); |
| 334 return; | 340 return; |
| 335 } | 341 } |
| 336 | 342 |
| 337 // Check whether the root is unavailable and therefore cannot be laid out. | 343 // Check whether the root is unavailable and therefore cannot be laid out. |
| 338 // This is not an error. | 344 // This is not an error. |
| 339 if (!tree_state->root()) { | 345 if (!tree_state->root()) { |
| 340 callback.Run(nullptr); | 346 callback.Run(nullptr); |
| 341 return; | 347 return; |
| 342 } | 348 } |
| 343 | 349 |
| 344 SetLayout(tree_state->root(), root_layout_params.Pass(), callback); | 350 SetLayout(tree_state->root(), root_layout_params.Pass(), callback); |
| 345 } | 351 } |
| 346 | 352 |
| 347 ViewState* ViewRegistry::FindView(uint32_t view_token) { | 353 void ViewRegistry::ConnectToViewTreeService( |
| 348 auto it = views_by_token_.find(view_token); | 354 ViewTreeState* tree_state, |
| 355 const mojo::String& service_name, |
| 356 mojo::ScopedMessagePipeHandle client_handle) { |
| 357 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); |
| 358 |
| 359 associate_table_.ConnectToViewTreeService( |
| 360 tree_state->view_tree_token()->Clone(), service_name, |
| 361 client_handle.Pass()); |
| 362 } |
| 363 |
| 364 ViewState* ViewRegistry::FindView(uint32_t view_token_value) { |
| 365 auto it = views_by_token_.find(view_token_value); |
| 349 return it != views_by_token_.end() ? it->second : nullptr; | 366 return it != views_by_token_.end() ? it->second : nullptr; |
| 350 } | 367 } |
| 351 | 368 |
| 352 void ViewRegistry::LinkChild(ViewState* parent_state, | 369 void ViewRegistry::LinkChild(ViewState* parent_state, |
| 353 uint32_t child_key, | 370 uint32_t child_key, |
| 354 ViewState* child_state) { | 371 ViewState* child_state) { |
| 355 DCHECK(IsViewStateRegisteredDebug(parent_state)); | 372 DCHECK(IsViewStateRegisteredDebug(parent_state)); |
| 356 DCHECK(parent_state->children().find(child_key) == | 373 DCHECK(parent_state->children().find(child_key) == |
| 357 parent_state->children().end()); | 374 parent_state->children().end()); |
| 358 DCHECK(IsViewStateRegisteredDebug(child_state)); | 375 DCHECK(IsViewStateRegisteredDebug(child_state)); |
| 359 | 376 |
| 360 DVLOG(2) << "Added child " << child_key << " {" | 377 DVLOG(2) << "Added child " << child_key << " {" << child_state->label() |
| 361 << child_state->view_token_value() << "} to parent {" | 378 << "} to parent {" << parent_state->label() << "}"; |
| 362 << parent_state->view_token_value() << "}"; | |
| 363 | 379 |
| 364 parent_state->children().insert({child_key, child_state}); | 380 parent_state->children().insert({child_key, child_state}); |
| 365 child_state->SetParent(parent_state, child_key); | 381 child_state->SetParent(parent_state, child_key); |
| 366 | 382 |
| 367 // Schedule layout of the parent on behalf of its newly added child. | 383 // Schedule layout of the parent on behalf of its newly added child. |
| 368 // We don't need to schedule layout of the child until the parent provides | 384 // We don't need to schedule layout of the child until the parent provides |
| 369 // new layout parameters. | 385 // new layout parameters. |
| 370 InvalidateLayoutForChild(parent_state, child_key); | 386 InvalidateLayoutForChild(parent_state, child_key); |
| 371 } | 387 } |
| 372 | 388 |
| 373 void ViewRegistry::LinkChildAsUnavailable(ViewState* parent_state, | 389 void ViewRegistry::LinkChildAsUnavailable(ViewState* parent_state, |
| 374 uint32_t child_key) { | 390 uint32_t child_key) { |
| 375 DCHECK(IsViewStateRegisteredDebug(parent_state)); | 391 DCHECK(IsViewStateRegisteredDebug(parent_state)); |
| 376 DCHECK(parent_state->children().find(child_key) == | 392 DCHECK(parent_state->children().find(child_key) == |
| 377 parent_state->children().end()); | 393 parent_state->children().end()); |
| 378 | 394 |
| 379 DVLOG(2) << "Added unavailable child " << child_key << " to parent {" | 395 DVLOG(2) << "Added unavailable child " << child_key << " to parent {" |
| 380 << parent_state->view_token_value() << "}"; | 396 << parent_state->label() << "}"; |
| 381 | 397 |
| 382 parent_state->children().insert({child_key, nullptr}); | 398 parent_state->children().insert({child_key, nullptr}); |
| 383 SendChildUnavailable(parent_state, child_key); | 399 SendChildUnavailable(parent_state, child_key); |
| 384 | 400 |
| 385 // Don't schedule layout for the parent just yet. Wait for it to | 401 // Don't schedule layout for the parent just yet. Wait for it to |
| 386 // remove its child in response to the OnChildUnavailable notification. | 402 // remove its child in response to the OnChildUnavailable notification. |
| 387 } | 403 } |
| 388 | 404 |
| 389 void ViewRegistry::MarkChildAsUnavailable(ViewState* parent_state, | 405 void ViewRegistry::MarkChildAsUnavailable(ViewState* parent_state, |
| 390 uint32_t child_key) { | 406 uint32_t child_key) { |
| 391 DCHECK(IsViewStateRegisteredDebug(parent_state)); | 407 DCHECK(IsViewStateRegisteredDebug(parent_state)); |
| 392 auto child_it = parent_state->children().find(child_key); | 408 auto child_it = parent_state->children().find(child_key); |
| 393 DCHECK(child_it != parent_state->children().end()); | 409 DCHECK(child_it != parent_state->children().end()); |
| 394 DCHECK(child_it->second); | 410 DCHECK(child_it->second); |
| 395 | 411 |
| 396 DVLOG(2) << "Marked unavailable child " << child_key << " {" | 412 DVLOG(2) << "Marked unavailable child " << child_key << " {" |
| 397 << child_it->second->view_token_value() << "} from parent {" | 413 << child_it->second->label() << "} from parent {" |
| 398 << parent_state->view_token_value() << "}"; | 414 << parent_state->label() << "}"; |
| 399 | 415 |
| 400 ResetStateWhenUnlinking(child_it->second); | 416 ResetStateWhenUnlinking(child_it->second); |
| 401 child_it->second->ResetContainer(); | 417 child_it->second->ResetContainer(); |
| 402 child_it->second = nullptr; | 418 child_it->second = nullptr; |
| 403 SendChildUnavailable(parent_state, child_key); | 419 SendChildUnavailable(parent_state, child_key); |
| 404 | 420 |
| 405 // Don't schedule layout for the parent just yet. Wait for it to | 421 // Don't schedule layout for the parent just yet. Wait for it to |
| 406 // remove its child in response to the OnChildUnavailable notification. | 422 // remove its child in response to the OnChildUnavailable notification. |
| 407 // We don't need to schedule layout for the child either since it will | 423 // We don't need to schedule layout for the child either since it will |
| 408 // retain its old layout parameters. | 424 // retain its old layout parameters. |
| 409 } | 425 } |
| 410 | 426 |
| 411 void ViewRegistry::UnlinkChild(ViewState* parent_state, | 427 void ViewRegistry::UnlinkChild(ViewState* parent_state, |
| 412 ViewState::ChildrenMap::iterator child_it) { | 428 ViewState::ChildrenMap::iterator child_it) { |
| 413 DCHECK(IsViewStateRegisteredDebug(parent_state)); | 429 DCHECK(IsViewStateRegisteredDebug(parent_state)); |
| 414 DCHECK(child_it != parent_state->children().end()); | 430 DCHECK(child_it != parent_state->children().end()); |
| 415 | 431 |
| 416 ViewState* child_state = child_it->second; | 432 ViewState* child_state = child_it->second; |
| 417 if (child_state) { | 433 if (child_state) { |
| 418 DVLOG(2) << "Removed child " << child_state->key() << " {" | 434 DVLOG(2) << "Removed child " << child_state->key() << " {" |
| 419 << child_state->view_token_value() << "} from parent {" | 435 << child_state->label() << "} from parent {" |
| 420 << parent_state->view_token_value() << "}"; | 436 << parent_state->label() << "}"; |
| 421 ResetStateWhenUnlinking(child_it->second); | 437 ResetStateWhenUnlinking(child_it->second); |
| 422 child_state->ResetContainer(); | 438 child_state->ResetContainer(); |
| 423 } else { | 439 } else { |
| 424 DVLOG(2) << "Removed unavailable child " << child_it->first | 440 DVLOG(2) << "Removed unavailable child " << child_it->first |
| 425 << "} from parent {" << parent_state->view_token_value() << "}"; | 441 << "} from parent {" << parent_state->label() << "}"; |
| 426 } | 442 } |
| 427 parent_state->children().erase(child_it); | 443 parent_state->children().erase(child_it); |
| 428 | 444 |
| 429 // Schedule layout for the parent now that it has lost its child. | 445 // Schedule layout for the parent now that it has lost its child. |
| 430 // We don't need to schedule layout for the child itself since it will | 446 // We don't need to schedule layout for the child itself since it will |
| 431 // retain its old layout parameters. | 447 // retain its old layout parameters. |
| 432 InvalidateLayout(parent_state); | 448 InvalidateLayout(parent_state); |
| 433 } | 449 } |
| 434 | 450 |
| 451 ViewTreeState* ViewRegistry::FindViewTree(uint32_t view_tree_token_value) { |
| 452 auto it = view_trees_by_token_.find(view_tree_token_value); |
| 453 return it != view_trees_by_token_.end() ? it->second : nullptr; |
| 454 } |
| 455 |
| 435 void ViewRegistry::LinkRoot(ViewTreeState* tree_state, | 456 void ViewRegistry::LinkRoot(ViewTreeState* tree_state, |
| 436 ViewState* root_state, | 457 ViewState* root_state, |
| 437 uint32_t root_key) { | 458 uint32_t root_key) { |
| 438 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); | 459 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); |
| 439 DCHECK(IsViewStateRegisteredDebug(root_state)); | 460 DCHECK(IsViewStateRegisteredDebug(root_state)); |
| 440 DCHECK(!tree_state->root()); | 461 DCHECK(!tree_state->root()); |
| 441 DCHECK(!root_state->parent()); | 462 DCHECK(!root_state->parent()); |
| 442 | 463 |
| 443 DVLOG(2) << "Linked view tree root " << root_key << " {" | 464 DVLOG(2) << "Linked view tree root " << root_key << " {" |
| 444 << root_state->view_token_value() << "}"; | 465 << root_state->label() << "}"; |
| 445 | 466 |
| 446 tree_state->SetRoot(root_state, root_key); | 467 tree_state->SetRoot(root_state, root_key); |
| 447 | 468 |
| 448 // Schedule layout of the tree on behalf of its newly added root. | 469 // Schedule layout of the tree on behalf of its newly added root. |
| 449 // We don't need to schedule layout of the root until the tree provides | 470 // We don't need to schedule layout of the root until the tree provides |
| 450 // new layout parameters. | 471 // new layout parameters. |
| 451 InvalidateLayoutForRoot(tree_state); | 472 InvalidateLayoutForRoot(tree_state); |
| 452 } | 473 } |
| 453 | 474 |
| 454 void ViewRegistry::UnlinkRoot(ViewTreeState* tree_state) { | 475 void ViewRegistry::UnlinkRoot(ViewTreeState* tree_state) { |
| 455 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); | 476 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); |
| 456 DCHECK(tree_state->root()); | 477 DCHECK(tree_state->root()); |
| 457 | 478 |
| 458 DVLOG(2) << "Unlinked view tree root " << tree_state->root()->key() << " {" | 479 DVLOG(2) << "Unlinked view tree root " << tree_state->root()->key() << " {" |
| 459 << tree_state->root()->view_token_value() << "}"; | 480 << tree_state->root()->label() << "}"; |
| 460 | 481 |
| 461 ResetStateWhenUnlinking(tree_state->root()); | 482 ResetStateWhenUnlinking(tree_state->root()); |
| 462 tree_state->ResetRoot(); | 483 tree_state->ResetRoot(); |
| 463 | 484 |
| 464 // We don't need to schedule layout for the root since it will retain | 485 // We don't need to schedule layout for the root since it will retain |
| 465 // its old layout parameters. | 486 // its old layout parameters. |
| 466 } | 487 } |
| 467 | 488 |
| 468 void ViewRegistry::HijackView(ViewState* view_state) { | 489 void ViewRegistry::HijackView(ViewState* view_state) { |
| 469 if (view_state->parent()) { | 490 if (view_state->parent()) { |
| 470 MarkChildAsUnavailable(view_state->parent(), view_state->key()); | 491 MarkChildAsUnavailable(view_state->parent(), view_state->key()); |
| 471 } else if (view_state->tree()) { | 492 } else if (view_state->tree()) { |
| 472 ViewTreeState* tree_state = view_state->tree(); | 493 ViewTreeState* tree_state = view_state->tree(); |
| 473 uint32_t root_key = tree_state->root()->key(); | 494 uint32_t root_key = tree_state->root()->key(); |
| 474 UnlinkRoot(tree_state); | 495 UnlinkRoot(tree_state); |
| 475 SendRootUnavailable(tree_state, root_key); | 496 SendRootUnavailable(tree_state, root_key); |
| 476 } | 497 } |
| 477 } | 498 } |
| 478 | 499 |
| 479 void ViewRegistry::InvalidateLayout(ViewState* view_state) { | 500 void ViewRegistry::InvalidateLayout(ViewState* view_state) { |
| 480 DCHECK(IsViewStateRegisteredDebug(view_state)); | 501 DCHECK(IsViewStateRegisteredDebug(view_state)); |
| 481 | 502 |
| 482 // We can consider the layout request to have been satisfied if | 503 // We can consider the layout request to have been satisfied if |
| 483 // there is already a pending layout request in the queue that has not | 504 // there is already a pending layout request in the queue that has not |
| 484 // yet been issued (this is coalescing). Otherwise we must manufacture | 505 // yet been issued (this is coalescing). Otherwise we must manufacture |
| 485 // a new one based on the current layout parameters. | 506 // a new one based on the current layout parameters. |
| 486 if (view_state->layout_params() && | 507 if (view_state->layout_params() && |
| 487 (view_state->pending_layout_requests().empty() || | 508 (view_state->pending_layout_requests().empty() || |
| 488 view_state->pending_layout_requests().back()->issued())) { | 509 view_state->pending_layout_requests().back()->issued())) { |
| 489 EnqueueLayoutRequest(view_state, view_state->layout_params().Clone()); | 510 EnqueueLayoutRequest(view_state, view_state->layout_params()->Clone()); |
| 490 IssueNextViewLayoutRequest(view_state); | 511 IssueNextViewLayoutRequest(view_state); |
| 491 } | 512 } |
| 492 } | 513 } |
| 493 | 514 |
| 494 void ViewRegistry::InvalidateLayoutForChild(ViewState* parent_state, | 515 void ViewRegistry::InvalidateLayoutForChild(ViewState* parent_state, |
| 495 uint32_t child_key) { | 516 uint32_t child_key) { |
| 496 DCHECK(IsViewStateRegisteredDebug(parent_state)); | 517 DCHECK(IsViewStateRegisteredDebug(parent_state)); |
| 497 DCHECK(parent_state->children().find(child_key) != | 518 DCHECK(parent_state->children().find(child_key) != |
| 498 parent_state->children().end()); | 519 parent_state->children().end()); |
| 499 | 520 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 512 | 533 |
| 513 void ViewRegistry::SetLayout(ViewState* view_state, | 534 void ViewRegistry::SetLayout(ViewState* view_state, |
| 514 mojo::ui::ViewLayoutParamsPtr layout_params, | 535 mojo::ui::ViewLayoutParamsPtr layout_params, |
| 515 const ViewLayoutCallback& callback) { | 536 const ViewLayoutCallback& callback) { |
| 516 DCHECK(IsViewStateRegisteredDebug(view_state)); | 537 DCHECK(IsViewStateRegisteredDebug(view_state)); |
| 517 DCHECK(AreViewLayoutParamsValid(layout_params.get())); | 538 DCHECK(AreViewLayoutParamsValid(layout_params.get())); |
| 518 | 539 |
| 519 // Check whether the currently cached layout parameters are the same | 540 // Check whether the currently cached layout parameters are the same |
| 520 // and we already have a result and we have no pending layout requests. | 541 // and we already have a result and we have no pending layout requests. |
| 521 if (view_state->pending_layout_requests().empty() && | 542 if (view_state->pending_layout_requests().empty() && |
| 522 view_state->layout_params() && view_state->layout_info() && | 543 view_state->layout_params() && |
| 523 view_state->layout_params()->Equals(*layout_params)) { | 544 view_state->layout_params()->Equals(*layout_params)) { |
| 524 DVLOG(2) << "Layout cache hit"; | 545 mojo::ui::ViewLayoutInfoPtr info = view_state->CreateLayoutInfo(); |
| 525 callback.Run(view_state->layout_info().Clone()); | 546 if (info) { |
| 526 return; | 547 DVLOG(2) << "Layout cache hit"; |
| 548 view_state->set_scene_changed_since_last_report(false); |
| 549 callback.Run(info.Pass()); |
| 550 return; |
| 551 } |
| 527 } | 552 } |
| 528 | 553 |
| 529 // Check whether the layout parameters are different from the most | 554 // Check whether the layout parameters are different from the most |
| 530 // recent pending layout request if we have one. | 555 // recent pending layout request if we have one. |
| 531 if (view_state->pending_layout_requests().empty() || | 556 if (view_state->pending_layout_requests().empty() || |
| 532 !view_state->pending_layout_requests().back()->layout_params()->Equals( | 557 !view_state->pending_layout_requests().back()->layout_params()->Equals( |
| 533 *layout_params)) { | 558 *layout_params)) { |
| 534 // Enqueue a new request for these parameters. | 559 // Enqueue a new request for these parameters. |
| 535 EnqueueLayoutRequest(view_state, layout_params.Pass()); | 560 EnqueueLayoutRequest(view_state, layout_params.Pass()); |
| 536 } | 561 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 tree_state->set_layout_request_issued(true); | 602 tree_state->set_layout_request_issued(true); |
| 578 SendViewTreeLayoutRequest(tree_state); | 603 SendViewTreeLayoutRequest(tree_state); |
| 579 } | 604 } |
| 580 } | 605 } |
| 581 | 606 |
| 582 void ViewRegistry::ResetStateWhenUnlinking(ViewState* view_state) { | 607 void ViewRegistry::ResetStateWhenUnlinking(ViewState* view_state) { |
| 583 // Clean up parent's recorded state for the child. | 608 // Clean up parent's recorded state for the child. |
| 584 if (view_state->parent()) { | 609 if (view_state->parent()) { |
| 585 view_state->parent()->children_needing_layout().erase(view_state->key()); | 610 view_state->parent()->children_needing_layout().erase(view_state->key()); |
| 586 } | 611 } |
| 587 | |
| 588 // Clean up child's recorded state for the parent or tree. | |
| 589 if (view_state->wrapped_surface()) { | |
| 590 surface_manager_->DestroySurface(view_state->wrapped_surface().Pass()); | |
| 591 } | |
| 592 } | 612 } |
| 593 | 613 |
| 594 void ViewRegistry::SendChildUnavailable(ViewState* parent_state, | 614 void ViewRegistry::SendChildUnavailable(ViewState* parent_state, |
| 595 uint32_t child_key) { | 615 uint32_t child_key) { |
| 596 DCHECK(IsViewStateRegisteredDebug(parent_state)); | 616 DCHECK(IsViewStateRegisteredDebug(parent_state)); |
| 597 | 617 |
| 598 // TODO: Detect ANRs | 618 // TODO: Detect ANRs |
| 599 DVLOG(1) << "SendChildUnavailable: child_key=" << child_key; | 619 DVLOG(1) << "SendChildUnavailable: child_key=" << child_key; |
| 600 parent_state->view()->OnChildUnavailable(child_key, | 620 parent_state->view()->OnChildUnavailable(child_key, |
| 601 base::Bind(&base::DoNothing)); | 621 base::Bind(&base::DoNothing)); |
| 602 } | 622 } |
| 603 | 623 |
| 604 void ViewRegistry::SendRootUnavailable(ViewTreeState* tree_state, | 624 void ViewRegistry::SendRootUnavailable(ViewTreeState* tree_state, |
| 605 uint32_t root_key) { | 625 uint32_t root_key) { |
| 606 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); | 626 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); |
| 607 | 627 |
| 608 // TODO: Detect ANRs | 628 // TODO: Detect ANRs |
| 609 DVLOG(1) << "SendRootUnavailable: root_key=" << root_key; | 629 DVLOG(1) << "SendRootUnavailable: root_key=" << root_key; |
| 610 tree_state->view_tree()->OnRootUnavailable(root_key, | 630 tree_state->view_tree()->OnRootUnavailable(root_key, |
| 611 base::Bind(&base::DoNothing)); | 631 base::Bind(&base::DoNothing)); |
| 612 } | 632 } |
| 613 | 633 |
| 614 void ViewRegistry::SendViewLayoutRequest(ViewState* view_state) { | 634 void ViewRegistry::SendViewLayoutRequest(ViewState* view_state) { |
| 615 DCHECK(IsViewStateRegisteredDebug(view_state)); | 635 DCHECK(IsViewStateRegisteredDebug(view_state)); |
| 616 DCHECK(!view_state->pending_layout_requests().empty()); | 636 DCHECK(!view_state->pending_layout_requests().empty()); |
| 617 DCHECK(view_state->pending_layout_requests().front()->issued()); | 637 DCHECK(view_state->pending_layout_requests().front()->issued()); |
| 618 | 638 |
| 619 // TODO: Detect ANRs | 639 // TODO: Detect ANRs |
| 620 DVLOG(1) << "SendViewLayoutRequest: view.token=" | 640 DVLOG(1) << "SendViewLayoutRequest: view.token=" << view_state->label(); |
| 621 << view_state->view_token_value(); | |
| 622 view_state->view()->OnLayout( | 641 view_state->view()->OnLayout( |
| 623 view_state->pending_layout_requests().front()->layout_params()->Clone(), | 642 view_state->pending_layout_requests().front()->layout_params()->Clone(), |
| 624 mojo::Array<uint32_t>::From(view_state->children_needing_layout()), | 643 mojo::Array<uint32_t>::From(view_state->children_needing_layout()), |
| 625 base::Bind(&ViewRegistry::OnViewLayoutResult, base::Unretained(this), | 644 base::Bind(&ViewRegistry::OnViewLayoutResult, base::Unretained(this), |
| 626 view_state->GetWeakPtr())); | 645 view_state->GetWeakPtr())); |
| 627 view_state->children_needing_layout().clear(); | 646 view_state->children_needing_layout().clear(); |
| 628 } | 647 } |
| 629 | 648 |
| 630 void ViewRegistry::SendViewTreeLayoutRequest(ViewTreeState* tree_state) { | 649 void ViewRegistry::SendViewTreeLayoutRequest(ViewTreeState* tree_state) { |
| 631 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); | 650 DCHECK(IsViewTreeStateRegisteredDebug(tree_state)); |
| 632 DCHECK(tree_state->layout_request_issued()); | 651 DCHECK(tree_state->layout_request_issued()); |
| 633 | 652 |
| 634 // TODO: Detect ANRs | 653 // TODO: Detect ANRs |
| 635 DVLOG(1) << "SendViewTreeLayoutRequest"; | 654 DVLOG(1) << "SendViewTreeLayoutRequest"; |
| 636 tree_state->view_tree()->OnLayout( | 655 tree_state->view_tree()->OnLayout( |
| 637 base::Bind(&ViewRegistry::OnViewTreeLayoutResult, base::Unretained(this), | 656 base::Bind(&ViewRegistry::OnViewTreeLayoutResult, base::Unretained(this), |
| 638 tree_state->GetWeakPtr())); | 657 tree_state->GetWeakPtr())); |
| 639 } | 658 } |
| 640 | 659 |
| 641 static bool IsSizeInBounds(mojo::ui::BoxConstraints* constraints, | 660 static bool IsSizeInBounds(mojo::ui::BoxConstraints* constraints, |
| 642 mojo::Size* size) { | 661 mojo::Size* size) { |
| 643 return size && size->width >= constraints->min_width && | 662 return size && size->width >= constraints->min_width && |
| 644 size->width <= constraints->max_width && | 663 size->width <= constraints->max_width && |
| 645 size->height >= constraints->min_height && | 664 size->height >= constraints->min_height && |
| 646 size->height <= constraints->max_height; | 665 size->height <= constraints->max_height; |
| 647 } | 666 } |
| 648 | 667 |
| 649 void ViewRegistry::OnViewLayoutResult(base::WeakPtr<ViewState> view_state_weak, | 668 void ViewRegistry::OnViewLayoutResult(base::WeakPtr<ViewState> view_state_weak, |
| 650 mojo::ui::ViewLayoutInfoPtr info) { | 669 mojo::ui::ViewLayoutResultPtr result) { |
| 651 DCHECK(info); | 670 DCHECK(result); |
| 652 DCHECK(info->surface_id); // checked by mojom | |
| 653 | 671 |
| 654 ViewState* view_state = view_state_weak.get(); | 672 ViewState* view_state = view_state_weak.get(); |
| 655 if (!view_state) | 673 if (!view_state) |
| 656 return; | 674 return; |
| 657 | 675 |
| 658 DCHECK(!view_state->pending_layout_requests().empty()); | 676 DCHECK(!view_state->pending_layout_requests().empty()); |
| 659 DCHECK(view_state->pending_layout_requests().front()->issued()); | 677 DCHECK(view_state->pending_layout_requests().front()->issued()); |
| 660 | 678 |
| 661 std::unique_ptr<ViewLayoutRequest> request( | 679 std::unique_ptr<ViewLayoutRequest> request( |
| 662 std::move(view_state->pending_layout_requests().front())); | 680 std::move(view_state->pending_layout_requests().front())); |
| 663 view_state->pending_layout_requests().erase( | 681 view_state->pending_layout_requests().erase( |
| 664 view_state->pending_layout_requests().begin()); | 682 view_state->pending_layout_requests().begin()); |
| 665 | 683 |
| 666 DVLOG(1) << "OnViewLayoutResult: view=" << view_state | 684 DVLOG(1) << "OnViewLayoutResult: view=" << view_state |
| 667 << ", params=" << request->layout_params() | 685 << ", params=" << request->layout_params() << ", result=" << result; |
| 668 << ", info=" << info.get(); | |
| 669 | 686 |
| 670 // Validate the layout info. | 687 // Validate the layout info. |
| 671 if (!IsSizeInBounds(request->layout_params()->constraints.get(), | 688 if (!IsSizeInBounds(request->layout_params()->constraints.get(), |
| 672 info->size.get())) { | 689 result->size.get())) { |
| 673 LOG(ERROR) << "View returned invalid size in its layout info: " | 690 LOG(ERROR) << "View returned invalid size in its layout info: " |
| 674 << "view=" << view_state | 691 << "view=" << view_state |
| 675 << ", params=" << request->layout_params() | 692 << ", params=" << request->layout_params() |
| 676 << ", info=" << info.get(); | 693 << ", result=" << result; |
| 677 UnregisterView(view_state); | 694 UnregisterView(view_state); |
| 678 return; | 695 return; |
| 679 } | 696 } |
| 680 | 697 |
| 681 // Assume the parent or root will not see the new layout information if | 698 // Assume the parent or root will not see the new layout information if |
| 682 // there are no callbacks so we need to inform it when things change. | 699 // there are no callbacks so we need to inform it when things change. |
| 683 const bool size_changed = | 700 const bool size_changed = |
| 684 !view_state->layout_info() || | 701 !view_state->layout_result() || |
| 685 !view_state->layout_info()->size->Equals(*info->size); | 702 !view_state->layout_result()->size->Equals(*result->size); |
| 686 const bool surface_changed = | |
| 687 !view_state->layout_info() || | |
| 688 !view_state->layout_info()->surface_id->Equals(*info->surface_id); | |
| 689 const bool recurse = | 703 const bool recurse = |
| 690 !request->has_callbacks() && (surface_changed || size_changed); | 704 !request->has_callbacks() && |
| 705 (size_changed || view_state->scene_changed_since_last_report()); |
| 691 | 706 |
| 692 view_state->layout_params() = request->TakeLayoutParams().Pass(); | 707 view_state->set_layout_params(request->TakeLayoutParams().Pass()); |
| 693 view_state->layout_info() = info.Pass(); | 708 view_state->set_layout_result(result.Pass()); |
| 694 | 709 |
| 695 if (surface_changed) { | 710 mojo::ui::ViewLayoutInfoPtr info = view_state->CreateLayoutInfo(); |
| 696 if (view_state->wrapped_surface()) | 711 if (info) { |
| 697 surface_manager_->DestroySurface(view_state->wrapped_surface().Pass()); | 712 view_state->set_scene_changed_since_last_report(false); |
| 698 view_state->wrapped_surface() = surface_manager_->CreateWrappedSurface( | 713 request->DispatchLayoutInfo(info.Pass()); |
| 699 view_state->layout_info()->surface_id.get()); | |
| 700 } | 714 } |
| 701 | 715 |
| 702 request->DispatchLayoutInfo(view_state->layout_info().get()); | |
| 703 | |
| 704 if (recurse) { | 716 if (recurse) { |
| 705 if (view_state->parent()) { | 717 if (view_state->parent()) { |
| 706 InvalidateLayoutForChild(view_state->parent(), view_state->key()); | 718 InvalidateLayoutForChild(view_state->parent(), view_state->key()); |
| 707 } else if (view_state->tree()) { | 719 } else if (view_state->tree()) { |
| 708 InvalidateLayoutForRoot(view_state->tree()); | 720 InvalidateLayoutForRoot(view_state->tree()); |
| 709 } | 721 } |
| 710 } | 722 } |
| 711 | 723 |
| 712 IssueNextViewLayoutRequest(view_state); | 724 IssueNextViewLayoutRequest(view_state); |
| 713 } | 725 } |
| 714 | 726 |
| 715 void ViewRegistry::OnViewTreeLayoutResult( | 727 void ViewRegistry::OnViewTreeLayoutResult( |
| 716 base::WeakPtr<ViewTreeState> tree_state_weak) { | 728 base::WeakPtr<ViewTreeState> tree_state_weak) { |
| 717 ViewTreeState* tree_state = tree_state_weak.get(); | 729 ViewTreeState* tree_state = tree_state_weak.get(); |
| 718 if (tree_state) { | 730 if (tree_state) { |
| 719 DCHECK(tree_state->layout_request_issued()); | 731 DCHECK(tree_state->layout_request_issued()); |
| 720 | 732 |
| 721 DVLOG(1) << "OnViewTreeLayoutResult"; | 733 DVLOG(1) << "OnViewTreeLayoutResult"; |
| 722 | 734 |
| 723 tree_state->set_layout_request_issued(false); | 735 tree_state->set_layout_request_issued(false); |
| 724 IssueNextViewTreeLayoutRequest(tree_state); | 736 IssueNextViewTreeLayoutRequest(tree_state); |
| 725 } | 737 } |
| 726 } | 738 } |
| 727 | 739 |
| 728 } // namespace view_manager | 740 } // namespace view_manager |
| OLD | NEW |