1 /* 2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #import "common.h" 27 #import "com_sun_glass_events_KeyEvent.h" 28 #import "com_sun_glass_ui_mac_MacApplication.h" 29 30 #import "GlassApplication.h" 31 #import "GlassMacros.h" 32 #import "GlassKey.h" 33 34 //#define VERBOSE 35 #ifndef VERBOSE 36 #define LOG(MSG, ...) 37 #else 38 #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__); 39 #endif 40 41 struct KeyMapEntry 42 { 43 unsigned short keyCode; 44 jint jKeyCode; 45 BOOL sendJavaChars; 46 }; 47 48 static const struct KeyMapEntry gKeyMap[] = 49 { 50 {0x00, com_sun_glass_events_KeyEvent_VK_A, YES}, 51 {0x01, com_sun_glass_events_KeyEvent_VK_S, YES}, 52 {0x02, com_sun_glass_events_KeyEvent_VK_D, YES}, 53 {0x03, com_sun_glass_events_KeyEvent_VK_F, YES}, 54 {0x04, com_sun_glass_events_KeyEvent_VK_H, YES}, 55 {0x05, com_sun_glass_events_KeyEvent_VK_G, YES}, 56 {0x06, com_sun_glass_events_KeyEvent_VK_Z, YES}, 57 {0x07, com_sun_glass_events_KeyEvent_VK_X, YES}, 58 {0x08, com_sun_glass_events_KeyEvent_VK_C, YES}, 59 {0x09, com_sun_glass_events_KeyEvent_VK_V, YES}, 60 {0x0A, com_sun_glass_events_KeyEvent_VK_BACK_QUOTE, YES}, 61 {0x0B, com_sun_glass_events_KeyEvent_VK_B, YES}, 62 {0x0C, com_sun_glass_events_KeyEvent_VK_Q, YES}, 63 {0x0D, com_sun_glass_events_KeyEvent_VK_W, YES}, 64 {0x0E, com_sun_glass_events_KeyEvent_VK_E, YES}, 65 {0x0F, com_sun_glass_events_KeyEvent_VK_R, YES}, 66 {0x10, com_sun_glass_events_KeyEvent_VK_Y, YES}, 67 {0x11, com_sun_glass_events_KeyEvent_VK_T, YES}, 68 {0x12, com_sun_glass_events_KeyEvent_VK_1, YES}, 69 {0x13, com_sun_glass_events_KeyEvent_VK_2, YES}, 70 {0x14, com_sun_glass_events_KeyEvent_VK_3, YES}, 71 {0x15, com_sun_glass_events_KeyEvent_VK_4, YES}, 72 {0x16, com_sun_glass_events_KeyEvent_VK_6, YES}, 73 {0x17, com_sun_glass_events_KeyEvent_VK_5, YES}, 74 {0x18, com_sun_glass_events_KeyEvent_VK_EQUALS, YES}, 75 {0x19, com_sun_glass_events_KeyEvent_VK_9, YES}, 76 {0x1A, com_sun_glass_events_KeyEvent_VK_7, YES}, 77 {0x1B, com_sun_glass_events_KeyEvent_VK_MINUS, YES}, 78 {0x1C, com_sun_glass_events_KeyEvent_VK_8, YES}, 79 {0x1D, com_sun_glass_events_KeyEvent_VK_0, YES}, 80 {0x1E, com_sun_glass_events_KeyEvent_VK_CLOSE_BRACKET, YES}, 81 {0x1F, com_sun_glass_events_KeyEvent_VK_O, YES}, 82 {0x20, com_sun_glass_events_KeyEvent_VK_U, YES}, 83 {0x21, com_sun_glass_events_KeyEvent_VK_OPEN_BRACKET, YES}, 84 {0x22, com_sun_glass_events_KeyEvent_VK_I, YES}, 85 {0x23, com_sun_glass_events_KeyEvent_VK_P, YES}, 86 {0x24, com_sun_glass_events_KeyEvent_VK_ENTER, YES}, 87 {0x25, com_sun_glass_events_KeyEvent_VK_L, YES}, 88 {0x26, com_sun_glass_events_KeyEvent_VK_J, YES}, 89 {0x27, com_sun_glass_events_KeyEvent_VK_QUOTE, YES}, 90 {0x28, com_sun_glass_events_KeyEvent_VK_K, YES}, 91 {0x29, com_sun_glass_events_KeyEvent_VK_SEMICOLON, YES}, 92 {0x2A, com_sun_glass_events_KeyEvent_VK_BACK_SLASH, YES}, 93 {0x2B, com_sun_glass_events_KeyEvent_VK_COMMA, YES}, 94 {0x2C, com_sun_glass_events_KeyEvent_VK_SLASH, YES}, 95 {0x2D, com_sun_glass_events_KeyEvent_VK_N, YES}, 96 {0x2E, com_sun_glass_events_KeyEvent_VK_M, YES}, 97 {0x2F, com_sun_glass_events_KeyEvent_VK_PERIOD, YES}, 98 {0x30, com_sun_glass_events_KeyEvent_VK_TAB, YES}, 99 {0x31, com_sun_glass_events_KeyEvent_VK_SPACE, YES}, 100 {0x32, com_sun_glass_events_KeyEvent_VK_BACK_QUOTE, YES}, 101 {0x33, com_sun_glass_events_KeyEvent_VK_BACKSPACE, NO}, 102 {0x34, com_sun_glass_events_KeyEvent_VK_ENTER, YES}, 103 {0x35, com_sun_glass_events_KeyEvent_VK_ESCAPE, NO}, 104 {0x36, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 105 {0x37, com_sun_glass_events_KeyEvent_VK_COMMAND, NO}, 106 {0x38, com_sun_glass_events_KeyEvent_VK_SHIFT, NO}, 107 {0x39, com_sun_glass_events_KeyEvent_VK_CAPS_LOCK, NO}, 108 {0x3A, com_sun_glass_events_KeyEvent_VK_ALT, NO}, 109 {0x3B, com_sun_glass_events_KeyEvent_VK_CONTROL, NO}, 110 {0x3C, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 111 {0x3D, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 112 {0x3E, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 113 {0x3F, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 114 {0x40, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 115 {0x41, com_sun_glass_events_KeyEvent_VK_DECIMAL, YES}, 116 {0x42, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 117 {0x43, com_sun_glass_events_KeyEvent_VK_MULTIPLY, YES}, 118 {0x44, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 119 {0x45, com_sun_glass_events_KeyEvent_VK_ADD, YES}, 120 {0x46, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 121 {0x47, com_sun_glass_events_KeyEvent_VK_CLEAR, NO}, 122 {0x48, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 123 {0x49, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 124 {0x4A, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 125 {0x4B, com_sun_glass_events_KeyEvent_VK_DIVIDE, YES}, 126 {0x4C, com_sun_glass_events_KeyEvent_VK_ENTER, YES}, 127 {0x4D, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 128 {0x4E, com_sun_glass_events_KeyEvent_VK_SUBTRACT, YES}, 129 {0x4F, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 130 {0x50, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 131 {0x51, com_sun_glass_events_KeyEvent_VK_EQUALS, YES}, 132 {0x52, com_sun_glass_events_KeyEvent_VK_NUMPAD0, YES}, 133 {0x53, com_sun_glass_events_KeyEvent_VK_NUMPAD1, YES}, 134 {0x54, com_sun_glass_events_KeyEvent_VK_NUMPAD2, YES}, 135 {0x55, com_sun_glass_events_KeyEvent_VK_NUMPAD3, YES}, 136 {0x56, com_sun_glass_events_KeyEvent_VK_NUMPAD4, YES}, 137 {0x57, com_sun_glass_events_KeyEvent_VK_NUMPAD5, YES}, 138 {0x58, com_sun_glass_events_KeyEvent_VK_NUMPAD6, YES}, 139 {0x59, com_sun_glass_events_KeyEvent_VK_NUMPAD7, YES}, 140 {0x5A, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 141 {0x5B, com_sun_glass_events_KeyEvent_VK_NUMPAD8, YES}, 142 {0x5C, com_sun_glass_events_KeyEvent_VK_NUMPAD9, YES}, 143 {0x5D, com_sun_glass_events_KeyEvent_VK_BACK_SLASH, YES}, 144 {0x5E, com_sun_glass_events_KeyEvent_VK_UNDERSCORE, YES}, 145 {0x5F, com_sun_glass_events_KeyEvent_VK_COMMA, YES}, 146 {0x60, com_sun_glass_events_KeyEvent_VK_F5, NO}, 147 {0x61, com_sun_glass_events_KeyEvent_VK_F6, NO}, 148 {0x62, com_sun_glass_events_KeyEvent_VK_F7, NO}, 149 {0x63, com_sun_glass_events_KeyEvent_VK_F3, NO}, 150 {0x64, com_sun_glass_events_KeyEvent_VK_F8, NO}, 151 {0x65, com_sun_glass_events_KeyEvent_VK_F9, NO}, 152 // {0x66, com_sun_glass_events_KeyEvent_VK_ALPHANUMERIC, NO}, 153 {0x67, com_sun_glass_events_KeyEvent_VK_F11, NO}, 154 // {0x68, com_sun_glass_events_KeyEvent_VK_KATAKANA, NO}, 155 // {0x69, com_sun_glass_events_KeyEvent_VK_F13, NO}, 156 // {0x6A, com_sun_glass_events_KeyEvent_VK_F16, NO}, 157 // {0x6B, com_sun_glass_events_KeyEvent_VK_F14, NO}, 158 {0x6C, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 159 {0x6D, com_sun_glass_events_KeyEvent_VK_F10, NO}, 160 {0x6E, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 161 {0x6F, com_sun_glass_events_KeyEvent_VK_F12, NO}, 162 {0x70, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 163 // {0x71, com_sun_glass_events_KeyEvent_VK_F15, NO}, 164 {0x72, com_sun_glass_events_KeyEvent_VK_HELP, NO}, 165 {0x73, com_sun_glass_events_KeyEvent_VK_HOME, NO}, 166 {0x74, com_sun_glass_events_KeyEvent_VK_PAGE_UP, NO}, 167 {0x75, com_sun_glass_events_KeyEvent_VK_DELETE, NO}, 168 {0x76, com_sun_glass_events_KeyEvent_VK_F4, NO}, 169 {0x77, com_sun_glass_events_KeyEvent_VK_END, NO}, 170 {0x78, com_sun_glass_events_KeyEvent_VK_F2, NO}, 171 {0x79, com_sun_glass_events_KeyEvent_VK_PAGE_DOWN, NO}, 172 {0x7A, com_sun_glass_events_KeyEvent_VK_F1, NO}, 173 {0x7B, com_sun_glass_events_KeyEvent_VK_LEFT, NO}, 174 {0x7C, com_sun_glass_events_KeyEvent_VK_RIGHT, NO}, 175 {0x7D, com_sun_glass_events_KeyEvent_VK_DOWN, NO}, 176 {0x7E, com_sun_glass_events_KeyEvent_VK_UP, NO}, 177 {0x7F, com_sun_glass_events_KeyEvent_VK_UNDEFINED, NO}, 178 }; 179 static const int gKeyMapSize = sizeof(gKeyMap) / sizeof(struct KeyMapEntry); 180 181 jint GetJavaKeyModifiers(NSEvent *event) 182 { 183 jint jModifiers = 0; 184 185 NSUInteger modifierFlags = ([event modifierFlags] & NSDeviceIndependentModifierFlagsMask); 186 if (((modifierFlags & NSShiftKeyMask) != 0) == YES) 187 { 188 jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_SHIFT; 189 } 190 if (((modifierFlags & NSFunctionKeyMask) != 0) == YES) 191 { 192 jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_FUNCTION; 193 } 194 if (((modifierFlags & NSControlKeyMask) != 0) == YES) 195 { 196 jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_CONTROL; 197 } 198 if (((modifierFlags & NSAlternateKeyMask) != 0) == YES) 199 { 200 jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_OPTION; 201 } 202 if (((modifierFlags & NSCommandKeyMask) != 0) == YES) 203 { 204 jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_COMMAND; 205 } 206 return jModifiers; 207 } 208 209 jint GetJavaMouseModifiers(NSUInteger buttons) 210 { 211 jint jModifiers = 0; 212 if (buttons & (1 << 0)) { 213 jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_PRIMARY; 214 } 215 if (buttons & (1 << 1)) { 216 jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_SECONDARY; 217 } 218 if (buttons & (1 << 2)) { 219 jModifiers |= com_sun_glass_events_KeyEvent_MODIFIER_BUTTON_MIDDLE; 220 } 221 return jModifiers; 222 } 223 224 jint GetJavaModifiers(NSEvent *event) 225 { 226 return GetJavaKeyModifiers(event) | GetJavaMouseModifiers([NSEvent pressedMouseButtons]); 227 } 228 229 jint GetJavaKeyCodeFor(unsigned short keyCode) 230 { 231 // Not the fastest implementation... 232 for (int i=0; i<gKeyMapSize; i++) 233 { 234 if (gKeyMap[i].keyCode == keyCode) 235 { 236 return gKeyMap[i].jKeyCode; 237 } 238 } 239 return com_sun_glass_events_KeyEvent_VK_UNDEFINED; 240 } 241 242 jint GetJavaKeyCode(NSEvent *event) 243 { 244 return GetJavaKeyCodeFor([event keyCode]); 245 } 246 247 jcharArray GetJavaKeyChars(JNIEnv *env, NSEvent *event) 248 { 249 NSString *chars = [event characters]; 250 251 unsigned short keyCode = [event keyCode]; 252 BOOL needChars = NO; 253 // Not the fastest implementation... 254 for (int i=0; i<gKeyMapSize; i++) 255 { 256 if (gKeyMap[i].keyCode == keyCode) 257 { 258 needChars = gKeyMap[i].sendJavaChars; 259 break; 260 } 261 } 262 if (needChars == NO) 263 { 264 // Return an empty array instead of NULL 265 return (*env)->NewCharArray(env, 0); 266 } 267 268 jchar jc[16]; 269 [chars getCharacters:jc range:NSMakeRange(0, [chars length])]; 270 jcharArray jChars = (*env)->NewCharArray(env, (jsize)[chars length]); 271 (*env)->SetCharArrayRegion(env, jChars, 0, (jsize)[chars length], jc); 272 GLASS_CHECK_EXCEPTION(env); 273 return jChars; 274 } 275 276 BOOL GetMacKey(jint javaKeyCode, unsigned short *outMacKeyCode) 277 { 278 for (int index=0; index<gKeyMapSize; index++) 279 { 280 if (gKeyMap[index].jKeyCode == javaKeyCode) 281 { 282 *outMacKeyCode = gKeyMap[index].keyCode; 283 return YES; 284 } 285 } 286 287 // ??? unknown VK 288 return NO; 289 } 290 291 NSString* GetStringForJavaKey(jchar jKeyCode) { 292 if (jKeyCode == '\0') 293 return @""; 294 295 if (islower(jKeyCode)) 296 { 297 return [[NSString stringWithFormat:@"%c", jKeyCode] lowercaseString]; 298 } 299 300 unichar unicode = 0; 301 switch (jKeyCode) 302 { 303 case com_sun_glass_events_KeyEvent_VK_LEFT: 304 unicode = 0x2190; break; 305 case com_sun_glass_events_KeyEvent_VK_RIGHT: 306 unicode = 0x2192; break; 307 case com_sun_glass_events_KeyEvent_VK_UP: 308 unicode = 0x2191; break; 309 case com_sun_glass_events_KeyEvent_VK_DOWN: 310 unicode = 0x2193; break; 311 case com_sun_glass_events_KeyEvent_VK_ESCAPE: 312 unicode = 0x238B; break; 313 case com_sun_glass_events_KeyEvent_VK_LEFT_PARENTHESIS: 314 unicode = 0x0028; break; 315 case com_sun_glass_events_KeyEvent_VK_RIGHT_PARENTHESIS: 316 unicode = 0x0029; break; 317 case com_sun_glass_events_KeyEvent_VK_COLON: 318 unicode = 0x003A; break; 319 case com_sun_glass_events_KeyEvent_VK_DOLLAR: 320 unicode = 0x0024; break; 321 case com_sun_glass_events_KeyEvent_VK_EURO_SIGN: 322 unicode = 0x20AC; break; 323 case com_sun_glass_events_KeyEvent_VK_EXCLAMATION: 324 unicode = 0x0021; break; 325 case com_sun_glass_events_KeyEvent_VK_UNDERSCORE: 326 unicode = 0x005F; break; 327 case com_sun_glass_events_KeyEvent_VK_AT: 328 unicode = 0x0040; break; 329 case com_sun_glass_events_KeyEvent_VK_BRACELEFT: 330 unicode = 0x007B; break; 331 case com_sun_glass_events_KeyEvent_VK_BRACERIGHT: 332 unicode = 0x007D; break; 333 case com_sun_glass_events_KeyEvent_VK_LESS: 334 unicode = 0x003C; break; 335 case com_sun_glass_events_KeyEvent_VK_GREATER: 336 unicode = 0x003E; break; 337 case com_sun_glass_events_KeyEvent_VK_QUOTE: 338 unicode = 0x0027; break; 339 case com_sun_glass_events_KeyEvent_VK_BACK_QUOTE: 340 unicode = 0x0060; break; 341 case com_sun_glass_events_KeyEvent_VK_AMPERSAND: 342 unicode = 0x0026; break; 343 case com_sun_glass_events_KeyEvent_VK_MULTIPLY: 344 case com_sun_glass_events_KeyEvent_VK_ASTERISK: 345 unicode = 0x002A; break; 346 case com_sun_glass_events_KeyEvent_VK_DOUBLE_QUOTE: 347 unicode = 0x0022; break; 348 case com_sun_glass_events_KeyEvent_VK_NUMBER_SIGN: 349 unicode = 0x0023; break; 350 case com_sun_glass_events_KeyEvent_VK_PLUS: 351 case com_sun_glass_events_KeyEvent_VK_ADD: 352 unicode = 0x002B; break; 353 case com_sun_glass_events_KeyEvent_VK_MINUS: 354 case com_sun_glass_events_KeyEvent_VK_SUBTRACT: 355 unicode = 0x2013; break; 356 case com_sun_glass_events_KeyEvent_VK_DIVIDE: 357 unicode = 0x002F; break; 358 case com_sun_glass_events_KeyEvent_VK_CIRCUMFLEX: 359 unicode = 0x005E; break; 360 case com_sun_glass_events_KeyEvent_VK_DECIMAL: 361 unicode = 0x002E; break; 362 case com_sun_glass_events_KeyEvent_VK_DELETE: 363 unicode = 0x2326; break; 364 default: 365 break; 366 } 367 368 if (unicode != 0) 369 { 370 LOG("GetStringForJavaKey: unicode %x", unicode); 371 return [NSString stringWithCharacters:&unicode length:1]; 372 } 373 else 374 { 375 return [[NSString stringWithFormat:@"%c", jKeyCode] lowercaseString]; 376 } 377 378 } 379 380 /* 381 * Class: com_sun_glass_ui_mac_MacApplication 382 * Method: _getKeyCodeForChar 383 * Signature: (C)I 384 */ 385 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_mac_MacApplication__1getKeyCodeForChar 386 (JNIEnv * env, jobject jApplication, jchar c) 387 { 388 LOG("Java_com_sun_glass_ui_mac_MacApplication__1getKeyCodeForChar"); 389 390 return [GlassApplication getKeyCodeForChar:c]; 391 } 392