1 /* 2 * Copyright (c) 2011, 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 <JavaNativeFoundation/JavaNativeFoundation.h> 27 #import <JavaRuntimeSupport/JavaRuntimeSupport.h> 28 #import <sys/time.h> 29 30 #import "LWCToolkit.h" 31 #import "ThreadUtilities.h" 32 33 #import "java_awt_event_InputEvent.h" 34 #import "java_awt_event_KeyEvent.h" 35 #import "java_awt_event_MouseEvent.h" 36 37 /* 38 * Table to map typed characters to their Java virtual key equivalent and back. 39 * We use the incoming unichar (ignoring all modifiers) and try to figure out 40 * which virtual key code is appropriate. A lot of them just have direct 41 * mappings (the function keys, arrow keys, etc.) so they aren't a problem. 42 * We had to do something a little funky to catch the keys on the numeric 43 * key pad (i.e. using event mask to distinguish between period on regular 44 * keyboard and decimal on keypad). We also have to do something incredibly 45 * hokey with regards to the shifted punctuation characters. For examples, 46 * consider '&' which is usually Shift-7. For the Java key typed events, 47 * that's no problem, we just say pass the unichar. But for the 48 * KeyPressed/Released events, we need to identify the virtual key code 49 * (which roughly correspond to hardware keys) which means we are supposed 50 * to say the virtual 7 key was pressed. But how are we supposed to know 51 * when we get a punctuation char what was the real hardware key was that 52 * was pressed? Although '&' often comes from Shift-7 the keyboard can be 53 * remapped! I don't think there really is a good answer, and hopefully 54 * all good applets are only interested in logical key typed events not 55 * press/release. Meanwhile, we are hard-coding the shifted punctuation 56 * to trigger the virtual keys that are the expected ones under a standard 57 * keymapping. Looking at Windows & Mac, they don't actually do this, the 58 * Mac seems to just put the ascii code in for the shifted punctuation 59 * (which means they actually end up with bogus key codes on the Java side), 60 * Windows I can't even figure out what it's doing. 61 */ 62 #define KL_STANDARD java_awt_event_KeyEvent_KEY_LOCATION_STANDARD 63 #define KL_NUMPAD java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD 64 #define KL_UNKNOWN java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN 65 static struct _key 66 { 67 unsigned short keyCode; 68 BOOL postsTyped; 69 jint javaKeyLocation; 70 jint javaKeyCode; 71 } 72 const keyTable[] = 73 { 74 {0x00, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_A}, 75 {0x01, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_S}, 76 {0x02, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_D}, 77 {0x03, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_F}, 78 {0x04, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_H}, 79 {0x05, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_G}, 80 {0x06, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Z}, 81 {0x07, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_X}, 82 {0x08, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_C}, 83 {0x09, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_V}, 84 {0x0A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_QUOTE}, 85 {0x0B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_B}, 86 {0x0C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Q}, 87 {0x0D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_W}, 88 {0x0E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_E}, 89 {0x0F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_R}, 90 {0x10, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_Y}, 91 {0x11, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_T}, 92 {0x12, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_1}, 93 {0x13, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_2}, 94 {0x14, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_3}, 95 {0x15, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_4}, 96 {0x16, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_6}, 97 {0x17, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_5}, 98 {0x18, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_EQUALS}, 99 {0x19, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_9}, 100 {0x1A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_7}, 101 {0x1B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_MINUS}, 102 {0x1C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_8}, 103 {0x1D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_0}, 104 {0x1E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_CLOSE_BRACKET}, 105 {0x1F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_O}, 106 {0x20, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_U}, 107 {0x21, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_OPEN_BRACKET}, 108 {0x22, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_I}, 109 {0x23, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_P}, 110 {0x24, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_ENTER}, 111 {0x25, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_L}, 112 {0x26, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_J}, 113 {0x27, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_QUOTE}, 114 {0x28, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_K}, 115 {0x29, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SEMICOLON}, 116 {0x2A, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH}, 117 {0x2B, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_COMMA}, 118 {0x2C, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SLASH}, 119 {0x2D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_N}, 120 {0x2E, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_M}, 121 {0x2F, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_PERIOD}, 122 {0x30, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_TAB}, 123 {0x31, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_SPACE}, 124 {0x32, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_QUOTE}, 125 {0x33, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SPACE}, 126 {0x34, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER}, 127 {0x35, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_ESCAPE}, 128 {0x36, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 129 {0x37, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_META}, // **** 130 {0x38, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_SHIFT}, // **** 131 {0x39, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_CAPS_LOCK}, 132 {0x3A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_ALT}, // **** 133 {0x3B, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_CONTROL}, // **** 134 {0x3C, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 135 {0x3D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 136 {0x3E, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 137 {0x3F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, // the 'fn' key on PowerBooks 138 {0x40, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 139 {0x41, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_DECIMAL}, 140 {0x42, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 141 {0x43, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_MULTIPLY}, 142 {0x44, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 143 {0x45, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ADD}, 144 {0x46, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 145 {0x47, NO, KL_NUMPAD, java_awt_event_KeyEvent_VK_CLEAR}, 146 {0x48, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 147 {0x49, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 148 {0x4A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 149 {0x4B, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_DIVIDE}, 150 {0x4C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER}, 151 {0x4D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 152 {0x4E, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_SUBTRACT}, 153 {0x4F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 154 {0x50, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 155 {0x51, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_EQUALS}, 156 {0x52, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD0}, 157 {0x53, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD1}, 158 {0x54, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD2}, 159 {0x55, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD3}, 160 {0x56, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD4}, 161 {0x57, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD5}, 162 {0x58, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD6}, 163 {0x59, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD7}, 164 {0x5A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 165 {0x5B, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD8}, 166 {0x5C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD9}, 167 {0x5D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH}, // This is a combo yen/backslash on JIS keyboards. 168 {0x5E, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_UNDERSCORE}, 169 {0x5F, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_COMMA}, 170 {0x60, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F5}, 171 {0x61, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F6}, 172 {0x62, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F7}, 173 {0x63, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F3}, 174 {0x64, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F8}, 175 {0x65, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F9}, 176 {0x66, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_ALPHANUMERIC}, 177 {0x67, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F11}, 178 {0x68, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_KATAKANA}, 179 {0x69, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F13}, 180 {0x6A, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F16}, 181 {0x6B, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F14}, 182 {0x6C, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 183 {0x6D, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F10}, 184 {0x6E, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 185 {0x6F, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F12}, 186 {0x70, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 187 {0x71, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F15}, 188 {0x72, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_HELP}, 189 {0x73, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_HOME}, 190 {0x74, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_PAGE_UP}, 191 {0x75, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_DELETE}, 192 {0x76, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F4}, 193 {0x77, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_END}, 194 {0x78, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F2}, 195 {0x79, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_PAGE_DOWN}, 196 {0x7A, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F1}, 197 {0x7B, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_LEFT}, 198 {0x7C, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_RIGHT}, 199 {0x7D, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_DOWN}, 200 {0x7E, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_UP}, 201 {0x7F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, 202 }; 203 204 /* 205 * This table was stolen from the Windows implementation for mapping 206 * Unicode values to VK codes for dead keys. On Windows, some layouts 207 * return ASCII punctuation for dead accents, while some return spacing 208 * accent chars, so both should be listed. However, in all of the 209 * keyboard layouts I tried only the Unicode values are used. 210 */ 211 struct CharToVKEntry { 212 UniChar c; 213 jint javaKey; 214 }; 215 static const struct CharToVKEntry charToDeadVKTable[] = { 216 {0x0060, java_awt_event_KeyEvent_VK_DEAD_GRAVE}, 217 {0x00B4, java_awt_event_KeyEvent_VK_DEAD_ACUTE}, 218 {0x0384, java_awt_event_KeyEvent_VK_DEAD_ACUTE}, // Unicode "GREEK TONOS" -- Greek keyboard, semicolon key 219 {0x005E, java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX}, 220 {0x007E, java_awt_event_KeyEvent_VK_DEAD_TILDE}, 221 {0x02DC, java_awt_event_KeyEvent_VK_DEAD_TILDE}, // Unicode "SMALL TILDE" 222 {0x00AF, java_awt_event_KeyEvent_VK_DEAD_MACRON}, 223 {0x02D8, java_awt_event_KeyEvent_VK_DEAD_BREVE}, 224 {0x02D9, java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT}, 225 {0x00A8, java_awt_event_KeyEvent_VK_DEAD_DIAERESIS}, 226 {0x02DA, java_awt_event_KeyEvent_VK_DEAD_ABOVERING}, 227 {0x02DD, java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE}, 228 {0x02C7, java_awt_event_KeyEvent_VK_DEAD_CARON}, 229 {0x00B8, java_awt_event_KeyEvent_VK_DEAD_CEDILLA}, 230 {0x02DB, java_awt_event_KeyEvent_VK_DEAD_OGONEK}, 231 {0x037A, java_awt_event_KeyEvent_VK_DEAD_IOTA}, 232 {0x309B, java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND}, 233 {0x309C, java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND}, 234 {0,0} 235 }; 236 237 // TODO: some constants below are part of CGS (private interfaces)... 238 // for now we will look at the raw key code to determine left/right status 239 // but not sure this is foolproof... 240 static struct _nsKeyToJavaModifier 241 { 242 NSUInteger nsMask; 243 //NSUInteger cgsLeftMask; 244 //NSUInteger cgsRightMask; 245 unsigned short leftKeyCode; 246 unsigned short rightKeyCode; 247 jint javaMask; 248 jint javaKey; 249 } 250 const nsKeyToJavaModifierTable[] = 251 { 252 { 253 NSAlphaShiftKeyMask, 254 0, 255 0, 256 0, // no Java equivalent 257 java_awt_event_KeyEvent_VK_CAPS_LOCK 258 }, 259 { 260 NSShiftKeyMask, 261 //kCGSFlagsMaskAppleShiftKey, 262 //kCGSFlagsMaskAppleRightShiftKey, 263 56, 264 60, 265 java_awt_event_InputEvent_SHIFT_DOWN_MASK, 266 java_awt_event_KeyEvent_VK_SHIFT 267 }, 268 { 269 NSControlKeyMask, 270 //kCGSFlagsMaskAppleControlKey, 271 //kCGSFlagsMaskAppleRightControlKey, 272 59, 273 62, 274 java_awt_event_InputEvent_CTRL_DOWN_MASK, 275 java_awt_event_KeyEvent_VK_CONTROL 276 }, 277 { 278 NSAlternateKeyMask, 279 //kCGSFlagsMaskAppleLeftAlternateKey, 280 //kCGSFlagsMaskAppleRightAlternateKey, 281 58, 282 61, 283 java_awt_event_InputEvent_ALT_DOWN_MASK, 284 java_awt_event_KeyEvent_VK_ALT 285 }, 286 { 287 NSCommandKeyMask, 288 //kCGSFlagsMaskAppleLeftCommandKey, 289 //kCGSFlagsMaskAppleRightCommandKey, 290 55, 291 54, 292 java_awt_event_InputEvent_META_DOWN_MASK, 293 java_awt_event_KeyEvent_VK_META 294 }, 295 // NSNumericPadKeyMask 296 { 297 NSHelpKeyMask, 298 0, 299 0, 300 0, // no Java equivalent 301 java_awt_event_KeyEvent_VK_HELP 302 }, 303 // NSFunctionKeyMask 304 {0, 0, 0, 0, 0} 305 }; 306 307 /* 308 * Almost all unicode characters just go from NS to Java with no translation. 309 * For the few exceptions, we handle it here with this small table. 310 */ 311 #define ALL_NS_KEY_MODIFIERS_MASK \ 312 (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask) 313 314 static struct _char { 315 NSUInteger modifier; 316 unichar nsChar; 317 unichar javaChar; 318 } 319 const charTable[] = { 320 // map enter on keypad to same as return key 321 {0, NSEnterCharacter, NSNewlineCharacter}, 322 323 // [3134616] return newline instead of carriage return 324 {0, NSCarriageReturnCharacter, NSNewlineCharacter}, 325 326 // "delete" means backspace in Java 327 {ALL_NS_KEY_MODIFIERS_MASK, NSDeleteCharacter, NSBackspaceCharacter}, 328 {ALL_NS_KEY_MODIFIERS_MASK, NSDeleteFunctionKey, NSDeleteCharacter}, 329 330 // back-tab is only differentiated from tab by Shift flag 331 {NSShiftKeyMask, NSBackTabCharacter, NSTabCharacter}, 332 333 {0, 0, 0} 334 }; 335 336 static unichar 337 NsCharToJavaChar(unichar nsChar, NSUInteger modifiers) 338 { 339 const struct _char *cur; 340 // Mask off just the keyboard modifiers from the event modifier mask. 341 NSUInteger testableFlags = (modifiers & ALL_NS_KEY_MODIFIERS_MASK); 342 343 // walk through table & find the match 344 for (cur = charTable; cur->nsChar != 0 ; cur++) { 345 // <rdar://Problem/3476426> Need to determine if we are looking at 346 // a plain keypress or a modified keypress. Don't adjust the 347 // character of a keypress with a modifier. 348 if (cur->nsChar == nsChar) { 349 if (cur->modifier == 0 && testableFlags == 0) { 350 // If the modifier field is 0, that means to transform 351 // this character if no additional keyboard modifiers are set. 352 // This lets ctrl-C be reported as ctrl-C and not transformed 353 // into Newline. 354 return cur->javaChar; 355 } else if (cur->modifier != 0 && 356 (testableFlags & cur->modifier) == testableFlags) 357 { 358 // Likewise, if the modifier field is nonzero, that means 359 // transform this character if only these modifiers are 360 // set in the testable flags. 361 return cur->javaChar; 362 } 363 } 364 } 365 366 if (nsChar >= NSUpArrowFunctionKey && nsChar <= NSModeSwitchFunctionKey) { 367 return java_awt_event_KeyEvent_CHAR_UNDEFINED; 368 } 369 370 // otherwise return character unchanged 371 return nsChar; 372 } 373 374 /* 375 * This is the function that uses the table above to take incoming 376 * NSEvent keyCodes and translate to the Java virtual key code. 377 */ 378 static void 379 NsCharToJavaVirtualKeyCode(unichar ch, unichar deadChar, 380 NSUInteger flags, unsigned short key, 381 jint *keyCode, jint *keyLocation, BOOL *postsTyped) 382 { 383 static size_t size = sizeof(keyTable) / sizeof(struct _key); 384 NSInteger offset; 385 386 if (deadChar) { 387 const struct CharToVKEntry *map; 388 for (map = charToDeadVKTable; map->c != 0; ++map) { 389 if (deadChar == map->c) { 390 *keyCode = map->javaKey; 391 *postsTyped = NO; 392 // TODO: use UNKNOWN here? 393 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; 394 return; 395 } 396 } 397 // If we got here, we keep looking for a normal key. 398 } 399 400 if ([[NSCharacterSet letterCharacterSet] characterIsMember:ch]) { 401 // key is an alphabetic character 402 unichar lower; 403 lower = tolower(ch); 404 offset = lower - 'a'; 405 if (offset >= 0 && offset <= 25) { 406 // some chars in letter set are NOT actually A-Z characters?! 407 // skip them... 408 *postsTyped = YES; 409 // do quick conversion 410 *keyCode = java_awt_event_KeyEvent_VK_A + offset; 411 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD; 412 return; 413 } 414 } 415 416 if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:ch]) { 417 // key is a digit 418 offset = ch - '0'; 419 // make sure in range for decimal digits 420 if (offset >= 0 && offset <= 9) { 421 jboolean numpad = (flags & NSNumericPadKeyMask) != 0; 422 *postsTyped = YES; 423 if (numpad) { 424 *keyCode = offset + java_awt_event_KeyEvent_VK_NUMPAD0; 425 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD; 426 } else { 427 *keyCode = offset + java_awt_event_KeyEvent_VK_0; 428 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD; 429 } 430 return; 431 } 432 } 433 434 if (key < size) { 435 *postsTyped = keyTable[key].postsTyped; 436 *keyCode = keyTable[key].javaKeyCode; 437 *keyLocation = keyTable[key].javaKeyLocation; 438 } else { 439 // Should we report this? This means we've got a keyboard 440 // we don't know about... 441 *postsTyped = NO; 442 *keyCode = java_awt_event_KeyEvent_VK_UNDEFINED; 443 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; 444 } 445 } 446 447 /* 448 * This returns the java key data for the key NSEvent modifiers 449 * (after NSFlagChanged). 450 */ 451 static void 452 NsKeyModifiersToJavaKeyInfo(NSUInteger nsFlags, unsigned short eventKeyCode, 453 jint *javaKeyCode, 454 jint *javaKeyLocation, 455 jint *javaKeyType) 456 { 457 static NSUInteger sPreviousNSFlags = 0; 458 459 const struct _nsKeyToJavaModifier* cur; 460 NSUInteger oldNSFlags = sPreviousNSFlags; 461 NSUInteger changedNSFlags = oldNSFlags ^ nsFlags; 462 sPreviousNSFlags = nsFlags; 463 464 *javaKeyCode = java_awt_event_KeyEvent_VK_UNDEFINED; 465 *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; 466 *javaKeyType = java_awt_event_KeyEvent_KEY_PRESSED; 467 468 for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) { 469 if (changedNSFlags & cur->nsMask) { 470 *javaKeyCode = cur->javaKey; 471 *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD; 472 // TODO: uses SPI... 473 //if (changedNSFlags & cur->cgsLeftMask) { 474 // *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT; 475 //} else if (changedNSFlags & cur->cgsRightMask) { 476 // *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; 477 //} 478 if (eventKeyCode == cur->leftKeyCode) { 479 *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT; 480 } else if (eventKeyCode == cur->rightKeyCode) { 481 *javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; 482 } 483 *javaKeyType = (cur->nsMask & nsFlags) ? 484 java_awt_event_KeyEvent_KEY_PRESSED : 485 java_awt_event_KeyEvent_KEY_RELEASED; 486 break; 487 } 488 } 489 } 490 491 /* 492 * This returns the java modifiers for a key NSEvent. 493 */ 494 static jint 495 NsKeyModifiersToJavaModifiers(NSUInteger nsFlags) 496 { 497 jint javaModifiers = 0; 498 const struct _nsKeyToJavaModifier* cur; 499 500 for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) { 501 if ((cur->nsMask & nsFlags) != 0) { 502 javaModifiers |= cur->javaMask; 503 } 504 } 505 506 return javaModifiers; 507 } 508 509 /* 510 * Returns the correct java character for a key event. Most unicode 511 * characters don't require any fussing, but a few seem to need adjusting, 512 * see nsCharToJavaChar. 513 */ 514 static unichar 515 GetJavaCharacter(NSEvent *event, unsigned int index) 516 { 517 unichar returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED; 518 NSString *chars = nil; 519 unichar testChar = 0, testDeadChar = 0; 520 jint javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags]); 521 522 switch ([event type]) { 523 case NSFlagsChanged: 524 // no character for modifier keys 525 returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED; 526 break; 527 528 case NSKeyDown: 529 case NSKeyUp: 530 chars = [event characters]; 531 if ([chars length] > 0) { 532 testChar = [chars characterAtIndex:index]; 533 } 534 535 if (javaModifiers == 0) { 536 // TODO: uses SPI... 537 //if (TSMGetDeadKeyState() != 0) { 538 // testDeadChar = [self deadKeyCharacter]; 539 //} 540 } 541 542 if (testChar != 0) { 543 returnValue = NsCharToJavaChar(testChar, [event modifierFlags]); 544 } else if (testDeadChar != 0) { 545 returnValue = NsCharToJavaChar(testDeadChar, [event modifierFlags]); 546 } else { 547 returnValue = java_awt_event_KeyEvent_CHAR_UNDEFINED; 548 } 549 break; 550 551 default: 552 //[NSException raise:@"AWT error" format:@"Attempt to get character code from non-key event!"]; 553 break; 554 } 555 556 return returnValue; 557 } 558 559 /* 560 static jchar 561 GetDeadKeyCharacter(NSEvent *event) 562 { 563 // If the current event is not a dead key, return 0. 564 // TODO: this uses SPI; it's an optimization but not strictly necessary 565 //if (TSMGetDeadKeyState() == 0) { 566 // return 0; 567 //} 568 569 // AppKit does not track dead-key states directly, but TSM does. Even then, 570 // it's not necessarily all that accurate, because the dead key can change 571 // given some combination of modifier keys on certain layouts. 572 // As a result, finding the unicode value for the front end of the dead 573 // key is a bit of a heuristic. 574 575 // This algorithm was suggested by Aki Inoue. 576 // When you get a dead key, you need to simiulate what would happen in 577 // the current dead-key and modifier state if the user hit the spacebar. 578 // That will tell you the front end of the dead-key combination. 579 580 unichar returnValue = 0; 581 const UInt16 VIRTUAL_KEY_SPACE = 49; 582 UInt32 deadKeyState = 0; 583 UInt32 appkitFlags = [event modifierFlags]; 584 UniCharCount actualStringLength; 585 UniChar unicodeInputString[16]; 586 TISInputSourceRef keyLayout; 587 const void *chrData; 588 589 keyLayout = TISCopyCurrentKeyboardLayoutInputSource(); 590 CFDataRef cfUchrData = 591 TISGetInputSourceProperty(keyLayout, kTISPropertyUnicodeKeyLayoutData); 592 593 if (cfUchrData == NULL) { 594 return returnValue; 595 } 596 597 // The actual 'uchr' table is inside the CFDataRef. 598 chrData = CFDataGetBytePtr(cfUchrData); 599 600 UInt8 keyboardType = LMGetKbdType(); 601 UInt32 keyEventModifiers = 0; 602 if (appkitFlags & NSShiftKeyMask) keyEventModifiers |= shiftKey; 603 if (appkitFlags & NSCommandKeyMask) keyEventModifiers |= cmdKey; 604 if (appkitFlags & NSAlphaShiftKeyMask) keyEventModifiers |= alphaLock; 605 if (appkitFlags & NSControlKeyMask) keyEventModifiers |= controlKey; 606 if (appkitFlags & NSAlternateKeyMask) keyEventModifiers |= optionKey; 607 608 if (noErr == UCKeyTranslate(chrData, 609 VIRTUAL_KEY_SPACE, 610 ([event type] == NSKeyDown ? kUCKeyActionDown : kUCKeyActionUp), 611 keyEventModifiers, 612 keyboardType, 613 kUCKeyTranslateNoDeadKeysMask, 614 &deadKeyState, 615 16, 616 &actualStringLength, 617 unicodeInputString)) 618 { 619 if (actualStringLength > 0) { 620 returnValue = unicodeInputString[0]; 621 } 622 } 623 624 return returnValue; 625 } 626 */ 627 628 629 // REMIND: The fix for MACOSX_PORT-539 introduces Java-level implementation 630 // of the function below (see CPlatformResponder). Consider removing this code. 631 632 void 633 DeliverJavaKeyEvent(JNIEnv *env, NSEvent *event, jobject peer) 634 { 635 jint javaKeyType = java_awt_event_KeyEvent_KEY_PRESSED; 636 jint javaKeyCode = java_awt_event_KeyEvent_VK_UNDEFINED; 637 jint javaKeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; 638 NSString *chars = nil; 639 BOOL postsTyped; 640 unichar testChar = java_awt_event_KeyEvent_CHAR_UNDEFINED; 641 unichar testDeadChar = 0; 642 jint javaModifiers = 0; 643 644 switch ([event type]) { 645 case NSFlagsChanged: 646 NsKeyModifiersToJavaKeyInfo([event modifierFlags], 647 [event keyCode], 648 &javaKeyCode, 649 &javaKeyLocation, 650 &javaKeyType); 651 break; 652 653 case NSKeyDown: 654 case NSKeyUp: 655 chars = [event charactersIgnoringModifiers]; 656 if ([chars length] > 0) { 657 testChar = [chars characterAtIndex:0]; 658 } 659 660 javaModifiers = NsKeyModifiersToJavaModifiers([event modifierFlags]); 661 if (javaModifiers == 0) { 662 // TODO: dead key chars 663 // testDeadChar = GetDeadKeyCharacter(event); 664 } 665 666 NsCharToJavaVirtualKeyCode(testChar, testDeadChar, 667 [event modifierFlags], [event keyCode], 668 &javaKeyCode, &javaKeyLocation, &postsTyped); 669 if( !postsTyped ) { 670 testChar = java_awt_event_KeyEvent_CHAR_UNDEFINED; 671 } 672 673 javaKeyType = ([event type] == NSKeyDown) ? 674 java_awt_event_KeyEvent_KEY_PRESSED : 675 java_awt_event_KeyEvent_KEY_RELEASED; 676 break; 677 678 default: 679 //[NSException raise:@"AWT error" format:@"Attempt to get virtual key code from non-key event!"]; 680 break; 681 } 682 683 if (env != NULL) { 684 static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView"); 685 static JNF_MEMBER_CACHE(jm_deliverKeyEvent, jc_CPlatformView, "deliverKeyEvent", "(IICII)V"); 686 JNFCallVoidMethod(env, peer, jm_deliverKeyEvent, 687 javaKeyType, javaModifiers, 688 testChar, javaKeyCode, javaKeyLocation); 689 } 690 } 691 692 jint GetJavaMouseModifiers(NSInteger button, NSUInteger modifierFlags) 693 { 694 // Mousing needs the key modifiers 695 jint modifiers = NsKeyModifiersToJavaModifiers(modifierFlags); 696 697 698 /* 699 * Ask Quartz about mouse buttons state 700 */ 701 702 if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState, 703 kCGMouseButtonLeft)) { 704 modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK; 705 } 706 707 if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState, 708 kCGMouseButtonRight)) { 709 modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK; 710 } 711 712 if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState, 713 kCGMouseButtonCenter)) { 714 modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK; 715 } 716 717 NSInteger extraButton = 3; 718 for (; extraButton < gNumberOfButtons; extraButton++) { 719 if (CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState, 720 extraButton)) { 721 modifiers |= gButtonDownMasks[extraButton]; 722 } 723 } 724 725 return modifiers; 726 } 727 728 /* 729 * Converts an NSEvent button number to a MouseEvent constant. 730 */ 731 static jint 732 NSButtonToJavaButton(NSInteger nsButtonNumber) 733 { 734 jint jbutton = java_awt_event_MouseEvent_NOBUTTON; 735 736 if (nsButtonNumber == 0) { // left 737 jbutton = java_awt_event_MouseEvent_BUTTON1; 738 } else if (nsButtonNumber == 1) { // right 739 jbutton = java_awt_event_MouseEvent_BUTTON3; 740 } else if (nsButtonNumber == 2) { // middle 741 jbutton = java_awt_event_MouseEvent_BUTTON2; 742 } 743 744 return jbutton; 745 } 746 747 748 static BOOL isDragging = NO; 749 750 void 751 DeliverMouseClickedEvent(JNIEnv *env, NSEvent *event, jobject peer) 752 { 753 NSPoint pt = [event locationInWindow]; 754 NSPoint pOnScreen = [NSEvent mouseLocation]; 755 jint etype = java_awt_event_MouseEvent_MOUSE_CLICKED; 756 jint modifiers = GetJavaMouseModifiers([event buttonNumber], [event modifierFlags]); 757 jint clickCount = [event clickCount]; 758 jint button = NSButtonToJavaButton([event buttonNumber]); 759 760 if (env != NULL) { 761 static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView"); 762 static JNF_MEMBER_CACHE(jm_deliverMouseEvent, jc_CPlatformView, 763 "deliverMouseEvent", "(IIIIFFFF)V"); 764 JNFCallVoidMethod(env, peer, jm_deliverMouseEvent, 765 etype, modifiers, 766 clickCount, button, 767 pt.x, pt.y, 768 pOnScreen.x, pOnScreen.y); 769 } 770 } 771 772 /* 773 * After every key down event, this is called to make the matching 774 * KEY_TYPED (if this key posts those). We use the same NSEvent for it, 775 * but create a KEY_TYPED java event this time. 776 * If this key doesn't post typed, we don't post the event. 777 * 778 * TODO: some duplicated effort here; could just fold it 779 * into DeliverJavaKeyEvent... 780 */ 781 static void 782 DeliverKeyTypedEvents(JNIEnv *env, NSEvent *nsEvent, jobject peer) 783 { 784 if (peer == NULL) { 785 return; 786 } 787 788 jint javaKeyCode, javaKeyLocation; 789 BOOL postsTyped = NO; 790 unichar testChar, testDeadChar = 0; 791 jint javaModifiers = NsKeyModifiersToJavaModifiers([nsEvent modifierFlags]); 792 793 if (javaModifiers == 0) { 794 testDeadChar = [nsEvent deadKeyCharacter]; 795 } 796 797 NSString *theChars = [nsEvent characters]; 798 unsigned i, stringLength = [theChars length]; 799 800 for (i = 0; i < stringLength; i++) { 801 testChar = [theChars characterAtIndex:i]; 802 NsCharToJavaVirtualKeyCode(testChar, testDeadChar, 803 [nsEvent modifierFlags], [nsEvent keyCode], 804 &javaKeyCode, &javaKeyLocation, &postsTyped); 805 806 if (postsTyped) { 807 // Some keys may generate a KEY_TYPED, but we can't determine 808 // what that character is. That's likely a bug, but for now we 809 // just check for CHAR_UNDEFINED. 810 unichar theChar = GetJavaCharacter(nsEvent, i); 811 if (theChar != java_awt_event_KeyEvent_CHAR_UNDEFINED) { 812 if (env != NULL) { 813 static JNF_CLASS_CACHE(jc_CPlatformView, 814 "sun/lwawt/macosx/CPlatformView"); 815 static JNF_MEMBER_CACHE(jm_deliverKeyEvent, jc_CPlatformView, 816 "deliverKeyEvent", "(IICII)V"); 817 JNFCallVoidMethod(env, peer, jm_deliverKeyEvent, 818 java_awt_event_KeyEvent_KEY_TYPED, 819 javaModifiers, 820 theChar, 821 java_awt_event_KeyEvent_VK_UNDEFINED, 822 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN); 823 } 824 } 825 } 826 } 827 } 828 829 /* 830 * There are a couple of extra events that Java expects to get that don't 831 * actually correspond to a direct NSEvent, KEY_TYPED and MOUSE_CLICKED are 832 * both extra events that are sort of redundant with ordinary 833 * key downs and mouse ups. In this extra message, we take the original 834 * input event and if necessary, cons up a special follow-on event which 835 * we dispatch over to Java. 836 * 837 * For Java, keyDown's generate a KeyPressed (for each hardware key as it 838 * goes down) and then a "logical KeyTyped" event for the key event. (So 839 * a shift-a generates two presses, one keytyped of "A", and then two 840 * releases). The standard event utility function converts a key down to 841 * a key pressed. When appropriate, we need to cons up another event 842 * (KEY_TYPED) to follow a keyDown. 843 * 844 * Java expects you to send a clicked event if you got a down & up, with no 845 * intervening drag. So in addition to the MOUSE_RELEASED event that a 846 * mouseUp is translated to, we also have to cons up a MOUSE_CLICKED event 847 * for that case. Mike Paquette, god of Window Server event handling, 848 * confirmed this fact about how to determine if a mouse up event had an 849 * intervening drag: 850 * An initial mouse-down gets a click count of 1. Subsequent left or right 851 * mouse-downs within the space/time tolerance limits increment the click 852 * count. A mouse-up will have the clickCount of the last mouseDown if 853 * mouse is not outside the tolerance limits, but 0 otherwise. Thus, a 854 * down-up sequence without any intervening drag will have a click count 855 * of 0 in the mouse-up event. NOTE: The problem with this is that 856 * clickCount goes to zero after some point in time. So a long, click & 857 * hold without moving and then release the mouse doesn't create a 858 * MOUSE_CLICK event as it should. Java AWT now tracks the drag state itself. 859 * 860 * As another add-on, we also check for the status of mouse-motion events 861 * after a mouse-down, so we know whether to generate mouse-dragged events 862 * during this down sequence. 863 */ 864 void 865 SendAdditionalJavaEvents(JNIEnv *env, NSEvent *nsEvent, jobject peer) 866 { 867 AWT_ASSERT_APPKIT_THREAD; 868 869 NSEventType type = [nsEvent type]; 870 switch (type) { 871 case NSKeyDown: 872 break; 873 874 case NSLeftMouseUp: 875 case NSRightMouseUp: 876 case NSOtherMouseUp: 877 // TODO: we may need to pull in changedDragToMove here... 878 //if (!isDragging && ([NSViewAWT changedDragToMove]==NO)) { 879 if (!isDragging) { 880 // got down/up pair with no dragged in between; ignores drag events 881 // that have been morphed to move events 882 DeliverMouseClickedEvent(env, nsEvent, peer); 883 } 884 break; 885 886 // TODO: to be implemented... 887 #if 0 888 case NSLeftMouseDragged: 889 case NSRightMouseDragged: 890 case NSOtherMouseDragged: 891 // 892 // During a drag, the AppKit does not send mouseEnter and mouseExit 893 // events. It turns out that doing a hitTest causes the window's 894 // view hierarchy to be locked from drawing and that, of course, 895 // slows everything way down. Synthesize mouseEnter and mouseExit 896 // then forward. 897 // 898 NSView *hitView = [[source model] hitTest:[nsEvent locationInWindow]]; 899 900 if ((hitView != nil) && 901 ([hitView conformsToProtocol:@protocol(AWTPeerControl)])) 902 { 903 if (sLastMouseDraggedView == nil) { 904 sLastMouseDraggedView = hitView; 905 } 906 else if (hitView != sLastMouseDraggedView) { 907 // We know sLastMouseDraggedView is a AWTPeerControl. 908 jobject lastPeer = 909 [(id <AWTPeerControl>)sLastMouseDraggedView peer]; 910 911 // Send mouseExit to sLastMouseDraggedView 912 jobject exitEvent = 913 makeMouseEvent(env, nsEvent, lastPeer, 914 sLastMouseDraggedView, 915 java_awt_event_MouseEvent_MOUSE_EXITED); 916 pushEventForward(exitEvent, env); 917 (*env)->DeleteLocalRef(env, exitEvent); 918 919 // Send mouseEnter to hitView 920 jobject enterEvent = 921 makeMouseEvent(env, nsEvent, peer, hitView, 922 java_awt_event_MouseEvent_MOUSE_ENTERED); 923 pushEventForward(enterEvent, env); 924 925 (*env)->DeleteLocalRef(env, enterEvent); 926 927 // Set sLastMouseDraggedView = hitView 928 sLastMouseDraggedView = hitView; 929 } 930 } 931 break; 932 #endif 933 934 default: 935 break; 936 } 937 } 938 939 jlong UTC(NSEvent *event) { 940 struct timeval tv; 941 if (gettimeofday(&tv, NULL) == 0) { 942 long long sec = (long long)tv.tv_sec; 943 return (sec*1000) + (tv.tv_usec/1000); 944 } 945 return 0; 946 } 947 948 JNIEXPORT void JNICALL 949 Java_java_awt_AWTEvent_nativeSetSource 950 (JNIEnv *env, jobject self, jobject newSource) 951 { 952 } 953 954 /* 955 * Class: sun_lwawt_macosx_event_NSEvent 956 * Method: nsToJavaMouseModifiers 957 * Signature: (II)I 958 */ 959 JNIEXPORT jint JNICALL 960 Java_sun_lwawt_macosx_event_NSEvent_nsToJavaMouseModifiers 961 (JNIEnv *env, jclass cls, jint buttonNumber, jint modifierFlags) 962 { 963 jint jmodifiers = 0; 964 965 JNF_COCOA_ENTER(env); 966 967 jmodifiers = GetJavaMouseModifiers(buttonNumber, modifierFlags); 968 969 JNF_COCOA_EXIT(env); 970 971 return jmodifiers; 972 } 973 974 /* 975 * Class: sun_lwawt_macosx_event_NSEvent 976 * Method: nsToJavaKeyModifiers 977 * Signature: (I)I 978 */ 979 JNIEXPORT jint JNICALL 980 Java_sun_lwawt_macosx_event_NSEvent_nsToJavaKeyModifiers 981 (JNIEnv *env, jclass cls, jint modifierFlags) 982 { 983 jint jmodifiers = 0; 984 985 JNF_COCOA_ENTER(env); 986 987 jmodifiers = NsKeyModifiersToJavaModifiers(modifierFlags); 988 989 JNF_COCOA_EXIT(env); 990 991 return jmodifiers; 992 } 993 994 /* 995 * Class: sun_lwawt_macosx_event_NSEvent 996 * Method: nsToJavaKeyInfo 997 * Signature: ([I[I)Z 998 */ 999 JNIEXPORT jboolean JNICALL 1000 Java_sun_lwawt_macosx_event_NSEvent_nsToJavaKeyInfo 1001 (JNIEnv *env, jclass cls, jintArray inData, jintArray outData) 1002 { 1003 BOOL postsTyped = NO; 1004 1005 JNF_COCOA_ENTER(env); 1006 1007 jboolean copy = JNI_FALSE; 1008 jint *data = (*env)->GetIntArrayElements(env, inData, ©); 1009 1010 // in = [testChar, testDeadChar, modifierFlags, keyCode] 1011 jchar testChar = (jchar)data[0]; 1012 jchar testDeadChar = (jchar)data[1]; 1013 jint modifierFlags = data[2]; 1014 jshort keyCode = (jshort)data[3]; 1015 1016 jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED; 1017 jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; 1018 1019 NsCharToJavaVirtualKeyCode((unichar)testChar, (unichar)testDeadChar, 1020 (NSUInteger)modifierFlags, (unsigned short)keyCode, 1021 &jkeyCode, &jkeyLocation, &postsTyped); 1022 1023 // out = [jkeyCode, jkeyLocation]; 1024 (*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode); 1025 (*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation); 1026 1027 (*env)->ReleaseIntArrayElements(env, inData, data, 0); 1028 1029 JNF_COCOA_EXIT(env); 1030 1031 return postsTyped; 1032 } 1033 1034 /* 1035 * Class: sun_lwawt_macosx_event_NSEvent 1036 * Method: nsKeyModifiersToJavaKeyInfo 1037 * Signature: ([I[I)V 1038 */ 1039 JNIEXPORT void JNICALL 1040 Java_sun_lwawt_macosx_event_NSEvent_nsKeyModifiersToJavaKeyInfo 1041 (JNIEnv *env, jclass cls, jintArray inData, jintArray outData) 1042 { 1043 JNF_COCOA_ENTER(env); 1044 1045 jboolean copy = JNI_FALSE; 1046 jint *data = (*env)->GetIntArrayElements(env, inData, ©); 1047 1048 // in = [modifierFlags, keyCode] 1049 jint modifierFlags = data[0]; 1050 jshort keyCode = (jshort)data[1]; 1051 1052 jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED; 1053 jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; 1054 jint jkeyType = java_awt_event_KeyEvent_KEY_PRESSED; 1055 1056 NsKeyModifiersToJavaKeyInfo(modifierFlags, 1057 keyCode, 1058 &jkeyCode, 1059 &jkeyLocation, 1060 &jkeyType); 1061 1062 // out = [jkeyCode, jkeyLocation, jkeyType]; 1063 (*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode); 1064 (*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation); 1065 (*env)->SetIntArrayRegion(env, outData, 2, 1, &jkeyType); 1066 1067 (*env)->ReleaseIntArrayElements(env, inData, data, 0); 1068 1069 JNF_COCOA_EXIT(env); 1070 } 1071 1072 /* 1073 * Class: sun_lwawt_macosx_event_NSEvent 1074 * Method: nsToJavaChar 1075 * Signature: (CI)C 1076 */ 1077 JNIEXPORT jint JNICALL 1078 Java_sun_lwawt_macosx_event_NSEvent_nsToJavaChar 1079 (JNIEnv *env, jclass cls, char nsChar, jint modifierFlags) 1080 { 1081 jchar javaChar = 0; 1082 1083 JNF_COCOA_ENTER(env); 1084 1085 javaChar = NsCharToJavaChar(nsChar, modifierFlags); 1086 1087 JNF_COCOA_EXIT(env); 1088 1089 return javaChar; 1090 }