5100701: Toolkit.getLockingKeyState() does not work on XToolkit, but works on Motif
authoryan
Mon, 06 Oct 2008 16:45:00 +0400
changeset 1966 12a51fb0db0d
parent 1965 726a2bc97146
child 1968 1a8fe25104ef
5100701: Toolkit.getLockingKeyState() does not work on XToolkit, but works on Motif Summary: Does not work on Motif but works on XToolkit now; implemented using XQueryPointer. Reviewed-by: anthony
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	Fri Oct 03 10:33:11 2008 +0400
+++ b/jdk/make/sun/xawt/mapfile-vers	Mon Oct 06 16:45:00 2008 +0400
@@ -289,6 +289,7 @@
         Java_sun_awt_X11_XlibWrapper_XGetIconSizes;
         Java_sun_awt_X11_XlibWrapper_XKeycodeToKeysym;
         Java_sun_awt_X11_XlibWrapper_XKeysymToKeycode;
+        Java_sun_awt_X11_XlibWrapper_XQueryKeymap;
         Java_sun_awt_X11_XlibWrapper_XGetModifierMapping;
         Java_sun_awt_X11_XlibWrapper_XFreeModifiermap;        
         Java_sun_awt_X11_XlibWrapper_XChangeActivePointerGrab;
--- a/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java	Fri Oct 03 10:33:11 2008 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java	Mon Oct 06 16:45:00 2008 +0400
@@ -63,6 +63,8 @@
     // TODO: or not to do: add reverse lookup javakeycode2keysym,
     // for robot only it seems to me. After that, we can remove lookup table
     // from XWindow.c altogether.
+    // Another use for reverse lookup: query keyboard state, for some keys.
+    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());
     public static char convertKeysym( long ks, int state ) {
@@ -196,6 +198,10 @@
         Keysym2JavaKeycode jkc = getJavaKeycode( ev );
         return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode();
     }
+    static long javaKeycode2Keysym( int jkey ) {
+        Long ks = javaKeycode2KeysymHash.get( jkey );
+        return  (ks == null ? 0 : ks.longValue());
+    }
     /**
         Return keysym derived from a keycode and modifiers.
         Usually an input method does this. However non-system input methods (e.g. Java IMs) do not.
@@ -1583,6 +1589,14 @@
         keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_asciitilde),     new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_TILDE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
 
         keysym2JavaKeycodeHash.put( Long.valueOf(XConstants.NoSymbol),     new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN));
+
+        /* Reverse search of keysym by keycode. */
+
+        /* Add keyboard locking codes. */
+        javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_CAPS_LOCK, XKeySymConstants.XK_Caps_Lock);
+        javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_NUM_LOCK, XKeySymConstants.XK_Num_Lock);
+        javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_SCROLL_LOCK, XKeySymConstants.XK_Scroll_Lock);
+        javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_KANA_LOCK, XKeySymConstants.XK_Kana_Lock);
     };
 
 }
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Fri Oct 03 10:33:11 2008 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Mon Oct 06 16:45:00 2008 +0400
@@ -27,6 +27,7 @@
 import java.awt.*;
 import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
+import java.awt.event.KeyEvent;
 import java.awt.datatransfer.Clipboard;
 import java.awt.dnd.DragSource;
 import java.awt.dnd.DragGestureListener;
@@ -1087,6 +1088,19 @@
     public Map mapInputMethodHighlight(InputMethodHighlight highlight)     {
         return XInputMethod.mapInputMethodHighlight(highlight);
     }
+    @Override
+    public boolean getLockingKeyState(int key) {
+        if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK ||
+               key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) {
+            throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState");
+        }
+        awtLock();
+        try {
+            return getModifierState( key );
+        } finally {
+            awtUnlock();
+        }
+    }
 
     public  Clipboard getSystemClipboard() {
         SecurityManager security = System.getSecurityManager();
@@ -1549,6 +1563,66 @@
             awtUnlock();
         }
     }
