6711676: Numpad keys trigger more than one KeyEvent.
Summary: Introduce a new sniffer based on server keymap.
Reviewed-by: art
--- a/jdk/make/sun/xawt/mapfile-vers Tue Jun 23 16:10:19 2009 +0400
+++ b/jdk/make/sun/xawt/mapfile-vers Fri Jun 26 11:48:58 2009 +0400
@@ -125,6 +125,7 @@
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;
--- a/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java Tue Jun 23 16:10:19 2009 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java Fri Jun 26 11:48:58 2009 +0400
@@ -145,7 +145,7 @@
{
// 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 @@
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;
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Tue Jun 23 16:10:19 2009 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Fri Jun 26 11:48:58 2009 +0400
@@ -2130,39 +2130,33 @@
*/
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( ! XlibWrapper.ServerVendor(getDisplay()).startsWith("Sun Microsystems") ) {
- awt_ServerInquired = true;
- awt_IsXsunServer = false;
- return false;
+ if( awt_IsXsunKPBehavior == 0 ) {
+ if( XlibWrapper.IsXsunKPBehavior(getDisplay()) ) {
+ awt_IsXsunKPBehavior = XSUN_KP_BEHAVIOR;
+ }else{
+ awt_IsXsunKPBehavior = XORG_KP_BEHAVIOR;
+ }
}
- // 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();
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java Tue Jun 23 16:10:19 2009 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java Fri Jun 26 11:48:58 2009 +0400
@@ -352,6 +352,7 @@
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);
--- a/jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h Tue Jun 23 16:10:19 2009 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h Fri Jun 26 11:48:58 2009 +0400
@@ -183,7 +183,7 @@
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 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;
--- a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c Tue Jun 23 16:10:19 2009 +0400
+++ b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c Fri Jun 26 11:48:58 2009 +0400
@@ -1181,6 +1181,38 @@
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) {