Keyboard autorepeat

I’m wondering if any of you LWJGL users need keyboard autorepeating and, if so, how you go about using the Keyboard class to achieve it. Keyboard tells you about key down and key up events only, it seems. If anyone uses anything cleverer than an “on key down, start a thread that generates the key event every X millseconds; on key up, stop the thread”-type malarky, I would be interested to know.

I’m writing some GUI components for LWJGL and want keyboard auto-repeat in my TextFields and TextAreas. (Yes, I know, there are plenty of GUI projects out there already :slight_smile: )

If you use your imagination a bit, you can get quite far with the following code.
It was taken from my project of generating AWT Events dispatching them on the EDT using input from LWJGL.

   private static final void keyAutoFire()
   {
      // fire keytyped events after a certain timeout
      Iterator<Integer> keys = keyToTime.keySet().iterator();
      while (keys.hasNext())
      {
         Integer awtKey = keys.next();
         long time = keyToTime.get(awtKey).longValue();
         int counter = keyToCounter.get(awtKey).intValue();
         long passed = Clock.getTime() - time;

         if (counter == 0)
         {
            // never continue
         }
         if (counter == 1)
         {
            if (passed < 375)
               continue;
         }
         if (counter >= 2)
         {
            if (passed < 33)
               continue;
         }

         keyToTime.put(awtKey, new Long(Clock.getTime()));
         keyToCounter.put(awtKey, new Integer(counter + 1));

         char ch = keyToChar.get(awtKey).charValue();
         <FIRE PRESS KEY EVENT>
         if (ch != 0)
            <FIRE TYPE KEY EVENT>
      }
   }

Riven,

I like your idea of just storing the timestamp of the key down and then comparing to the current time to determine whether a key event should be fired, rather than kicking off a Thread to generate the events in between sleeps. I think I’ll do the same. (I assume your keyAutoFire method is called every frame.)

One thing I notice is that you appear to be checking all keys; I assume you get auto-repeat from multiple keys if you hold down multiple at once. I suppose that’s the way you want it, but most applications don’t seem to work that way - only the most recently depressed key keeps autorepeating. I’m just going to autorepeat the most recently depressed key only, which will save iterating through all the keys each frame: quicker :wink:

Thanks for the reply; we LWJGL folks need to stick together! Most other people on these boards seem to be using JOGL !

My GeneralKeyInput class enables key repeat.

http://jasel.cvs.sourceforge.net/jasel/jasel2.input/src/jasel2/input/GeneralKeyInput.java?view=markup

Each time I poll the Keyboard, I do


  356 		if (keyRepeat) {
  357 			for (int i = 0; i < keyTimeouts.length; ++i) {
  358 				if (keyTimeouts[i] == NOT_DOWN)
  359 					continue;
  360 
  361 				if (keyTimeouts[i] > 0) {
  362 					keyTimeouts[i] -= millis;
  363 				}
  364 
  365 				if (keyTimeouts[i] <= 0) {
  366 					buffer.add(i, keyChars[i]);
  367 					keyTimeouts[i] += repeatRate;
  368 				}
  369 
  370 			}
  371 		}

keyTimeOuts is just a giant int[], one for each key on the keyboard. When a key is first pressed, I enter the repeat rate in millis in its corresponding keyTimeOuts index. Then each cycle i subtract the amount of elapsed millis from it. If it goes < 0, then it’s time to “fire” another key event for that key, in my case that means just adding it to the keys pressed buffer.

It’s not as efficient as I’d like, but I only enable key repeat for when the user is typing, and generally that’s at a low impact part of the game like entering a high score.

That’s the gist of it anyway. There is more going on in the class, like the initial repeat event is longer, to simulate what typically happens in typing (press and hold down a key, the second letter won’t appear for a bit, then they rapidly repeat from there)