+    static boolean getModifierState( int jkc ) {
+        int iKeyMask = 0;
+        long ks = XKeysym.javaKeycode2Keysym( jkc );
+        int  kc = XlibWrapper.XKeysymToKeycode(getDisplay(), ks);
+        if (kc == 0) {
+            return false;
+        }
+        awtLock();
+        try {
+            XModifierKeymap modmap = new XModifierKeymap(
+                 XlibWrapper.XGetModifierMapping(getDisplay()));
+
+            int nkeys = modmap.get_max_keypermod();
+
+            long map_ptr = modmap.get_modifiermap();
+            for( int k = 0; k < 8; k++ ) {
+                for (int i = 0; i < nkeys; ++i) {
+                    int keycode = Native.getUByte(map_ptr, k * nkeys + i);
+                    if (keycode == 0) {
+                        continue; // ignore zero keycode
+                    }
+                    if (kc == keycode) {
+                        iKeyMask = 1 << k;
+                        break;
+                    }
+                }
+                if( iKeyMask != 0 ) {
+                    break;
+                }
+            }
+            XlibWrapper.XFreeModifiermap(modmap.pData);
+            if (iKeyMask == 0 ) {
+                return false;
+            }
+            // Now we know to which modifier is assigned the keycode
+            // correspondent to the keysym correspondent to the java
+            // keycode. We are going to check a state of this modifier.
+            // If a modifier is a weird one, we cannot help it.
+            long window = 0;
+            try{
+                // get any application window
+                window = ((Long)(winMap.firstKey())).longValue();
+            }catch(NoSuchElementException nex) {
+                // get root window
+                window = getDefaultRootWindow();
+            }
+            boolean res = XlibWrapper.XQueryPointer(getDisplay(), window,
+                                            XlibWrapper.larg1, //root
+                                            XlibWrapper.larg2, //child
+                                            XlibWrapper.larg3, //root_x
+                                            XlibWrapper.larg4, //root_y
+                                            XlibWrapper.larg5, //child_x
+                                            XlibWrapper.larg6, //child_y
+                                            XlibWrapper.larg7);//mask
+            int mask = Native.getInt(XlibWrapper.larg7);
+            return ((mask & iKeyMask) != 0);
+        } finally {
+            awtUnlock();
+        }
+    }
 
     /* Assign meaning - alt, meta, etc. - to X modifiers mod1 ... mod5.
      * Only consider primary symbols on keycodes attached to modifiers.
--- a/jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java	Fri Oct 03 10:33:11 2008 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java	Mon Oct 06 16:45:00 2008 +0400
@@ -485,6 +485,7 @@
     static native int XdbeEndIdiom(long display);
     static native int XdbeSwapBuffers(long display, long swap_info, int num_windows);
 
+    static native void XQueryKeymap(long display, long vector);
     static native long XKeycodeToKeysym(long display, int keycode, int index);
 
     static native int XKeysymToKeycode(long display, long keysym);
--- a/jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h	Fri Oct 03 10:33:11 2008 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h	Mon Oct 06 16:45:00 2008 +0400
@@ -101,6 +101,8 @@
 tojava     // TODO: or not to do: add reverse lookup javakeycode2keysym,
 tojava     // for robot only it seems to me. After that, we can remove lookup table
 tojava     // from XWindow.c altogether.
+tojava     // Another use for reverse lookup: query keyboard state, for some keys.
+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     public static char convertKeysym( long ks, int state ) {
@@ -234,6 +236,10 @@
 tojava         Keysym2JavaKeycode jkc = getJavaKeycode( ev );
 tojava         return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode();
 tojava     }
+tojava     static long javaKeycode2Keysym( int jkey ) {
+tojava         Long ks = javaKeycode2KeysymHash.get( jkey );
+tojava         return  (ks == null ? 0 : ks.longValue());
+tojava     }
 tojava     /**
 tojava         Return keysym derived from a keycode and modifiers.
 tojava         Usually an input method does this. However non-system input methods (e.g. Java IMs) do not.
@@ -2634,6 +2640,14 @@
 tojava         keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_asciitilde),     new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_TILDE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
 tojava
 tojava         keysym2JavaKeycodeHash.put( Long.valueOf(XConstants.NoSymbol),     new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN));
+tojava
+tojava         /* Reverse search of keysym by keycode. */
+tojava
+tojava         /* Add keyboard locking codes. */
+tojava         javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_CAPS_LOCK, XKeySymConstants.XK_Caps_Lock);
+tojava         javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_NUM_LOCK, XKeySymConstants.XK_Num_Lock);
+tojava         javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_SCROLL_LOCK, XKeySymConstants.XK_Scroll_Lock);
+tojava         javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_KANA_LOCK, XKeySymConstants.XK_Kana_Lock);
 tojava     };
 tojava
 tojava }
--- a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c	Fri Oct 03 10:33:11 2008 +0400
+++ b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c	Mon Oct 06 16:45:00 2008 +0400
@@ -1641,6 +1641,13 @@
     AWT_CHECK_HAVE_LOCK();
     return XdbeSwapBuffers((Display*) jlong_to_ptr(display), (XdbeSwapInfo *) jlong_to_ptr(swap_info), num_windows);
 }
+JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XQueryKeymap
+(JNIEnv *env, jclass clazz, jlong display, jlong vector)
+{
+
+    AWT_CHECK_HAVE_LOCK();
+    XQueryKeymap( (Display *) jlong_to_ptr(display), (char *) jlong_to_ptr(vector));
+}
 
 JNIEXPORT jlong JNICALL
 Java_sun_awt_X11_XlibWrapper_XKeycodeToKeysym(JNIEnv *env, jclass clazz,