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);
};