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