diff options
Diffstat (limited to 'src/newt/native/NewtMacWindow.m')
-rw-r--r-- | src/newt/native/NewtMacWindow.m | 158 |
1 files changed, 100 insertions, 58 deletions
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index d7b357349..005e82d72 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -36,6 +36,9 @@ #import "KeyEvent.h" #import "MouseEvent.h" +#include <CoreFoundation/CoreFoundation.h> +#include <Carbon/Carbon.h> /* For kVK_ constants, and TIS functions. */ + #include <math.h> static jfloat GetDelta(NSEvent *event, jint javaMods[]) { @@ -82,9 +85,7 @@ static jfloat GetDelta(NSEvent *event, jint javaMods[]) { } static jmethodID enqueueMouseEventID = NULL; -static jmethodID sendMouseEventID = NULL; static jmethodID enqueueKeyEventID = NULL; -static jmethodID sendKeyEventID = NULL; static jmethodID requestFocusID = NULL; static jmethodID insetsChangedID = NULL; @@ -95,13 +96,11 @@ static jmethodID focusChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; static jmethodID windowRepaintID = NULL; -// Can't use USE_SENDIO_DIRECT, ie w/o enqueueing to EDT, +// Need to enqueue all events to EDT, // since we may operate on AWT-AppKit (Main Thread) // and direct issuing 'requestFocus()' would deadlock: // AWT-AppKit // AWT-EventQueue-0 -// -// #define USE_SENDIO_DIRECT 1 @implementation NewtView @@ -286,7 +285,7 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("drawRect: null JNIEnv\n"); return; @@ -298,9 +297,9 @@ static jmethodID windowRepaintID = NULL; dirtyRect.origin.x, viewFrame.size.height - dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height); - if (shallBeDetached) { + /* if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + } */ } - (void) viewDidHide @@ -310,7 +309,7 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("viewDidHide: null JNIEnv\n"); return; @@ -318,9 +317,9 @@ static jmethodID windowRepaintID = NULL; (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_FALSE); - if (shallBeDetached) { + /* if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + } */ [super viewDidHide]; } @@ -332,7 +331,7 @@ static jmethodID windowRepaintID = NULL; return; } int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("viewDidUnhide: null JNIEnv\n"); return; @@ -340,9 +339,9 @@ static jmethodID windowRepaintID = NULL; (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_TRUE); - if (shallBeDetached) { + /* if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + } */ [super viewDidUnhide]; } @@ -354,14 +353,71 @@ static jmethodID windowRepaintID = NULL; @end +static CFStringRef CKCH_CreateStringForKey(CGKeyCode keyCode, const UCKeyboardLayout *keyboardLayout) { + UInt32 keysDown = 0; + UniChar chars[4]; + UniCharCount realLength; + + UCKeyTranslate(keyboardLayout, keyCode, + kUCKeyActionDisplay, 0, + LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, + &keysDown, sizeof(chars) / sizeof(chars[0]), &realLength, chars); + + return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1); +} + +static CFMutableDictionaryRef CKCH_CreateCodeToCharDict(TISInputSourceRef keyboard) { + CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData); + const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); + + CFMutableDictionaryRef codeToCharDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 128, NULL, NULL); + if ( NULL != codeToCharDict ) { + intptr_t i; + for (i = 0; i < 128; ++i) { + CFStringRef string = CKCH_CreateStringForKey((CGKeyCode)i, keyboardLayout); + if( NULL != string ) { + CFIndex stringLen = CFStringGetLength (string); + if ( 0 < stringLen ) { + UniChar character = CFStringGetCharacterAtIndex(string, 0); + DBG_PRINT("CKCH: MAP 0x%X -> %c\n", (int)i, character); + CFDictionaryAddValue(codeToCharDict, (const void *)i, (const void *)(intptr_t)character); + } + CFRelease(string); + } + } + } + return codeToCharDict; +} + +static CFMutableDictionaryRef CKCH_USCodeToNNChar = NULL; + +static void CKCH_CreateDictionaries() { + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + CKCH_USCodeToNNChar = CKCH_CreateCodeToCharDict(currentKeyboard); + CFRelease(currentKeyboard); +} + +static UniChar CKCH_CharForKeyCode(jshort keyCode) { + UniChar rChar = 0; + + if ( NULL != CKCH_USCodeToNNChar ) { + intptr_t code = (intptr_t) keyCode; + intptr_t character = 0; + + if ( CFDictionaryGetValueIfPresent(CKCH_USCodeToNNChar, (void *)code, (const void **)&character) ) { + rChar = (UniChar) character; + DBG_PRINT("CKCH: OK 0x%X -> 0x%X\n", (int)keyCode, (int)rChar); + } + } + return rChar; +} + @implementation NewtMacWindow + (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz { enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V"); - sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V"); - enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISSC)V"); - sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V"); + enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); @@ -370,9 +426,10 @@ static jmethodID windowRepaintID = NULL; windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); - if (enqueueMouseEventID && sendMouseEventID && enqueueKeyEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID && + if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID && positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID) { + CKCH_CreateDictionaries(); return YES; } return NO; @@ -675,7 +732,7 @@ static jint mods2JavaMods(NSUInteger mods) } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("sendKeyEvent: null JNIEnv\n"); return; @@ -689,36 +746,27 @@ static jint mods2JavaMods(NSUInteger mods) // printable chars for (i = 0; i < len; i++) { // Note: the key code in the NSEvent does not map to anything we can use - jchar keyChar = (jchar) [chars characterAtIndex: i]; + UniChar keyChar = (UniChar) [chars characterAtIndex: i]; + UniChar keySymChar = CKCH_CharForKeyCode(keyCode); - DBG_PRINT("sendKeyEvent: %d/%d char 0x%X, code 0x%X\n", i, len, (int)keyChar, (int)keyCode); + DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar, (int)keySymChar); - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID, - evType, javaMods, keyCode, keyCode, keyChar); - #else (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, - evType, javaMods, keyCode, keyCode, keyChar); - #endif + evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar); } } else { // non-printable chars - jchar keyChar = (jchar) -1; + jchar keyChar = (jchar) 0; DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode); - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID, - evType, javaMods, keyCode, keyCode, keyChar); - #else (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, - evType, javaMods, keyCode, keyCode, keyChar); - #endif + evType, javaMods, keyCode, keyChar, keyChar); } - if (shallBeDetached) { + /* if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + } */ } - (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType @@ -735,7 +783,7 @@ static jint mods2JavaMods(NSUInteger mods) } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("sendMouseEvent: null JNIEnv\n"); return; @@ -780,21 +828,14 @@ static jint mods2JavaMods(NSUInteger mods) NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]]; - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, javaWindowObject, sendMouseEventID, - evType, javaMods[0], - (jint) location.x, (jint) location.y, - javaButtonNum, scrollDeltaY); - #else (*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE, evType, javaMods[0], (jint) location.x, (jint) location.y, javaButtonNum, scrollDeltaY); - #endif - if (shallBeDetached) { + /* if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + } */ } - (void) focusChanged: (BOOL) gained @@ -812,7 +853,7 @@ static jint mods2JavaMods(NSUInteger mods) } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("focusChanged: null JNIEnv\n"); return; @@ -820,9 +861,9 @@ static jint mods2JavaMods(NSUInteger mods) (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); - if (shallBeDetached) { + /* if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + } */ } - (BOOL) becomeFirstResponder @@ -1010,7 +1051,7 @@ static jint mods2JavaMods(NSUInteger mods) javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject != NULL) { jvmHandle = [view getJVMHandle]; - env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); + env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); } } @@ -1025,9 +1066,9 @@ static jint mods2JavaMods(NSUInteger mods) (jint) contentRect.size.width, (jint) contentRect.size.height, JNI_FALSE); - if (shallBeDetached) { + /* if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + } */ } } @@ -1045,7 +1086,7 @@ static jint mods2JavaMods(NSUInteger mods) } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("windowDidMove: null JNIEnv\n"); return; @@ -1055,9 +1096,9 @@ static jint mods2JavaMods(NSUInteger mods) p0 = [self getLocationOnScreen: p0]; (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_FALSE, (jint) p0.x, (jint) p0.y); - if (shallBeDetached) { + /* if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + } */ } - (BOOL)windowShouldClose: (id) sender @@ -1092,7 +1133,7 @@ static jint mods2JavaMods(NSUInteger mods) } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; - JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); + JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached); if(NULL==env) { DBG_PRINT("windowWillClose: null JNIEnv\n"); return NO; @@ -1105,9 +1146,9 @@ static jint mods2JavaMods(NSUInteger mods) [view setDestroyNotifySent: false]; } - if (shallBeDetached) { + /* if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); - } + } */ DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed); } else { DBG_PRINT( "*************** windowWillClose (skip)\n"); @@ -1117,3 +1158,4 @@ static jint mods2JavaMods(NSUInteger mods) } @end + |