Chromium Code Reviews| Index: services/ui/launcher/launcher_view_tree.cc |
| diff --git a/services/ui/launcher/launcher_view_tree.cc b/services/ui/launcher/launcher_view_tree.cc |
| index 052b3c0750e0e0d0965c4eb4cad26029ae4a823f..dae831aaad8b2b1233307f98f426369dfa4432d2 100644 |
| --- a/services/ui/launcher/launcher_view_tree.cc |
| +++ b/services/ui/launcher/launcher_view_tree.cc |
| @@ -2,32 +2,68 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -#include "base/bind.h" |
| #include "services/ui/launcher/launcher_view_tree.h" |
| +#include "base/bind.h" |
| +#include "mojo/public/cpp/application/connect.h" |
| +#include "mojo/services/gfx/composition/cpp/logging.h" |
| +#include "mojo/services/ui/views/cpp/logging.h" |
| + |
| namespace launcher { |
| -LauncherViewTree::LauncherViewTree(mojo::ApplicationImpl* app_impl, |
| - mojo::DisplayPtr display, |
| - mojo::ViewportMetricsPtr viewport_metrics) |
| - : display_(display.Pass()), |
| +constexpr uint32_t kViewSceneResourceId = 1; |
| +constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId; |
| +constexpr uint32_t kViewNodeId = 1; |
| +constexpr uint32_t kFallbackNodeId = 2; |
| + |
| +LauncherViewTree::LauncherViewTree( |
| + mojo::gfx::composition::Compositor* compositor, |
| + mojo::ui::ViewManager* view_manager, |
| + mojo::ContextProviderPtr context_provider, |
| + mojo::ViewportMetricsPtr viewport_metrics, |
| + const base::Closure& shutdown_callback) |
| + : compositor_(compositor), |
| + view_manager_(view_manager), |
| + context_provider_(context_provider.Pass()), |
| viewport_metrics_(viewport_metrics.Pass()), |
| - binding_(this), |
| - root_key_(0), |
| - frame_scheduled_(false), |
| - frame_pending_(false) { |
| - app_impl->ConnectToService("mojo:view_manager_service", &view_manager_); |
| - view_manager_.set_connection_error_handler(base::Bind( |
| - &LauncherViewTree::OnViewManagerConnectionError, base::Unretained(this))); |
| - |
| + shutdown_callback_(shutdown_callback), |
| + scene_listener_binding_(this), |
| + view_tree_binding_(this) { |
| + // Create the renderer. |
| + compositor_->CreateRenderer(context_provider_.Pass(), GetProxy(&renderer_), |
| + "Launcher"); |
| + renderer_.set_connection_error_handler(base::Bind( |
| + &LauncherViewTree::OnRendererConnectionError, base::Unretained(this))); |
|
abarth
2016/01/10 01:42:54
Do we not support lambdas here?
jeffbrown
2016/01/26 05:59:12
We do support lambdas but I've been avoiding mixin
|
| + |
| + // Create the root scene. |
| + compositor_->CreateScene( |
| + mojo::GetProxy(&scene_), "Launcher", |
| + base::Bind(&LauncherViewTree::OnSceneRegistered, base::Unretained(this))); |
| + mojo::gfx::composition::SceneListenerPtr scene_listener; |
| + scene_listener_binding_.Bind(mojo::GetProxy(&scene_listener)); |
| + scene_->SetListener(scene_listener.Pass()); |
| + scene_.set_connection_error_handler(base::Bind( |
| + &LauncherViewTree::OnSceneConnectionError, base::Unretained(this))); |
| + |
| + // Register the view tree. |
| mojo::ui::ViewTreePtr view_tree; |
| - binding_.Bind(mojo::GetProxy(&view_tree)); |
| + view_tree_binding_.Bind(mojo::GetProxy(&view_tree)); |
| view_manager_->RegisterViewTree( |
| - view_tree.Pass(), mojo::GetProxy(&view_tree_host_), |
| + view_tree.Pass(), mojo::GetProxy(&view_tree_host_), "Launcher", |
| base::Bind(&LauncherViewTree::OnViewTreeRegistered, |
| base::Unretained(this))); |
| - |
| - ScheduleFrame(); |
| + view_tree_host_.set_connection_error_handler(base::Bind( |
| + &LauncherViewTree::OnViewTreeConnectionError, base::Unretained(this))); |
| + |
| + // Get view tree services. |
| + mojo::ServiceProviderPtr view_tree_service_provider; |
| + view_tree_host_->GetServiceProvider( |
| + mojo::GetProxy(&view_tree_service_provider)); |
| + mojo::ConnectToService<mojo::ui::InputDispatcher>( |
| + view_tree_service_provider.get(), &input_dispatcher_); |
| + input_dispatcher_.set_connection_error_handler( |
| + base::Bind(&LauncherViewTree::OnInputDispatcherConnectionError, |
| + base::Unretained(this))); |
| } |
| LauncherViewTree::~LauncherViewTree() {} |
| @@ -45,17 +81,53 @@ void LauncherViewTree::SetViewportMetrics( |
| mojo::ViewportMetricsPtr viewport_metrics) { |
| viewport_metrics_ = viewport_metrics.Pass(); |
| view_tree_host_->RequestLayout(); |
| + SetRootScene(); |
| } |
| void LauncherViewTree::DispatchEvent(mojo::EventPtr event) { |
| - // TODO(jeffbrown): Support input dispatch. |
| + if (input_dispatcher_) |
| + input_dispatcher_->DispatchEvent(event.Pass()); |
| +} |
| + |
| +void LauncherViewTree::OnRendererConnectionError() { |
| + LOG(ERROR) << "Renderer connection error."; |
| + Shutdown(); |
| +} |
| + |
| +void LauncherViewTree::OnSceneConnectionError() { |
| + LOG(ERROR) << "Scene connection error."; |
| + Shutdown(); |
| +} |
| + |
| +void LauncherViewTree::OnViewTreeConnectionError() { |
| + LOG(ERROR) << "View tree connection error."; |
| + Shutdown(); |
| } |
| -void LauncherViewTree::OnViewManagerConnectionError() { |
| - LOG(ERROR) << "View manager connection error."; |
| +void LauncherViewTree::OnInputDispatcherConnectionError() { |
| + // This isn't considered a fatal error right now since it is still useful |
| + // to be able to test a view system that has graphics but no input. |
| + LOG(WARNING) << "Input dispatcher connection error, input will not work."; |
| + input_dispatcher_.reset(); |
| } |
| -void LauncherViewTree::OnViewTreeRegistered() {} |
| +void LauncherViewTree::OnSceneRegistered( |
| + mojo::gfx::composition::SceneTokenPtr scene_token) { |
| + DVLOG(1) << "OnSceneRegistered: scene_token=" << scene_token; |
| + scene_token_ = scene_token.Pass(); |
| + SetRootScene(); |
| +} |
| + |
| +void LauncherViewTree::OnViewTreeRegistered( |
| + mojo::ui::ViewTreeTokenPtr view_tree_token) { |
| + DVLOG(1) << "OnViewTreeRegistered: view_tree_token=" << view_tree_token; |
| +} |
| + |
| +void LauncherViewTree::OnResourceUnavailable( |
| + uint32_t resource_id, |
| + const OnResourceUnavailableCallback& callback) { |
| + LOG(ERROR) << "Resource lost: resource_id=" << resource_id; |
| +} |
| void LauncherViewTree::OnLayout(const OnLayoutCallback& callback) { |
| LayoutRoot(); |
| @@ -66,9 +138,8 @@ void LauncherViewTree::OnRootUnavailable( |
| uint32_t root_key, |
| const OnRootUnavailableCallback& callback) { |
| if (root_key_ == root_key) { |
| - // TODO(jeffbrown): We should probably shut down the launcher. |
| LOG(ERROR) << "Root view terminated unexpectedly."; |
| - SetRoot(mojo::ui::ViewTokenPtr()); |
| + Shutdown(); |
| } |
| callback.Run(); |
| } |
| @@ -97,63 +168,74 @@ void LauncherViewTree::OnLayoutResult(mojo::ui::ViewLayoutInfoPtr info) { |
| DVLOG(1) << "Root layout: size.width=" << info->size->width |
| << ", size.height=" << info->size->height |
| - << ", surface_id.id_namespace=" << info->surface_id->id_namespace |
| - << ", surface_id.local=" << info->surface_id->local; |
| + << ", scene_token.value=" << info->scene_token->value; |
| root_layout_info_ = info.Pass(); |
| - ScheduleFrame(); |
| + PublishFrame(); |
| } |
| -void LauncherViewTree::ScheduleFrame() { |
| - frame_scheduled_ = true; |
| - FinishFrame(); |
| +void LauncherViewTree::SetRootScene() { |
| + if (scene_token_) { |
| + mojo::Rect viewport; |
| + viewport.width = viewport_metrics_->size->width; |
| + viewport.height = viewport_metrics_->size->height; |
| + scene_version_++; |
| + renderer_->SetRootScene(scene_token_.Clone(), scene_version_, |
| + viewport.Clone()); |
| + PublishFrame(); |
| + } |
| } |
| -void LauncherViewTree::FinishFrame() { |
| - if (!frame_scheduled_ || frame_pending_) |
| - return; |
| - frame_scheduled_ = false; |
| - |
| - mojo::FramePtr frame = mojo::Frame::New(); |
| - frame->resources.resize(0u); |
| - |
| +void LauncherViewTree::PublishFrame() { |
| mojo::Rect bounds; |
| bounds.width = viewport_metrics_->size->width; |
| bounds.height = viewport_metrics_->size->height; |
| - mojo::PassPtr pass = mojo::CreateDefaultPass(1, bounds); |
| - pass->shared_quad_states.push_back( |
| - mojo::CreateDefaultSQS(*viewport_metrics_->size)); |
| - mojo::QuadPtr quad = mojo::Quad::New(); |
| - quad->rect = bounds.Clone(); |
| - quad->opaque_rect = bounds.Clone(); |
| - quad->visible_rect = bounds.Clone(); |
| - quad->shared_quad_state_index = 0u; |
| + auto update = mojo::gfx::composition::SceneUpdate::New(); |
| if (root_layout_info_) { |
| - quad->material = mojo::Material::SURFACE_CONTENT; |
| - quad->surface_quad_state = mojo::SurfaceQuadState::New(); |
| - quad->surface_quad_state->surface = root_layout_info_->surface_id.Clone(); |
| + auto view_resource = mojo::gfx::composition::Resource::New(); |
| + view_resource->set_scene(mojo::gfx::composition::SceneResource::New()); |
| + view_resource->get_scene()->scene_token = |
| + root_layout_info_->scene_token.Clone(); |
| + update->resources.insert(kViewSceneResourceId, view_resource.Pass()); |
| + |
| + auto view_node = mojo::gfx::composition::Node::New(); |
| + view_node->op = mojo::gfx::composition::NodeOp::New(); |
| + view_node->op->set_scene(mojo::gfx::composition::SceneNodeOp::New()); |
| + view_node->op->get_scene()->scene_resource_id = kViewSceneResourceId; |
| + update->nodes.insert(kViewNodeId, view_node.Pass()); |
| } else { |
| - quad->material = mojo::Material::SOLID_COLOR; |
| - quad->solid_color_quad_state = mojo::SolidColorQuadState::New(); |
| - quad->solid_color_quad_state->color = mojo::Color::New(); |
| - quad->solid_color_quad_state->color->rgba = 0xffff0000; |
| + update->resources.insert(kViewSceneResourceId, nullptr); |
| + update->nodes.insert(kViewNodeId, nullptr); |
| + } |
| + |
| + auto fallback_node = mojo::gfx::composition::Node::New(); |
| + fallback_node->op = mojo::gfx::composition::NodeOp::New(); |
| + fallback_node->op->set_rect(mojo::gfx::composition::RectNodeOp::New()); |
| + fallback_node->op->get_rect()->content_rect = bounds.Clone(); |
| + fallback_node->op->get_rect()->color = mojo::gfx::composition::Color::New(); |
| + fallback_node->op->get_rect()->color->red = 255; |
| + fallback_node->op->get_rect()->color->alpha = 255; |
| + update->nodes.insert(kFallbackNodeId, fallback_node.Pass()); |
| + |
| + auto root_node = mojo::gfx::composition::Node::New(); |
| + root_node->combinator = mojo::gfx::composition::Node::Combinator::FALLBACK; |
| + if (root_layout_info_) { |
| + root_node->child_node_ids.push_back(kViewNodeId); |
| } |
| + root_node->child_node_ids.push_back(kFallbackNodeId); |
| + update->nodes.insert(kRootNodeId, root_node.Pass()); |
| - pass->quads.push_back(quad.Pass()); |
| - frame->passes.push_back(pass.Pass()); |
| + auto metadata = mojo::gfx::composition::SceneMetadata::New(); |
| + metadata->version = scene_version_; |
| - frame_pending_ = true; |
| - display_->SubmitFrame( |
| - frame.Pass(), |
| - base::Bind(&LauncherViewTree::OnFrameSubmitted, base::Unretained(this))); |
| + scene_->Update(update.Pass()); |
| + scene_->Publish(metadata.Pass()); |
| } |
| -void LauncherViewTree::OnFrameSubmitted() { |
| - DCHECK(frame_pending_); |
| - frame_pending_ = false; |
| - FinishFrame(); |
| +void LauncherViewTree::Shutdown() { |
| + shutdown_callback_.Run(); |
| } |
| } // namespace launcher |