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) { | |
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 |