diff --git a/make/sun/xawt/mapfile-vers b/make/sun/xawt/mapfile-vers index d880ebb4f77a7e31e6c4ed6ad87966338124f492..82fe94f63ec9be055609e12985990200cbe1e8c8 100644 --- a/make/sun/xawt/mapfile-vers +++ b/make/sun/xawt/mapfile-vers @@ -126,6 +126,8 @@ SUNWprivate_1.1 { Java_sun_awt_X11_XlibWrapper_ServerVendor; Java_sun_awt_X11_XlibWrapper_VendorRelease; Java_sun_awt_X11_XlibWrapper_IsXsunKPBehavior; + Java_sun_awt_X11_XlibWrapper_IsSunKeyboard; + Java_sun_awt_X11_XlibWrapper_IsKanaKeyboard; Java_sun_awt_X11_XlibWrapper_SetToolkitErrorHandler; Java_sun_awt_X11_XlibWrapper_XSetErrorHandler; Java_sun_awt_X11_XlibWrapper_CallErrorHandler; @@ -306,6 +308,7 @@ SUNWprivate_1.1 { Java_sun_awt_X11_XlibWrapper_XkbTranslateKeyCode; Java_sun_awt_X11_XlibWrapper_XGetModifierMapping; Java_sun_awt_X11_XlibWrapper_XFreeModifiermap; + Java_sun_awt_X11_XlibWrapper_XRefreshKeyboardMapping; Java_sun_awt_X11_XlibWrapper_XChangeActivePointerGrab; Java_sun_awt_X11_XlibWrapper_XNextSecondaryLoopEvent; Java_sun_awt_X11_XlibWrapper_ExitSecondaryLoop; diff --git a/src/solaris/classes/sun/awt/X11/XEmbedHelper.java b/src/solaris/classes/sun/awt/X11/XEmbedHelper.java index 57267039bd1fe842c969a574c98c9e846de8e355..c60b4a53092759b56fea6c2e0ffdb4dd9ea66d87 100644 --- a/src/solaris/classes/sun/awt/X11/XEmbedHelper.java +++ b/src/solaris/classes/sun/awt/X11/XEmbedHelper.java @@ -216,7 +216,12 @@ public class XEmbedHelper { XToolkit.awtLock(); try { - keycode = XWindow.getAWTKeyCodeForKeySym((int)keysym); + XKeysym.Keysym2JavaKeycode kc = XKeysym.getJavaKeycode( keysym ); + if(kc == null) { + keycode = java.awt.event.KeyEvent.VK_UNDEFINED; + }else{ + keycode = kc.getJavaKeycode(); + } } finally { XToolkit.awtUnlock(); } diff --git a/src/solaris/classes/sun/awt/X11/XKeysym.java b/src/solaris/classes/sun/awt/X11/XKeysym.java index abf3c65c54757148406bf85619e7416604c1c62b..e81c6ce323e1f796de52b6b8e4df8a025e1551cb 100644 --- a/src/solaris/classes/sun/awt/X11/XKeysym.java +++ b/src/solaris/classes/sun/awt/X11/XKeysym.java @@ -69,6 +69,8 @@ public class XKeysym { static Hashtable javaKeycode2KeysymHash = new Hashtable(); static long keysym_lowercase = unsafe.allocateMemory(Native.getLongSize()); static long keysym_uppercase = unsafe.allocateMemory(Native.getLongSize()); + static Keysym2JavaKeycode kanaLock = new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KANA_LOCK, + java.awt.event.KeyEvent.KEY_LOCATION_STANDARD); private static PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.kye.XKeysym"); public static char convertKeysym( long ks, int state ) { @@ -214,12 +216,35 @@ public class XKeysym { } return keysym; } + + /** + Return java.awt.KeyEvent constant meaning (Java) keycode, derived from X keysym. + Some keysyms maps to more than one keycode, these would require extra processing. + */ + static Keysym2JavaKeycode getJavaKeycode( long keysym ) { + if(keysym == XKeySymConstants.XK_Mode_switch){ + /* XK_Mode_switch on solaris maps either to VK_ALT_GRAPH (default) or VK_KANA_LOCK */ + if( XToolkit.isKanaKeyboard() ) { + return kanaLock; + } + }else if(keysym == XKeySymConstants.XK_L1){ + /* if it is Sun keyboard, trick hash to return VK_STOP else VK_F11 (default) */ + if( XToolkit.isSunKeyboard() ) { + keysym = XKeySymConstants.SunXK_Stop; + } + }else if(keysym == XKeySymConstants.XK_L2) { + /* if it is Sun keyboard, trick hash to return VK_AGAIN else VK_F12 (default) */ + if( XToolkit.isSunKeyboard() ) { + keysym = XKeySymConstants.SunXK_Again; + } + } + + return keysym2JavaKeycodeHash.get( keysym ); + } /** Return java.awt.KeyEvent constant meaning (Java) keycode, derived from X Window KeyEvent. Algorithm is, extract via XKeycodeToKeysym a proper keysym according to Xlib spec rules and err exceptions, then search a java keycode in a table. - Some keysyms maps to more than one keycode, these would require extra processing. If someone - points me to such a keysym. */ static Keysym2JavaKeycode getJavaKeycode( XKeyEvent ev ) { // get from keysym2JavaKeycodeHash. @@ -234,7 +259,7 @@ public class XKeysym { keysym = xkeycode2keysym(ev, ndx); } - Keysym2JavaKeycode jkc = keysym2JavaKeycodeHash.get( keysym ); + Keysym2JavaKeycode jkc = getJavaKeycode( keysym ); return jkc; } static int getJavaKeycodeOnly( XKeyEvent ev ) { @@ -259,7 +284,7 @@ public class XKeysym { ndx = 0; keysym = xkeycode2keysym_noxkb(ev, ndx); } - Keysym2JavaKeycode jkc = keysym2JavaKeycodeHash.get( keysym ); + Keysym2JavaKeycode jkc = getJavaKeycode( keysym ); return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode(); } static long javaKeycode2Keysym( int jkey ) { diff --git a/src/solaris/classes/sun/awt/X11/XToolkit.java b/src/solaris/classes/sun/awt/X11/XToolkit.java index f1ec80042646b53099ae2360ce7f3290ce679381..b260a329cf7bbe1b607836c1dcbccf6c784e6386 100644 --- a/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -533,6 +533,16 @@ public final class XToolkit extends UNIXToolkit implements Runnable { processGlobalMotionEvent(ev); } + if( ev.get_type() == XConstants.MappingNotify ) { + // The 'window' field in this event is unused. + // This application itself does nothing to initiate such an event + // (no calls of XChangeKeyboardMapping etc.). + // SunRay server sends this event to the application once on every + // keyboard (not just layout) change which means, quite seldom. + XlibWrapper.XRefreshKeyboardMapping(ev.pData); + resetKeyboardSniffer(); + setupModifierMap(); + } XBaseWindow.dispatchToWindow(ev); Collection dispatchers = null; @@ -2112,6 +2122,11 @@ public final class XToolkit extends UNIXToolkit implements Runnable { static final int XSUN_KP_BEHAVIOR = 1; static final int XORG_KP_BEHAVIOR = 2; + static final int IS_SUN_KEYBOARD = 1; + static final int IS_NONSUN_KEYBOARD = 2; + static final int IS_KANA_KEYBOARD = 1; + static final int IS_NONKANA_KEYBOARD = 2; + static int awt_IsXsunKPBehavior = 0; static boolean awt_UseXKB = false; @@ -2141,6 +2156,33 @@ public final class XToolkit extends UNIXToolkit implements Runnable { awtUnlock(); } } + + static int sunOrNotKeyboard = 0; + static int kanaOrNotKeyboard = 0; + static void resetKeyboardSniffer() { + sunOrNotKeyboard = 0; + kanaOrNotKeyboard = 0; + } + static boolean isSunKeyboard() { + if( sunOrNotKeyboard == 0 ) { + if( XlibWrapper.IsSunKeyboard( getDisplay() )) { + sunOrNotKeyboard = IS_SUN_KEYBOARD; + }else{ + sunOrNotKeyboard = IS_NONSUN_KEYBOARD; + } + } + return (sunOrNotKeyboard == IS_SUN_KEYBOARD); + } + static boolean isKanaKeyboard() { + if( kanaOrNotKeyboard == 0 ) { + if( XlibWrapper.IsKanaKeyboard( getDisplay() )) { + kanaOrNotKeyboard = IS_KANA_KEYBOARD; + }else{ + kanaOrNotKeyboard = IS_NONKANA_KEYBOARD; + } + } + return (kanaOrNotKeyboard == IS_KANA_KEYBOARD); + } static boolean isXKBenabled() { awtLock(); try { diff --git a/src/solaris/classes/sun/awt/X11/XlibWrapper.java b/src/solaris/classes/sun/awt/X11/XlibWrapper.java index 3ef2f69ae8580190e21cb89a82a46702bce458cf..551e256427c07baf9364aee1c97cebb7c0e2d2c8 100644 --- a/src/solaris/classes/sun/awt/X11/XlibWrapper.java +++ b/src/solaris/classes/sun/awt/X11/XlibWrapper.java @@ -353,6 +353,8 @@ static native String XSetLocaleModifiers(String modifier_list); static native String ServerVendor(long display); static native int VendorRelease(long display); static native boolean IsXsunKPBehavior(long display); + static native boolean IsSunKeyboard(long display); + static native boolean IsKanaKeyboard(long display); static native void XBell(long display, int percent); @@ -513,8 +515,9 @@ static native String XSetLocaleModifiers(String modifier_list); long keysym_uppercase); static native long XGetModifierMapping(long display); - static native void XFreeModifiermap(long keymap); + static native void XRefreshKeyboardMapping(long event); + static native void XChangeActivePointerGrab(long display, int mask, long cursor, long time); diff --git a/src/solaris/classes/sun/awt/X11/keysym2ucs.h b/src/solaris/classes/sun/awt/X11/keysym2ucs.h index 32ecd66c9870b35fc775a7bf24442638fe646054..e7c2c40b9a4395d38ef1635f27d5d50351a19b88 100644 --- a/src/solaris/classes/sun/awt/X11/keysym2ucs.h +++ b/src/solaris/classes/sun/awt/X11/keysym2ucs.h @@ -107,6 +107,8 @@ tojava // Another use for reverse lookup: query keyboard state, for some key tojava static Hashtable javaKeycode2KeysymHash = new Hashtable(); tojava static long keysym_lowercase = unsafe.allocateMemory(Native.getLongSize()); tojava static long keysym_uppercase = unsafe.allocateMemory(Native.getLongSize()); +tojava static Keysym2JavaKeycode kanaLock = new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KANA_LOCK, +tojava java.awt.event.KeyEvent.KEY_LOCATION_STANDARD); tojava private static PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.kye.XKeysym"); tojava public static char convertKeysym( long ks, int state ) { tojava @@ -252,12 +254,35 @@ tojava } tojava } tojava return keysym; tojava } +tojava +tojava /** +tojava Return java.awt.KeyEvent constant meaning (Java) keycode, derived from X keysym. +tojava Some keysyms maps to more than one keycode, these would require extra processing. +tojava */ +tojava static Keysym2JavaKeycode getJavaKeycode( long keysym ) { +tojava if(keysym == XKeySymConstants.XK_Mode_switch){ +tojava /* XK_Mode_switch on solaris maps either to VK_ALT_GRAPH (default) or VK_KANA_LOCK */ +tojava if( XToolkit.isKanaKeyboard() ) { +tojava return kanaLock; +tojava } +tojava }else if(keysym == XKeySymConstants.XK_L1){ +tojava /* if it is Sun keyboard, trick hash to return VK_STOP else VK_F11 (default) */ +tojava if( XToolkit.isSunKeyboard() ) { +tojava keysym = XKeySymConstants.SunXK_Stop; +tojava } +tojava }else if(keysym == XKeySymConstants.XK_L2) { +tojava /* if it is Sun keyboard, trick hash to return VK_AGAIN else VK_F12 (default) */ +tojava if( XToolkit.isSunKeyboard() ) { +tojava keysym = XKeySymConstants.SunXK_Again; +tojava } +tojava } +tojava +tojava return keysym2JavaKeycodeHash.get( keysym ); +tojava } tojava /** tojava Return java.awt.KeyEvent constant meaning (Java) keycode, derived from X Window KeyEvent. tojava Algorithm is, extract via XKeycodeToKeysym a proper keysym according to Xlib spec rules and tojava err exceptions, then search a java keycode in a table. -tojava Some keysyms maps to more than one keycode, these would require extra processing. If someone -tojava points me to such a keysym. tojava */ tojava static Keysym2JavaKeycode getJavaKeycode( XKeyEvent ev ) { tojava // get from keysym2JavaKeycodeHash. @@ -272,7 +297,7 @@ tojava ndx = 0; tojava keysym = xkeycode2keysym(ev, ndx); tojava } tojava -tojava Keysym2JavaKeycode jkc = keysym2JavaKeycodeHash.get( keysym ); +tojava Keysym2JavaKeycode jkc = getJavaKeycode( keysym ); tojava return jkc; tojava } tojava static int getJavaKeycodeOnly( XKeyEvent ev ) { @@ -297,7 +322,7 @@ tojava // we only need primary-layer keysym to derive a java keycode tojava ndx = 0; tojava keysym = xkeycode2keysym_noxkb(ev, ndx); tojava } -tojava Keysym2JavaKeycode jkc = keysym2JavaKeycodeHash.get( keysym ); +tojava Keysym2JavaKeycode jkc = getJavaKeycode( keysym ); tojava return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode(); tojava } tojava static long javaKeycode2Keysym( int jkey ) { diff --git a/src/solaris/native/sun/xawt/XlibWrapper.c b/src/solaris/native/sun/xawt/XlibWrapper.c index 93fc0971c4626ec09816cdf61a30cb16a7658d7b..9607b6022d50aedf727ea3d4c7eaf71f5dd76a4f 100644 --- a/src/solaris/native/sun/xawt/XlibWrapper.c +++ b/src/solaris/native/sun/xawt/XlibWrapper.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1214,6 +1215,48 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsXsunKPBehavior } } + +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsSunKeyboard +(JNIEnv *env, jclass clazz, jlong display) +{ + int xx; + AWT_CHECK_HAVE_LOCK(); + xx = XKeysymToKeycode((Display*)jlong_to_ptr(display), SunXK_F37); + return (!xx) ? JNI_FALSE : JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsKanaKeyboard +(JNIEnv *env, jclass clazz, jlong display) +{ + int xx; + AWT_CHECK_HAVE_LOCK(); + static jboolean result = JNI_FALSE; + + int32_t minKeyCode, maxKeyCode, keySymsPerKeyCode; + KeySym *keySyms, *keySymsStart, keySym; + int32_t i; + int32_t kanaCount = 0; + + // There's no direct way to determine whether the keyboard has + // a kana lock key. From available keyboard mapping tables, it looks + // like only keyboards with the kana lock key can produce keysyms + // for kana characters. So, as an indirect test, we check for those. + XDisplayKeycodes((Display*)jlong_to_ptr(display), &minKeyCode, &maxKeyCode); + keySyms = XGetKeyboardMapping((Display*)jlong_to_ptr(display), minKeyCode, maxKeyCode - minKeyCode + 1, &keySymsPerKeyCode); + keySymsStart = keySyms; + for (i = 0; i < (maxKeyCode - minKeyCode + 1) * keySymsPerKeyCode; i++) { + keySym = *keySyms++; + if ((keySym & 0xff00) == 0x0400) { + kanaCount++; + } + } + XFree(keySymsStart); + + // use a (somewhat arbitrary) minimum so we don't get confused by a stray function key + result = kanaCount > 10; + return result ? JNI_TRUE : JNI_FALSE; +} + JavaVM* jvm = NULL; static int ToolkitErrorHandler(Display * dpy, XErrorEvent * event) { if (jvm != NULL) { @@ -1261,6 +1304,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_CallErrorHandler return (*(XErrorHandler)jlong_to_ptr(handler))((Display*) jlong_to_ptr(display), (XErrorEvent*) jlong_to_ptr(event_ptr)); } + /* * Class: sun_awt_X11_XlibWrapper * Method: PrintXErrorEvent @@ -1853,6 +1897,17 @@ Java_sun_awt_X11_XlibWrapper_XFreeModifiermap(JNIEnv *env, jclass clazz, AWT_CHECK_HAVE_LOCK(); XFreeModifiermap((XModifierKeymap*) jlong_to_ptr(keymap)); } +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XRefreshKeyboardMapping + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XRefreshKeyboardMapping +(JNIEnv *env, jclass clazz, jlong event_ptr) +{ + AWT_CHECK_HAVE_LOCK(); + XRefreshKeyboardMapping((XMappingEvent*) jlong_to_ptr(event_ptr)); +} JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XChangeActivePointerGrab(JNIEnv *env, jclass clazz,