Update the UI examples. Port the Spinning Cube, Tile, Ganesh (aka. Shapes), PNG, and PDF examples to the new Mozart compositor and view manager. BUG= R=abarth@google.com, viettrungluu@chromium.org Review URL: https://codereview.chromium.org/1559723002 .
diff --git a/examples/BUILD.gn b/examples/BUILD.gn index c639c07..8b33176 100644 --- a/examples/BUILD.gn +++ b/examples/BUILD.gn
@@ -36,8 +36,17 @@ deps = [ ":portable_examples", + "//examples/ui/png_viewer", + "//examples/ui/shapes", + "//examples/ui/spinning_cube", + "//examples/ui/tile", ] + # TODO(cstout) - javascript/v8 build support for fnl/musl + if (!is_android && !is_fnl) { + deps += [ "//examples/ui/pdf_viewer" ] + } + if (is_android) { deps += [ "//examples/device_name",
diff --git a/examples/ganesh_app/BUILD.gn b/examples/ganesh_app/BUILD.gn deleted file mode 100644 index 915558c..0000000 --- a/examples/ganesh_app/BUILD.gn +++ /dev/null
@@ -1,35 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/mojo_application.gni") - -mojo_native_application("ganesh_app") { - sources = [ - "ganesh_app.cc", - "ganesh_view.cc", - "ganesh_view.h", - "texture_uploader.cc", - "texture_uploader.h", - ] - - deps = [ - "//base", - "//mojo/application", - "//mojo/common:tracing_impl", - "//mojo/environment:chromium", - "//mojo/gpu", - "//mojo/public/c/gpu", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/public/interfaces/application", - "//mojo/services/geometry/cpp", - "//mojo/services/geometry/interfaces", - "//mojo/services/surfaces/cpp", - "//mojo/services/surfaces/interfaces", - "//mojo/services/surfaces/interfaces:surface_id", - "//mojo/services/view_manager/cpp", - "//mojo/skia", - "//skia", - ] -}
diff --git a/examples/ganesh_app/README.md b/examples/ganesh_app/README.md deleted file mode 100644 index e4baf6b..0000000 --- a/examples/ganesh_app/README.md +++ /dev/null
@@ -1,15 +0,0 @@ -# Running ganesh_app - -To run ganesh_app, use one of the following command from the root of your Mojo repo. - -## Android - -``` -mojo/devtools/common/mojo_run --android "mojo:kiosk_wm mojo:ganesh_app" -``` - -## Linux - -``` -mojo/devtools/common/mojo_run "mojo:kiosk_wm mojo:ganesh_app" -```
diff --git a/examples/ganesh_app/ganesh_app.cc b/examples/ganesh_app/ganesh_app.cc deleted file mode 100644 index c382765..0000000 --- a/examples/ganesh_app/ganesh_app.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/macros.h" -#include "base/trace_event/trace_event.h" -#include "examples/ganesh_app/ganesh_view.h" -#include "mojo/application/application_runner_chromium.h" -#include "mojo/common/tracing_impl.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_connection.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/services/view_manager/cpp/view_manager.h" -#include "mojo/services/view_manager/cpp/view_manager_client_factory.h" -#include "mojo/services/view_manager/cpp/view_manager_delegate.h" - -namespace examples { - -class GaneshApp : public mojo::ApplicationDelegate, - public mojo::ViewManagerDelegate { - public: - GaneshApp() {} - ~GaneshApp() override {} - - void Initialize(mojo::ApplicationImpl* app) override { - tracing_.Initialize(app); - TRACE_EVENT0("ganesh_app", __func__); - shell_ = app->shell(); - view_manager_client_factory_.reset( - new mojo::ViewManagerClientFactory(app->shell(), this)); - } - - bool ConfigureIncomingConnection( - mojo::ApplicationConnection* connection) override { - TRACE_EVENT0("ganesh_app", __func__); - connection->AddService(view_manager_client_factory_.get()); - return true; - } - - void OnEmbed(mojo::View* root, - mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services) override { - TRACE_EVENT0("ganesh_app", __func__); - new GaneshView(shell_, root); - } - - void OnViewManagerDisconnected(mojo::ViewManager* view_manager) override { - base::MessageLoop::current()->Quit(); - } - - private: - mojo::TracingImpl tracing_; - mojo::Shell* shell_; - scoped_ptr<mojo::ViewManagerClientFactory> view_manager_client_factory_; - - DISALLOW_COPY_AND_ASSIGN(GaneshApp); -}; - -} // namespace examples - -MojoResult MojoMain(MojoHandle application_request) { - mojo::ApplicationRunnerChromium runner(new examples::GaneshApp); - return runner.Run(application_request); -}
diff --git a/examples/ganesh_app/ganesh_view.cc b/examples/ganesh_app/ganesh_view.cc deleted file mode 100644 index 4807548..0000000 --- a/examples/ganesh_app/ganesh_view.cc +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "examples/ganesh_app/ganesh_view.h" - -#include "base/logging.h" -#include "base/trace_event/trace_event.h" -#include "mojo/skia/ganesh_texture_surface.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkColor.h" - -namespace examples { - -namespace { - -mojo::Size ToSize(const mojo::Rect& rect) { - mojo::Size size; - size.width = rect.width; - size.height = rect.height; - return size; -} - -} // namespace - -GaneshView::GaneshView(mojo::Shell* shell, mojo::View* view) - : view_(view), - gl_context_(mojo::GLContext::Create(shell)), - gr_context_(new mojo::GaneshContext(gl_context_)), - texture_uploader_(this, shell, gl_context_) { - view_->AddObserver(this); - Draw(ToSize(view_->bounds())); -} - -GaneshView::~GaneshView() { - if (gl_context_) { - // GaneshContext needs to be destroyed before GLContext. - gr_context_.reset(); - gl_context_->Destroy(); - } -} - -void GaneshView::OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) { - view_->SetSurfaceId(surface_id.Pass()); -} - -void GaneshView::OnViewDestroyed(mojo::View* view) { - DCHECK(view == view_); - view_->RemoveObserver(this); - delete this; -} - -void GaneshView::OnViewInputEvent(mojo::View* view, - const mojo::EventPtr& event) { - Draw(ToSize(view_->bounds())); -} - -void GaneshView::OnViewBoundsChanged(mojo::View* view, - const mojo::Rect& old_bounds, - const mojo::Rect& new_bounds) { - Draw(ToSize(new_bounds)); -} - -void GaneshView::Draw(const mojo::Size& size) { - TRACE_EVENT0("ganesh_app", __func__); - mojo::GaneshContext::Scope scope(gr_context_.get()); - mojo::GaneshTextureSurface surface( - gr_context_.get(), - std::unique_ptr<mojo::GLTexture>(new mojo::GLTexture(gl_context_, size))); - - SkCanvas* canvas = surface.canvas(); - canvas->clear(SK_ColorCYAN); - - SkPaint paint; - paint.setColor(SK_ColorGREEN); - SkRect rect = SkRect::MakeWH(size.width, size.height); - rect.inset(10, 10); - canvas->drawRect(rect, paint); - - paint.setColor(SK_ColorRED); - paint.setFlags(SkPaint::kAntiAlias_Flag); - canvas->drawCircle(50, 100, 100, paint); - - canvas->flush(); - - texture_uploader_.Upload( - scoped_ptr<mojo::GLTexture>(surface.TakeTexture().release())); -} - -} // namespace examples
diff --git a/examples/ganesh_app/ganesh_view.h b/examples/ganesh_app/ganesh_view.h deleted file mode 100644 index e2c0c21..0000000 --- a/examples/ganesh_app/ganesh_view.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef EXAMPLES_GANESH_APP_GANESH_VIEW_H_ -#define EXAMPLES_GANESH_APP_GANESH_VIEW_H_ - -#include "examples/ganesh_app/texture_uploader.h" -#include "mojo/gpu/gl_context.h" -#include "mojo/services/surfaces/interfaces/surface_id.mojom.h" -#include "mojo/services/view_manager/cpp/view_observer.h" -#include "mojo/skia/ganesh_context.h" - -namespace mojo { -class Shell; -} - -namespace examples { - -class GaneshView : public TextureUploader::Client, public mojo::ViewObserver { - public: - GaneshView(mojo::Shell* shell, mojo::View* view); - ~GaneshView() override; - - private: - // mojo::ViewObserver implementation. - void OnViewDestroyed(mojo::View* view) override; - void OnViewBoundsChanged(mojo::View* view, - const mojo::Rect& old_bounds, - const mojo::Rect& new_bounds) override; - void OnViewInputEvent(mojo::View* view, const mojo::EventPtr& event) override; - - // TextureUploader::Client implementation. - void OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) override; - - void Draw(const mojo::Size& size); - - mojo::View* view_; - base::WeakPtr<mojo::GLContext> gl_context_; - scoped_ptr<mojo::GaneshContext> gr_context_; - TextureUploader texture_uploader_; - - DISALLOW_COPY_AND_ASSIGN(GaneshView); -}; - -} // namespace examples - -#endif // EXAMPLES_GANESH_APP_GANESH_VIEW_H_
diff --git a/examples/ganesh_app/texture_uploader.cc b/examples/ganesh_app/texture_uploader.cc deleted file mode 100644 index 9639460..0000000 --- a/examples/ganesh_app/texture_uploader.cc +++ /dev/null
@@ -1,172 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "examples/ganesh_app/texture_uploader.h" - -#ifndef GL_GLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES -#endif - -#include <GLES2/gl2.h> -#include <GLES2/gl2extmojo.h> - -#include "base/bind.h" -#include "base/trace_event/trace_event.h" -#include "mojo/public/cpp/application/connect.h" -#include "mojo/public/interfaces/application/shell.mojom.h" -#include "mojo/services/geometry/cpp/geometry_util.h" -#include "mojo/services/surfaces/cpp/surfaces_utils.h" - -namespace examples { - -TextureUploader::Client::~Client() {} - -TextureUploader::TextureUploader(Client* client, - mojo::Shell* shell, - base::WeakPtr<mojo::GLContext> context) - : client_(client), - context_(context), - next_resource_id_(0u), - id_namespace_(0u), - local_id_(0u), - returner_binding_(this) { - TRACE_EVENT0("ganesh_app", __func__); - context_->AddObserver(this); - - mojo::ServiceProviderPtr surfaces_service_provider; - shell->ConnectToApplication("mojo:surfaces_service", - mojo::GetProxy(&surfaces_service_provider), - nullptr); - mojo::ConnectToService(surfaces_service_provider.get(), &surface_); - surface_->GetIdNamespace( - base::Bind(&TextureUploader::SetIdNamespace, base::Unretained(this))); - mojo::ResourceReturnerPtr returner_ptr; - returner_binding_.Bind(GetProxy(&returner_ptr)); - surface_->SetResourceReturner(returner_ptr.Pass()); -} - -TextureUploader::~TextureUploader() { - if (context_.get()) - context_->RemoveObserver(this); -} - -void TextureUploader::Upload(scoped_ptr<mojo::GLTexture> texture) { - TRACE_EVENT0("ganesh_app", __func__); - mojo::Size size = texture->size(); - EnsureSurfaceForSize(size); - - mojo::FramePtr frame = mojo::Frame::New(); - frame->resources.resize(0u); - - mojo::Rect bounds; - bounds.width = size.width; - bounds.height = size.height; - mojo::PassPtr pass = mojo::CreateDefaultPass(1, bounds); - pass->quads.resize(0u); - pass->shared_quad_states.push_back(mojo::CreateDefaultSQS(size)); - - context_->MakeCurrent(); - glBindTexture(GL_TEXTURE_2D, texture->texture_id()); - GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; - glGenMailboxCHROMIUM(mailbox); - glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox); - GLuint sync_point = glInsertSyncPointCHROMIUM(); - - mojo::TransferableResourcePtr resource = mojo::TransferableResource::New(); - resource->id = next_resource_id_++; - resource_to_texture_map_[resource->id] = texture.release(); - resource->format = mojo::ResourceFormat::RGBA_8888; - resource->filter = GL_LINEAR; - resource->size = size.Clone(); - mojo::MailboxHolderPtr mailbox_holder = mojo::MailboxHolder::New(); - mailbox_holder->mailbox = mojo::Mailbox::New(); - for (int i = 0; i < GL_MAILBOX_SIZE_CHROMIUM; ++i) - mailbox_holder->mailbox->name.push_back(mailbox[i]); - mailbox_holder->texture_target = GL_TEXTURE_2D; - mailbox_holder->sync_point = sync_point; - resource->mailbox_holder = mailbox_holder.Pass(); - resource->is_repeated = false; - resource->is_software = false; - - mojo::QuadPtr quad = mojo::Quad::New(); - quad->material = mojo::Material::TEXTURE_CONTENT; - - mojo::RectPtr rect = mojo::Rect::New(); - rect->width = size.width; - rect->height = size.height; - quad->rect = rect.Clone(); - quad->opaque_rect = rect.Clone(); - quad->visible_rect = rect.Clone(); - quad->needs_blending = true; - quad->shared_quad_state_index = 0u; - - mojo::TextureQuadStatePtr texture_state = mojo::TextureQuadState::New(); - texture_state->resource_id = resource->id; - texture_state->premultiplied_alpha = true; - texture_state->uv_top_left = mojo::PointF::New(); - texture_state->uv_bottom_right = mojo::PointF::New(); - texture_state->uv_bottom_right->x = 1.f; - texture_state->uv_bottom_right->y = 1.f; - texture_state->background_color = mojo::Color::New(); - texture_state->background_color->rgba = 0; - for (int i = 0; i < 4; ++i) - texture_state->vertex_opacity.push_back(1.f); - texture_state->flipped = false; - - frame->resources.push_back(resource.Pass()); - quad->texture_quad_state = texture_state.Pass(); - pass->quads.push_back(quad.Pass()); - - frame->passes.push_back(pass.Pass()); - surface_->SubmitFrame(local_id_, frame.Pass(), mojo::Closure()); -} - -void TextureUploader::OnContextLost() { - LOG(FATAL) << "Context lost."; -} - -void TextureUploader::ReturnResources( - mojo::Array<mojo::ReturnedResourcePtr> resources) { - TRACE_EVENT0("ganesh_app", __func__); - context_->MakeCurrent(); - for (size_t i = 0u; i < resources.size(); ++i) { - mojo::ReturnedResourcePtr resource = resources[i].Pass(); - DCHECK_EQ(1, resource->count); - glWaitSyncPointCHROMIUM(resource->sync_point); - mojo::GLTexture* texture = resource_to_texture_map_[resource->id]; - DCHECK_NE(0u, texture->texture_id()); - resource_to_texture_map_.erase(resource->id); - delete texture; - } -} - -void TextureUploader::EnsureSurfaceForSize(const mojo::Size& size) { - TRACE_EVENT0("ganesh_app", __func__); - if (local_id_ != 0u && size == surface_size_) - return; - - if (local_id_ != 0u) { - surface_->DestroySurface(local_id_); - } - - local_id_++; - surface_->CreateSurface(local_id_); - surface_size_ = size; - if (id_namespace_ != 0u) - SendFullyQualifiedID(); -} -void TextureUploader::SendFullyQualifiedID() { - auto qualified_id = mojo::SurfaceId::New(); - qualified_id->id_namespace = id_namespace_; - qualified_id->local = local_id_; - client_->OnSurfaceIdAvailable(qualified_id.Pass()); -} - -void TextureUploader::SetIdNamespace(uint32_t id_namespace) { - id_namespace_ = id_namespace; - if (local_id_ != 0u) - SendFullyQualifiedID(); -} - -} // namespace examples
diff --git a/examples/ganesh_app/texture_uploader.h b/examples/ganesh_app/texture_uploader.h deleted file mode 100644 index 2b449e5..0000000 --- a/examples/ganesh_app/texture_uploader.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef EXAMPLES_GANESH_APP_TEXTURE_UPLOADER_H_ -#define EXAMPLES_GANESH_APP_TEXTURE_UPLOADER_H_ - -#include "base/containers/hash_tables.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "mojo/gpu/gl_context.h" -#include "mojo/gpu/gl_texture.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/services/geometry/interfaces/geometry.mojom.h" -#include "mojo/services/surfaces/interfaces/surface_id.mojom.h" -#include "mojo/services/surfaces/interfaces/surfaces.mojom.h" - -namespace mojo { -class Shell; -} - -namespace examples { - -class TextureUploader : public mojo::ResourceReturner, - public mojo::GLContext::Observer { - public: - class Client { - public: - virtual void OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) = 0; - - protected: - virtual ~Client(); - }; - - TextureUploader(Client* client, - mojo::Shell* shell, - base::WeakPtr<mojo::GLContext> context); - ~TextureUploader() override; - - void Upload(scoped_ptr<mojo::GLTexture> texture); - - private: - // mojo::GLContext::Observer - void OnContextLost() override; - - // mojo::ResourceReturner - void ReturnResources( - mojo::Array<mojo::ReturnedResourcePtr> resources) override; - - void SetIdNamespace(uint32_t id_namespace); - void EnsureSurfaceForSize(const mojo::Size& size); - void SendFullyQualifiedID(); - - Client* client_; - base::WeakPtr<mojo::GLContext> context_; - mojo::SurfacePtr surface_; - mojo::Size surface_size_; - uint32_t next_resource_id_; - uint32_t id_namespace_; - uint32_t local_id_; - base::hash_map<uint32_t, mojo::GLTexture*> resource_to_texture_map_; - mojo::Binding<mojo::ResourceReturner> returner_binding_; - - DISALLOW_COPY_AND_ASSIGN(TextureUploader); -}; - -} // namespace examples - -#endif // EXAMPLES_GANESH_APP_TEXTURE_UPLOADER_H_
diff --git a/examples/pdf_viewer/BUILD.gn b/examples/pdf_viewer/BUILD.gn deleted file mode 100644 index 58bf26e..0000000 --- a/examples/pdf_viewer/BUILD.gn +++ /dev/null
@@ -1,26 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/mojo_application.gni") - -mojo_native_application("pdf_viewer") { - sources = [ - "pdf_viewer.cc", - ] - - deps = [ - "//examples/bitmap_uploader", - "//mojo/application", - "//mojo/application:content_handler", - "//mojo/data_pipe_utils", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/utility", - "//mojo/services/content_handler/interfaces", - "//mojo/services/input_events/interfaces", - "//mojo/services/network/interfaces", - "//mojo/services/view_manager/cpp", - "//third_party/pdfium", - "//v8", - ] -}
diff --git a/examples/pdf_viewer/pdf_viewer.cc b/examples/pdf_viewer/pdf_viewer.cc deleted file mode 100644 index 57370d0..0000000 --- a/examples/pdf_viewer/pdf_viewer.cc +++ /dev/null
@@ -1,221 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <string> - -#include "examples/bitmap_uploader/bitmap_uploader.h" -#include "mojo/application/application_runner_chromium.h" -#include "mojo/application/content_handler_factory.h" -#include "mojo/data_pipe_utils/data_pipe_utils.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_connection.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/application/interface_factory_impl.h" -#include "mojo/public/cpp/application/service_provider_impl.h" -#include "mojo/services/content_handler/interfaces/content_handler.mojom.h" -#include "mojo/services/input_events/interfaces/input_events.mojom.h" -#include "mojo/services/input_events/interfaces/input_key_codes.mojom.h" -#include "mojo/services/view_manager/cpp/types.h" -#include "mojo/services/view_manager/cpp/view.h" -#include "mojo/services/view_manager/cpp/view_manager.h" -#include "mojo/services/view_manager/cpp/view_manager_client_factory.h" -#include "mojo/services/view_manager/cpp/view_manager_delegate.h" -#include "mojo/services/view_manager/cpp/view_observer.h" -#include "third_party/pdfium/fpdfsdk/include/fpdf_ext.h" -#include "third_party/pdfium/fpdfsdk/include/fpdfview.h" -#include "v8/include/v8.h" - -#define BACKGROUND_COLOR 0xFF888888 - -namespace mojo { -namespace examples { - -namespace { - -class EmbedderData { - public: - EmbedderData(Shell* shell, View* root) : bitmap_uploader_(root) { - bitmap_uploader_.Init(shell); - bitmap_uploader_.SetColor(BACKGROUND_COLOR); - } - - BitmapUploader& bitmap_uploader() { return bitmap_uploader_; } - - private: - BitmapUploader bitmap_uploader_; - - DISALLOW_COPY_AND_ASSIGN(EmbedderData); -}; - -} // namespace - -class PDFView : public ApplicationDelegate, - public ViewManagerDelegate, - public ViewObserver { - public: - PDFView(URLResponsePtr response) - : current_page_(0), page_count_(0), doc_(NULL), app_(nullptr) { - FetchPDF(response.Pass()); - } - - ~PDFView() override { - if (doc_) - FPDF_CloseDocument(doc_); - for (auto& roots : embedder_for_roots_) { - roots.first->RemoveObserver(this); - delete roots.second; - } - } - - private: - // Overridden from ApplicationDelegate: - void Initialize(ApplicationImpl* app) override { - app_ = app; - view_manager_client_factory_.reset( - new ViewManagerClientFactory(app->shell(), this)); - } - - bool ConfigureIncomingConnection(ApplicationConnection* connection) override { - connection->AddService(view_manager_client_factory_.get()); - return true; - } - - // Overridden from ViewManagerDelegate: - void OnEmbed(View* root, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services) override { - DCHECK(embedder_for_roots_.find(root) == embedder_for_roots_.end()); - root->AddObserver(this); - EmbedderData* embedder_data = new EmbedderData(app_->shell(), root); - embedder_for_roots_[root] = embedder_data; - DrawBitmap(embedder_data); - } - - void OnViewManagerDisconnected(ViewManager* view_manager) override {} - - // Overridden from ViewObserver: - void OnViewBoundsChanged(View* view, - const Rect& old_bounds, - const Rect& new_bounds) override { - DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end()); - DrawBitmap(embedder_for_roots_[view]); - } - - void OnViewInputEvent(View* view, const EventPtr& event) override { - DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end()); - if (event->key_data && - (event->action != EventType::KEY_PRESSED || event->key_data->is_char)) { - return; - } - if ((event->key_data && - event->key_data->windows_key_code == KeyboardCode::DOWN) || - (event->pointer_data && event->pointer_data->vertical_wheel < 0)) { - if (current_page_ < (page_count_ - 1)) { - current_page_++; - DrawBitmap(embedder_for_roots_[view]); - } - } else if ((event->key_data && - event->key_data->windows_key_code == KeyboardCode::UP) || - (event->pointer_data && - event->pointer_data->vertical_wheel > 0)) { - if (current_page_ > 0) { - current_page_--; - DrawBitmap(embedder_for_roots_[view]); - } - } - } - - void OnViewDestroyed(View* view) override { - DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end()); - const auto& it = embedder_for_roots_.find(view); - DCHECK(it != embedder_for_roots_.end()); - delete it->second; - embedder_for_roots_.erase(it); - if (embedder_for_roots_.size() == 0) - ApplicationImpl::Terminate(); - } - - void DrawBitmap(EmbedderData* embedder_data) { - if (!doc_) - return; - - FPDF_PAGE page = FPDF_LoadPage(doc_, current_page_); - int width = static_cast<int>(FPDF_GetPageWidth(page)); - int height = static_cast<int>(FPDF_GetPageHeight(page)); - - scoped_ptr<std::vector<unsigned char>> bitmap; - bitmap.reset(new std::vector<unsigned char>); - bitmap->resize(width * height * 4); - - FPDF_BITMAP f_bitmap = FPDFBitmap_CreateEx(width, height, FPDFBitmap_BGRA, - &(*bitmap)[0], width * 4); - FPDFBitmap_FillRect(f_bitmap, 0, 0, width, height, 0xFFFFFFFF); - FPDF_RenderPageBitmap(f_bitmap, page, 0, 0, width, height, 0, 0); - FPDFBitmap_Destroy(f_bitmap); - - FPDF_ClosePage(page); - - embedder_data->bitmap_uploader().SetBitmap(width, height, bitmap.Pass(), - BitmapUploader::BGRA); - } - - void FetchPDF(URLResponsePtr response) { - data_.clear(); - mojo::common::BlockingCopyToString(response->body.Pass(), &data_); - if (data_.length() >= static_cast<size_t>(std::numeric_limits<int>::max())) - return; - doc_ = FPDF_LoadMemDocument(data_.data(), static_cast<int>(data_.length()), - nullptr); - page_count_ = FPDF_GetPageCount(doc_); - } - - std::string data_; - int current_page_; - int page_count_; - FPDF_DOCUMENT doc_; - ApplicationImpl* app_; - std::map<View*, EmbedderData*> embedder_for_roots_; - scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_; - - DISALLOW_COPY_AND_ASSIGN(PDFView); -}; - -class PDFViewer : public ApplicationDelegate, - public ContentHandlerFactory::ManagedDelegate { - public: - PDFViewer() : content_handler_factory_(this) { - v8::V8::InitializeICU(); - FPDF_InitLibrary(); - } - - ~PDFViewer() override { FPDF_DestroyLibrary(); } - - private: - // Overridden from ApplicationDelegate: - bool ConfigureIncomingConnection(ApplicationConnection* connection) override { - connection->AddService(&content_handler_factory_); - return true; - } - - // Overridden from ContentHandlerFactory::ManagedDelegate: - scoped_ptr<ContentHandlerFactory::HandledApplicationHolder> - CreateApplication(InterfaceRequest<Application> application_request, - URLResponsePtr response) override { - return make_handled_factory_holder(new mojo::ApplicationImpl( - new PDFView(response.Pass()), application_request.Pass())); - } - - ContentHandlerFactory content_handler_factory_; - - DISALLOW_COPY_AND_ASSIGN(PDFViewer); -}; - -} // namespace examples -} // namespace mojo - -MojoResult MojoMain(MojoHandle application_request) { - mojo::ApplicationRunnerChromium runner(new mojo::examples::PDFViewer()); - return runner.Run(application_request); -}
diff --git a/examples/png_viewer/png_viewer.cc b/examples/png_viewer/png_viewer.cc deleted file mode 100644 index 47b31a0..0000000 --- a/examples/png_viewer/png_viewer.cc +++ /dev/null
@@ -1,198 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <algorithm> -#include <string> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "examples/bitmap_uploader/bitmap_uploader.h" -#include "mojo/application/application_runner_chromium.h" -#include "mojo/application/content_handler_factory.h" -#include "mojo/data_pipe_utils/data_pipe_utils.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_connection.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/application/interface_factory_impl.h" -#include "mojo/public/cpp/application/service_provider_impl.h" -#include "mojo/services/content_handler/interfaces/content_handler.mojom.h" -#include "mojo/services/view_manager/cpp/types.h" -#include "mojo/services/view_manager/cpp/view.h" -#include "mojo/services/view_manager/cpp/view_manager.h" -#include "mojo/services/view_manager/cpp/view_manager_client_factory.h" -#include "mojo/services/view_manager/cpp/view_manager_delegate.h" -#include "mojo/services/view_manager/cpp/view_observer.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/codec/png_codec.h" - -namespace mojo { -namespace examples { - -namespace { - -class EmbedderData { - public: - EmbedderData(Shell* shell, View* root) : bitmap_uploader_(root) { - bitmap_uploader_.Init(shell); - bitmap_uploader_.SetColor(SK_ColorGRAY); - } - - BitmapUploader& bitmap_uploader() { return bitmap_uploader_; } - - private: - BitmapUploader bitmap_uploader_; - - DISALLOW_COPY_AND_ASSIGN(EmbedderData); -}; - -} // namespace - -// TODO(aa): Hook up ZoomableMedia interface again. -class PNGView : public ApplicationDelegate, - public ViewManagerDelegate, - public ViewObserver { - public: - PNGView(URLResponsePtr response) - : width_(0), - height_(0), - app_(nullptr), - zoom_percentage_(kDefaultZoomPercentage) { - DecodePNG(response.Pass()); - } - - ~PNGView() override { - for (auto& roots : embedder_for_roots_) { - roots.first->RemoveObserver(this); - delete roots.second; - } - } - - private: - static const uint16_t kMaxZoomPercentage = 400; - static const uint16_t kMinZoomPercentage = 20; - static const uint16_t kDefaultZoomPercentage = 100; - static const uint16_t kZoomStep = 20; - - // Overridden from ApplicationDelegate: - void Initialize(ApplicationImpl* app) override { - app_ = app; - view_manager_client_factory_.reset( - new ViewManagerClientFactory(app->shell(), this)); - } - - // Overridden from ApplicationDelegate: - bool ConfigureIncomingConnection( - ApplicationConnection* connection) override { - connection->AddService(view_manager_client_factory_.get()); - return true; - } - - // Overridden from ViewManagerDelegate: - void OnEmbed(View* root, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services) override { - // TODO(qsr): The same view should be embeddable on multiple views. - DCHECK(embedder_for_roots_.find(root) == embedder_for_roots_.end()); - root->AddObserver(this); - EmbedderData* embedder_data = new EmbedderData(app_->shell(), root); - embedder_for_roots_[root] = embedder_data; - embedder_data->bitmap_uploader().SetBitmap( - width_, height_, - make_scoped_ptr(new std::vector<unsigned char>(*bitmap_)), - BitmapUploader::BGRA); - } - - void OnViewManagerDisconnected(ViewManager* view_manager) override { - } - - // Overridden from ViewObserver: - void OnViewBoundsChanged(View* view, - const Rect& old_bounds, - const Rect& new_bounds) override { - DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end()); - } - - void OnViewDestroyed(View* view) override { - // TODO(aa): Need to figure out how shutdown works. - const auto& it = embedder_for_roots_.find(view); - DCHECK(it != embedder_for_roots_.end()); - delete it->second; - embedder_for_roots_.erase(it); - if (embedder_for_roots_.size() == 0) - ApplicationImpl::Terminate(); - } - - void ZoomIn() { - // TODO(qsr,aa) Zoom should be per embedder view. - if (zoom_percentage_ >= kMaxZoomPercentage) - return; - zoom_percentage_ += kZoomStep; - } - - void ZoomOut() { - if (zoom_percentage_ <= kMinZoomPercentage) - return; - zoom_percentage_ -= kZoomStep; - } - - void ZoomToActualSize() { - if (zoom_percentage_ == kDefaultZoomPercentage) - return; - zoom_percentage_ = kDefaultZoomPercentage; - } - - void DecodePNG(URLResponsePtr response) { - std::string data; - mojo::common::BlockingCopyToString(response->body.Pass(), &data); - bitmap_.reset(new std::vector<unsigned char>); - gfx::PNGCodec::Decode(reinterpret_cast<const unsigned char*>(data.data()), - data.length(), gfx::PNGCodec::FORMAT_BGRA, - bitmap_.get(), &width_, &height_); - } - - int width_; - int height_; - scoped_ptr<std::vector<unsigned char>> bitmap_; - ApplicationImpl* app_; - std::map<View*, EmbedderData*> embedder_for_roots_; - scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_; - uint16_t zoom_percentage_; - - DISALLOW_COPY_AND_ASSIGN(PNGView); -}; - -class PNGViewer : public ApplicationDelegate, - public ContentHandlerFactory::ManagedDelegate { - public: - PNGViewer() : content_handler_factory_(this) {} - - private: - // Overridden from ApplicationDelegate: - bool ConfigureIncomingConnection(ApplicationConnection* connection) override { - connection->AddService(&content_handler_factory_); - return true; - } - - // Overridden from ContentHandlerFactory::ManagedDelegate: - scoped_ptr<ContentHandlerFactory::HandledApplicationHolder> - CreateApplication(InterfaceRequest<Application> application_request, - URLResponsePtr response) override { - return make_handled_factory_holder(new mojo::ApplicationImpl( - new PNGView(response.Pass()), application_request.Pass())); - } - - ContentHandlerFactory content_handler_factory_; - - DISALLOW_COPY_AND_ASSIGN(PNGViewer); -}; - -} // namespace examples -} // namespace mojo - -MojoResult MojoMain(MojoHandle application_request) { - mojo::ApplicationRunnerChromium runner(new mojo::examples::PNGViewer()); - return runner.Run(application_request); -}
diff --git a/examples/ui/pdf_viewer/BUILD.gn b/examples/ui/pdf_viewer/BUILD.gn new file mode 100644 index 0000000..7bb8927 --- /dev/null +++ b/examples/ui/pdf_viewer/BUILD.gn
@@ -0,0 +1,35 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/mojo_application.gni") + +mojo_native_application("pdf_viewer") { + sources = [ + "pdf_viewer.cc", + ] + + deps = [ + "//mojo/application", + "//mojo/data_pipe_utils", + "//mojo/environment:chromium", + "//mojo/gpu", + "//mojo/public/c/gpu", + "//mojo/public/cpp/bindings", + "//mojo/public/cpp/utility", + "//mojo/services/content_handler/interfaces", + "//mojo/services/geometry/interfaces", + "//mojo/services/gfx/composition/interfaces", + "//mojo/services/network/interfaces", + "//mojo/services/ui/input/interfaces", + "//mojo/services/ui/views/interfaces", + "//mojo/skia", + "//mojo/ui", + "//mojo/ui:content", + "//mojo/ui:ganesh", + "//mojo/ui:gl", + "//third_party/pdfium", + "//ui/gfx", + "//v8", + ] +}
diff --git a/examples/ui/pdf_viewer/README.md b/examples/ui/pdf_viewer/README.md new file mode 100644 index 0000000..1be9a65 --- /dev/null +++ b/examples/ui/pdf_viewer/README.md
@@ -0,0 +1,8 @@ +# PDF Content Handler Example + +This directory contains a simple application which decodes and views +PDFs by implementing a Mojo content handler. + +## USAGE + + out/Debug/mojo_shell "mojo:launcher http://.../my.pdf"
diff --git a/examples/ui/pdf_viewer/pdf_viewer.cc b/examples/ui/pdf_viewer/pdf_viewer.cc new file mode 100644 index 0000000..ee760ab --- /dev/null +++ b/examples/ui/pdf_viewer/pdf_viewer.cc
@@ -0,0 +1,305 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <string> + +#include "base/bind.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "mojo/application/application_runner_chromium.h" +#include "mojo/data_pipe_utils/data_pipe_utils.h" +#include "mojo/public/c/system/main.h" +#include "mojo/ui/choreographer.h" +#include "mojo/ui/content_viewer_app.h" +#include "mojo/ui/ganesh_view.h" +#include "mojo/ui/input_handler.h" +#include "third_party/pdfium/fpdfsdk/include/fpdf_ext.h" +#include "third_party/pdfium/fpdfsdk/include/fpdfview.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkData.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkImageInfo.h" +#include "third_party/skia/include/core/SkSurface.h" +#include "v8/include/v8.h" + +namespace examples { + +namespace { +constexpr uint32_t kContentImageResourceId = 1; +constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId; +} // namespace + +class PDFLibrary; + +class PDFDocument { + public: + PDFDocument(const std::shared_ptr<PDFLibrary>& pdf_library, + FPDF_DOCUMENT doc, + const std::string& data) + : pdf_library_(pdf_library), + doc_(doc), + data_(data), + page_count_(FPDF_GetPageCount(doc_)) {} + + ~PDFDocument() { FPDF_CloseDocument(doc_); } + + uint32_t page_count() { return page_count_; } + + skia::RefPtr<SkImage> DrawPage(int page_index, const mojo::Size& size) { + FPDF_PAGE page = FPDF_LoadPage(doc_, page_index); + + double width_pts = FPDF_GetPageWidth(page); + double height_pts = FPDF_GetPageHeight(page); + + int width, height; + if (size.width * height_pts < size.height * width_pts) { + width = size.width; + height = height_pts * size.width / width_pts; + } else { + width = width_pts * size.height / height_pts; + height = size.height; + } + + int stride = width * 4; + skia::RefPtr<SkData> pixels = + skia::AdoptRef(SkData::NewUninitialized(stride * height)); + DCHECK(pixels); + + FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(width, height, FPDFBitmap_BGRA, + pixels->writable_data(), stride); + FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF); + FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0); + FPDFBitmap_Destroy(bitmap); + + FPDF_ClosePage(page); + + SkImageInfo info = SkImageInfo::Make(width, height, kBGRA_8888_SkColorType, + kOpaque_SkAlphaType); + return skia::AdoptRef(SkImage::NewRasterData(info, pixels.get(), stride)); + } + + private: + std::shared_ptr<PDFLibrary> pdf_library_; + FPDF_DOCUMENT doc_; + std::string data_; + uint32_t page_count_; +}; + +class PDFLibrary : public std::enable_shared_from_this<PDFLibrary> { + public: + PDFLibrary() { + v8::V8::InitializeICU(); + FPDF_InitLibrary(); + } + + ~PDFLibrary() { FPDF_DestroyLibrary(); } + + std::shared_ptr<PDFDocument> Decode(mojo::URLResponsePtr response) { + std::string data; + mojo::common::BlockingCopyToString(response->body.Pass(), &data); + if (data.length() >= static_cast<size_t>(std::numeric_limits<int>::max())) + return nullptr; + + FPDF_DOCUMENT doc = FPDF_LoadMemDocument( + data.data(), static_cast<int>(data.length()), nullptr); + if (!doc) + return nullptr; + + return std::make_shared<PDFDocument>(shared_from_this(), doc, data); + } +}; + +class PDFDocumentView : public mojo::ui::GaneshView, + public mojo::ui::ChoreographerDelegate, + public mojo::ui::InputListener { + public: + PDFDocumentView( + mojo::ApplicationImpl* app_impl, + const std::shared_ptr<PDFDocument>& pdf_document, + const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback) + : GaneshView(app_impl, "PDFDocumentViewer", create_view_callback), + pdf_document_(pdf_document), + choreographer_(scene(), this), + input_handler_(view_service_provider(), this) { + DCHECK(pdf_document_); + } + + ~PDFDocumentView() override {} + + private: + // |GaneshView|: + void OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params, + mojo::Array<uint32_t> children_needing_layout, + const OnLayoutCallback& callback) override { + size_.width = layout_params->constraints->max_width; + size_.height = layout_params->constraints->max_height; + + auto info = mojo::ui::ViewLayoutResult::New(); + info->size = size_.Clone(); + callback.Run(info.Pass()); + + Redraw(); + } + + // |InputListener|: + void OnEvent(mojo::EventPtr event, const OnEventCallback& callback) override { + if (event->key_data && (event->action != mojo::EventType::KEY_PRESSED || + event->key_data->is_char)) { + callback.Run(false); + return; + } + + if ((event->key_data && + event->key_data->windows_key_code == mojo::KeyboardCode::DOWN) || + (event->pointer_data && event->pointer_data->vertical_wheel < 0)) { + GotoNextPage(); + callback.Run(true); + return; + } + + if ((event->key_data && + event->key_data->windows_key_code == mojo::KeyboardCode::UP) || + (event->pointer_data && event->pointer_data->vertical_wheel > 0)) { + GotoPreviousPage(); + callback.Run(true); + return; + } + + callback.Run(false); + } + + // |ChoreographerDelegate|: + void OnDraw(const mojo::gfx::composition::FrameInfo& frame_info, + const base::TimeDelta& time_delta) override { + mojo::Rect bounds; + bounds.width = size_.width; + bounds.height = size_.height; + + auto update = mojo::gfx::composition::SceneUpdate::New(); + mojo::gfx::composition::ResourcePtr content_resource = + ganesh_renderer()->DrawCanvas( + size_, + base::Bind(&PDFDocumentView::DrawContent, base::Unretained(this))); + DCHECK(content_resource); + update->resources.insert(kContentImageResourceId, content_resource.Pass()); + + auto root_node = mojo::gfx::composition::Node::New(); + root_node->op = mojo::gfx::composition::NodeOp::New(); + root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New()); + root_node->op->get_image()->content_rect = bounds.Clone(); + root_node->op->get_image()->image_resource_id = kContentImageResourceId; + update->nodes.insert(kRootNodeId, root_node.Pass()); + + scene()->Update(update.Pass()); + scene()->Publish(nullptr); + } + + void DrawContent(SkCanvas* canvas) { + if (!cached_image_) { + cached_image_ = pdf_document_->DrawPage(page_, size_); + } + + if (cached_image_) { + canvas->clear(SK_ColorBLACK); + canvas->drawImageRect( + cached_image_.get(), + SkRect::MakeWH(cached_image_->width(), cached_image_->height()), + SkRect::MakeXYWH((size_.width - cached_image_->width()) / 2, + (size_.height - cached_image_->height()) / 2, + cached_image_->width(), cached_image_->height()), + nullptr); + } else { + canvas->clear(SK_ColorBLUE); + } + } + + void GotoNextPage() { + if (page_ + 1 < pdf_document_->page_count()) { + page_++; + Redraw(); + } + } + + void GotoPreviousPage() { + if (page_ > 0) { + page_--; + Redraw(); + } + } + + void Redraw() { + cached_image_.clear(); + choreographer_.ScheduleDraw(); + } + + std::shared_ptr<PDFDocument> pdf_document_; + uint32_t page_ = 0u; + skia::RefPtr<SkImage> cached_image_; + + mojo::Size size_; + mojo::ui::Choreographer choreographer_; + mojo::ui::InputHandler input_handler_; + + DISALLOW_COPY_AND_ASSIGN(PDFDocumentView); +}; + +class PDFContentViewProviderApp : public mojo::ui::ViewProviderApp { + public: + PDFContentViewProviderApp(const std::shared_ptr<PDFLibrary>& pdf_library, + const std::shared_ptr<PDFDocument>& pdf_document) + : pdf_library_(pdf_library), pdf_document_(pdf_document) { + DCHECK(pdf_library_); + DCHECK(pdf_document_); + } + + ~PDFContentViewProviderApp() override {} + + bool CreateView( + const std::string& connection_url, + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services, + const mojo::ui::ViewProvider::CreateViewCallback& callback) override { + new PDFDocumentView(app_impl(), pdf_document_, callback); + return true; + } + + private: + std::shared_ptr<PDFLibrary> pdf_library_; + std::shared_ptr<PDFDocument> pdf_document_; + + DISALLOW_COPY_AND_ASSIGN(PDFContentViewProviderApp); +}; + +class PDFContentViewerApp : public mojo::ui::ContentViewerApp { + public: + PDFContentViewerApp() : pdf_library_(std::make_shared<PDFLibrary>()) {} + + ~PDFContentViewerApp() override {} + + mojo::ui::ViewProviderApp* LoadContent( + const std::string& content_handler_url, + mojo::URLResponsePtr response) override { + std::shared_ptr<PDFDocument> pdf_document = + pdf_library_->Decode(response.Pass()); + if (!pdf_document) { + LOG(ERROR) << "Could not decode PDFDocument."; + return nullptr; + } + + return new PDFContentViewProviderApp(pdf_library_, pdf_document); + } + + private: + std::shared_ptr<PDFLibrary> pdf_library_; + + DISALLOW_COPY_AND_ASSIGN(PDFContentViewerApp); +}; + +} // namespace examples + +MojoResult MojoMain(MojoHandle application_request) { + mojo::ApplicationRunnerChromium runner(new examples::PDFContentViewerApp()); + return runner.Run(application_request); +}
diff --git a/examples/png_viewer/BUILD.gn b/examples/ui/png_viewer/BUILD.gn similarity index 62% rename from examples/png_viewer/BUILD.gn rename to examples/ui/png_viewer/BUILD.gn index 16061bc..6ff4b26 100644 --- a/examples/png_viewer/BUILD.gn +++ b/examples/ui/png_viewer/BUILD.gn
@@ -10,15 +10,23 @@ ] deps = [ - "//examples/bitmap_uploader", "//mojo/application", - "//mojo/application:content_handler", "//mojo/data_pipe_utils", + "//mojo/environment:chromium", + "//mojo/gpu", + "//mojo/public/c/gpu", "//mojo/public/cpp/bindings", "//mojo/public/cpp/utility", "//mojo/services/content_handler/interfaces", + "//mojo/services/geometry/interfaces", + "//mojo/services/gfx/composition/interfaces", "//mojo/services/network/interfaces", - "//mojo/services/view_manager/cpp", + "//mojo/services/ui/views/interfaces", + "//mojo/skia", + "//mojo/ui", + "//mojo/ui:content", + "//mojo/ui:ganesh", + "//mojo/ui:gl", "//ui/gfx", ] }
diff --git a/examples/ui/png_viewer/README.md b/examples/ui/png_viewer/README.md new file mode 100644 index 0000000..44f51cf --- /dev/null +++ b/examples/ui/png_viewer/README.md
@@ -0,0 +1,8 @@ +# PNG Content Handler Example + +This directory contains a simple application which decodes and views +PNGs by implementing a Mojo content handler. + +## USAGE + + out/Debug/mojo_shell "mojo:launcher http://.../my.png"
diff --git a/examples/ui/png_viewer/png_viewer.cc b/examples/ui/png_viewer/png_viewer.cc new file mode 100644 index 0000000..abd5c48 --- /dev/null +++ b/examples/ui/png_viewer/png_viewer.cc
@@ -0,0 +1,157 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "base/bind.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "mojo/application/application_runner_chromium.h" +#include "mojo/data_pipe_utils/data_pipe_utils.h" +#include "mojo/public/c/system/main.h" +#include "mojo/ui/content_viewer_app.h" +#include "mojo/ui/ganesh_view.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkSurface.h" +#include "ui/gfx/codec/png_codec.h" + +namespace examples { + +namespace { +constexpr uint32_t kContentImageResourceId = 1; +constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId; +} // namespace + +class PNGView : public mojo::ui::GaneshView { + public: + PNGView( + mojo::ApplicationImpl* app_impl, + const skia::RefPtr<SkImage>& image, + const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback) + : GaneshView(app_impl, "PNGViewer", create_view_callback), image_(image) { + DCHECK(image_); + } + + ~PNGView() override {} + + private: + // |GaneshView|: + void OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params, + mojo::Array<uint32_t> children_needing_layout, + const OnLayoutCallback& callback) override { + size_.width = layout_params->constraints->max_width; + size_.height = layout_params->constraints->max_height; + + auto info = mojo::ui::ViewLayoutResult::New(); + info->size = size_.Clone(); + callback.Run(info.Pass()); + + UpdateScene(); + } + + void UpdateScene() { + mojo::Rect bounds; + bounds.width = size_.width; + bounds.height = size_.height; + + auto update = mojo::gfx::composition::SceneUpdate::New(); + mojo::gfx::composition::ResourcePtr content_resource = + ganesh_renderer()->DrawCanvas( + size_, base::Bind(&PNGView::DrawContent, base::Unretained(this))); + DCHECK(content_resource); + update->resources.insert(kContentImageResourceId, content_resource.Pass()); + + auto root_node = mojo::gfx::composition::Node::New(); + root_node->op = mojo::gfx::composition::NodeOp::New(); + root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New()); + root_node->op->get_image()->content_rect = bounds.Clone(); + root_node->op->get_image()->image_resource_id = kContentImageResourceId; + update->nodes.insert(kRootNodeId, root_node.Pass()); + + scene()->Update(update.Pass()); + scene()->Publish(nullptr); + } + + void DrawContent(SkCanvas* canvas) { + canvas->clear(SK_ColorBLACK); + + int32_t w, h; + if (size_.width * image_->height() < size_.height * image_->width()) { + w = size_.width; + h = image_->height() * size_.width / image_->width(); + } else { + w = image_->width() * size_.height / image_->height(); + h = size_.height; + } + canvas->drawImageRect( + image_.get(), SkRect::MakeWH(image_->width(), image_->height()), + SkRect::MakeXYWH((size_.width - w) / 2, (size_.height - h) / 2, w, h), + nullptr); + } + + skia::RefPtr<SkImage> image_; + mojo::Size size_; + + DISALLOW_COPY_AND_ASSIGN(PNGView); +}; + +class PNGContentViewProviderApp : public mojo::ui::ViewProviderApp { + public: + PNGContentViewProviderApp(skia::RefPtr<SkImage> image) : image_(image) { + DCHECK(image_); + } + + ~PNGContentViewProviderApp() override {} + + bool CreateView( + const std::string& connection_url, + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services, + const mojo::ui::ViewProvider::CreateViewCallback& callback) override { + new PNGView(app_impl(), image_, callback); + return true; + } + + private: + skia::RefPtr<SkImage> image_; + + DISALLOW_COPY_AND_ASSIGN(PNGContentViewProviderApp); +}; + +class PNGContentViewerApp : public mojo::ui::ContentViewerApp { + public: + PNGContentViewerApp() {} + + ~PNGContentViewerApp() override {} + + mojo::ui::ViewProviderApp* LoadContent( + const std::string& content_handler_url, + mojo::URLResponsePtr response) override { + std::string data; + mojo::common::BlockingCopyToString(response->body.Pass(), &data); + SkBitmap bitmap; + if (!::gfx::PNGCodec::Decode( + reinterpret_cast<const unsigned char*>(data.data()), data.length(), + &bitmap) || + bitmap.empty()) { + LOG(ERROR) << "Could not decode PNG."; + return nullptr; + } + + return new PNGContentViewProviderApp( + skia::AdoptRef(SkImage::NewFromBitmap(bitmap))); + } + + private: + DISALLOW_COPY_AND_ASSIGN(PNGContentViewerApp); +}; + +} // namespace examples + +MojoResult MojoMain(MojoHandle application_request) { + mojo::ApplicationRunnerChromium runner(new examples::PNGContentViewerApp()); + return runner.Run(application_request); +}
diff --git a/examples/ui/shapes/BUILD.gn b/examples/ui/shapes/BUILD.gn new file mode 100644 index 0000000..4462987 --- /dev/null +++ b/examples/ui/shapes/BUILD.gn
@@ -0,0 +1,37 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/mojo_application.gni") + +mojo_native_application("shapes") { + output_name = "shapes_view" + + sources = [ + "main.cc", + "shapes_app.cc", + "shapes_app.h", + "shapes_view.cc", + "shapes_view.h", + ] + + deps = [ + "//base", + "//mojo/application", + "//mojo/common", + "//mojo/environment:chromium", + "//mojo/gpu", + "//mojo/public/c/gpu", + "//mojo/public/cpp/bindings", + "//mojo/public/cpp/environment", + "//mojo/public/cpp/system", + "//mojo/services/geometry/interfaces", + "//mojo/services/gfx/composition/interfaces", + "//mojo/services/ui/views/interfaces", + "//mojo/skia", + "//mojo/ui", + "//mojo/ui:ganesh", + "//mojo/ui:gl", + "//skia", + ] +}
diff --git a/examples/ui/shapes/README.md b/examples/ui/shapes/README.md new file mode 100644 index 0000000..968dc4a --- /dev/null +++ b/examples/ui/shapes/README.md
@@ -0,0 +1,8 @@ +# Skia GPU Accelerated Drawing Example (Ganesh) + +This directory contains a simple application which uses Skia's +Ganesh renderer to draw some simple shapes in a view. + +## USAGE + + out/Debug/mojo_shell "mojo:launcher mojo:shapes_view"
diff --git a/examples/ui/shapes/main.cc b/examples/ui/shapes/main.cc new file mode 100644 index 0000000..bf4925e --- /dev/null +++ b/examples/ui/shapes/main.cc
@@ -0,0 +1,12 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "examples/ui/shapes/shapes_app.h" +#include "mojo/application/application_runner_chromium.h" +#include "mojo/public/c/system/main.h" + +MojoResult MojoMain(MojoHandle application_request) { + mojo::ApplicationRunnerChromium runner(new examples::ShapesApp); + return runner.Run(application_request); +}
diff --git a/examples/ui/shapes/shapes_app.cc b/examples/ui/shapes/shapes_app.cc new file mode 100644 index 0000000..86443a1 --- /dev/null +++ b/examples/ui/shapes/shapes_app.cc
@@ -0,0 +1,24 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "examples/ui/shapes/shapes_app.h" + +#include "examples/ui/shapes/shapes_view.h" + +namespace examples { + +ShapesApp::ShapesApp() {} + +ShapesApp::~ShapesApp() {} + +bool ShapesApp::CreateView( + const std::string& connection_url, + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services, + const mojo::ui::ViewProvider::CreateViewCallback& callback) { + new ShapesView(app_impl(), callback); + return true; +} + +} // namespace examples
diff --git a/examples/ui/shapes/shapes_app.h b/examples/ui/shapes/shapes_app.h new file mode 100644 index 0000000..4aba71c --- /dev/null +++ b/examples/ui/shapes/shapes_app.h
@@ -0,0 +1,29 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXAMPLES_UI_SHAPES_SHAPES_APP_H_ +#define EXAMPLES_UI_SHAPES_SHAPES_APP_H_ + +#include "mojo/ui/view_provider_app.h" + +namespace examples { + +class ShapesApp : public mojo::ui::ViewProviderApp { + public: + ShapesApp(); + ~ShapesApp() override; + + bool CreateView( + const std::string& connection_url, + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services, + const mojo::ui::ViewProvider::CreateViewCallback& callback) override; + + private: + DISALLOW_COPY_AND_ASSIGN(ShapesApp); +}; + +} // namespace examples + +#endif // EXAMPLES_UI_SHAPES_SHAPES_APP_H_
diff --git a/examples/ui/shapes/shapes_view.cc b/examples/ui/shapes/shapes_view.cc new file mode 100644 index 0000000..8bea9c3 --- /dev/null +++ b/examples/ui/shapes/shapes_view.cc
@@ -0,0 +1,86 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "examples/ui/shapes/shapes_view.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkSurface.h" + +namespace examples { + +namespace { +constexpr uint32_t kContentImageResourceId = 1; +constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId; +} // namespace + +ShapesView::ShapesView( + mojo::ApplicationImpl* app_impl, + const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback) + : GaneshView(app_impl, "Shapes", create_view_callback) {} + +ShapesView::~ShapesView() {} + +void ShapesView::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params, + mojo::Array<uint32_t> children_needing_layout, + const OnLayoutCallback& callback) { + size_.width = layout_params->constraints->max_width; + size_.height = layout_params->constraints->max_height; + + // Submit the new layout information. + auto info = mojo::ui::ViewLayoutResult::New(); + info->size = size_.Clone(); + callback.Run(info.Pass()); + + // Draw! + UpdateScene(); +} + +void ShapesView::UpdateScene() { + mojo::Rect bounds; + bounds.width = size_.width; + bounds.height = size_.height; + + auto update = mojo::gfx::composition::SceneUpdate::New(); + + // Draw the content of the view to a texture and include it as an + // image resource in the scene. + mojo::gfx::composition::ResourcePtr content_resource = + ganesh_renderer()->DrawCanvas( + size_, base::Bind(&ShapesView::DrawContent, base::Unretained(this))); + DCHECK(content_resource); + update->resources.insert(kContentImageResourceId, content_resource.Pass()); + + // Add a root node to the scene graph to draw the image resource to + // the screen such that it fills the entire view. + auto root_node = mojo::gfx::composition::Node::New(); + root_node->op = mojo::gfx::composition::NodeOp::New(); + root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New()); + root_node->op->get_image()->content_rect = bounds.Clone(); + root_node->op->get_image()->image_resource_id = kContentImageResourceId; + update->nodes.insert(kRootNodeId, root_node.Pass()); + + // Submit the scene update then publish it to cause the changes to be + // applied. + scene()->Update(update.Pass()); + scene()->Publish(nullptr); +} + +void ShapesView::DrawContent(SkCanvas* canvas) { + canvas->clear(SK_ColorCYAN); + + SkPaint paint; + paint.setColor(SK_ColorGREEN); + SkRect rect = SkRect::MakeWH(size_.width, size_.height); + rect.inset(10, 10); + canvas->drawRect(rect, paint); + + paint.setColor(SK_ColorRED); + paint.setFlags(SkPaint::kAntiAlias_Flag); + canvas->drawCircle(50, 100, 100, paint); +} + +} // namespace examples
diff --git a/examples/ui/shapes/shapes_view.h b/examples/ui/shapes/shapes_view.h new file mode 100644 index 0000000..d041f7e --- /dev/null +++ b/examples/ui/shapes/shapes_view.h
@@ -0,0 +1,38 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXAMPLES_UI_SHAPES_SHAPES_VIEW_H_ +#define EXAMPLES_UI_SHAPES_SHAPES_VIEW_H_ + +#include "mojo/ui/ganesh_view.h" + +class SkCanvas; + +namespace examples { + +class ShapesView : public mojo::ui::GaneshView { + public: + ShapesView( + mojo::ApplicationImpl* app_impl, + const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback); + + ~ShapesView() override; + + private: + // |GaneshView|: + void OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params, + mojo::Array<uint32_t> children_needing_layout, + const OnLayoutCallback& callback) override; + + void UpdateScene(); + void DrawContent(SkCanvas* canvas); + + mojo::Size size_; + + DISALLOW_COPY_AND_ASSIGN(ShapesView); +}; + +} // namespace examples + +#endif // EXAMPLES_UI_SHAPES_SHAPES_VIEW_H_
diff --git a/examples/ui/spinning_cube/BUILD.gn b/examples/ui/spinning_cube/BUILD.gn index db71418..ef0ee43 100644 --- a/examples/ui/spinning_cube/BUILD.gn +++ b/examples/ui/spinning_cube/BUILD.gn
@@ -23,13 +23,17 @@ "//mojo/environment:chromium", "//mojo/gpu", "//mojo/public/c/gpu", - "//mojo/public/c/gpu:gpu_onscreen", "//mojo/public/cpp/bindings", "//mojo/public/cpp/environment", "//mojo/public/cpp/system", + "//mojo/services/geometry/cpp", "//mojo/services/geometry/interfaces", + "//mojo/services/gfx/composition/interfaces", "//mojo/services/input_events/interfaces", - "//mojo/services/surfaces/interfaces", + "//mojo/services/ui/input/interfaces", "//mojo/services/ui/views/interfaces", + "//mojo/ui", + "//mojo/ui:ganesh", + "//mojo/ui:gl", ] }
diff --git a/examples/ui/spinning_cube/spinning_cube_app.cc b/examples/ui/spinning_cube/spinning_cube_app.cc index 6bee8d4..79818ee 100644 --- a/examples/ui/spinning_cube/spinning_cube_app.cc +++ b/examples/ui/spinning_cube/spinning_cube_app.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "examples/ui/spinning_cube/spinning_cube_app.h" + #include "examples/ui/spinning_cube/spinning_cube_view.h" namespace examples { @@ -11,27 +12,13 @@ SpinningCubeApp::~SpinningCubeApp() {} -void SpinningCubeApp::Initialize(mojo::ApplicationImpl* app_impl) { - app_impl_ = app_impl; -} - -bool SpinningCubeApp::ConfigureIncomingConnection( - mojo::ApplicationConnection* connection) { - connection->AddService<mojo::ui::ViewProvider>(this); - return true; -} - -void SpinningCubeApp::Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<mojo::ui::ViewProvider> request) { - bindings_.AddBinding(this, request.Pass()); -} - -void SpinningCubeApp::CreateView( +bool SpinningCubeApp::CreateView( + const std::string& connection_url, mojo::InterfaceRequest<mojo::ServiceProvider> services, mojo::ServiceProviderPtr exposed_services, - const CreateViewCallback& callback) { - new SpinningCubeView(app_impl_, callback); + const mojo::ui::ViewProvider::CreateViewCallback& callback) { + new SpinningCubeView(app_impl(), callback); + return true; } } // namespace examples
diff --git a/examples/ui/spinning_cube/spinning_cube_app.h b/examples/ui/spinning_cube/spinning_cube_app.h index d1e99e7..e658717 100644 --- a/examples/ui/spinning_cube/spinning_cube_app.h +++ b/examples/ui/spinning_cube/spinning_cube_app.h
@@ -5,43 +5,22 @@ #ifndef EXAMPLES_UI_SPINNING_CUBE_SPINNING_CUBE_APP_H_ #define EXAMPLES_UI_SPINNING_CUBE_SPINNING_CUBE_APP_H_ -#include "base/bind.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/common/binding_set.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_connection.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/macros.h" -#include "mojo/services/ui/views/interfaces/view_provider.mojom.h" +#include "mojo/ui/view_provider_app.h" namespace examples { -class SpinningCubeApp : public mojo::ApplicationDelegate, - public mojo::InterfaceFactory<mojo::ui::ViewProvider>, - public mojo::ui::ViewProvider { +class SpinningCubeApp : public mojo::ui::ViewProviderApp { public: SpinningCubeApp(); ~SpinningCubeApp() override; + bool CreateView( + const std::string& connection_url, + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services, + const mojo::ui::ViewProvider::CreateViewCallback& callback) override; + private: - // |ApplicationDelegate|: - void Initialize(mojo::ApplicationImpl* app) override; - bool ConfigureIncomingConnection( - mojo::ApplicationConnection* connection) override; - - // |InterfaceFactory<mojo::ui::ViewProvider>|: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<mojo::ui::ViewProvider> request) override; - - // |ViewProvider|: - void CreateView(mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services, - const CreateViewCallback& callback) override; - - mojo::ApplicationImpl* app_impl_; - mojo::BindingSet<mojo::ui::ViewProvider> bindings_; - DISALLOW_COPY_AND_ASSIGN(SpinningCubeApp); };
diff --git a/examples/ui/spinning_cube/spinning_cube_view.cc b/examples/ui/spinning_cube/spinning_cube_view.cc index 8c3ce7a..68fb4f6 100644 --- a/examples/ui/spinning_cube/spinning_cube_view.cc +++ b/examples/ui/spinning_cube/spinning_cube_view.cc
@@ -2,161 +2,191 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "examples/ui/spinning_cube/spinning_cube_view.h" + +#ifndef GL_GLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES +#endif + #include <GLES2/gl2.h> #include <GLES2/gl2extmojo.h> -#include <MGL/mgl.h> -#include "base/message_loop/message_loop.h" -#include "examples/ui/spinning_cube/spinning_cube_view.h" +#include <cmath> + +#include "base/bind.h" +#include "mojo/services/geometry/cpp/geometry_util.h" namespace examples { +namespace { +constexpr uint32_t kCubeImageResourceId = 1; +constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId; + +// TODO(johngro) : investigate extending mojom with a formal flags type which it +// generates good bindings for, so we don't need to resort to this. +constexpr bool operator&(const mojo::EventFlags& f1, + const mojo::EventFlags& f2) { + return ((static_cast<uint32_t>(f1) & static_cast<uint32_t>(f2)) != 0); +} + +float CalculateDragDistance(const mojo::PointF& start, + const mojo::PointF& end) { + return std::hypot(start.x - end.x, start.y - end.y); +} + +float GetRandomColor() { + return static_cast<float>(rand()) / static_cast<float>(RAND_MAX); +} + +// Return a direction multiplier to apply to drag distances: +// 1 for natural (positive) motion, -1 for reverse (negative) motion +int GetEventDirection(const mojo::PointF& current, + const mojo::PointF& initial, + const mojo::PointF& last) { + // Axis of motion is determined by coarse alignment of overall movement + bool use_x = + std::abs(current.y - initial.y) < std::abs(current.x - initial.x); + // Current direction is determined by comparison with previous point + float delta = use_x ? (current.x - last.x) : (current.y - last.y); + return delta > 0 ? -1 : 1; +} +} // namespace + SpinningCubeView::SpinningCubeView( - mojo::ApplicationImpl* app, - const mojo::ui::ViewProvider::CreateViewCallback& callback) - : callback_(callback), - binding_(this), - context_owner_(app->shell()), - texture_cache_(context_owner_.context(), &resource_returner_), - surface_id_namespace_(0), - draw_scheduled_(false), + mojo::ApplicationImpl* app_impl, + const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback) + : GLView(app_impl, "SpinningCube", create_view_callback), + choreographer_(scene(), this), + input_handler_(view_service_provider(), this), weak_ptr_factory_(this) { - app->ConnectToService("mojo:surfaces_service", &surfaces_); - app->ConnectToService("mojo:view_manager_service", &view_manager_); - - surfaces_->SetResourceReturner(resource_returner_.Pass()); - surfaces_->GetIdNamespace( - base::Bind(&SpinningCubeView::OnSurfaceIdNamespaceAvailable, - base::Unretained(this))); - - InitCube(); + gl_renderer()->gl_context()->MakeCurrent(); + cube_.Init(); } SpinningCubeView::~SpinningCubeView() {} -void SpinningCubeView::OnSurfaceIdNamespaceAvailable(uint32_t id_namespace) { - surface_id_namespace_ = id_namespace; - InitView(); -} - -void SpinningCubeView::InitView() { - mojo::ui::ViewPtr view; - binding_.Bind(mojo::GetProxy(&view)); - view_manager_->RegisterView(view.Pass(), mojo::GetProxy(&view_host_), - callback_); - - view_host_->GetServiceProvider(mojo::GetProxy(&view_service_provider_)); -} - void SpinningCubeView::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params, mojo::Array<uint32_t> children_needing_layout, const OnLayoutCallback& callback) { - // Create a new surface the first time or if the size has changed. - mojo::Size new_size; - new_size.width = layout_params->constraints->max_width; - new_size.height = layout_params->constraints->max_height; - if (!surface_id_ || !size_.Equals(new_size)) { - if (!surface_id_) { - surface_id_ = mojo::SurfaceId::New(); - surface_id_->id_namespace = surface_id_namespace_; - } else { - surfaces_->DestroySurface(surface_id_->local); - } - surface_id_->local++; - size_ = new_size; - surfaces_->CreateSurface(surface_id_->local); - } + size_.width = layout_params->constraints->max_width; + size_.height = layout_params->constraints->max_height; // Submit the new layout information. - auto info = mojo::ui::ViewLayoutInfo::New(); + auto info = mojo::ui::ViewLayoutResult::New(); info->size = size_.Clone(); - info->surface_id = surface_id_->Clone(); callback.Run(info.Pass()); // Draw! - ScheduleDraw(); + choreographer_.ScheduleDraw(); } -void SpinningCubeView::OnChildUnavailable( - uint32_t child_key, - const OnChildUnavailableCallback& callback) { - callback.Run(); -} - -void SpinningCubeView::InitCube() { - context_owner_.context()->MakeCurrent(); - cube_.Init(); - last_draw_ = mojo::GetTimeTicksNow(); -} - -void SpinningCubeView::DrawCube() { - draw_scheduled_ = false; - - scoped_ptr<mojo::TextureCache::TextureInfo> texture_info = - texture_cache_.GetTexture(size_); - if (!texture_info) { - LOG(ERROR) << "Could not allocate texture of size " << size_.width << "x" - << size_.height; +void SpinningCubeView::OnEvent(mojo::EventPtr event, + const OnEventCallback& callback) { + if (!event->pointer_data) { + callback.Run(false); return; } - context_owner_.context()->MakeCurrent(); - scoped_ptr<mojo::GLTexture> texture = texture_info->TakeTexture(); + switch (event->action) { + case mojo::EventType::POINTER_DOWN: + if (event->flags & mojo::EventFlags::RIGHT_MOUSE_BUTTON) + break; + capture_point_.x = event->pointer_data->x; + capture_point_.y = event->pointer_data->y; + last_drag_point_ = capture_point_; + drag_start_time_ = mojo::GetTimeTicksNow(); + cube_.SetFlingMultiplier(0.0f, 1.0f); + break; - GLuint fbo = 0u; - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - GLuint depth_buffer = 0u; - glGenRenderbuffers(1, &depth_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size_.width, - size_.height); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - texture->texture_id(), 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, depth_buffer); - DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), - glCheckFramebufferStatus(GL_FRAMEBUFFER)); - glClearColor(1, 0, 0, 0.5); + case mojo::EventType::POINTER_MOVE: { + if (!(event->flags & mojo::EventFlags::LEFT_MOUSE_BUTTON) && + event->pointer_data->kind == mojo::PointerKind::MOUSE) { + break; + } + mojo::PointF event_location; + event_location.x = event->pointer_data->x; + event_location.y = event->pointer_data->y; + int direction = + GetEventDirection(event_location, capture_point_, last_drag_point_); + cube_.UpdateForDragDistance( + direction * CalculateDragDistance(last_drag_point_, event_location)); + last_drag_point_ = event_location; + break; + } - cube_.set_size(size_.width, size_.height); + case mojo::EventType::POINTER_UP: { + if (event->flags & mojo::EventFlags::RIGHT_MOUSE_BUTTON) { + cube_.set_color(GetRandomColor(), GetRandomColor(), GetRandomColor()); + break; + } + mojo::PointF event_location; + event_location.x = event->pointer_data->x; + event_location.y = event->pointer_data->y; + MojoTimeTicks offset = mojo::GetTimeTicksNow() - drag_start_time_; + float delta = static_cast<float>(offset) / 1000000.f; + // Last drag point is the same as current point here; use initial capture + // point instead + int direction = + GetEventDirection(event_location, capture_point_, capture_point_); + cube_.SetFlingMultiplier( + direction * CalculateDragDistance(capture_point_, event_location), + delta); + capture_point_ = last_drag_point_ = mojo::PointF(); + break; + } - MojoTimeTicks now = mojo::GetTimeTicksNow(); - MojoTimeTicks offset = now - last_draw_; - cube_.UpdateForTimeDelta(offset * 0.000001f); - last_draw_ = now; - - cube_.Draw(); - - glDeleteFramebuffers(1, &fbo); - glDeleteRenderbuffers(1, &depth_buffer); - - mojo::FramePtr frame = mojo::TextureUploader::GetUploadFrame( - context_owner_.context(), texture_info->resource_id(), texture); - surfaces_->SubmitFrame(surface_id_->local, frame.Pass(), - base::Bind(&SpinningCubeView::OnSurfaceSubmitted, - base::Unretained(this))); - - texture_cache_.NotifyPendingResourceReturn(texture_info->resource_id(), - texture.Pass()); -} - -void SpinningCubeView::OnSurfaceSubmitted() { - ScheduleDraw(); -} - -void SpinningCubeView::ScheduleDraw() { - if (!draw_scheduled_) { - draw_scheduled_ = true; - - // TODO(jeffbrown): For now, we need to throttle this down because - // drawing as fast as we can appears to cause starvation of the - // Mojo message loop and makes X11 unhappy. - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, - base::Bind(&SpinningCubeView::DrawCube, weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(30)); + default: + break; } + + callback.Run(true); +} + +void SpinningCubeView::OnDraw( + const mojo::gfx::composition::FrameInfo& frame_info, + const base::TimeDelta& time_delta) { + // Update the state of the cube. + cube_.UpdateForTimeDelta(time_delta.InSecondsF()); + + // Update the contents of the scene. + mojo::Rect bounds; + bounds.width = size_.width; + bounds.height = size_.height; + + auto update = mojo::gfx::composition::SceneUpdate::New(); + mojo::gfx::composition::ResourcePtr cube_resource = gl_renderer()->DrawGL( + size_, true, + base::Bind(&SpinningCubeView::DrawCubeWithGL, base::Unretained(this))); + DCHECK(cube_resource); + update->resources.insert(kCubeImageResourceId, cube_resource.Pass()); + + auto root_node = mojo::gfx::composition::Node::New(); + root_node->content_transform = mojo::Transform::New(); + mojo::SetIdentityTransform(root_node->content_transform.get()); + // TODO(jeffbrown): Figure out why spinning cube is drawing upside down. + // Other GL based programs don't seem to have this problem. + root_node->content_transform->matrix[5] = -1; // flip image vertically + root_node->content_transform->matrix[7] = size_.height; + root_node->op = mojo::gfx::composition::NodeOp::New(); + root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New()); + root_node->op->get_image()->content_rect = bounds.Clone(); + root_node->op->get_image()->image_resource_id = kCubeImageResourceId; + update->nodes.insert(kRootNodeId, root_node.Pass()); + + auto metadata = mojo::gfx::composition::SceneMetadata::New(); + metadata->presentation_time = frame_info.presentation_time; + + // Publish the scene. + scene()->Update(update.Pass()); + scene()->Publish(metadata.Pass()); + + // Loop! + choreographer_.ScheduleDraw(); +} + +void SpinningCubeView::DrawCubeWithGL() { + cube_.set_size(size_.width, size_.height); + cube_.Draw(); } } // namespace examples
diff --git a/examples/ui/spinning_cube/spinning_cube_view.h b/examples/ui/spinning_cube/spinning_cube_view.h index 1a5b7fe..e65220c 100644 --- a/examples/ui/spinning_cube/spinning_cube_view.h +++ b/examples/ui/spinning_cube/spinning_cube_view.h
@@ -7,71 +7,48 @@ #include <memory> -#include "base/bind.h" -#include "base/memory/weak_ptr.h" #include "examples/spinning_cube/spinning_cube.h" -#include "mojo/gpu/gl_context.h" -#include "mojo/gpu/gl_context_owner.h" -#include "mojo/gpu/gl_texture.h" -#include "mojo/gpu/texture_cache.h" -#include "mojo/gpu/texture_uploader.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/cpp/environment/environment.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/macros.h" -#include "mojo/services/surfaces/interfaces/quads.mojom.h" -#include "mojo/services/surfaces/interfaces/surfaces.mojom.h" -#include "mojo/services/ui/views/interfaces/view_manager.mojom.h" -#include "mojo/services/ui/views/interfaces/view_provider.mojom.h" -#include "mojo/services/ui/views/interfaces/views.mojom.h" +#include "mojo/ui/choreographer.h" +#include "mojo/ui/gl_view.h" +#include "mojo/ui/input_handler.h" namespace examples { -class SpinningCubeView : public mojo::ui::View { +class SpinningCubeView : public mojo::ui::GLView, + public mojo::ui::ChoreographerDelegate, + public mojo::ui::InputListener { public: - SpinningCubeView(mojo::ApplicationImpl* app, - const mojo::ui::ViewProvider::CreateViewCallback& callback); + SpinningCubeView( + mojo::ApplicationImpl* app_impl, + const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback); ~SpinningCubeView() override; private: - // |View|: + // |GLView|: void OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params, mojo::Array<uint32_t> children_needing_layout, const OnLayoutCallback& callback) override; - void OnChildUnavailable(uint32_t child_key, - const OnChildUnavailableCallback& callback) override; - void OnSurfaceIdNamespaceAvailable(uint32_t id_namespace); + // |ChoreographerDelegate|: + void OnDraw(const mojo::gfx::composition::FrameInfo& frame_info, + const base::TimeDelta& time_delta) override; - void InitView(); + // |InputListener|: + void OnEvent(mojo::EventPtr event, const OnEventCallback& callback) override; - void InitCube(); - void DrawCube(); - void OnSurfaceSubmitted(); - void ScheduleDraw(); + void DrawCubeWithGL(); - mojo::ui::ViewProvider::CreateViewCallback callback_; - mojo::StrongBinding<mojo::ui::View> binding_; - - mojo::GLContextOwner context_owner_; - mojo::ResourceReturnerPtr resource_returner_; // must be before texture cache - mojo::TextureCache texture_cache_; - - mojo::SurfacePtr surfaces_; - mojo::SurfaceIdPtr surface_id_; - uint32_t surface_id_namespace_; - - mojo::ui::ViewManagerPtr view_manager_; - mojo::ui::ViewHostPtr view_host_; - mojo::ServiceProviderPtr view_service_provider_; + mojo::ui::Choreographer choreographer_; + mojo::ui::InputHandler input_handler_; mojo::Size size_; SpinningCube cube_; - MojoTimeTicks last_draw_; - bool draw_scheduled_; + + mojo::PointF capture_point_; + mojo::PointF last_drag_point_; + MojoTimeTicks drag_start_time_ = 0u; base::WeakPtrFactory<SpinningCubeView> weak_ptr_factory_;
diff --git a/examples/ui/tile/BUILD.gn b/examples/ui/tile/BUILD.gn index 1727e09..3393ba4 100644 --- a/examples/ui/tile/BUILD.gn +++ b/examples/ui/tile/BUILD.gn
@@ -22,15 +22,17 @@ "//mojo/environment:chromium", "//mojo/gpu", "//mojo/public/c/gpu", - "//mojo/public/c/gpu:gpu_onscreen", "//mojo/public/cpp/bindings", "//mojo/public/cpp/environment", "//mojo/public/cpp/system", + "//mojo/services/geometry/cpp", "//mojo/services/geometry/interfaces", + "//mojo/services/gfx/composition/interfaces", "//mojo/services/input_events/interfaces", - "//mojo/services/surfaces/cpp", - "//mojo/services/surfaces/interfaces", "//mojo/services/ui/views/interfaces", + "//mojo/ui", + "//mojo/ui:ganesh", + "//mojo/ui:gl", "//url", ] }
diff --git a/examples/ui/tile/tile_app.cc b/examples/ui/tile/tile_app.cc index 3360e1c..2f5d4a4 100644 --- a/examples/ui/tile/tile_app.cc +++ b/examples/ui/tile/tile_app.cc
@@ -11,55 +11,27 @@ namespace examples { -class TileViewProvider : public mojo::ui::ViewProvider { - public: - TileViewProvider(mojo::ApplicationImpl* app_impl, - const std::vector<std::string>& view_urls) - : app_impl_(app_impl), view_urls_(view_urls) {} - ~TileViewProvider() override {} - - private: - // |ViewProvider|: - void CreateView(mojo::InterfaceRequest<mojo::ServiceProvider> services, - mojo::ServiceProviderPtr exposed_services, - const CreateViewCallback& callback) override { - new TileView(app_impl_, view_urls_, callback); - } - - mojo::ApplicationImpl* app_impl_; - std::vector<std::string> view_urls_; - - DISALLOW_COPY_AND_ASSIGN(TileViewProvider); -}; - TileApp::TileApp() {} TileApp::~TileApp() {} -void TileApp::Initialize(mojo::ApplicationImpl* app_impl) { - app_impl_ = app_impl; -} - -bool TileApp::ConfigureIncomingConnection( - mojo::ApplicationConnection* connection) { - connection->AddService<mojo::ui::ViewProvider>(this); - return true; -} - -void TileApp::Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<mojo::ui::ViewProvider> request) { - GURL url(connection->GetConnectionURL()); +bool TileApp::CreateView( + const std::string& connection_url, + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services, + const mojo::ui::ViewProvider::CreateViewCallback& callback) { + GURL url(connection_url); std::vector<std::string> view_urls; base::SplitString(url.query(), ',', &view_urls); if (view_urls.empty()) { LOG(ERROR) << "Must supply comma-delimited URLs of mojo views to tile as a " "query parameter."; - return; + return false; } - bindings_.AddBinding(new TileViewProvider(app_impl_, view_urls), - request.Pass()); + new TileView(app_impl(), view_urls, callback); + return true; } } // namespace examples
diff --git a/examples/ui/tile/tile_app.h b/examples/ui/tile/tile_app.h index 35227db..1b4d619 100644 --- a/examples/ui/tile/tile_app.h +++ b/examples/ui/tile/tile_app.h
@@ -5,37 +5,22 @@ #ifndef EXAMPLES_UI_TILE_TILE_APP_H_ #define EXAMPLES_UI_TILE_TILE_APP_H_ -#include "base/bind.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/common/strong_binding_set.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_connection.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/macros.h" -#include "mojo/services/ui/views/interfaces/view_provider.mojom.h" +#include "mojo/ui/view_provider_app.h" namespace examples { -class TileApp : public mojo::ApplicationDelegate, - public mojo::InterfaceFactory<mojo::ui::ViewProvider> { +class TileApp : public mojo::ui::ViewProviderApp { public: TileApp(); ~TileApp() override; - // |ApplicationDelegate|: - void Initialize(mojo::ApplicationImpl* app) override; - bool ConfigureIncomingConnection( - mojo::ApplicationConnection* connection) override; - - // |InterfaceFactory<mojo::ui::ViewProvider>|: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<mojo::ui::ViewProvider> request) override; + bool CreateView( + const std::string& connection_url, + mojo::InterfaceRequest<mojo::ServiceProvider> services, + mojo::ServiceProviderPtr exposed_services, + const mojo::ui::ViewProvider::CreateViewCallback& callback) override; private: - mojo::ApplicationImpl* app_impl_; - mojo::StrongBindingSet<mojo::ui::ViewProvider> bindings_; - DISALLOW_COPY_AND_ASSIGN(TileApp); };
diff --git a/examples/ui/tile/tile_view.cc b/examples/ui/tile/tile_view.cc index 34c984e..744f9c4 100644 --- a/examples/ui/tile/tile_view.cc +++ b/examples/ui/tile/tile_view.cc
@@ -2,50 +2,38 @@ // 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 "examples/ui/tile/tile_view.h" -#include "mojo/services/surfaces/cpp/surfaces_utils.h" -#include "mojo/services/surfaces/interfaces/quads.mojom.h" +#include "mojo/services/geometry/cpp/geometry_util.h" namespace examples { +namespace { +constexpr uint32_t kViewResourceIdBase = 100; +constexpr uint32_t kViewResourceIdSpacing = 100; + +constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId; +constexpr uint32_t kViewNodeIdBase = 100; +constexpr uint32_t kViewNodeIdSpacing = 100; +constexpr uint32_t kViewSceneNodeIdOffset = 1; +constexpr uint32_t kViewFallbackNodeIdOffset = 2; +} // namespace + TileView::TileView(mojo::ApplicationImpl* app_impl, const std::vector<std::string>& view_urls, const mojo::ui::ViewProvider::CreateViewCallback& callback) - : app_impl_(app_impl), - view_urls_(view_urls), - callback_(callback), - binding_(this), - surface_id_namespace_(0), - pending_child_layout_count_(0), - frame_pending_(false), - weak_ptr_factory_(this) { - app_impl_->ConnectToService("mojo:surfaces_service", &surfaces_); - app_impl_->ConnectToService("mojo:view_manager_service", &view_manager_); - - surfaces_->GetIdNamespace(base::Bind(&TileView::OnSurfaceIdNamespaceAvailable, - base::Unretained(this))); + : BaseView(app_impl, "Tile", callback), view_urls_(view_urls) { + ConnectViews(); } TileView::~TileView() {} -void TileView::OnSurfaceIdNamespaceAvailable(uint32_t id_namespace) { - surface_id_namespace_ = id_namespace; - InitView(); -} - -void TileView::InitView() { - // Register the view. - mojo::ui::ViewPtr view; - binding_.Bind(mojo::GetProxy(&view)); - view_manager_->RegisterView(view.Pass(), mojo::GetProxy(&view_host_), - callback_); - - // Connect to all child views. +void TileView::ConnectViews() { uint32_t child_key = 0; for (const auto& url : view_urls_) { // Start connecting to the view provider. mojo::ui::ViewProviderPtr provider; - app_impl_->ConnectToService(url, &provider); + app_impl()->ConnectToService(url, &provider); provider.set_connection_error_handler( base::Bind(&TileView::OnChildConnectionError, base::Unretained(this), child_key, url)); @@ -76,9 +64,9 @@ DCHECK(views_.find(child_key) == views_.end()); LOG(INFO) << "View created: child_key=" << child_key << ", url=" << url; - view_host_->AddChild(child_key, token.Pass()); - views_.emplace( - std::make_pair(child_key, std::unique_ptr<ViewData>(new ViewData(url)))); + view_host()->AddChild(child_key, token.Pass()); + views_.emplace(std::make_pair( + child_key, std::unique_ptr<ViewData>(new ViewData(url, child_key)))); // Note that the view provider will be destroyed once this function // returns which is fine now that we are done creating the view. @@ -94,7 +82,7 @@ std::unique_ptr<ViewData> view_data = std::move(it->second); views_.erase(it); - view_host_->RemoveChild(child_key); + view_host()->RemoveChild(child_key); if (view_data->layout_pending) { DCHECK(pending_child_layout_count_); @@ -108,21 +96,8 @@ void TileView::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params, mojo::Array<uint32_t> children_needing_layout, const OnLayoutCallback& callback) { - // Create a new surface the first time or if the size has changed. - mojo::Size new_size; - new_size.width = layout_params->constraints->max_width; - new_size.height = layout_params->constraints->max_height; - if (!surface_id_ || !size_.Equals(new_size)) { - if (!surface_id_) { - surface_id_ = mojo::SurfaceId::New(); - surface_id_->id_namespace = surface_id_namespace_; - } else { - surfaces_->DestroySurface(surface_id_->local); - } - surface_id_->local++; - size_ = new_size; - surfaces_->CreateSurface(surface_id_->local); - } + size_.width = layout_params->constraints->max_width; + size_.height = layout_params->constraints->max_height; // Wipe out cached layout information for children needing layout. for (uint32_t child_key : children_needing_layout) { @@ -134,8 +109,8 @@ // Layout all children in a row. if (!views_.empty()) { uint32_t index = 0; - uint32_t base_width = new_size.width / views_.size(); - uint32_t excess_width = new_size.width % views_.size(); + uint32_t base_width = size_.width / views_.size(); + uint32_t excess_width = size_.width % views_.size(); uint32_t x = 0; for (auto it = views_.begin(); it != views_.end(); ++it, ++index) { ViewData* view_data = it->second.get(); @@ -147,7 +122,7 @@ child_width++; excess_width--; } - uint32_t child_height = new_size.height; + uint32_t child_height = size_.height; uint32_t child_x = x; x += child_width; @@ -172,9 +147,9 @@ view_data->layout_params = params.Clone(); view_data->layout_info.reset(); - view_host_->LayoutChild(it->first, params.Pass(), - base::Bind(&TileView::OnChildLayoutFinished, - base::Unretained(this), it->first)); + view_host()->LayoutChild(it->first, params.Pass(), + base::Bind(&TileView::OnChildLayoutFinished, + base::Unretained(this), it->first)); } } @@ -199,7 +174,7 @@ } void TileView::FinishLayout() { - if (frame_pending_ || pending_layout_callback_.is_null()) + if (pending_layout_callback_.is_null()) return; // Wait until all children have laid out. @@ -207,76 +182,91 @@ if (pending_child_layout_count_) return; - // Produce a new frame. - mojo::FramePtr frame = mojo::Frame::New(); - frame->resources.resize(0u); + // Update the scene. + // TODO: only send the resources once, be more incremental + auto update = mojo::gfx::composition::SceneUpdate::New(); - mojo::Rect bounds; - bounds.width = size_.width; - bounds.height = size_.height; - mojo::PassPtr pass = mojo::CreateDefaultPass(1, bounds); - pass->shared_quad_states.resize(0u); - pass->quads.resize(0u); + // Create the root node. + auto root_node = mojo::gfx::composition::Node::New(); + // Add the children. for (auto it = views_.cbegin(); it != views_.cend(); it++) { const ViewData& view_data = *(it->second.get()); + const uint32_t scene_resource_id = + kViewResourceIdBase + view_data.key * kViewResourceIdSpacing; + const uint32_t container_node_id = + kViewNodeIdBase + view_data.key * kViewNodeIdSpacing; + const uint32_t scene_node_id = container_node_id + kViewSceneNodeIdOffset; + const uint32_t fallback_node_id = + container_node_id + kViewFallbackNodeIdOffset; - mojo::QuadPtr quad = mojo::Quad::New(); - quad->rect = view_data.layout_bounds.Clone(); - quad->rect->x = 0; - quad->rect->y = 0; - quad->opaque_rect = quad->rect.Clone(); - quad->visible_rect = quad->rect.Clone(); - quad->shared_quad_state_index = pass->shared_quad_states.size(); + mojo::Rect extent; + extent.width = view_data.layout_bounds.width; + extent.height = view_data.layout_bounds.height; - mojo::Size size; - size.width = view_data.layout_bounds.width; - size.height = view_data.layout_bounds.height; + // Create a container to represent the place where the child view + // will be presented. The children of the container provide + // fallback behavior in case the view is not available. + auto container_node = mojo::gfx::composition::Node::New(); + container_node->content_clip = extent.Clone(); + container_node->content_transform = mojo::Transform::New(); + SetTranslationTransform(container_node->content_transform.get(), + view_data.layout_bounds.x, + view_data.layout_bounds.y, 0.f); + container_node->combinator = + mojo::gfx::composition::Node::Combinator::FALLBACK; - mojo::SharedQuadStatePtr quad_state = mojo::CreateDefaultSQS(size); - quad_state->content_to_target_transform->matrix[3] = - view_data.layout_bounds.x; - pass->shared_quad_states.push_back(quad_state.Pass()); + // If we have the view, add it to the scene. + if (view_data.layout_info) { + auto scene_resource = mojo::gfx::composition::Resource::New(); + scene_resource->set_scene(mojo::gfx::composition::SceneResource::New()); + scene_resource->get_scene()->scene_token = + view_data.layout_info->scene_token.Clone(); + update->resources.insert(scene_resource_id, scene_resource.Pass()); - if (it->second->layout_info) { - quad->material = mojo::Material::SURFACE_CONTENT; - quad->surface_quad_state = mojo::SurfaceQuadState::New(); - quad->surface_quad_state->surface = - view_data.layout_info->surface_id.Clone(); + auto scene_node = mojo::gfx::composition::Node::New(); + scene_node->op = mojo::gfx::composition::NodeOp::New(); + scene_node->op->set_scene(mojo::gfx::composition::SceneNodeOp::New()); + scene_node->op->get_scene()->scene_resource_id = scene_resource_id; + update->nodes.insert(scene_node_id, scene_node.Pass()); + container_node->child_node_ids.push_back(scene_node_id); } 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 = 0xffff00ff; + update->resources.insert(fallback_node_id, nullptr); + update->nodes.insert(scene_node_id, nullptr); } - pass->quads.push_back(quad.Pass()); + // Add the fallback content. + 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 = extent.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(fallback_node_id, fallback_node.Pass()); + container_node->child_node_ids.push_back(fallback_node_id); + + // Add the container. + update->nodes.insert(container_node_id, container_node.Pass()); + root_node->child_node_ids.push_back(container_node_id); } - frame->passes.push_back(pass.Pass()); + // Add the root node. + update->nodes.insert(kRootNodeId, root_node.Pass()); - frame_pending_ = true; - surfaces_->SubmitFrame( - surface_id_->local, frame.Pass(), - base::Bind(&TileView::OnFrameSubmitted, base::Unretained(this))); + // Publish the scene. + scene()->Update(update.Pass()); + scene()->Publish(nullptr); // Submit the new layout information. - mojo::ui::ViewLayoutInfoPtr info = mojo::ui::ViewLayoutInfo::New(); + auto info = mojo::ui::ViewLayoutResult::New(); info->size = size_.Clone(); - info->surface_id = surface_id_->Clone(); pending_layout_callback_.Run(info.Pass()); pending_layout_callback_.reset(); } -void TileView::OnFrameSubmitted() { - DCHECK(frame_pending_); - - frame_pending_ = false; - FinishLayout(); -} - -TileView::ViewData::ViewData(const std::string& url) - : url(url), layout_pending(false) {} +TileView::ViewData::ViewData(const std::string& url, uint32_t key) + : url(url), key(key), layout_pending(false) {} TileView::ViewData::~ViewData() {}
diff --git a/examples/ui/tile/tile_view.h b/examples/ui/tile/tile_view.h index a0132cf..085e431 100644 --- a/examples/ui/tile/tile_view.h +++ b/examples/ui/tile/tile_view.h
@@ -8,22 +8,11 @@ #include <map> #include <memory> -#include "base/bind.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/cpp/environment/environment.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/macros.h" -#include "mojo/services/geometry/interfaces/geometry.mojom.h" -#include "mojo/services/surfaces/interfaces/surfaces.mojom.h" -#include "mojo/services/ui/views/interfaces/view_manager.mojom.h" -#include "mojo/services/ui/views/interfaces/view_provider.mojom.h" -#include "mojo/services/ui/views/interfaces/views.mojom.h" +#include "mojo/ui/base_view.h" namespace examples { -class TileView : public mojo::ui::View { +class TileView : public mojo::ui::BaseView { public: TileView(mojo::ApplicationImpl* app_impl_, const std::vector<std::string>& view_urls, @@ -33,10 +22,11 @@ private: struct ViewData { - explicit ViewData(const std::string& url); + explicit ViewData(const std::string& url, uint32_t key); ~ViewData(); const std::string url; + const uint32_t key; bool layout_pending; mojo::ui::ViewLayoutParamsPtr layout_params; @@ -44,16 +34,14 @@ mojo::Rect layout_bounds; }; - // |View|: + // |BaseView|: void OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params, mojo::Array<uint32_t> children_needing_layout, const OnLayoutCallback& callback) override; void OnChildUnavailable(uint32_t child_key, const OnChildUnavailableCallback& callback) override; - void OnSurfaceIdNamespaceAvailable(uint32_t id_namespace); - - void InitView(); + void ConnectViews(); void OnChildConnectionError(uint32_t child_key, const std::string& url); void OnChildCreated(uint32_t child_key, const std::string& url, @@ -65,26 +53,12 @@ void OnFrameSubmitted(); - mojo::ApplicationImpl* app_impl_; std::vector<std::string> view_urls_; - mojo::ui::ViewProvider::CreateViewCallback callback_; - mojo::StrongBinding<mojo::ui::View> binding_; - - mojo::SurfacePtr surfaces_; - mojo::SurfaceIdPtr surface_id_; - uint32_t surface_id_namespace_; - - mojo::ui::ViewManagerPtr view_manager_; - mojo::ui::ViewHostPtr view_host_; - std::map<uint32_t, std::unique_ptr<ViewData>> views_; mojo::Size size_; OnLayoutCallback pending_layout_callback_; - uint32_t pending_child_layout_count_; - bool frame_pending_; - - base::WeakPtrFactory<TileView> weak_ptr_factory_; + uint32_t pending_child_layout_count_ = 0u; DISALLOW_COPY_AND_ASSIGN(TileView); };