From c61b48b28b5d592b56ba2481243c4e1bd28dd125 Mon Sep 17 00:00:00 2001 From: Yuri Nesterenko Date: Fri, 26 Jun 2009 11:48:58 +0400 Subject: [PATCH] 6711676: Numpad keys trigger more than one KeyEvent Introduce a new sniffer based on server keymap. Reviewed-by: art --- jdk/make/sun/xawt/mapfile-vers | 1 + .../solaris/classes/sun/awt/X11/XKeysym.java | 4 +- .../solaris/classes/sun/awt/X11/XToolkit.java | 40 ++++++++----------- .../classes/sun/awt/X11/XlibWrapper.java | 1 + .../solaris/classes/sun/awt/X11/keysym2ucs.h | 4 +- jdk/src/solaris/native/sun/xawt/XlibWrapper.c | 32 +++++++++++++++ 6 files changed, 55 insertions(+), 27 deletions(-) diff --git a/jdk/make/sun/xawt/mapfile-vers b/jdk/make/sun/xawt/mapfile-vers index 87d274b5f2b..ce536f7a459 100644 --- a/jdk/make/sun/xawt/mapfile-vers +++ b/jdk/make/sun/xawt/mapfile-vers @@ -125,6 +125,7 @@ SUNWprivate_1.1 { Java_sun_awt_X11_XlibWrapper_XFree; Java_sun_awt_X11_XlibWrapper_ServerVendor; Java_sun_awt_X11_XlibWrapper_VendorRelease; + Java_sun_awt_X11_XlibWrapper_IsXsunKPBehavior; Java_sun_awt_X11_XlibWrapper_SetToolkitErrorHandler; Java_sun_awt_X11_XlibWrapper_XSetErrorHandler; Java_sun_awt_X11_XlibWrapper_CallErrorHandler; diff --git a/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java b/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java index 46137fbea96..ea39aeacc94 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java @@ -145,7 +145,7 @@ public class XKeysym { { // Xsun without XKB uses keysymarray[2] keysym to determine if it is KP event. // Otherwise, it is [1]. - int ndx = XToolkit.isXsunServer() && + int ndx = XToolkit.isXsunKPBehavior() && ! XToolkit.isXKBenabled() ? 2 : 1; // Even if XKB is enabled, we have another problem: some symbol tables (e.g. cz) force // a regular comma instead of KP_comma for a decimal separator. Result is, @@ -193,7 +193,7 @@ public class XKeysym { private static long getKeypadKeysym( XKeyEvent ev ) { int ndx = 0; long keysym = XConstants.NoSymbol; - if( XToolkit.isXsunServer() && + if( XToolkit.isXsunKPBehavior() && ! XToolkit.isXKBenabled() ) { if( (ev.get_state() & XConstants.ShiftMask) != 0 ) { // shift modifier is on ndx = 3; diff --git a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java index 038f8534499..14839c7b671 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -2130,39 +2130,33 @@ public final class XToolkit extends UNIXToolkit implements Runnable { */ private static int backingStoreType; - static boolean awt_ServerInquired = false; - static boolean awt_IsXsunServer = false; + static final int XSUN_KP_BEHAVIOR = 1; + static final int XORG_KP_BEHAVIOR = 2; + + static int awt_IsXsunKPBehavior = 0; static boolean awt_UseXKB = false; static boolean awt_UseXKB_Calls = false; static int awt_XKBBaseEventCode = 0; static int awt_XKBEffectiveGroup = 0; // so far, I don't use it leaving all calculations // to XkbTranslateKeyCode static long awt_XKBDescPtr = 0; + /** - Try to understand if it is Xsun server. - By now (2005) Sun is vendor of Xsun and Xorg servers; we only return true if Xsun is running. - */ - static boolean isXsunServer() { + * Check for Xsun convention regarding numpad keys. + * Xsun and some other servers (i.e. derived from Xsun) + * under certain conditions process numpad keys unlike Xorg. + */ + static boolean isXsunKPBehavior() { awtLock(); try { - if( awt_ServerInquired ) { - return awt_IsXsunServer; + if( awt_IsXsunKPBehavior == 0 ) { + if( XlibWrapper.IsXsunKPBehavior(getDisplay()) ) { + awt_IsXsunKPBehavior = XSUN_KP_BEHAVIOR; + }else{ + awt_IsXsunKPBehavior = XORG_KP_BEHAVIOR; + } } - if( ! XlibWrapper.ServerVendor(getDisplay()).startsWith("Sun Microsystems") ) { - awt_ServerInquired = true; - awt_IsXsunServer = false; - return false; - } - // Now, it's Sun. It still may be Xorg though, eg on Solaris 10, x86. - // Today (2005), VendorRelease of Xorg is a Big Number unlike Xsun. - if( XlibWrapper.VendorRelease(getDisplay()) > 10000 ) { - awt_ServerInquired = true; - awt_IsXsunServer = false; - return false; - } - awt_ServerInquired = true; - awt_IsXsunServer = true; - return true; + return awt_IsXsunKPBehavior == XSUN_KP_BEHAVIOR ? true : false; } finally { awtUnlock(); } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java b/jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java index 19fd7df206a..3ef2f69ae85 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java @@ -352,6 +352,7 @@ static native String XSetLocaleModifiers(String modifier_list); static native int XIconifyWindow(long display, long window, long screenNumber); static native String ServerVendor(long display); static native int VendorRelease(long display); + static native boolean IsXsunKPBehavior(long display); static native void XBell(long display, int percent); diff --git a/jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h b/jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h index 09ea14b1f95..e03e2a79c04 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h +++ b/jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h @@ -183,7 +183,7 @@ tojava public static boolean isKPEvent( XKeyEvent ev ) tojava { tojava // Xsun without XKB uses keysymarray[2] keysym to determine if it is KP event. tojava // Otherwise, it is [1]. -tojava int ndx = XToolkit.isXsunServer() && +tojava int ndx = XToolkit.isXsunKPBehavior() && tojava ! XToolkit.isXKBenabled() ? 2 : 1; tojava // Even if XKB is enabled, we have another problem: some symbol tables (e.g. cz) force tojava // a regular comma instead of KP_comma for a decimal separator. Result is, @@ -231,7 +231,7 @@ tojava */ tojava private static long getKeypadKeysym( XKeyEvent ev ) { tojava int ndx = 0; tojava long keysym = XConstants.NoSymbol; -tojava if( XToolkit.isXsunServer() && +tojava if( XToolkit.isXsunKPBehavior() && tojava ! XToolkit.isXKBenabled() ) { tojava if( (ev.get_state() & XConstants.ShiftMask) != 0 ) { // shift modifier is on tojava ndx = 3; diff --git a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c index ce8cadbf391..93fc0971c46 100644 --- a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c +++ b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c @@ -1181,6 +1181,38 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_VendorRelease AWT_CHECK_HAVE_LOCK(); return VendorRelease((Display*)jlong_to_ptr(display)); } +/* + * Class: sun_awt_X11_XlibWrapper + * Method: IsXsunKPBehavior + * Signature: (J)Z; + */ +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsXsunKPBehavior +(JNIEnv *env, jclass clazz, jlong display) +{ + // Xsun without XKB uses keysymarray[2] keysym to determine if it is KP event. + // Otherwise, it is [1] or sometimes [0]. + // This sniffer first tries to determine what is a keycode for XK_KP_7 + // using XKeysymToKeycode; + // second, in which place in the keysymarray is XK_KP_7 + // using XKeycodeToKeysym. + int kc7; + AWT_CHECK_HAVE_LOCK(); + kc7 = XKeysymToKeycode((Display*)jlong_to_ptr(display), XK_KP_7); + if( !kc7 ) { + // keycode is not defined. Why, it's a reduced keyboard perhaps: + // report arbitrarily false. + return JNI_FALSE; + } else { + long ks2 = XKeycodeToKeysym((Display*)jlong_to_ptr(display), kc7, 2); + if( ks2 == XK_KP_7 ) { + //XXX If some Xorg server would put XK_KP_7 in keysymarray[2] as well, + //XXX for yet unknown to me reason, the sniffer would lie. + return JNI_TRUE; + }else{ + return JNI_FALSE; + } + } +} JavaVM* jvm = NULL; static int ToolkitErrorHandler(Display * dpy, XErrorEvent * event) {