JDK-4834514 : Toolkit.getLockingKeyState doesn't work with XKB enabled.
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic,linux
  • CPU: generic,x86
  • Submitted: 2003-03-19
  • Updated: 2016-06-01
  • Resolved: 2016-06-01
Related Reports
Duplicate :  
Description
If you enable the XKB extension on the Linux or Solaris X servers the
Toolkit.getLockingKeyState() method never returns the correct values.

In the case of XKB off, the call used to determine the state of the 
locking keys is valid, in that it will set the correct bit in the mask
for the lock keys if the toggle is on. Unfortunately in the case of
XKB being enabled this is no longer the case, in and this state bit
is only set if the key is physically held down. This is best described
in a quote from a discussion I had with Ivan Pascal in the XFree86 
organisation:

     It's a compatibility issue. True.  But is it a bug of a new extension? I
     don't think so.  The problem is an unflexibility and even a dumbness of a
     core protocol in the keyboard part.  It assumes modifier bits are
     strongly bound to keys (not kesyms) and they automaticaly change a state
     with a changing of key logical state.

     But in XKB all modifiers can be changed by actions that are bound to
     keysyms.  And there are at least two methods to change a modifier bit: a
     temporary activation while a key is physycaly down and a 'toggling' where
     a modifier keeps its state after a key release until a next pressing.

     It allows to control modifiers in a more flexible way.  The same key can
     change more the one modifier (and do some other tasks) in depend on other
     modifier keys (such as Shift/Alt/Ctrl) state or a current layout (XKB
     allows to have up to four layouts in a one keyboard map).

     For example, the NumLock key your are talking about, in default
     configuration do two tasks.  Being pressed alone it changes the NumLock
     modifier bit but with Shift key pressed it toggles the 'Mouse Keys mode'.
     And how you suggest to interpret its 'logical state'?  As the modifier
     state or the state of Mouse Keys mode?

On Linux XKB is enabled by default, on Solaris it's not, but should be
for accessibility support. 

This is a core API of Java and should be fixed to return the correct values
regardless of the Xserver configuration.

Because of this it's not possible to correctly implement the Java Accessiblity
Bridge for GNOME such that it can inform GNOME Accessibility Tools about
the state of keys such as NUM_LOCK / CAPS_LOCK, etc.

I've attached a simple program led.c that implements the same mechanism
used by Java to determine the key states - try running it with XKB
off first, and you can see the expected behaviour. Then turn on XKB
and see how the behaviour differs.

BTW, this is not specific to any single version of Java, it seems to be
present in ALL implementations of Sun VMs that I've tested from 1.4 up...

Comments
Hi Pete, it seems it was fixed in https://bugs.openjdk.java.net/browse/JDK-5100701
01-06-2016

Semyon, Please look at this Linux keyboard handling issue.
01-06-2016

WORK AROUND There is no Java based workaround available.
17-09-2004

EVALUATION The XKB extension is described at: http://ftp.xfree86.org/pub/XFree86/4.0.3/doc/PostScript/XKBlib.PS ###@###.### 2003-03-20 According to the comments, XKB is not compatible with the core X protocol. In other words, existing X-Windows programs will break when XKB is running. If this is really true, this is a request for support for interoperability with a new and incompatible protocol. It will have to be approved by the CCC, and (I think) communicated to the ARC. Therefore, I have to change this to an RFE. ###@###.### 2003-03-28 On RedHat Linux 9, I tried running led.c with xkb on (the default) and off. I had to edit /etc/X11/XF86Config to do it, and then restart the xserver. XKB off ------- Numlock is off : $ ./led 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 False Numlock is on: $ ./led 00 00 00 00 10 00 00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 True So, they are different. XKB on ------ Numlock is on or off returns the same result $ ./led 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 False ###@###.### 2003-05-12
12-05-2003

SUGGESTED FIX The fix is to handle the case where XKB is enabled and use the XKB API to determine the state of the Lock keys, or use another method for which Ivan had a possible solution, but it will require modification to the Java implementation: In the core protocol there is only one reliable way to get a current state of a mofifier bit - to catch any key event and get the modifier state from it. ============================================================================== Saving away the state of the numlock key on any key event is certainly possible. If we did this, it would be necessary to note that the state doesn't change on the event - it changes after the event has been fired. So, if the key pressed/released is the numlock key, we would need to remember that the state should be inverted. Below is the output of xev. NumLock was off when I started. I then typed a, numlock, a, numlock, a. So NumLock was off when I finished as well. KeyPress event, serial 23, synthetic NO, window 0xf000001, root 0x25, subw 0xf000002, time 148360096, (42,26), root:(330,50), state 0x0, keycode 84 (keysym 0x61, a), same_screen YES, XLookupString gives 1 characters: "a" KeyRelease event, serial 23, synthetic NO, window 0xf000001, root 0x25, subw 0xf000002, time 148360194, (42,26), root:(330,50), state 0x0, keycode 84 (keysym 0x61, a), same_screen YES, XLookupString gives 1 characters: "a" KeyPress event, serial 23, synthetic NO, window 0xf000001, root 0x25, subw 0xf000002, time 148361670, (42,26), root:(330,50), state 0x0, keycode 105 (keysym 0xff7f, Num_Lock), same_screen YES, XLookupString gives 0 characters: "" KeyPress event, serial 23, synthetic NO, window 0xf000001, root 0x25, subw 0xf000002, time 148365638, (42,26), root:(330,50), state 0x20, keycode 84 (keysym 0x61, a), same_screen YES, XLookupString gives 1 characters: "a" KeyRelease event, serial 23, synthetic NO, window 0xf000001, root 0x25, subw 0xf000002, time 148365743, (42,26), root:(330,50), state 0x20, keycode 84 (keysym 0x61, a), same_screen YES, XLookupString gives 1 characters: "a" KeyRelease event, serial 23, synthetic NO, window 0xf000001, root 0x25, subw 0xf000002, time 148366595, (42,26), root:(330,50), state 0x20, keycode 105 (keysym 0xff7f, Num_Lock), same_screen YES, XLookupString gives 0 characters: "" KeyPress event, serial 23, synthetic NO, window 0xf000001, root 0x25, subw 0xf000002, time 148369192, (42,26), root:(330,50), state 0x0, keycode 84 (keysym 0x61, a), same_screen YES, XLookupString gives 1 characters: "a" KeyRelease event, serial 23, synthetic NO, window 0xf000001, root 0x25, subw 0xf000002, time 148369303, (42,26), root:(330,50), state 0x0, keycode 84 (keysym 0x61, a), same_screen YES, XLookupString gives 1 characters: "a" This is probably true for other locking keys as well. However, I noticed that ScrollLock doesn't change the state of the Xevent, but CapsLock does. We ought to find out how KanaLock behaves if we pursue this. There are two other problems with this approach. 1) If the program calls Toolkit.getLockingKeyState before the user presses a key, we won't know what the state is at that point. 2) If the user switches to another application, presses NumLock, and then switches to a Java application, then calls Toolkit.getLockingKeyState before pressing a key, the Java application won't know that the state has changed. Thus, Toolkit.getLockingKeyState would still report the wrong value. ###@###.### 2003-03-19
19-03-2003