summaryrefslogtreecommitdiffstats
path: root/src/newt/native/NewtMacWindow.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/native/NewtMacWindow.m')
-rw-r--r--src/newt/native/NewtMacWindow.m158
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
+