1

Apparently this question has been asked before and before and before, but either the answers are not solving the problem or use a language not understandable by me.

I have to register a keyboard action using JComponent.WHEN_IN_FOCUSED_WINDOW, so a KeyListener is not an alternative. I have to track pressing down and releasing the key, say a cursor key. I cannot have multiple press/release firings due to some built-in key repeat. I really want to know when the key is physically pressed and depressed. E.g., start a timer when pressed, stop the timer when released (and do not start and stop the timer dozens of times because of the virtual key repeats).

I believe this worked correctly on OS X, but I am on Linux now (OpenJDK 7).

How?

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
0__
  • 66,707
  • 21
  • 171
  • 266

1 Answers1

2

As multiple people have noted, this is an oddity (or: bug) on Linux.

The work-around goes as follows. Let's say the press action class is called ActionPress, and the release action class is called ActionRelease.

  • both maintain a long lastWhen that is updated in actionPerformed with e.getWhen. They have a public method getLastWhen that can be called by their counterparts.
  • ActionRelease maintains a javax.swing.Timer with a few milliseconds. It's regular actionPerformed restarts the timer, nothing else.
  • ActionPress in its actionPerformed calls the corresponding ActionRelease's getLastWhen. If the result is identical to its own lastWhen, ignore the action and return, otherwise perform the action.
  • ActionRelease in the additional ActionListener for the Timer performs the actual action. In its getLastWhen implementation, it stops the timer before return lastWhen.
0__
  • 66,707
  • 21
  • 171
  • 266
  • 1. whats returns from AWTEventListener, there is repeat delay, this is part of setting in/from Native OS, 2. Swing Timer doesn't solve something – mKorbel Oct 08 '14 at 06:54
  • @mKorbel - the timer is only needed to skip release events that are part of the repeat. In that case, you get a release followed by a pressed with the _same time stamp_. So as long as you have a delay of at least 1 millisecond, this works, it doesn't matter what the OS's key repeat rate is actually. What is important is that the `ActionPress` can kick in first and "invalidate" the previous release event. – 0__ Oct 08 '14 at 09:51