import android.app.Activity;
import android.os.Bundle;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
+import android.view.View;
+
+public class ViewerActivity
+ extends Activity implements SurfaceHolder.Callback, View.OnTouchListener {
+ private static final float FLING_VELOCITY_THRESHOLD = 1000;
-public class ViewerActivity extends Activity implements SurfaceHolder.Callback {
private SurfaceView mView;
private ViewerApplication mApplication;
+ private GestureDetector mGestureDetector;
private native void onSurfaceCreated(long handle, Surface surface);
private native void onSurfaceChanged(long handle, Surface surface);
private native void onSurfaceDestroyed(long handle);
+ private native void onKeyPressed(long handle, int keycode);
+
+ private class GestureListener extends GestureDetector.SimpleOnGestureListener {
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return true;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ if (Math.abs(velocityX) > Math.abs(velocityY)
+ && Math.abs(velocityX) > FLING_VELOCITY_THRESHOLD) {
+ if (velocityX > 0) {
+ // Fling right
+ onKeyPressed(mApplication.getNativeHandle(), KeyEvent.KEYCODE_SOFT_RIGHT);
+ } else {
+ // Fling left
+ onKeyPressed(mApplication.getNativeHandle(), KeyEvent.KEYCODE_SOFT_LEFT);
+ }
+ return true;
+ }
+ return false;
+ }
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
mApplication = (ViewerApplication) getApplication();
mView = (SurfaceView) findViewById(R.id.surfaceView);
mView.getHolder().addCallback(this);
+
+ mGestureDetector = new GestureDetector(getApplicationContext(), new GestureListener());
+ mView.setOnTouchListener(this);
}
@Override
onSurfaceDestroyed(mApplication.getNativeHandle());
}
}
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mGestureDetector.onTouchEvent(event);
+ }
}
uint32_t width() { return fWidth; }
uint32_t height() { return fHeight; }
- const DisplayParams& getDisplayParams();
+ virtual const DisplayParams& getDisplayParams();
void setDisplayParams(const DisplayParams& params);
protected:
return true;
}
+const DisplayParams& Window_android::getDisplayParams() {
+ if (fWindowContext) {
+ return fWindowContext->getDisplayParams();
+ } else {
+ // fWindowContext doesn't exist because we haven't
+ // initDisplay yet.
+ return fDisplayParams;
+ }
+}
+
void Window_android::setTitle(const char* title) {
//todo
SkDebugf("Title: %s", title);
ContextPlatformData_android platformData;
platformData.fNativeWindow = window;
fWindowContext = VulkanWindowContext::Create((void*)&platformData, fDisplayParams);
- fNativeWindowInitialized = true;
}
void Window_android::onDisplayDestroyed() {
- fNativeWindowInitialized = false;
detach();
}
void initDisplay(ANativeWindow* window);
void onDisplayDestroyed();
+ const DisplayParams& getDisplayParams() override;
void setTitle(const char*) override;
void show() override {}
SkiaAndroidApp* fSkiaAndroidApp = nullptr;
SkRect fContentRect;
DisplayParams fDisplayParams;
- bool fNativeWindowInitialized = false;
};
} // namespace sk_app
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
+#include <unordered_map>
+#include <android/keycodes.h>
#include <android/looper.h>
#include <android/native_window_jni.h>
static const int LOOPER_ID_MESSAGEPIPE = 1;
+static const std::unordered_map<int, Window::Key> ANDROID_TO_WINDOW_KEYMAP({
+ {AKEYCODE_SOFT_LEFT, Window::Key::kLeft},
+ {AKEYCODE_SOFT_RIGHT, Window::Key::kRight}
+});
+
void* pthread_main(void* arg);
SkiaAndroidApp::SkiaAndroidApp() {
message.fNativeWindow);
int width = ANativeWindow_getWidth(skiaAndroidApp->fNativeWindow);
int height = ANativeWindow_getHeight(skiaAndroidApp->fNativeWindow);
- skiaAndroidApp->fWindow->onResize(width, height);
auto window_android = (Window_android*)skiaAndroidApp->fWindow;
window_android->setContentRect(0, 0, width, height);
skiaAndroidApp->paintIfNeeded();
}
break;
}
+ case kKeyPressed: {
+ auto it = ANDROID_TO_WINDOW_KEYMAP.find(message.keycode);
+ 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;
+ }
default: {
// do nothing
}
skiaAndroidApp->postMessage(Message(kSurfaceDestroyed));
}
+extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_ViewerActivity_onKeyPressed(JNIEnv* env,
+ jobject activity,
+ jlong handle,
+ jint keycode) {
+ auto skiaAndroidApp = (SkiaAndroidApp*)handle;
+ Message message(kKeyPressed);
+ message.keycode = keycode;
+ skiaAndroidApp->postMessage(message);
+}
+
} // namespace sk_app
kSurfaceChanged,
kSurfaceDestroyed,
kDestroyApp,
- kContentInvalidated
+ kContentInvalidated,
+ kKeyPressed
};
struct Message {
MessageType fType = kUndefined;
ANativeWindow* fNativeWindow = nullptr;
+ int keycode = 0;
Message() {}
Message(MessageType t) : fType(t) {}