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
--- 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,