From 8bdad9784dcecc2d5167a3b29ea9b3f76ec7e761 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 18 Feb 2015 16:57:32 -0800 Subject: [PATCH] Port touch-demo.sky to Dart and make it work in SkyShell We still don't quite handle multitouch correctly, but single touches work now. R=eseidel@chromium.org Review URL: https://codereview.chromium.org/932283002 --- examples/touch-demo.sky | 29 ++++----- services/viewport/BUILD.gn | 12 ++++ services/viewport/input_event.mojom | 43 +++++++++++++ services/viewport/viewport_observer.mojom | 12 ++++ shell/BUILD.gn | 4 ++ .../org/domokit/sky/shell/PlatformView.java | 58 +++++++++++++++-- shell/platform_view.cc | 27 ++++---- shell/platform_view.h | 3 + shell/ui/engine.cc | 26 ++++++-- shell/ui/engine.h | 11 +++- shell/ui/input_event_converter.cc | 64 +++++++++++++++++++ shell/ui/input_event_converter.h | 21 ++++++ shell/ui_delegate.h | 6 +- 13 files changed, 274 insertions(+), 42 deletions(-) create mode 100644 services/viewport/BUILD.gn create mode 100644 services/viewport/input_event.mojom create mode 100644 services/viewport/viewport_observer.mojom create mode 100644 shell/ui/input_event_converter.cc create mode 100644 shell/ui/input_event_converter.h diff --git a/examples/touch-demo.sky b/examples/touch-demo.sky index 78b86d20b..2afefd757 100644 --- a/examples/touch-demo.sky +++ b/examples/touch-demo.sky @@ -1,6 +1,5 @@ #!mojo mojo:sky_viewer - Ready - diff --git a/services/viewport/BUILD.gn b/services/viewport/BUILD.gn new file mode 100644 index 000000000..0e024d4ef --- /dev/null +++ b/services/viewport/BUILD.gn @@ -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. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("viewport") { + sources = [ + "input_event.mojom", + "viewport_observer.mojom", + ] +} diff --git a/services/viewport/input_event.mojom b/services/viewport/input_event.mojom new file mode 100644 index 000000000..21cf84c76 --- /dev/null +++ b/services/viewport/input_event.mojom @@ -0,0 +1,43 @@ +// 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. + +module sky; + +enum EventType { + UNKNOWN, + POINTER_DOWN, + POINTER_UP, + POINTER_MOVE, + POINTER_CANCEL, +}; + +enum PointerKind { + TOUCH, +}; + +struct PointerData { + int32 pointer; + PointerKind kind; + float x; + float y; + int32 buttons; + float pressure; + float pressure_min; + float pressure_max; + float distance; + float distance_min; + float distance_max; + float radius_major; + float radius_minor; + float radius_min; + float radius_max; + float orientation; + float tilt; +}; + +struct InputEvent { + EventType type; + int64 time_stamp; + PointerData? pointer_data; +}; diff --git a/services/viewport/viewport_observer.mojom b/services/viewport/viewport_observer.mojom new file mode 100644 index 000000000..5fc996d13 --- /dev/null +++ b/services/viewport/viewport_observer.mojom @@ -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. + +module sky; + +import "sky/services/viewport/input_event.mojom"; + +interface ViewportObserver { + OnViewportMetricsChanged(int32 width, int32 height, float device_pixel_ratio); + OnInputEvent(InputEvent event); +}; diff --git a/shell/BUILD.gn b/shell/BUILD.gn index 30be3cf84..287cb0f90 100644 --- a/shell/BUILD.gn +++ b/shell/BUILD.gn @@ -45,6 +45,8 @@ shared_library("sky_shell") { "ui/animator.h", "ui/engine.cc", "ui/engine.h", + "ui/input_event_converter.cc", + "ui/input_event_converter.h", "ui/platform_impl.cc", "ui/platform_impl.h", "ui_delegate.cc", @@ -63,6 +65,7 @@ shared_library("sky_shell") { "//mojo/services/network/public/interfaces", "//skia", "//sky/engine", + "//sky/services/viewport", "//ui/gfx/geometry", "//ui/gl", ":jni_headers", @@ -86,6 +89,7 @@ android_library("java") { "//mojo/public/java:system", "//mojo/services/network/public/interfaces:interfaces_java", "//sky/services/oknet", + "//sky/services/viewport:viewport_java", ] } diff --git a/shell/apk/src/org/domokit/sky/shell/PlatformView.java b/shell/apk/src/org/domokit/sky/shell/PlatformView.java index ac8879d43..0934fc507 100644 --- a/shell/apk/src/org/domokit/sky/shell/PlatformView.java +++ b/shell/apk/src/org/domokit/sky/shell/PlatformView.java @@ -5,12 +5,22 @@ package org.domokit.sky.shell; import android.content.Context; +import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import org.chromium.base.JNINamespace; +import org.chromium.mojo.bindings.InterfaceRequest; +import org.chromium.mojo.system.Core; +import org.chromium.mojo.system.Pair; +import org.chromium.mojo.system.impl.CoreImpl; +import org.chromium.mojom.sky.EventType; +import org.chromium.mojom.sky.InputEvent; +import org.chromium.mojom.sky.PointerData; +import org.chromium.mojom.sky.PointerKind; +import org.chromium.mojom.sky.ViewportObserver; /** * A view containing Sky @@ -18,6 +28,7 @@ import org.chromium.base.JNINamespace; @JNINamespace("sky::shell") public class PlatformView extends SurfaceView { private long mNativePlatformView; + private ViewportObserver.Proxy mViewportObserver; private final SurfaceHolder.Callback mSurfaceCallback; public PlatformView(Context context) { @@ -26,7 +37,7 @@ public class PlatformView extends SurfaceView { setFocusable(true); setFocusableInTouchMode(true); - mNativePlatformView = nativeAttach(); + attach(); assert mNativePlatformView != 0; final float density = context.getResources().getDisplayMetrics().density; @@ -34,8 +45,8 @@ public class PlatformView extends SurfaceView { mSurfaceCallback = new SurfaceHolder.Callback() { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - assert mNativePlatformView != 0; - nativeSurfaceSetSize(mNativePlatformView, width, height, density); + assert mViewportObserver != null; + mViewportObserver.onViewportMetricsChanged(width, height, density); } @Override @@ -69,10 +80,45 @@ public class PlatformView extends SurfaceView { } } - private static native long nativeAttach(); + private int getTypeForAction(int maskedAction) { + if (maskedAction == MotionEvent.ACTION_DOWN) + return EventType.POINTER_DOWN; + if (maskedAction == MotionEvent.ACTION_UP) + return EventType.POINTER_UP; + if (maskedAction == MotionEvent.ACTION_MOVE) + return EventType.POINTER_MOVE; + if (maskedAction == MotionEvent.ACTION_CANCEL) + return EventType.POINTER_CANCEL; + return EventType.UNKNOWN; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + PointerData pointerData = new PointerData(); + pointerData.pointer = event.getPointerId(0); + pointerData.kind = PointerKind.TOUCH; + pointerData.x = event.getX(); + pointerData.y = event.getY(); + + InputEvent inputEvent = new InputEvent(); + inputEvent.type = getTypeForAction(event.getActionMasked()); + inputEvent.timeStamp = event.getEventTime(); + inputEvent.pointerData = pointerData; + + mViewportObserver.onInputEvent(inputEvent); + return true; + } + + private void attach() { + Core core = CoreImpl.getInstance(); + Pair> result = + ViewportObserver.MANAGER.getInterfaceRequest(core); + mViewportObserver = result.first; + mNativePlatformView = nativeAttach(result.second.passHandle().releaseNativeHandle()); + } + + private static native long nativeAttach(int inputObserverHandle); private static native void nativeDetach(long nativePlatformView); private static native void nativeSurfaceCreated(long nativePlatformView, Surface surface); private static native void nativeSurfaceDestroyed(long nativePlatformView); - private static native void nativeSurfaceSetSize( - long nativePlatformView, int width, int height, float density); } diff --git a/shell/platform_view.cc b/shell/platform_view.cc index e31498dcb..69a7b10a1 100644 --- a/shell/platform_view.cc +++ b/shell/platform_view.cc @@ -16,8 +16,12 @@ namespace sky { namespace shell { -static jlong Attach(JNIEnv* env, jclass clazz) { - return reinterpret_cast(Shell::Shared().view()); +static jlong Attach(JNIEnv* env, jclass clazz, jint viewportObserverHandle) { + PlatformView* view = Shell::Shared().view(); + view->ConnectToViewportObserver( + mojo::MakeRequest(mojo::ScopedMessagePipeHandle( + mojo::MessagePipeHandle(viewportObserverHandle)))); + return reinterpret_cast(view); } // static @@ -34,6 +38,14 @@ PlatformView::~PlatformView() { ReleaseWindow(); } +void PlatformView::ConnectToViewportObserver( + mojo::InterfaceRequest request) { + config_.ui_task_runner->PostTask( + FROM_HERE, + base::Bind(&UIDelegate::ConnectToViewportObserver, config_.ui_delegate, + base::Passed(&request))); +} + void PlatformView::Detach(JNIEnv* env, jobject obj) { DCHECK(!window_); } @@ -60,17 +72,6 @@ void PlatformView::SurfaceDestroyed(JNIEnv* env, jobject obj) { ReleaseWindow(); } -void PlatformView::SurfaceSetSize(JNIEnv* env, - jobject obj, - jint width, - jint height, - jfloat density) { - config_.ui_task_runner->PostTask( - FROM_HERE, - base::Bind(&UIDelegate::OnViewportMetricsChanged, config_.ui_delegate, - gfx::Size(width, height), density)); -} - void PlatformView::ReleaseWindow() { ANativeWindow_release(window_); window_ = nullptr; diff --git a/shell/platform_view.h b/shell/platform_view.h index 7f83cde08..c6da2e3b6 100644 --- a/shell/platform_view.h +++ b/shell/platform_view.h @@ -33,6 +33,9 @@ class PlatformView { explicit PlatformView(const Config& config); ~PlatformView(); + void ConnectToViewportObserver( + mojo::InterfaceRequest request); + // Called from Java void Detach(JNIEnv* env, jobject obj); void SurfaceCreated(JNIEnv* env, jobject obj, jobject jsurface); diff --git a/shell/ui/engine.cc b/shell/ui/engine.cc index b316c4cfe..5b1e6da61 100644 --- a/shell/ui/engine.cc +++ b/shell/ui/engine.cc @@ -5,10 +5,12 @@ #include "sky/shell/ui/engine.h" #include "base/bind.h" +#include "sky/engine/public/platform/WebInputEvent.h" #include "sky/engine/public/web/Sky.h" #include "sky/engine/public/web/WebLocalFrame.h" #include "sky/engine/public/web/WebView.h" #include "sky/shell/ui/animator.h" +#include "sky/shell/ui/input_event_converter.h" #include "sky/shell/ui/platform_impl.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPictureRecorder.h" @@ -19,6 +21,8 @@ namespace shell { Engine::Engine(const Config& config) : animator_(new Animator(config, this)), web_view_(nullptr), + device_pixel_ratio_(1.0f), + viewport_observer_binding_(this), weak_factory_(this) { } @@ -39,7 +43,7 @@ void Engine::Init(mojo::ScopedMessagePipeHandle service_provider) { web_view_ = blink::WebView::create(this); web_view_->setMainFrame(blink::WebLocalFrame::create(this)); web_view_->mainFrame()->load( - GURL("http://127.0.0.1:8000/sky/examples/spinning-square.sky")); + GURL("http://domokit.github.io/sky/examples/spinning-square.sky")); } void Engine::BeginFrame(base::TimeTicks frame_time) { @@ -63,16 +67,30 @@ skia::RefPtr Engine::Paint() { return skia::AdoptRef(recorder.endRecordingAsPicture()); } -void Engine::OnViewportMetricsChanged(const gfx::Size& physical_size, +void Engine::ConnectToViewportObserver( + mojo::InterfaceRequest request) { + viewport_observer_binding_.Bind(request.Pass()); +} + +void Engine::OnViewportMetricsChanged(int width, int height, float device_pixel_ratio) { - physical_size_ = physical_size; + physical_size_.SetSize(width, height); + device_pixel_ratio_ = device_pixel_ratio; web_view_->setDeviceScaleFactor(device_pixel_ratio); - gfx::SizeF size = gfx::ScaleSize(physical_size, 1 / device_pixel_ratio); + gfx::SizeF size = gfx::ScaleSize(physical_size_, 1 / device_pixel_ratio); // FIXME: We should be able to set the size of the WebView in floating point // because its in logical pixels. web_view_->resize(blink::WebSize(size.width(), size.height())); } +void Engine::OnInputEvent(InputEventPtr event) { + scoped_ptr web_event = + ConvertEvent(event, device_pixel_ratio_); + if (!web_event) + return; + web_view_->handleInputEvent(*web_event); +} + void Engine::initializeLayerTreeView() { } diff --git a/shell/ui/engine.h b/shell/ui/engine.h index ec21ab4e8..1aafbb39f 100644 --- a/shell/ui/engine.h +++ b/shell/ui/engine.h @@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" +#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/core.h" #include "skia/ext/refptr.h" #include "sky/engine/public/web/WebFrameClient.h" @@ -24,6 +25,7 @@ class Animator; class PlatformImpl; class Engine : public UIDelegate, + public ViewportObserver, public blink::WebFrameClient, public blink::WebViewClient { public: @@ -44,8 +46,13 @@ class Engine : public UIDelegate, private: // UIDelegate methods: - void OnViewportMetricsChanged(const gfx::Size& physical_size, + void ConnectToViewportObserver( + mojo::InterfaceRequest request) override; + + // ViewportObserver: + void OnViewportMetricsChanged(int width, int height, float device_pixel_ratio) override; + void OnInputEvent(InputEventPtr event) override; // WebViewClient methods: void initializeLayerTreeView() override; @@ -54,7 +61,9 @@ class Engine : public UIDelegate, scoped_ptr platform_impl_; scoped_ptr animator_; blink::WebView* web_view_; + float device_pixel_ratio_; gfx::Size physical_size_; + mojo::Binding viewport_observer_binding_; base::WeakPtrFactory weak_factory_; diff --git a/shell/ui/input_event_converter.cc b/shell/ui/input_event_converter.cc new file mode 100644 index 000000000..9fcf49c3d --- /dev/null +++ b/shell/ui/input_event_converter.cc @@ -0,0 +1,64 @@ +// 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 "sky/shell/ui/input_event_converter.h" + +#include "base/logging.h" +#include "base/time/time.h" +#include "sky/engine/public/platform/WebInputEvent.h" + +namespace sky { +namespace { + +scoped_ptr BuildWebPointerEvent( + const InputEventPtr& event, float device_pixel_ratio) { + scoped_ptr web_event(new blink::WebPointerEvent); + + web_event->timeStampMS = + base::TimeDelta::FromInternalValue(event->time_stamp).InMillisecondsF(); + + switch (event->type) { + case EVENT_TYPE_POINTER_DOWN: + web_event->type = blink::WebInputEvent::PointerDown; + break; + case EVENT_TYPE_POINTER_UP: + web_event->type = blink::WebInputEvent::PointerUp; + break; + case EVENT_TYPE_POINTER_MOVE: + web_event->type = blink::WebInputEvent::PointerMove; + break; + case EVENT_TYPE_POINTER_CANCEL: + web_event->type = blink::WebInputEvent::PointerCancel; + break; + default: + NOTIMPLEMENTED() << "Received unexpected event: " << event->type; + break; + } + + if (event->pointer_data) { + if (event->pointer_data->kind == POINTER_KIND_TOUCH) + web_event->kind = blink::WebPointerEvent::Touch; + web_event->pointer = event->pointer_data->pointer; + web_event->x = event->pointer_data->x / device_pixel_ratio; + web_event->y = event->pointer_data->y / device_pixel_ratio; + } + + return web_event.Pass(); +} + +} // namespace + +scoped_ptr ConvertEvent(const InputEventPtr& event, + float device_pixel_ratio) { + if (event->type == EVENT_TYPE_POINTER_DOWN || + event->type == EVENT_TYPE_POINTER_UP || + event->type == EVENT_TYPE_POINTER_MOVE || + event->type == EVENT_TYPE_POINTER_CANCEL) { + return BuildWebPointerEvent(event, device_pixel_ratio); + } + + return scoped_ptr(); +} + +} // namespace mojo diff --git a/shell/ui/input_event_converter.h b/shell/ui/input_event_converter.h new file mode 100644 index 000000000..05a797f0a --- /dev/null +++ b/shell/ui/input_event_converter.h @@ -0,0 +1,21 @@ +// 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 SKY_SHELL_UI_INPUT_EVENT_CONVERTER_H_ +#define SKY_SHELL_UI_INPUT_EVENT_CONVERTER_H_ + +#include "base/memory/scoped_ptr.h" +#include "sky/services/viewport/input_event.mojom.h" + +namespace blink { +class WebInputEvent; +} + +namespace sky { + +scoped_ptr ConvertEvent(const InputEventPtr& event, + float device_pixel_ratio); +} + +#endif // SKY_SHELL_UI_INPUT_EVENT_CONVERTER_H_ diff --git a/shell/ui_delegate.h b/shell/ui_delegate.h index bb7e44b8c..d50a34acd 100644 --- a/shell/ui_delegate.h +++ b/shell/ui_delegate.h @@ -5,6 +5,8 @@ #ifndef SKY_SHELL_UI_DELEGATE_H_ #define SKY_SHELL_UI_DELEGATE_H_ +#include "mojo/public/cpp/bindings/interface_request.h" +#include "sky/services/viewport/viewport_observer.mojom.h" #include "ui/gfx/geometry/size.h" namespace sky { @@ -12,8 +14,8 @@ namespace shell { class UIDelegate { public: - virtual void OnViewportMetricsChanged(const gfx::Size& size, - float device_pixel_ratio) = 0; + virtual void ConnectToViewportObserver( + mojo::InterfaceRequest request) = 0; protected: virtual ~UIDelegate(); -- GitLab