OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2016 Google Inc. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. |
| 6 */ |
| 7 |
| 8 #include "Window_android.h" |
| 9 |
| 10 #include "VulkanTestContext_android.h" |
| 11 |
| 12 Window* Window::CreateNativeWindow(void* platformData) { |
| 13 Window_android* window = new Window_android(); |
| 14 if (!window->init((android_app*)platformData)) { |
| 15 delete window; |
| 16 return nullptr; |
| 17 } |
| 18 return window; |
| 19 } |
| 20 |
| 21 static void handle_cmd(struct android_app* app, int32_t cmd); |
| 22 static int32_t handle_input(struct android_app* app, AInputEvent* event); |
| 23 |
| 24 bool Window_android::init(android_app* app) { |
| 25 SkASSERT(app); |
| 26 mApp = app; |
| 27 mApp->userData = this; |
| 28 mApp->onAppCmd = handle_cmd; |
| 29 mApp->onInputEvent = handle_input; |
| 30 return true; |
| 31 } |
| 32 |
| 33 void Window_android::setTitle(const char* title) { |
| 34 //todo |
| 35 SkDebugf("Title: %s", title); |
| 36 } |
| 37 |
| 38 bool Window_android::attach(BackEndType attachType, int msaaSampleCount, Attachm
entInfo*) { |
| 39 if (kVulkan_BackendType != attachType) { |
| 40 return false; |
| 41 } |
| 42 |
| 43 mSampleCount = msaaSampleCount; |
| 44 |
| 45 // We delay the creation of fTestContext until Android informs us that |
| 46 // the native window is ready to use. |
| 47 return true; |
| 48 } |
| 49 |
| 50 void Window_android::initDisplay(ANativeWindow* window) { |
| 51 SkASSERT(window); |
| 52 ContextPlatformData_android platformData; |
| 53 platformData.fNativeWindow = window; |
| 54 fTestContext = VulkanTestContext::Create((void*)&platformData, mSampleCount)
; |
| 55 } |
| 56 |
| 57 static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { |
| 58 if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { |
| 59 SkDebugf("Failure writing android_app cmd: %s\n", strerror(errno)); |
| 60 } |
| 61 } |
| 62 |
| 63 void Window_android::inval() { |
| 64 android_app_write_cmd(mApp, APP_CMD_INVAL_WINDOW); |
| 65 } |
| 66 |
| 67 void Window_android::paintIfNeeded() { |
| 68 if (mApp->window || !mContentRect.isEmpty()) { |
| 69 this->onPaint(); |
| 70 } |
| 71 } |
| 72 |
| 73 /** |
| 74 * Process the next main command. |
| 75 */ |
| 76 static void handle_cmd(struct android_app* app, int32_t cmd) { |
| 77 Window_android* window = (Window_android*)app->userData; |
| 78 switch (cmd) { |
| 79 case APP_CMD_INIT_WINDOW: |
| 80 // The window is being shown, get it ready. |
| 81 SkASSERT(app->window); |
| 82 window->initDisplay(app->window); |
| 83 window->paintIfNeeded(); |
| 84 break; |
| 85 case APP_CMD_WINDOW_RESIZED: { |
| 86 int width = ANativeWindow_getWidth(app->window); |
| 87 int height = ANativeWindow_getHeight(app->window); |
| 88 window->onResize(width, height); |
| 89 break; |
| 90 } |
| 91 case APP_CMD_CONTENT_RECT_CHANGED: |
| 92 window->setContentRect(app->contentRect.left, app->contentRect.top, |
| 93 app->contentRect.right, app->contentRect.bott
om); |
| 94 window->paintIfNeeded(); |
| 95 break; |
| 96 case APP_CMD_TERM_WINDOW: |
| 97 // The window is being hidden or closed, clean it up. |
| 98 window->detach(); |
| 99 break; |
| 100 case APP_CMD_INVAL_WINDOW: |
| 101 window->paintIfNeeded(); |
| 102 break; |
| 103 } |
| 104 } |
| 105 |
| 106 static Window::Key get_key(int32_t keycode) { |
| 107 static const struct { |
| 108 int32_t fAndroidKey; |
| 109 Window::Key fWindowKey; |
| 110 } gPair[] = { |
| 111 { AKEYCODE_BACK, Window::kBack_Key }, |
| 112 { AKEYCODE_VOLUME_UP, Window::kLeft_Key }, |
| 113 { AKEYCODE_VOLUME_DOWN, Window::kRight_Key } |
| 114 }; |
| 115 for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { |
| 116 if (gPair[i].fAndroidKey == keycode) { |
| 117 return gPair[i].fWindowKey; |
| 118 } |
| 119 } |
| 120 return Window::kNONE_Key; |
| 121 } |
| 122 |
| 123 static Window::InputState get_action(int32_t action) { |
| 124 static const struct { |
| 125 int32_t fAndroidAction; |
| 126 Window::InputState fInputState; |
| 127 } gPair[] = { |
| 128 { AKEY_STATE_DOWN, Window::kDown_InputState }, |
| 129 { AKEY_STATE_UP, Window::kUp_InputState }, |
| 130 }; |
| 131 for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { |
| 132 if (gPair[i].fAndroidAction == action) { |
| 133 return gPair[i].fInputState; |
| 134 } |
| 135 } |
| 136 return Window::kMove_InputState; |
| 137 } |
| 138 |
| 139 static int32_t get_key_modifiers(AInputEvent* event) { |
| 140 static const struct { |
| 141 int32_t fAndroidState; |
| 142 int32_t fWindowModifier; |
| 143 } gPair[] = { |
| 144 { AMETA_SHIFT_ON, Window::kShift_ModifierKey }, |
| 145 { AMETA_CTRL_ON, Window::kControl_ModifierKey }, |
| 146 }; |
| 147 |
| 148 int32_t metaState = AKeyEvent_getMetaState(event); |
| 149 int32_t modifiers = 0; |
| 150 |
| 151 if (AKeyEvent_getRepeatCount(event) == 0) { |
| 152 modifiers |= Window::kFirstPress_ModifierKey; |
| 153 } |
| 154 |
| 155 for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { |
| 156 if (gPair[i].fAndroidState == metaState) { |
| 157 modifiers |= gPair[i].fWindowModifier; |
| 158 } |
| 159 } |
| 160 return modifiers; |
| 161 } |
| 162 |
| 163 /** |
| 164 * Process the next input event. |
| 165 */ |
| 166 static int32_t handle_input(struct android_app* app, AInputEvent* event) { |
| 167 Window_android* window = (Window_android*)app->userData; |
| 168 switch(AInputEvent_getType(event)) { |
| 169 case AINPUT_EVENT_TYPE_MOTION: |
| 170 break; |
| 171 case AINPUT_EVENT_TYPE_KEY: |
| 172 Window::Key key = get_key(AKeyEvent_getKeyCode(event)); |
| 173 Window::InputState state = get_action(AKeyEvent_getAction(event)); |
| 174 int32_t mod = get_key_modifiers(event); |
| 175 window->onKey(key, state, mod); |
| 176 return true; // eat all key events |
| 177 } |
| 178 return 0; |
| 179 } |
OLD | NEW |