aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar liyuqian <liyuqian@google.com>2016-05-17 12:44:20 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-05-17 12:44:20 -0700
commitd3cdbcad65673596ae37e65fec842d8d4d81c5a7 (patch)
treef7b71e933a44a18e17af1d93d996ac4b2d0c4f59
parent1483d0f73ea484bf582b81f031222082f33d6d35 (diff)
Implement touch control
-rw-r--r--gyp/viewer.gyp2
-rw-r--r--platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java11
-rw-r--r--tools/viewer/Viewer.cpp42
-rw-r--r--tools/viewer/Viewer.h6
-rw-r--r--tools/viewer/sk_app/Window.cpp10
-rw-r--r--tools/viewer/sk_app/Window.h14
-rw-r--r--tools/viewer/sk_app/android/Window_android.cpp4
-rw-r--r--tools/viewer/sk_app/android/surface_glue_android.cpp42
-rw-r--r--tools/viewer/sk_app/android/surface_glue_android.h15
9 files changed, 127 insertions, 19 deletions
diff --git a/gyp/viewer.gyp b/gyp/viewer.gyp
index d8082ef949..84daa8d4c5 100644
--- a/gyp/viewer.gyp
+++ b/gyp/viewer.gyp
@@ -18,6 +18,7 @@
'include_dirs': [
'../bench',
'../gm',
+ '../include/views',
'../include/private',
'../src/core',
'../src/effects',
@@ -28,6 +29,7 @@
],
'sources': [
'../gm/gm.cpp',
+ '../src/views/SkTouchGesture.cpp',
'<!@(python find.py ../tools/viewer "*.cpp")',
],
'dependencies': [
diff --git a/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java b/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java
index d6fe710aeb..49f711d517 100644
--- a/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java
+++ b/platform_tools/android/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java
@@ -32,6 +32,7 @@ public class ViewerActivity
private native void onSurfaceChanged(long handle, Surface surface);
private native void onSurfaceDestroyed(long handle);
private native void onKeyPressed(long handle, int keycode);
+ private native void onTouched(long handle, int owner, int state, float x, float y);
@Override
public boolean onCreateOptionsMenu(Menu menu) {
@@ -96,6 +97,14 @@ public class ViewerActivity
@Override
public boolean onTouch(View v, MotionEvent event) {
- return false; // TODO pass the touch event to native code
+ int count = event.getPointerCount();
+ for (int i = 0; i < count; i++) {
+ final float x = event.getX(i);
+ final float y = event.getY(i);
+ final int owner = event.getPointerId(i);
+ int action = event.getAction() & MotionEvent.ACTION_MASK;
+ onTouched(mApplication.getNativeHandle(), owner, action, x, y);
+ }
+ return true;
}
}
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 644dd22e5e..7f18652c2c 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -28,6 +28,13 @@ static void on_paint_handler(SkCanvas* canvas, void* userData) {
return vv->onPaint(canvas);
}
+static bool on_touch_handler(int owner, Window::InputState state, float x, float y, void* userData)
+{
+ Viewer* viewer = reinterpret_cast<Viewer*>(userData);
+
+ return viewer->onTouch(owner, state, x, y);
+}
+
DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
DEFINE_string(key, "", "Space-separated key/value pairs to add to JSON identifying this builder.");
DEFINE_string2(match, m, nullptr,
@@ -71,6 +78,7 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
// register callbacks
fCommands.attach(fWindow);
fWindow->registerPaintFunc(on_paint_handler, this);
+ fWindow->registerTouchFunc(on_touch_handler, this);
// add key-bindings
fCommands.addCommand('s', "Overlays", "Toggle stats display", [this]() {
@@ -134,7 +142,6 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
// set up first frame
fCurrentSlide = 0;
setupCurrentSlide(-1);
- updateMatrix();
fWindow->show();
}
@@ -228,10 +235,9 @@ void Viewer::changeZoomLevel(float delta) {
} else {
fZoomScale = SK_Scalar1;
}
- this->updateMatrix();
}
-void Viewer::updateMatrix(){
+SkMatrix Viewer::computeMatrix() {
SkMatrix m;
m.reset();
@@ -247,12 +253,10 @@ void Viewer::updateMatrix(){
m.postTranslate(cx, cy);
}
- // TODO: add gesture support
- // Apply any gesture matrix
- //m.preConcat(fGesture.localM());
- //m.preConcat(fGesture.globalM());
+ m.preConcat(fGesture.localM());
+ m.preConcat(fGesture.globalM());
- fLocalMatrix = m;
+ return m;
}
void Viewer::onPaint(SkCanvas* canvas) {
@@ -273,7 +277,7 @@ void Viewer::onPaint(SkCanvas* canvas) {
matrix.setRectToRect(slideBounds, contentRect, SkMatrix::kCenter_ScaleToFit);
canvas->concat(matrix);
}
- canvas->concat(fLocalMatrix);
+ canvas->concat(computeMatrix());
fSlides[fCurrentSlide]->draw(canvas);
canvas->restoreToCount(count);
@@ -284,6 +288,26 @@ void Viewer::onPaint(SkCanvas* canvas) {
fCommands.drawHelp(canvas);
}
+bool Viewer::onTouch(int owner, Window::InputState state, float x, float y) {
+ void* castedOwner = reinterpret_cast<void*>(owner);
+ switch (state) {
+ case Window::kUp_InputState: {
+ fGesture.touchEnd(castedOwner);
+ break;
+ }
+ case Window::kDown_InputState: {
+ fGesture.touchBegin(castedOwner, x, y);
+ break;
+ }
+ case Window::kMove_InputState: {
+ fGesture.touchMoved(castedOwner, x, y);
+ break;
+ }
+ }
+ fWindow->inval();
+ return true;
+}
+
void Viewer::drawStats(SkCanvas* canvas) {
static const float kPixelPerMS = 2.0f;
static const int kDisplayWidth = 130;
diff --git a/tools/viewer/Viewer.h b/tools/viewer/Viewer.h
index 3579e4d296..c785cff78e 100644
--- a/tools/viewer/Viewer.h
+++ b/tools/viewer/Viewer.h
@@ -24,6 +24,7 @@ public:
void onPaint(SkCanvas* canvas);
void onIdle(double ms) override;
+ bool onTouch(int owner, sk_app::Window::InputState state, float x, float y);
private:
void initSlides();
@@ -33,7 +34,7 @@ private:
void drawStats(SkCanvas* canvas);
void changeZoomLevel(float delta);
- void updateMatrix();
+ SkMatrix computeMatrix();
sk_app::Window* fWindow;
@@ -50,13 +51,14 @@ private:
sk_app::Window::BackendType fBackendType;
// transform data
- SkMatrix fLocalMatrix;
SkScalar fZoomCenterX;
SkScalar fZoomCenterY;
SkScalar fZoomLevel;
SkScalar fZoomScale;
sk_app::CommandSet fCommands;
+
+ SkTouchGesture fGesture;
};
diff --git a/tools/viewer/sk_app/Window.cpp b/tools/viewer/sk_app/Window.cpp
index dc0bf995d0..0a7bcf8a70 100644
--- a/tools/viewer/sk_app/Window.cpp
+++ b/tools/viewer/sk_app/Window.cpp
@@ -27,11 +27,17 @@ static bool default_mouse_func(int x, int y, Window::InputState state, uint32_t
return false;
}
+static bool default_touch_func(int owner, Window::InputState state, float x, float y,
+ void* userData) {
+ return false;
+}
+
static void default_paint_func(SkCanvas*, void* userData) {}
Window::Window() : fCharFunc(default_char_func)
, fKeyFunc(default_key_func)
, fMouseFunc(default_mouse_func)
+ , fTouchFunc(default_touch_func)
, fPaintFunc(default_paint_func) {
}
@@ -52,6 +58,10 @@ bool Window::onMouse(int x, int y, InputState state, uint32_t modifiers) {
return fMouseFunc(x, y, state, modifiers, fMouseUserData);
}
+bool Window::onTouch(int owner, InputState state, float x, float y) {
+ return fTouchFunc(owner, state, x, y, fTouchUserData);
+}
+
void Window::onPaint() {
sk_sp<SkSurface> backbuffer = fWindowContext->getBackbufferSurface();
if (backbuffer) {
diff --git a/tools/viewer/sk_app/Window.h b/tools/viewer/sk_app/Window.h
index 5b41f87f07..63d5e19e55 100644
--- a/tools/viewer/sk_app/Window.h
+++ b/tools/viewer/sk_app/Window.h
@@ -9,8 +9,9 @@
#define Window_DEFINED
#include "DisplayParams.h"
-#include "SkTypes.h"
#include "SkRect.h"
+#include "SkTouchGesture.h"
+#include "SkTypes.h"
class SkCanvas;
@@ -104,6 +105,7 @@ public:
typedef bool(*OnCharFunc)(SkUnichar c, uint32_t modifiers, void* userData);
typedef bool(*OnKeyFunc)(Key key, InputState state, uint32_t modifiers, void* userData);
typedef bool(*OnMouseFunc)(int x, int y, InputState state, uint32_t modifiers, void* userData);
+ typedef bool(*OnTouchFunc)(int owner, InputState state, float x, float y, void* userData);
typedef void(*OnPaintFunc)(SkCanvas*, void* userData);
void registerCharFunc(OnCharFunc func, void* userData) {
@@ -126,9 +128,15 @@ public:
fPaintUserData = userData;
}
+ void registerTouchFunc(OnTouchFunc func, void* userData) {
+ fTouchFunc = func;
+ fTouchUserData = userData;
+ }
+
bool onChar(SkUnichar c, uint32_t modifiers);
bool onKey(Key key, InputState state, uint32_t modifiers);
bool onMouse(int x, int y, InputState state, uint32_t modifiers);
+ bool onTouch(int owner, InputState state, float x, float y); // multi-owner = multi-touch
void onPaint();
void onResize(uint32_t width, uint32_t height);
@@ -150,10 +158,12 @@ protected:
void* fKeyUserData;
OnMouseFunc fMouseFunc;
void* fMouseUserData;
+ OnTouchFunc fTouchFunc;
+ void* fTouchUserData;
OnPaintFunc fPaintFunc;
void* fPaintUserData;
- WindowContext* fWindowContext;
+ WindowContext* fWindowContext = nullptr;
};
} // namespace sk_app
diff --git a/tools/viewer/sk_app/android/Window_android.cpp b/tools/viewer/sk_app/android/Window_android.cpp
index 21998d5b41..106c40b7b0 100644
--- a/tools/viewer/sk_app/android/Window_android.cpp
+++ b/tools/viewer/sk_app/android/Window_android.cpp
@@ -64,6 +64,8 @@ void Window_android::onDisplayDestroyed() {
detach();
}
-void Window_android::inval() { fSkiaAndroidApp->postMessage(Message(kContentInvalidated)); }
+void Window_android::inval() {
+ fSkiaAndroidApp->inval();
+}
} // namespace sk_app
diff --git a/tools/viewer/sk_app/android/surface_glue_android.cpp b/tools/viewer/sk_app/android/surface_glue_android.cpp
index 3d8617f0aa..e8715582c0 100644
--- a/tools/viewer/sk_app/android/surface_glue_android.cpp
+++ b/tools/viewer/sk_app/android/surface_glue_android.cpp
@@ -13,6 +13,7 @@
#include <unistd.h>
#include <unordered_map>
+#include <android/input.h>
#include <android/keycodes.h>
#include <android/looper.h>
#include <android/native_window_jni.h>
@@ -31,6 +32,15 @@ static const std::unordered_map<int, Window::Key> ANDROID_TO_WINDOW_KEYMAP({
{AKEYCODE_SOFT_RIGHT, Window::Key::kRight}
});
+static const std::unordered_map<int, Window::InputState> ANDROID_TO_WINDOW_STATEMAP({
+ {AMOTION_EVENT_ACTION_DOWN, Window::kDown_InputState},
+ {AMOTION_EVENT_ACTION_POINTER_DOWN, Window::kDown_InputState},
+ {AMOTION_EVENT_ACTION_UP, Window::kUp_InputState},
+ {AMOTION_EVENT_ACTION_POINTER_UP, Window::kUp_InputState},
+ {AMOTION_EVENT_ACTION_MOVE, Window::kMove_InputState},
+ {AMOTION_EVENT_ACTION_CANCEL, Window::kUp_InputState},
+});
+
SkiaAndroidApp::SkiaAndroidApp(JNIEnv* env, jobject androidApp) {
env->GetJavaVM(&fJavaVM);
fAndroidApp = env->NewGlobalRef(androidApp);
@@ -76,6 +86,14 @@ void SkiaAndroidApp::readMessage(Message* message) const {
SkASSERT(readSize == sizeof(Message));
}
+void SkiaAndroidApp::inval() {
+ SkAutoMutexAcquire ama(fMutex);
+ if (!fIsContentInvalidated) {
+ postMessage(Message(kContentInvalidated));
+ fIsContentInvalidated = true;
+ }
+}
+
int SkiaAndroidApp::message_callback(int fd, int events, void* data) {
auto skiaAndroidApp = (SkiaAndroidApp*)data;
Message message;
@@ -90,6 +108,8 @@ int SkiaAndroidApp::message_callback(int fd, int events, void* data) {
return 0;
}
case kContentInvalidated: {
+ SkAutoMutexAcquire ama(skiaAndroidApp->fMutex);
+ skiaAndroidApp->fIsContentInvalidated = false;
skiaAndroidApp->paintIfNeeded();
break;
}
@@ -121,13 +141,20 @@ int SkiaAndroidApp::message_callback(int fd, int events, void* data) {
break;
}
case kKeyPressed: {
- auto it = ANDROID_TO_WINDOW_KEYMAP.find(message.keycode);
+ auto it = ANDROID_TO_WINDOW_KEYMAP.find(message.fKeycode);
SkASSERT(it != ANDROID_TO_WINDOW_KEYMAP.end());
// No modifier is supported so far
skiaAndroidApp->fWindow->onKey(it->second, Window::kDown_InputState, 0);
skiaAndroidApp->fWindow->onKey(it->second, Window::kUp_InputState, 0);
break;
}
+ case kTouched: {
+ auto it = ANDROID_TO_WINDOW_STATEMAP.find(message.fTouchState);
+ SkASSERT(it != ANDROID_TO_WINDOW_STATEMAP.end());
+ skiaAndroidApp->fWindow->onTouch(message.fTouchOwner, it->second, message.fTouchX,
+ message.fTouchY);
+ break;
+ }
default: {
// do nothing
}
@@ -203,7 +230,18 @@ extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_ViewerActivity_onKeyPress
jint keycode) {
auto skiaAndroidApp = (SkiaAndroidApp*)handle;
Message message(kKeyPressed);
- message.keycode = keycode;
+ message.fKeycode = keycode;
+ skiaAndroidApp->postMessage(message);
+}
+
+extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_ViewerActivity_onTouched(
+ JNIEnv* env, jobject activity, jlong handle, jint owner, jfloat x, jfloat y, jint state) {
+ auto skiaAndroidApp = (SkiaAndroidApp*)handle;
+ Message message(kTouched);
+ message.fTouchOwner = owner;
+ message.fTouchState = state;
+ message.fTouchX = x;
+ message.fTouchY = y;
skiaAndroidApp->postMessage(message);
}
diff --git a/tools/viewer/sk_app/android/surface_glue_android.h b/tools/viewer/sk_app/android/surface_glue_android.h
index 1ce06674b9..7ffba3080a 100644
--- a/tools/viewer/sk_app/android/surface_glue_android.h
+++ b/tools/viewer/sk_app/android/surface_glue_android.h
@@ -12,6 +12,7 @@
#include <android/native_window_jni.h>
+#include "../private/SkMutex.h"
#include "../Application.h"
#include "../Window.h"
@@ -24,13 +25,16 @@ enum MessageType {
kSurfaceDestroyed,
kDestroyApp,
kContentInvalidated,
- kKeyPressed
+ kKeyPressed,
+ kTouched
};
struct Message {
MessageType fType = kUndefined;
ANativeWindow* fNativeWindow = nullptr;
- int keycode = 0;
+ int fKeycode = 0;
+ int fTouchOwner, fTouchState;
+ float fTouchX, fTouchY;
Message() {}
Message(MessageType t) : fType(t) {}
@@ -49,6 +53,10 @@ struct SkiaAndroidApp {
// This must be called in SkiaAndroidApp's own pthread because the JNIEnv is thread sensitive
void setTitle(const char* title) const;
+
+ // This posts a kContentInvalidated message if there's no such message currently in the queue
+ void inval();
+
private:
pthread_t fThread;
ANativeWindow* fNativeWindow;
@@ -57,6 +65,9 @@ private:
JNIEnv* fPThreadEnv;
jmethodID fSetTitleMethodID;
+ bool fIsContentInvalidated = false; // use this to avoid duplicate invalidate events
+ SkMutex fMutex;
+
// This must be called in SkiaAndroidApp's own pthread because the JNIEnv is thread sensitive
~SkiaAndroidApp();