The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2006, The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include <ui/KeyCharacterMap.h> |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 18 | #include <ui/Input.h> |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 19 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 20 | #include <android_runtime/AndroidRuntime.h> |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 21 | #include <nativehelper/jni.h> |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 22 | #include <nativehelper/JNIHelp.h> |
| 23 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 24 | #include "android_view_KeyEvent.h" |
| 25 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 26 | namespace android { |
| 27 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 28 | static struct { |
| 29 | jclass clazz; |
| 30 | } gKeyEventClassInfo; |
| 31 | |
Jeff Brown | 49ed71d | 2010-12-06 17:13:33 -0800 | [diff] [blame] | 32 | static struct { |
Jeff Brown | 49ed71d | 2010-12-06 17:13:33 -0800 | [diff] [blame] | 33 | jfieldID keyCode; |
| 34 | jfieldID metaState; |
| 35 | } gFallbackActionClassInfo; |
| 36 | |
| 37 | |
Jeff Brown | 1e08fe9 | 2011-11-15 17:48:10 -0800 | [diff] [blame^] | 38 | static jint nativeLoad(JNIEnv *env, jobject clazz, jstring fileStr) { |
| 39 | const char* file = env->GetStringUTFChars(fileStr, NULL); |
| 40 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 41 | KeyCharacterMap* map; |
Jeff Brown | 1e08fe9 | 2011-11-15 17:48:10 -0800 | [diff] [blame^] | 42 | status_t status = KeyCharacterMap::load(String8(file), &map); |
| 43 | jint result; |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 44 | if (status) { |
| 45 | String8 msg; |
Jeff Brown | 1e08fe9 | 2011-11-15 17:48:10 -0800 | [diff] [blame^] | 46 | msg.appendFormat("Could not load key character map '%s' due to error %d. " |
| 47 | "Refer to the log for details.", file, status); |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 48 | jniThrowException(env, "android/view/KeyCharacterMap$KeyCharacterMapUnavailableException", |
| 49 | msg.string()); |
Jeff Brown | 1e08fe9 | 2011-11-15 17:48:10 -0800 | [diff] [blame^] | 50 | result = 0; |
| 51 | } else { |
| 52 | result = reinterpret_cast<jint>(map); |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 53 | } |
Jeff Brown | 1e08fe9 | 2011-11-15 17:48:10 -0800 | [diff] [blame^] | 54 | |
| 55 | env->ReleaseStringUTFChars(fileStr, file); |
| 56 | return result; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 57 | } |
| 58 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 59 | static void nativeDispose(JNIEnv *env, jobject clazz, jint ptr) { |
| 60 | KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); |
| 61 | delete map; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 62 | } |
| 63 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 64 | static jchar nativeGetCharacter(JNIEnv *env, jobject clazz, jint ptr, |
| 65 | jint keyCode, jint metaState) { |
| 66 | KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); |
| 67 | return map->getCharacter(keyCode, metaState); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 68 | } |
| 69 | |
Jeff Brown | 49ed71d | 2010-12-06 17:13:33 -0800 | [diff] [blame] | 70 | static jboolean nativeGetFallbackAction(JNIEnv *env, jobject clazz, jint ptr, jint keyCode, |
| 71 | jint metaState, jobject fallbackActionObj) { |
| 72 | KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); |
| 73 | KeyCharacterMap::FallbackAction fallbackAction; |
| 74 | |
| 75 | bool result = map->getFallbackAction(keyCode, metaState, &fallbackAction); |
| 76 | if (result) { |
| 77 | env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.keyCode, |
| 78 | fallbackAction.keyCode); |
| 79 | env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.metaState, |
| 80 | fallbackAction.metaState); |
| 81 | } |
| 82 | return result; |
| 83 | } |
| 84 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 85 | static jchar nativeGetNumber(JNIEnv *env, jobject clazz, jint ptr, jint keyCode) { |
| 86 | KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); |
| 87 | return map->getNumber(keyCode); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 88 | } |
| 89 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 90 | static jchar nativeGetMatch(JNIEnv *env, jobject clazz, jint ptr, jint keyCode, |
| 91 | jcharArray charsArray, jint metaState) { |
| 92 | KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 93 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 94 | jsize numChars = env->GetArrayLength(charsArray); |
| 95 | jchar* chars = static_cast<jchar*>(env->GetPrimitiveArrayCritical(charsArray, NULL)); |
| 96 | if (!chars) { |
| 97 | return 0; |
| 98 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 99 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 100 | char16_t result = map->getMatch(keyCode, chars, size_t(numChars), metaState); |
| 101 | |
| 102 | env->ReleasePrimitiveArrayCritical(charsArray, chars, JNI_ABORT); |
| 103 | return result; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 104 | } |
| 105 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 106 | static jchar nativeGetDisplayLabel(JNIEnv *env, jobject clazz, jint ptr, jint keyCode) { |
| 107 | KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); |
| 108 | return map->getDisplayLabel(keyCode); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 109 | } |
| 110 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 111 | static jint nativeGetKeyboardType(JNIEnv *env, jobject clazz, jint ptr) { |
| 112 | KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); |
| 113 | return map->getKeyboardType(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 114 | } |
| 115 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 116 | static jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jint ptr, jint deviceId, |
| 117 | jcharArray charsArray) { |
| 118 | KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 119 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 120 | jchar* chars = env->GetCharArrayElements(charsArray, NULL); |
| 121 | if (!chars) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 122 | return NULL; |
| 123 | } |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 124 | jsize numChars = env->GetArrayLength(charsArray); |
| 125 | |
| 126 | Vector<KeyEvent> events; |
| 127 | jobjectArray result = NULL; |
| 128 | if (map->getEvents(deviceId, chars, size_t(numChars), events)) { |
| 129 | result = env->NewObjectArray(jsize(events.size()), gKeyEventClassInfo.clazz, NULL); |
| 130 | if (result) { |
| 131 | for (size_t i = 0; i < events.size(); i++) { |
| 132 | jobject keyEventObj = android_view_KeyEvent_fromNative(env, &events.itemAt(i)); |
| 133 | if (!keyEventObj) break; // threw OOM exception |
| 134 | env->SetObjectArrayElement(result, jsize(i), keyEventObj); |
| 135 | env->DeleteLocalRef(keyEventObj); |
| 136 | } |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | env->ReleaseCharArrayElements(charsArray, chars, JNI_ABORT); |
| 141 | return result; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 142 | } |
| 143 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 144 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 145 | /* |
| 146 | * JNI registration. |
| 147 | */ |
| 148 | |
| 149 | static JNINativeMethod g_methods[] = { |
| 150 | /* name, signature, funcPtr */ |
Jeff Brown | 1e08fe9 | 2011-11-15 17:48:10 -0800 | [diff] [blame^] | 151 | { "nativeLoad", "(Ljava/lang/String;)I", |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 152 | (void*)nativeLoad }, |
| 153 | { "nativeDispose", "(I)V", |
| 154 | (void*)nativeDispose }, |
| 155 | { "nativeGetCharacter", "(III)C", |
| 156 | (void*)nativeGetCharacter }, |
Jeff Brown | 49ed71d | 2010-12-06 17:13:33 -0800 | [diff] [blame] | 157 | { "nativeGetFallbackAction", "(IIILandroid/view/KeyCharacterMap$FallbackAction;)Z", |
| 158 | (void*)nativeGetFallbackAction }, |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 159 | { "nativeGetNumber", "(II)C", |
| 160 | (void*)nativeGetNumber }, |
| 161 | { "nativeGetMatch", "(II[CI)C", |
| 162 | (void*)nativeGetMatch }, |
| 163 | { "nativeGetDisplayLabel", "(II)C", |
| 164 | (void*)nativeGetDisplayLabel }, |
| 165 | { "nativeGetKeyboardType", "(I)I", |
| 166 | (void*)nativeGetKeyboardType }, |
| 167 | { "nativeGetEvents", "(II[C)[Landroid/view/KeyEvent;", |
| 168 | (void*)nativeGetEvents }, |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 169 | }; |
| 170 | |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 171 | #define FIND_CLASS(var, className) \ |
| 172 | var = env->FindClass(className); \ |
Carl Shapiro | 17cc33a | 2011-03-05 20:53:16 -0800 | [diff] [blame] | 173 | LOG_FATAL_IF(! var, "Unable to find class " className); |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 174 | |
Jeff Brown | 49ed71d | 2010-12-06 17:13:33 -0800 | [diff] [blame] | 175 | #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ |
| 176 | var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ |
| 177 | LOG_FATAL_IF(! var, "Unable to find field " fieldName); |
| 178 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 179 | int register_android_text_KeyCharacterMap(JNIEnv* env) |
| 180 | { |
Jeff Brown | 6b53e8d | 2010-11-10 16:03:06 -0800 | [diff] [blame] | 181 | FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent"); |
Carl Shapiro | 17cc33a | 2011-03-05 20:53:16 -0800 | [diff] [blame] | 182 | gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz)); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 183 | |
Carl Shapiro | 17cc33a | 2011-03-05 20:53:16 -0800 | [diff] [blame] | 184 | jclass clazz; |
| 185 | FIND_CLASS(clazz, "android/view/KeyCharacterMap$FallbackAction"); |
Jeff Brown | 49ed71d | 2010-12-06 17:13:33 -0800 | [diff] [blame] | 186 | |
Carl Shapiro | 17cc33a | 2011-03-05 20:53:16 -0800 | [diff] [blame] | 187 | GET_FIELD_ID(gFallbackActionClassInfo.keyCode, clazz, |
Jeff Brown | 49ed71d | 2010-12-06 17:13:33 -0800 | [diff] [blame] | 188 | "keyCode", "I"); |
| 189 | |
Carl Shapiro | 17cc33a | 2011-03-05 20:53:16 -0800 | [diff] [blame] | 190 | GET_FIELD_ID(gFallbackActionClassInfo.metaState, clazz, |
Jeff Brown | 49ed71d | 2010-12-06 17:13:33 -0800 | [diff] [blame] | 191 | "metaState", "I"); |
| 192 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 193 | return AndroidRuntime::registerNativeMethods(env, |
| 194 | "android/view/KeyCharacterMap", g_methods, NELEM(g_methods)); |
| 195 | } |
| 196 | |
| 197 | }; // namespace android |