提交 13d6d8d8 编写于 作者: Y yan

5099725: AWT doesn't seem to handle MappingNotify events under X11.

5036807: Pressing action keys "STOP/AGAIN/COMPOSE" generates keycode of F11/F12 keys.
4787377: VK_STOP key on Solaris generates wrong Key Code
Summary: Added an event processing lumped with similar native code for similar bugs.
Reviewed-by: art
上级 408c7436
......@@ -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;
......
......@@ -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();
}
......
......@@ -69,6 +69,8 @@ public class XKeysym {
static Hashtable<Integer, Long> javaKeycode2KeysymHash = new Hashtable<Integer, Long>();
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 ) {
......
......@@ -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 {
......
......@@ -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);
......
......@@ -107,6 +107,8 @@ tojava // Another use for reverse lookup: query keyboard state, for some key
tojava static Hashtable<Integer, Long> javaKeycode2KeysymHash = new Hashtable<Integer, Long>();
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 ) {
......
......@@ -33,6 +33,7 @@
#include <X11/extensions/shape.h>
#include <string.h>
#include <stdlib.h>
#include <X11/Sunkeysym.h>
#include <jni.h>
#include <jni_util.h>
......@@ -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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册