diff options
Diffstat (limited to 'src/newt/native')
-rw-r--r-- | src/newt/native/KeyEvent.h | 389 | ||||
-rw-r--r-- | src/newt/native/NewtCommon.c | 9 | ||||
-rw-r--r-- | src/newt/native/NewtCommon.h | 2 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.m | 158 | ||||
-rw-r--r-- | src/newt/native/WindowsWindow.c | 36 | ||||
-rw-r--r-- | src/newt/native/X11Display.c | 113 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 4 |
7 files changed, 422 insertions, 289 deletions
diff --git a/src/newt/native/KeyEvent.h b/src/newt/native/KeyEvent.h index 0f7b1606b..7a63b19ce 100644 --- a/src/newt/native/KeyEvent.h +++ b/src/newt/native/KeyEvent.h @@ -33,195 +33,206 @@ #define EVENT_KEY_RELEASED 301 #define EVENT_KEY_TYPED 302 -#define J_CHAR_UNDEFINED 0xFFFF; -#define J_VK_ENTER '\n' -#define J_VK_BACK_SPACE '\b' -#define J_VK_TAB '\t' -#define J_VK_CANCEL 0x03 -#define J_VK_CLEAR 0x0C -#define J_VK_SHIFT 0x10 -#define J_VK_CONTROL 0x11 -#define J_VK_ALT 0x12 -#define J_VK_PAUSE 0x13 -#define J_VK_CAPS_LOCK 0x14 -#define J_VK_ESCAPE 0x1B -#define J_VK_SPACE 0x20 -#define J_VK_PAGE_UP 0x21 -#define J_VK_PAGE_DOWN 0x22 -#define J_VK_END 0x23 -#define J_VK_HOME 0x24 -#define J_VK_LEFT 0x25 -#define J_VK_UP 0x26 -#define J_VK_RIGHT 0x27 -#define J_VK_DOWN 0x28 -#define J_VK_COMMA 0x2C -#define J_VK_MINUS 0x2D -#define J_VK_PERIOD 0x2E -#define J_VK_SLASH 0x2F -#define J_VK_0 0x30 -#define J_VK_1 0x31 -#define J_VK_2 0x32 -#define J_VK_3 0x33 -#define J_VK_4 0x34 -#define J_VK_5 0x35 -#define J_VK_6 0x36 -#define J_VK_7 0x37 -#define J_VK_8 0x38 -#define J_VK_9 0x39 -#define J_VK_SEMICOLON 0x3B -#define J_VK_EQUALS 0x3D -#define J_VK_A 0x41 -#define J_VK_B 0x42 -#define J_VK_C 0x43 -#define J_VK_D 0x44 -#define J_VK_E 0x45 -#define J_VK_F 0x46 -#define J_VK_G 0x47 -#define J_VK_H 0x48 -#define J_VK_I 0x49 -#define J_VK_J 0x4A -#define J_VK_K 0x4B -#define J_VK_L 0x4C -#define J_VK_M 0x4D -#define J_VK_N 0x4E -#define J_VK_O 0x4F -#define J_VK_P 0x50 -#define J_VK_Q 0x51 -#define J_VK_R 0x52 -#define J_VK_S 0x53 -#define J_VK_T 0x54 -#define J_VK_U 0x55 -#define J_VK_V 0x56 -#define J_VK_W 0x57 -#define J_VK_X 0x58 -#define J_VK_Y 0x59 -#define J_VK_Z 0x5A -#define J_VK_OPEN_BRACKET 0x5B -#define J_VK_BACK_SLASH 0x5C -#define J_VK_CLOSE_BRACKET 0x5D -#define J_VK_NUMPAD0 0x60 -#define J_VK_NUMPAD1 0x61 -#define J_VK_NUMPAD2 0x62 -#define J_VK_NUMPAD3 0x63 -#define J_VK_NUMPAD4 0x64 -#define J_VK_NUMPAD5 0x65 -#define J_VK_NUMPAD6 0x66 -#define J_VK_NUMPAD7 0x67 -#define J_VK_NUMPAD8 0x68 -#define J_VK_NUMPAD9 0x69 -#define J_VK_MULTIPLY 0x6A -#define J_VK_ADD 0x6B -#define J_VK_SEPARATOR 0x6C -#define J_VK_SUBTRACT 0x6D -#define J_VK_DECIMAL 0x6E -#define J_VK_DIVIDE 0x6F -#define J_VK_DELETE 0x7F /* ASCII DEL */ -#define J_VK_NUM_LOCK 0x90 -#define J_VK_SCROLL_LOCK 0x91 -#define J_VK_F1 0x70 -#define J_VK_F2 0x71 -#define J_VK_F3 0x72 -#define J_VK_F4 0x73 -#define J_VK_F5 0x74 -#define J_VK_F6 0x75 -#define J_VK_F7 0x76 -#define J_VK_F8 0x77 -#define J_VK_F9 0x78 -#define J_VK_F10 0x79 -#define J_VK_F11 0x7A -#define J_VK_F12 0x7B -#define J_VK_F13 0xF000 -#define J_VK_F14 0xF001 -#define J_VK_F15 0xF002 -#define J_VK_F16 0xF003 -#define J_VK_F17 0xF004 -#define J_VK_F18 0xF005 -#define J_VK_F19 0xF006 -#define J_VK_F20 0xF007 -#define J_VK_F21 0xF008 -#define J_VK_F22 0xF009 -#define J_VK_F23 0xF00A -#define J_VK_F24 0xF00B -#define J_VK_PRINTSCREEN 0x9A -#define J_VK_INSERT 0x9B -#define J_VK_HELP 0x9C -#define J_VK_META 0x9D -#define J_VK_BACK_QUOTE 0xC0 -#define J_VK_QUOTE 0xDE -#define J_VK_KP_UP 0xE0 -#define J_VK_KP_DOWN 0xE1 -#define J_VK_KP_LEFT 0xE2 -#define J_VK_KP_RIGHT 0xE3 -#define J_VK_DEAD_GRAVE 0x80 -#define J_VK_DEAD_ACUTE 0x81 -#define J_VK_DEAD_CIRCUMFLEX 0x82 -#define J_VK_DEAD_TILDE 0x83 -#define J_VK_DEAD_MACRON 0x84 -#define J_VK_DEAD_BREVE 0x85 -#define J_VK_DEAD_ABOVEDOT 0x86 -#define J_VK_DEAD_DIAERESIS 0x87 -#define J_VK_DEAD_ABOVERING 0x88 -#define J_VK_DEAD_DOUBLEACUTE 0x89 -#define J_VK_DEAD_CARON 0x8a -#define J_VK_DEAD_CEDILLA 0x8b -#define J_VK_DEAD_OGONEK 0x8c -#define J_VK_DEAD_IOTA 0x8d -#define J_VK_DEAD_VOICED_SOUND 0x8e -#define J_VK_DEAD_SEMIVOICED_SOUND 0x8f -#define J_VK_AMPERSAND 0x96 -#define J_VK_ASTERISK 0x97 -#define J_VK_QUOTEDBL 0x98 -#define J_VK_LESS 0x99 -#define J_VK_GREATER 0xa0 -#define J_VK_BRACELEFT 0xa1 -#define J_VK_BRACERIGHT 0xa2 -#define J_VK_AT 0x0200 -#define J_VK_COLON 0x0201 -#define J_VK_CIRCUMFLEX 0x0202 -#define J_VK_DOLLAR 0x0203 -#define J_VK_EURO_SIGN 0x0204 -#define J_VK_EXCLAMATION_MARK 0x0205 -#define J_VK_INVERTED_EXCLAMATION_MARK 0x0206 -#define J_VK_LEFT_PARENTHESIS 0x0207 -#define J_VK_NUMBER_SIGN 0x0208 -#define J_VK_PLUS 0x0209 -#define J_VK_RIGHT_PARENTHESIS 0x020A -#define J_VK_UNDERSCORE 0x020B -#define J_VK_WINDOWS 0x020C -#define J_VK_CONTEXT_MENU 0x020D -#define J_VK_FINAL 0x0018 -#define J_VK_CONVERT 0x001C -#define J_VK_NONCONVERT 0x001D -#define J_VK_ACCEPT 0x001E -#define J_VK_MODECHANGE 0x001F -#define J_VK_KANA 0x0015 -#define J_VK_KANJI 0x0019 -#define J_VK_ALPHANUMERIC 0x00F0 -#define J_VK_KATAKANA 0x00F1 -#define J_VK_HIRAGANA 0x00F2 -#define J_VK_FULL_WIDTH 0x00F3 -#define J_VK_HALF_WIDTH 0x00F4 -#define J_VK_ROMAN_CHARACTERS 0x00F5 -#define J_VK_ALL_CANDIDATES 0x0100 -#define J_VK_PREVIOUS_CANDIDATE 0x0101 -#define J_VK_CODE_INPUT 0x0102 -#define J_VK_JAPANESE_KATAKANA 0x0103 -#define J_VK_JAPANESE_HIRAGANA 0x0104 -#define J_VK_JAPANESE_ROMAN 0x0105 -#define J_VK_KANA_LOCK 0x0106 -#define J_VK_INPUT_METHOD_ON_OFF 0x0107 -#define J_VK_CUT 0xFFD1 -#define J_VK_COPY 0xFFCD -#define J_VK_PASTE 0xFFCF -#define J_VK_UNDO 0xFFCB -#define J_VK_AGAIN 0xFFC9 -#define J_VK_FIND 0xFFD0 -#define J_VK_PROPS 0xFFCA -#define J_VK_STOP 0xFFC8 -#define J_VK_COMPOSE 0xFF20 -#define J_VK_ALT_GRAPH 0xFF7E -#define J_VK_BEGIN 0xFF58 -#define J_VK_UNDEFINED 0x0 +#define J_VK_UNDEFINED ( 0x0U ) +#define J_VK_HOME ( 0x02U ) +#define J_VK_END ( 0x03U ) +#define J_VK_FINAL ( 0x04U ) +#define J_VK_PRINTSCREEN ( 0x05U ) +#define J_VK_BACK_SPACE ( 0x08U ) +#define J_VK_TAB ( 0x09U ) +#define J_VK_ENTER ( 0x0AU ) +#define J_VK_PAGE_DOWN ( 0x0BU ) +#define J_VK_CLEAR ( 0x0CU ) +#define J_VK_SHIFT ( 0x0FU ) +#define J_VK_PAGE_UP ( 0x10U ) +#define J_VK_CONTROL ( 0x11U ) +#define J_VK_ALT ( 0x12U ) +#define J_VK_ALT_GRAPH ( 0x13U ) +#define J_VK_CAPS_LOCK ( 0x14U ) +#define J_VK_PAUSE ( 0x16U ) +#define J_VK_SCROLL_LOCK ( 0x17U ) +#define J_VK_CANCEL ( 0x18U ) +#define J_VK_INSERT ( 0x1AU ) +#define J_VK_ESCAPE ( 0x1BU ) +#define J_VK_CONVERT ( 0x1CU ) +#define J_VK_NONCONVERT ( 0x1DU ) +#define J_VK_ACCEPT ( 0x1EU ) +#define J_VK_MODECHANGE ( 0x1FU ) + +// +// Unicode: Printable [0x20 - 0x7E] +// + +#define J_VK_SPACE ( 0x20U ) +#define J_VK_EXCLAMATION_MARK ( 0x21U ) +#define J_VK_QUOTEDBL ( 0x22U ) +#define J_VK_NUMBER_SIGN ( 0x23U ) +#define J_VK_DOLLAR ( 0x24U ) +#define J_VK_PERCENT ( 0x25U ) +#define J_VK_AMPERSAND ( 0x26U ) +#define J_VK_QUOTE ( 0x27U ) +#define J_VK_LEFT_PARENTHESIS ( 0x28U ) +#define J_VK_RIGHT_PARENTHESIS ( 0x29U ) +#define J_VK_ASTERISK ( 0x2AU ) +#define J_VK_PLUS ( 0x2BU ) +#define J_VK_COMMA ( 0x2CU ) +#define J_VK_MINUS ( 0x2DU ) +#define J_VK_PERIOD ( 0x2EU ) +#define J_VK_SLASH ( 0x2FU ) +#define J_VK_0 ( 0x30U ) +#define J_VK_1 ( 0x31U ) +#define J_VK_2 ( 0x32U ) +#define J_VK_3 ( 0x33U ) +#define J_VK_4 ( 0x34U ) +#define J_VK_5 ( 0x35U ) +#define J_VK_6 ( 0x36U ) +#define J_VK_7 ( 0x37U ) +#define J_VK_8 ( 0x38U ) +#define J_VK_9 ( 0x39U ) +#define J_VK_COLON ( 0x3AU ) +#define J_VK_SEMICOLON ( 0x3BU ) +#define J_VK_LESS ( 0x3CU ) +#define J_VK_EQUALS ( 0x3DU ) +#define J_VK_GREATER ( 0x3EU ) +#define J_VK_QUESTIONMARK ( 0x3FU ) +#define J_VK_AT ( 0x40U ) +#define J_VK_A ( 0x41U ) +#define J_VK_B ( 0x42U ) +#define J_VK_C ( 0x43U ) +#define J_VK_D ( 0x44U ) +#define J_VK_E ( 0x45U ) +#define J_VK_F ( 0x46U ) +#define J_VK_G ( 0x47U ) +#define J_VK_H ( 0x48U ) +#define J_VK_I ( 0x49U ) +#define J_VK_J ( 0x4AU ) +#define J_VK_K ( 0x4BU ) +#define J_VK_L ( 0x4CU ) +#define J_VK_M ( 0x4DU ) +#define J_VK_N ( 0x4EU ) +#define J_VK_O ( 0x4FU ) +#define J_VK_P ( 0x50U ) +#define J_VK_Q ( 0x51U ) +#define J_VK_R ( 0x52U ) +#define J_VK_S ( 0x53U ) +#define J_VK_T ( 0x54U ) +#define J_VK_U ( 0x55U ) +#define J_VK_V ( 0x56U ) +#define J_VK_W ( 0x57U ) +#define J_VK_X ( 0x58U ) +#define J_VK_Y ( 0x59U ) +#define J_VK_Z ( 0x5AU ) +#define J_VK_OPEN_BRACKET ( 0x5BU ) +#define J_VK_BACK_SLASH ( 0x5CU ) +#define J_VK_CLOSE_BRACKET ( 0x5DU ) +#define J_VK_CIRCUMFLEX ( 0x5EU ) +#define J_VK_UNDERSCORE ( 0x5FU ) +#define J_VK_BACK_QUOTE ( 0x60U ) +#define J_VK_F1 ( 0x60U+ 1U ) +#define J_VK_F2 ( 0x60U+ 2U ) +#define J_VK_F3 ( 0x60U+ 3U ) +#define J_VK_F4 ( 0x60U+ 4U ) +#define J_VK_F5 ( 0x60U+ 5U ) +#define J_VK_F6 ( 0x60U+ 6U ) +#define J_VK_F7 ( 0x60U+ 7U ) +#define J_VK_F8 ( 0x60U+ 8U ) +#define J_VK_F9 ( 0x60U+ 9U ) +#define J_VK_F10 ( 0x60U+10U ) +#define J_VK_F11 ( 0x60U+11U ) +#define J_VK_F12 ( 0x60U+12U ) +#define J_VK_F13 ( 0x60U+13U ) +#define J_VK_F14 ( 0x60U+14U ) +#define J_VK_F15 ( 0x60U+15U ) +#define J_VK_F16 ( 0x60U+16U ) +#define J_VK_F17 ( 0x60U+17U ) +#define J_VK_F18 ( 0x60U+18U ) +#define J_VK_F19 ( 0x60U+19U ) +#define J_VK_F20 ( 0x60U+20U ) +#define J_VK_F21 ( 0x60U+21U ) +#define J_VK_F22 ( 0x60U+22U ) +#define J_VK_F23 ( 0x60U+23U ) +#define J_VK_F24 ( 0x60U+24U ) +#define J_VK_LEFT_BRACE ( 0x7BU ) +#define J_VK_PIPE ( 0x7CU ) +#define J_VK_RIGHT_BRACE ( 0x7DU ) +#define J_VK_TILDE ( 0x7EU ) + +// +// Unicode: Non printable controls: [0x7F - 0x9F] +// + +#define J_VK_DELETE ( 0x7FU ) +#define J_VK_NUMPAD0 ( 0x80U ) +#define J_VK_NUMPAD1 ( 0x81U ) +#define J_VK_NUMPAD2 ( 0x82U ) +#define J_VK_NUMPAD3 ( 0x83U ) +#define J_VK_NUMPAD4 ( 0x84U ) +#define J_VK_NUMPAD5 ( 0x85U ) +#define J_VK_NUMPAD6 ( 0x86U ) +#define J_VK_NUMPAD7 ( 0x87U ) +#define J_VK_NUMPAD8 ( 0x88U ) +#define J_VK_NUMPAD9 ( 0x89U ) +#define J_VK_DECIMAL ( 0x8AU ) +#define J_VK_SEPARATOR ( 0x8BU ) +#define J_VK_ADD ( 0x8CU ) +#define J_VK_SUBTRACT ( 0x8DU ) +#define J_VK_MULTIPLY ( 0x8EU ) +#define J_VK_DIVIDE ( 0x8FU ) +#define J_VK_NUM_LOCK ( 0x90U ) +#define J_VK_KP_LEFT ( 0x91U ) +#define J_VK_KP_UP ( 0x92U ) +#define J_VK_KP_RIGHT ( 0x93U ) +#define J_VK_KP_DOWN ( 0x94U ) +#define J_VK_LEFT ( 0x95U ) +#define J_VK_UP ( 0x96U ) +#define J_VK_RIGHT ( 0x97U ) +#define J_VK_DOWN ( 0x98U ) +#define J_VK_CONTEXT_MENU ( 0x99U ) +#define J_VK_WINDOWS ( 0x9AU ) +#define J_VK_META ( 0x9BU ) +#define J_VK_HELP ( 0x9CU ) +#define J_VK_COMPOSE ( 0x9DU ) +#define J_VK_BEGIN ( 0x9EU ) +#define J_VK_STOP ( 0x9FU ) + + +// +// Unicode: Printable [0x00A0 - 0xDFFF] +// + +#define J_VK_INVERTED_EXCLAMATION_MARK ( 0xA1U ) +#define J_VK_EURO_SIGN ( 0x20ACU ) + +// +// Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable) +// + +/* for Sun keyboards */ +#define J_VK_CUT ( 0xF879U ) +#define J_VK_COPY ( 0xF87AU ) +#define J_VK_PASTE ( 0xF87BU ) +#define J_VK_UNDO ( 0xF87CU ) +#define J_VK_AGAIN ( 0xF87DU ) +#define J_VK_FIND ( 0xF87EU ) +#define J_VK_PROPS ( 0xF87FU ) + +/* for input method support on Asian Keyboards */ +#define J_VK_INPUT_METHOD_ON_OFF ( 0xF890U ) +#define J_VK_CODE_INPUT ( 0xF891U ) +#define J_VK_ROMAN_CHARACTERS ( 0xF892U ) +#define J_VK_ALL_CANDIDATES ( 0xF893U ) +#define J_VK_PREVIOUS_CANDIDATE ( 0xF894U ) +#define J_VK_ALPHANUMERIC ( 0xF895U ) +#define J_VK_KATAKANA ( 0xF896U ) +#define J_VK_HIRAGANA ( 0xF897U ) +#define J_VK_FULL_WIDTH ( 0xF898U ) +#define J_VK_HALF_WIDTH ( 0xF89AU ) +#define J_VK_JAPANESE_KATAKANA ( 0xF89BU ) +#define J_VK_JAPANESE_HIRAGANA ( 0xF89CU ) +#define J_VK_JAPANESE_ROMAN ( 0xF89DU ) +#define J_VK_KANA_LOCK ( 0xF89FU ) + +#define J_VK_KEYBOARD_INVISIBLE ( 0xF8FFU ) #endif diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c index 7f070e7d3..c294b6e0b 100644 --- a/src/newt/native/NewtCommon.c +++ b/src/newt/native/NewtCommon.c @@ -72,7 +72,7 @@ jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str) return strChars; } -JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached) { +JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) { JNIEnv* curEnv = NULL; JNIEnv* newEnv = NULL; int envRes; @@ -81,7 +81,12 @@ JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int * shallBeDe envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ; if( JNI_EDETACHED == envRes ) { // detached thread - attach to JVM - if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) { + if( asDaemon ) { + envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL); + } else { + envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL); + } + if( JNI_OK != envRes ) { fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes); return NULL; } diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h index 9a4e5ac70..9cc9e93a6 100644 --- a/src/newt/native/NewtCommon.h +++ b/src/newt/native/NewtCommon.h @@ -76,6 +76,6 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...); (*jvmHandle)->DetachCurrentThread(jvmHandle); } */ -JNIEnv* NewtCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached); +JNIEnv* NewtCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached); #endif 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 + diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index ae09490f8..eecc2e075 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -162,7 +162,7 @@ static KeyMapEntry keyMapTable[] = { {J_VK_CONTROL, VK_RCONTROL, 0}, {J_VK_ALT, VK_MENU, 0}, {J_VK_ALT, VK_LMENU, 0}, - {J_VK_ALT, VK_RMENU, 0}, + {J_VK_ALT_GRAPH, VK_RMENU, 0}, {J_VK_NUM_LOCK, VK_NUMLOCK, 0}, // Miscellaneous Windows keys @@ -432,7 +432,7 @@ static void ParseWmVKeyAndScanCode(USHORT winVKey, BYTE winScanCode, BYTE flags, #endif } -static jint GetModifiers(BOOL altKeyFlagged, USHORT jkey) { +static jint GetModifiers(USHORT jkey) { jint modifiers = 0; // have to do &0xFFFF to avoid runtime assert caused by compiling with // /RTCcsu @@ -442,9 +442,12 @@ static jint GetModifiers(BOOL altKeyFlagged, USHORT jkey) { if ( HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0 || J_VK_SHIFT == jkey ) { modifiers |= EVENT_SHIFT_MASK; } - if ( altKeyFlagged || HIBYTE((GetKeyState(VK_MENU) & 0xFFFF)) != 0 || J_VK_ALT == jkey ) { + if ( HIBYTE((GetKeyState(VK_LMENU) & 0xFFFF)) != 0 || J_VK_ALT == jkey ) { modifiers |= EVENT_ALT_MASK; } + if ( HIBYTE((GetKeyState(VK_RMENU) & 0xFFFF)) != 0 || (USHORT)J_VK_ALT_GRAPH == jkey ) { + modifiers |= EVENT_ALT_GRAPH_MASK; + } if ( HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0 ) { modifiers |= EVENT_BUTTON1_MASK; } @@ -458,11 +461,12 @@ static jint GetModifiers(BOOL altKeyFlagged, USHORT jkey) { return modifiers; } +/** static BOOL IsAltKeyDown(BYTE flags, BOOL system) { // The Alt modifier is reported in the 29th bit of the lParam, // i.e., it is the 5th bit of `flags' (which is HIBYTE(HIWORD(lParam))). return system && ( flags & (1<<5) ) != 0; -} +} */ static int WmKeyDown(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) { UINT modifiers = 0; @@ -473,7 +477,7 @@ static int WmKeyDown(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE ParseWmVKeyAndScanCode(wkey, scanCode, flags, &javaVKeyUS, &javaVKeyXX, &utf16Char); - modifiers = GetModifiers( IsAltKeyDown(flags, system), javaVKeyXX ); + modifiers = GetModifiers( javaVKeyUS ); (*env)->CallVoidMethod(env, window, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, @@ -491,7 +495,7 @@ static int WmKeyUp(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE s ParseWmVKeyAndScanCode(wkey, scanCode, flags, &javaVKeyUS, &javaVKeyXX, &utf16Char); - modifiers = GetModifiers( IsAltKeyDown(flags, system), javaVKeyXX ); + modifiers = GetModifiers( javaVKeyUS ); (*env)->CallVoidMethod(env, window, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, @@ -860,7 +864,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, - GetModifiers( FALSE, 0 ), + GetModifiers( 0 ), (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jshort) 1, (jfloat) 0.0f); useDefWindowProc = 1; @@ -869,7 +873,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP case WM_LBUTTONUP: (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, - GetModifiers( FALSE, 0 ), + GetModifiers( 0 ), (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jshort) 1, (jfloat) 0.0f); useDefWindowProc = 1; @@ -880,7 +884,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, - GetModifiers( FALSE, 0 ), + GetModifiers( 0 ), (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jshort) 2, (jfloat) 0.0f); useDefWindowProc = 1; @@ -889,7 +893,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP case WM_MBUTTONUP: (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, - GetModifiers( FALSE, 0 ), + GetModifiers( 0 ), (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jshort) 2, (jfloat) 0.0f); useDefWindowProc = 1; @@ -900,7 +904,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, - GetModifiers( FALSE, 0 ), + GetModifiers( 0 ), (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jshort) 3, (jfloat) 0.0f); useDefWindowProc = 1; @@ -909,17 +913,17 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP case WM_RBUTTONUP: (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, - GetModifiers( FALSE, 0 ), + GetModifiers( 0 ), (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jshort) 3, (jfloat) 0.0f); useDefWindowProc = 1; break; case WM_MOUSEMOVE: - DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d\n", (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam)); + // DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d\n", (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam)); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, - GetModifiers( FALSE, 0 ), + GetModifiers( 0 ), (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jshort) 0, (jfloat) 0.0f); useDefWindowProc = 1; @@ -937,7 +941,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP case WM_HSCROLL: { // Only delivered if windows has WS_HSCROLL, hence dead code! int sb = LOWORD(wParam); - int modifiers = GetModifiers( FALSE, 0 ) | EVENT_SHIFT_MASK; + int modifiers = GetModifiers( 0 ) | EVENT_SHIFT_MASK; float rotation; switch(sb) { case SB_LINELEFT: @@ -967,7 +971,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP // need to convert the coordinates to component-relative int x = GET_X_LPARAM(lParam); int y = GET_Y_LPARAM(lParam); - int modifiers = GetModifiers( FALSE, 0 ); + int modifiers = GetModifiers( 0 ); float rotationOrTilt = (float)(GET_WHEEL_DELTA_WPARAM(wParam))/WHEEL_DELTAf; int vKeys = GET_KEYSTATE_WPARAM(wParam); POINT eventPt; diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c index 9b11ff0dd..56b7251d2 100644 --- a/src/newt/native/X11Display.c +++ b/src/newt/native/X11Display.c @@ -28,6 +28,8 @@ #include "X11Common.h" +// #include <X11/XKBlib.h> // XKB disabled for now + jclass X11NewtWindowClazz = NULL; jmethodID insetsChangedID = NULL; jmethodID visibleChangedID = NULL; @@ -52,9 +54,11 @@ static jmethodID requestFocusID = NULL; * Keycode */ +// #define DEBUG_KEYS 1 + #define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b)) -static jint X11KeySym2NewtVKey(KeySym keySym) { +static short X11KeySym2NewtVKey(KeySym keySym) { if( IS_WITHIN( keySym, XK_a, XK_z ) ) { return ( keySym - XK_a ) + J_VK_A ; } @@ -89,8 +93,14 @@ static jint X11KeySym2NewtVKey(KeySym keySym) { case XK_Control_R: return J_VK_CONTROL; case XK_Alt_L: - case XK_Alt_R: return J_VK_ALT; + case XK_Alt_R: + return J_VK_ALT_GRAPH; + case XK_Super_L: + case XK_Super_R: + return J_VK_WINDOWS; + case XK_Menu: + return J_VK_CONTEXT_MENU; case XK_Pause: return J_VK_PAUSE; case XK_Caps_Lock: @@ -158,7 +168,11 @@ static jint X11KeySym2NewtVKey(KeySym keySym) { return keySym; } -static jint X11InputState2NewtModifiers(unsigned int xstate, int javaVKey) { +#define ShiftCtrlModMask ( ShiftMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask ) + +static jboolean altGraphDown = JNI_FALSE; + +static jint X11InputState2NewtModifiers(unsigned int xstate, jshort javaVKey, jboolean keyDown) { jint modifiers = 0; if ( (ControlMask & xstate) != 0 || J_VK_CONTROL == javaVKey ) { modifiers |= EVENT_CTRL_MASK; @@ -166,8 +180,15 @@ static jint X11InputState2NewtModifiers(unsigned int xstate, int javaVKey) { if ( (ShiftMask & xstate) != 0 || J_VK_SHIFT == javaVKey ) { modifiers |= EVENT_SHIFT_MASK; } - if ( (Mod1Mask & xstate) != 0 || J_VK_ALT == javaVKey ) { + if ( J_VK_ALT == javaVKey ) { + altGraphDown = JNI_FALSE; modifiers |= EVENT_ALT_MASK; + } else if ( (short)J_VK_ALT_GRAPH == javaVKey ) { + altGraphDown = keyDown; + modifiers |= EVENT_ALT_GRAPH_MASK; + } else if ( (Mod1Mask & xstate) != 0 ) { + // XK_Alt_L or XK_Alt_R + modifiers |= altGraphDown ? EVENT_ALT_GRAPH_MASK : EVENT_ALT_MASK; } if ( (Button1Mask & xstate) != 0 ) { modifiers |= EVENT_BUTTON1_MASK; @@ -211,6 +232,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 } } + // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJ)V"); // Variant using XKB displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V"); getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;"); dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V"); @@ -223,7 +245,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V"); sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V"); - sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSC)V"); + sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V"); requestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "requestFocus", "(Z)V"); if (displayCompletedID == NULL || @@ -258,6 +280,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay Display * dpy = (Display *)(intptr_t)display; jlong javaObjectAtom; jlong windowDeleteAtom; + // jlong kbdHandle; // XKB disabled for now if(dpy==NULL) { NewtCommon_FatalError(env, "invalid display connection.."); @@ -276,10 +299,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay } // XSetCloseDownMode(dpy, RetainTemporary); // Just a try .. + // kbdHandle = (jlong) (intptr_t) XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd); // XKB disabled for now DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy); - (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom); + (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom /*, kbdHandle*/); // XKB disabled for now } /* @@ -288,11 +312,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay * Signature: (JJJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0 - (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom) + (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/) { Display * dpy = (Display *)(intptr_t)display; Atom wm_javaobject_atom = (Atom)javaObjectAtom; Atom wm_delete_atom = (Atom)windowDeleteAtom; + // XkbDescPtr kbdDesc = (XkbDescPtr)(intptr_t)kbdHandle; // XKB disabled for now if(dpy==NULL) { NewtCommon_FatalError(env, "invalid display connection.."); @@ -302,6 +327,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0 (void) wm_javaobject_atom; (void) wm_delete_atom; + // XkbFreeKeyboard(kbdDesc, XkbAllNamesMask, True); // XKB disabled for now + XSync(dpy, True); // discard all pending events DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy); } @@ -309,13 +336,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0 /* * Class: jogamp_newt_driver_x11_DisplayDriver * Method: DispatchMessages - * Signature: (JIJJ)V + * Signature: (JJJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0 - (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom) + (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/) { Display * dpy = (Display *) (intptr_t) display; Atom wm_delete_atom = (Atom)windowDeleteAtom; + // XkbDescPtr kbdDesc = (XkbDescPtr)(intptr_t)kbdHandle; // XKB disabled for now int num_events = 100; int autoRepeatModifiers = 0; @@ -323,6 +351,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage return; } + /** XKB disabled for now + if( NULL == kbdDesc) { + NewtCommon_throwNewRuntimeException(env, "NULL kbd handle, bail out!"); + return; + } */ + // Periodically take a break while( num_events > 0 ) { jobject jwindow = NULL; @@ -332,7 +366,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage jshort javaVKeyUS = 0; jshort javaVKeyNN = 0; jint modifiers = 0; - char keyChar = 0; + uint16_t keyChar = 0; + jstring keyString = NULL; char text[255]; // XEventsQueued(dpy, X): @@ -391,27 +426,59 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage // fall through intended case KeyPress: { KeySym shiftedKeySym; // layout depending keySym w/ SHIFT + KeySym unShiftedKeySym; // layout depending keySym w/o SHIFT + unsigned int xkey_state = evt.xkey.state; keyCode = evt.xkey.keycode; - keySym = XkbKeycodeToKeysym(dpy, keyCode, 0 /* group */, 0 /* shift level */); // layout depending keySym w/o SHIFT - if( XLookupString(&evt.xkey, text, 255, &shiftedKeySym, 0) == 1 ) { - keyChar=text[0]; + // Layout depending keySym w/o SHIFT, + // using fixed group 0 (US default layout) + // + // unsigned int mods_rtrn = 0; + // Bool res = XkbTranslateKeyCode (kbdDesc, keyCode, 0, &mods_rtrn, &keySym); // XKB disabled for now + // if( !res ) { + keySym = XkbKeycodeToKeysym(dpy, keyCode, 0 /* group */, 0 /* shift level */); + // } + + text[0] = 0; text[1] = 0; text[2] = 0; + int charCount = XLookupString(&evt.xkey, text, 2, &shiftedKeySym, NULL); + if( 1 == charCount ) { + keyChar = 0x00FF & (uint16_t) (text[0]); + } else if( 2 == charCount ) { + // Example: UTF-16: 00DF, UTF-8: c3 9f, LATIN SMALL LETTER SHARP S + keyChar = ( 0x00FF & (uint16_t)(text[0]) ) << 8 | ( 0x00FF & (uint16_t)(text[1]) ); // UTF-16BE + keyString = (*env)->NewStringUTF(env, text); } - javaVKeyNN = X11KeySym2NewtVKey(keySym); - javaVKeyUS = javaVKeyNN; // FIXME! - modifiers |= X11InputState2NewtModifiers(evt.xkey.state, javaVKeyNN) | autoRepeatModifiers; + if( 0 == keyChar ) { + // Use keyCode's keySym for dead-key (aka modifiers, etc) + unShiftedKeySym = keySym; + } else if( 0 == ( evt.xkey.state & ShiftCtrlModMask ) ) { + // Use non modded keySym + unShiftedKeySym = shiftedKeySym; + } else { + evt.xkey.state = evt.xkey.state & ~ShiftCtrlModMask; // clear shift, ctrl and Mod* + XLookupString(&evt.xkey, text, 0, &unShiftedKeySym, NULL); + // unShiftedKeySym = XLookupKeysym(&evt.xkey, 0 /* index ? */); + } - fprintf(stderr, "NEWT X11 Key: keyCode 0x%X keySym 0x%X (shifted: 0x%X), keyChar '%c', javaVKey[US 0x%X, NN 0x%X]\n", - (int)keyCode, (int)keySym, (int)shiftedKeySym, (int)keyChar, (int)javaVKeyUS, (int)javaVKeyNN); + javaVKeyNN = X11KeySym2NewtVKey(unShiftedKeySym); + javaVKeyUS = X11KeySym2NewtVKey(keySym); + modifiers |= X11InputState2NewtModifiers(xkey_state, javaVKeyNN, evt.type == KeyPress) | autoRepeatModifiers; + + #ifdef DEBUG_KEYS + fprintf(stderr, "NEWT X11 Key: keyCode 0x%X keySym 0x%X, (0x%X, shifted: 0x%X), keyChar '%c' 0x%X %d, javaVKey[US 0x%X, NN 0x%X], xstate 0x%X %u, jmods 0x%X\n", + (int)keyCode, (int)keySym, (int) unShiftedKeySym, (int)shiftedKeySym, keyChar, keyChar, charCount, + (int)javaVKeyUS, (int)javaVKeyNN, + (int)xkey_state, (int)xkey_state, (int)modifiers); + #endif } break; case ButtonPress: case ButtonRelease: case MotionNotify: - modifiers |= X11InputState2NewtModifiers(evt.xbutton.state, 0); + modifiers |= X11InputState2NewtModifiers(evt.xbutton.state, 0, JNI_FALSE); break; default: @@ -447,13 +514,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); break; + case MappingNotify: + DBG_PRINT( "X11: event . MappingNotify call %p type %d\n", (void*)evt.xmapping.window, evt.xmapping.type); + XRefreshKeyboardMapping(&evt.xmapping); + break; case KeyPress: (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, - modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar); + modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString); break; case KeyRelease: (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, - modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar); + modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString); break; case DestroyNotify: DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n", diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index 202ad6fff..9e96169f5 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -671,7 +671,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0 * Signature: (JJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 - (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom) + (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/) // XKB disabled for now { Display * dpy = (Display *) (intptr_t) display; Window w = (Window)window; @@ -698,7 +698,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 XUnmapWindow(dpy, w); // Drain all events related to this window .. - Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom); + Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now XDestroyWindow(dpy, w); XSync(dpy, True); // discard all events now, no more handler |