# HG changeset patch # User yan # Date 1223297100 -14400 # Node ID 12a51fb0db0d21c913ed3c146c215e88a30b3edc # Parent 726a2bc97146948e3a821ef300058ea532e0eb25 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 diff -r 726a2bc97146 -r 12a51fb0db0d jdk/make/sun/xawt/mapfile-vers --- 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; diff -r 726a2bc97146 -r 12a51fb0db0d jdk/src/solaris/classes/sun/awt/X11/XKeysym.java --- 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 javaKeycode2KeysymHash = new Hashtable(); 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); }; } diff -r 726a2bc97146 -r 12a51fb0db0d jdk/src/solaris/classes/sun/awt/X11/XToolkit.java --- 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. diff -r 726a2bc97146 -r 12a51fb0db0d jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java --- 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); diff -r 726a2bc97146 -r 12a51fb0db0d jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h --- 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 javaKeycode2KeysymHash = new Hashtable(); 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 } diff -r 726a2bc97146 -r 12a51fb0db0d jdk/src/solaris/native/sun/xawt/XlibWrapper.c --- 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,