diff options
Diffstat (limited to 'tools/viewer/sk_app/android/Window_android.cpp')
-rw-r--r-- | tools/viewer/sk_app/android/Window_android.cpp | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/tools/viewer/sk_app/android/Window_android.cpp b/tools/viewer/sk_app/android/Window_android.cpp new file mode 100644 index 0000000000..94be02c933 --- /dev/null +++ b/tools/viewer/sk_app/android/Window_android.cpp @@ -0,0 +1,183 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#include "Window_android.h" + +#include "VulkanWindowContext_android.h" + +namespace sk_app { + +Window* Window::CreateNativeWindow(void* platformData) { + Window_android* window = new Window_android(); + if (!window->init((android_app*)platformData)) { + delete window; + return nullptr; + } + return window; +} + +static void handle_cmd(struct android_app* app, int32_t cmd); +static int32_t handle_input(struct android_app* app, AInputEvent* event); + +bool Window_android::init(android_app* app) { + SkASSERT(app); + mApp = app; + mApp->userData = this; + mApp->onAppCmd = handle_cmd; + mApp->onInputEvent = handle_input; + return true; +} + +void Window_android::setTitle(const char* title) { + //todo + SkDebugf("Title: %s", title); +} + +bool Window_android::attach(BackEndType attachType, int msaaSampleCount) { + if (kVulkan_BackendType != attachType) { + return false; + } + + mSampleCount = msaaSampleCount; + + // We delay the creation of fTestContext until Android informs us that + // the native window is ready to use. + return true; +} + +void Window_android::initDisplay(ANativeWindow* window) { + SkASSERT(window); + ContextPlatformData_android platformData; + platformData.fNativeWindow = window; + fWindowContext = VulkanWindowContext::Create((void*)&platformData, mSampleCount); +} + +static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { + if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { + SkDebugf("Failure writing android_app cmd: %s\n", strerror(errno)); + } +} + +void Window_android::inval() { + android_app_write_cmd(mApp, APP_CMD_INVAL_WINDOW); +} + +void Window_android::paintIfNeeded() { + if (mApp->window || !mContentRect.isEmpty()) { + this->onPaint(); + } +} + +/** + * Process the next main command. + */ +static void handle_cmd(struct android_app* app, int32_t cmd) { + Window_android* window = (Window_android*)app->userData; + switch (cmd) { + case APP_CMD_INIT_WINDOW: + // The window is being shown, get it ready. + SkASSERT(app->window); + window->initDisplay(app->window); + window->paintIfNeeded(); + break; + case APP_CMD_WINDOW_RESIZED: { + int width = ANativeWindow_getWidth(app->window); + int height = ANativeWindow_getHeight(app->window); + window->onResize(width, height); + break; + } + case APP_CMD_CONTENT_RECT_CHANGED: + window->setContentRect(app->contentRect.left, app->contentRect.top, + app->contentRect.right, app->contentRect.bottom); + window->paintIfNeeded(); + break; + case APP_CMD_TERM_WINDOW: + // The window is being hidden or closed, clean it up. + window->detach(); + break; + case APP_CMD_INVAL_WINDOW: + window->paintIfNeeded(); + break; + } +} + +static Window::Key get_key(int32_t keycode) { + static const struct { + int32_t fAndroidKey; + Window::Key fWindowKey; + } gPair[] = { + { AKEYCODE_BACK, Window::kBack_Key }, + { AKEYCODE_VOLUME_UP, Window::kLeft_Key }, + { AKEYCODE_VOLUME_DOWN, Window::kRight_Key } + }; + for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { + if (gPair[i].fAndroidKey == keycode) { + return gPair[i].fWindowKey; + } + } + return Window::kNONE_Key; +} + +static Window::InputState get_action(int32_t action) { + static const struct { + int32_t fAndroidAction; + Window::InputState fInputState; + } gPair[] = { + { AKEY_STATE_DOWN, Window::kDown_InputState }, + { AKEY_STATE_UP, Window::kUp_InputState }, + }; + for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { + if (gPair[i].fAndroidAction == action) { + return gPair[i].fInputState; + } + } + return Window::kMove_InputState; +} + +static int32_t get_key_modifiers(AInputEvent* event) { + static const struct { + int32_t fAndroidState; + int32_t fWindowModifier; + } gPair[] = { + { AMETA_SHIFT_ON, Window::kShift_ModifierKey }, + { AMETA_CTRL_ON, Window::kControl_ModifierKey }, + }; + + int32_t metaState = AKeyEvent_getMetaState(event); + int32_t modifiers = 0; + + if (AKeyEvent_getRepeatCount(event) == 0) { + modifiers |= Window::kFirstPress_ModifierKey; + } + + for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { + if (gPair[i].fAndroidState == metaState) { + modifiers |= gPair[i].fWindowModifier; + } + } + return modifiers; +} + +/** + * Process the next input event. + */ +static int32_t handle_input(struct android_app* app, AInputEvent* event) { + Window_android* window = (Window_android*)app->userData; + switch(AInputEvent_getType(event)) { + case AINPUT_EVENT_TYPE_MOTION: + break; + case AINPUT_EVENT_TYPE_KEY: + Window::Key key = get_key(AKeyEvent_getKeyCode(event)); + Window::InputState state = get_action(AKeyEvent_getAction(event)); + int32_t mod = get_key_modifiers(event); + window->onKey(key, state, mod); + return true; // eat all key events + } + return 0; +} + +} // namespace sk_app |