6711676: Numpad keys trigger more than one KeyEvent.
authoryan
Fri, 26 Jun 2009 11:48:58 +0400
changeset 3088 b0260407a050
parent 3087 e5f156d403ad
child 3089 31511b19b797
6711676: Numpad keys trigger more than one KeyEvent. Summary: Introduce a new sniffer based on server keymap. Reviewed-by: art
jdk/make/sun/xawt/mapfile-vers
jdk/src/solaris/classes/sun/awt/X11/XKeysym.java
jdk/src/solaris/classes/sun/awt/X11/XToolkit.java
jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java
jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h
jdk/src/solaris/native/sun/xawt/XlibWrapper.c
--- 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) {