src/macosx/native/sun/awt/AWTEvent.m

Print this page




   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


 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         }


 598 }
 599 
 600 /*
 601  * Class:     sun_lwawt_macosx_event_NSEvent
 602  * Method:    nsToJavaKeyInfo
 603  * Signature: ([I[I)Z
 604  */
 605 JNIEXPORT jboolean JNICALL
 606 Java_sun_lwawt_macosx_event_NSEvent_nsToJavaKeyInfo
 607 (JNIEnv *env, jclass cls, jintArray inData, jintArray outData)
 608 {
 609     BOOL postsTyped = NO;
 610 
 611 JNF_COCOA_ENTER(env);
 612 
 613     jboolean copy = JNI_FALSE;
 614     jint *data = (*env)->GetIntArrayElements(env, inData, &copy);
 615 
 616     // in  = [testChar, testDeadChar, modifierFlags, keyCode]
 617     jchar testChar = (jchar)data[0];
 618     jchar testDeadChar = (jchar)data[1];
 619     jint modifierFlags = data[2];
 620     jshort keyCode = (jshort)data[3];
 621 
 622     jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
 623     jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;

 624 
 625     NsCharToJavaVirtualKeyCode((unichar)testChar, (unichar)testDeadChar,
 626                                (NSUInteger)modifierFlags, (unsigned short)keyCode,
 627                                &jkeyCode, &jkeyLocation, &postsTyped);
 628 
 629     // out = [jkeyCode, jkeyLocation];
 630     (*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode);
 631     (*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation);

 632 
 633     (*env)->ReleaseIntArrayElements(env, inData, data, 0);
 634 
 635 JNF_COCOA_EXIT(env);
 636 
 637     return postsTyped;
 638 }
 639 
 640 /*
 641  * Class:     sun_lwawt_macosx_event_NSEvent
 642  * Method:    nsKeyModifiersToJavaKeyInfo
 643  * Signature: ([I[I)V
 644  */
 645 JNIEXPORT void JNICALL
 646 Java_sun_lwawt_macosx_event_NSEvent_nsKeyModifiersToJavaKeyInfo
 647 (JNIEnv *env, jclass cls, jintArray inData, jintArray outData)
 648 {
 649 JNF_COCOA_ENTER(env);
 650 
 651     jboolean copy = JNI_FALSE;




   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 #include <Carbon/Carbon.h>
  30 
  31 #import "LWCToolkit.h"
  32 #import "ThreadUtilities.h"
  33 
  34 #import "java_awt_event_InputEvent.h"
  35 #import "java_awt_event_KeyEvent.h"
  36 #import "java_awt_event_MouseEvent.h"
  37 
  38 /*
  39  * Table to map typed characters to their Java virtual key equivalent and back.
  40  * We use the incoming unichar (ignoring all modifiers) and try to figure out
  41  * which virtual key code is appropriate. A lot of them just have direct
  42  * mappings (the function keys, arrow keys, etc.) so they aren't a problem.
  43  * We had to do something a little funky to catch the keys on the numeric
  44  * key pad (i.e. using event mask to distinguish between period on regular
  45  * keyboard and decimal on keypad). We also have to do something incredibly
  46  * hokey with regards to the shifted punctuation characters. For examples,
  47  * consider '&' which is usually Shift-7.  For the Java key typed events,
  48  * that's no problem, we just say pass the unichar. But for the
  49  * KeyPressed/Released events, we need to identify the virtual key code


 355                 return cur->javaChar;
 356             } else if (cur->modifier != 0 &&
 357                        (testableFlags & cur->modifier) == testableFlags)
 358             {
 359                 // Likewise, if the modifier field is nonzero, that means
 360                 // transform this character if only these modifiers are
 361                 // set in the testable flags.
 362                 return cur->javaChar;
 363             }
 364         }
 365     }
 366 
 367     if (nsChar >= NSUpArrowFunctionKey && nsChar <= NSModeSwitchFunctionKey) {
 368         return java_awt_event_KeyEvent_CHAR_UNDEFINED;
 369     }
 370 
 371     // otherwise return character unchanged
 372     return nsChar;
 373 }
 374 
 375 static unichar NsGetDeadKeyChar(unsigned short keyCode)
 376 {    
 377     TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
 378     CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
 379     const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
 380     // Carbon modifiers should be used instead of NSEvent modifiers    
 381     UInt32 modifierKeyState = (GetCurrentEventKeyModifiers() >> 8) & 0xFF;
 382     
 383     if (keyboardLayout) {
 384         UInt32 deadKeyState = 0;
 385         UniCharCount maxStringLength = 255;
 386         UniCharCount actualStringLength = 0;
 387         UniChar unicodeString[maxStringLength];
 388         
 389         // get the deadKeyState
 390         OSStatus status = UCKeyTranslate(keyboardLayout,
 391                                          keyCode, kUCKeyActionDown, modifierKeyState,
 392                                          LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit,
 393                                          &deadKeyState,
 394                                          maxStringLength,
 395                                          &actualStringLength, unicodeString);
 396         
 397         if (status == noErr && deadKeyState != 0) {
 398             // Press SPACE to get the dead key char
 399             status = UCKeyTranslate(keyboardLayout,
 400                                     kVK_Space, kUCKeyActionDown, 0,
 401                                     LMGetKbdType(), 0,
 402                                     &deadKeyState,
 403                                     maxStringLength,
 404                                     &actualStringLength, unicodeString);
 405             
 406             if (status == noErr && actualStringLength > 0) {
 407                 return unicodeString[0];
 408             }
 409         }
 410     }
 411     return 0;
 412 }
 413 
 414 /*
 415  * This is the function that uses the table above to take incoming
 416  * NSEvent keyCodes and translate to the Java virtual key code.
 417  */
 418 static void
 419 NsCharToJavaVirtualKeyCode(unichar ch, BOOL isDeadChar,
 420                            NSUInteger flags, unsigned short key,
 421                            jint *keyCode, jint *keyLocation, BOOL *postsTyped, unichar *deadChar)
 422 {
 423     static size_t size = sizeof(keyTable) / sizeof(struct _key);
 424     NSInteger offset;
 425 
 426     if (isDeadChar) {
 427         unichar testDeadChar = NsGetDeadKeyChar(key);
 428         const struct CharToVKEntry *map;
 429         for (map = charToDeadVKTable; map->c != 0; ++map) {
 430             if (testDeadChar == map->c) {
 431                 *keyCode = map->javaKey;
 432                 *postsTyped = NO;
 433                 // TODO: use UNKNOWN here?
 434                 *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
 435                 *deadChar = testDeadChar;
 436                 return;
 437             }
 438         }
 439         // If we got here, we keep looking for a normal key.
 440     }
 441 
 442     if ([[NSCharacterSet letterCharacterSet] characterIsMember:ch]) {
 443         // key is an alphabetic character
 444         unichar lower;
 445         lower = tolower(ch);
 446         offset = lower - 'a';
 447         if (offset >= 0 && offset <= 25) {
 448             // some chars in letter set are NOT actually A-Z characters?!
 449             // skip them...
 450             *postsTyped = YES;
 451             // do quick conversion
 452             *keyCode = java_awt_event_KeyEvent_VK_A + offset;
 453             *keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
 454             return;
 455         }


 640 }
 641 
 642 /*
 643  * Class:     sun_lwawt_macosx_event_NSEvent
 644  * Method:    nsToJavaKeyInfo
 645  * Signature: ([I[I)Z
 646  */
 647 JNIEXPORT jboolean JNICALL
 648 Java_sun_lwawt_macosx_event_NSEvent_nsToJavaKeyInfo
 649 (JNIEnv *env, jclass cls, jintArray inData, jintArray outData)
 650 {
 651     BOOL postsTyped = NO;
 652 
 653 JNF_COCOA_ENTER(env);
 654 
 655     jboolean copy = JNI_FALSE;
 656     jint *data = (*env)->GetIntArrayElements(env, inData, &copy);
 657 
 658     // in  = [testChar, testDeadChar, modifierFlags, keyCode]
 659     jchar testChar = (jchar)data[0];
 660     BOOL isDeadChar = (data[1] != 0);
 661     jint modifierFlags = data[2];
 662     jshort keyCode = (jshort)data[3];
 663 
 664     jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
 665     jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
 666     jchar testDeadChar = 0;
 667 
 668     NsCharToJavaVirtualKeyCode((unichar)testChar, isDeadChar,
 669                                (NSUInteger)modifierFlags, (unsigned short)keyCode,
 670                                &jkeyCode, &jkeyLocation, &postsTyped, &testDeadChar);
 671 
 672     // out = [jkeyCode, jkeyLocation];
 673     (*env)->SetIntArrayRegion(env, outData, 0, 1, &jkeyCode);
 674     (*env)->SetIntArrayRegion(env, outData, 1, 1, &jkeyLocation);
 675     (*env)->SetIntArrayRegion(env, outData, 2, 1, (jint *)&testDeadChar);
 676 
 677     (*env)->ReleaseIntArrayElements(env, inData, data, 0);
 678 
 679 JNF_COCOA_EXIT(env);
 680 
 681     return postsTyped;
 682 }
 683 
 684 /*
 685  * Class:     sun_lwawt_macosx_event_NSEvent
 686  * Method:    nsKeyModifiersToJavaKeyInfo
 687  * Signature: ([I[I)V
 688  */
 689 JNIEXPORT void JNICALL
 690 Java_sun_lwawt_macosx_event_NSEvent_nsKeyModifiersToJavaKeyInfo
 691 (JNIEnv *env, jclass cls, jintArray inData, jintArray outData)
 692 {
 693 JNF_COCOA_ENTER(env);
 694 
 695     jboolean copy = JNI_FALSE;