# Keyboard and Mouse callbacks in GLUT

I'm using OpenGL via GLUT in Ubuntu.

While writing text in a text editor, the first keystroke is printed immediately.
But if we keep pressing the key, it waits for a moment and then prints a trail of that character.


This is to reduce the sensitivity while typing.

With GLUT, function callbacks for keyboard behave like that.

glutKeyboardFunc( keyboard );
glutKeyboardUpFunc( keyboard_up );


Now if we keep pressing a key, there is a considerable delay between the first and the second call of keyboard ( and keyboard_up) function. But in real gaming, this not should be the case.

Question 1: How to solve the problem?

Question 2: keyboard_up gets called even if I press and hold a key. Why so? I think it is supposed to get called only when I release it. Moreover, this also suffers from the above jerk problem.

Question 3: For glutMouseFunc( mouse ), the mouse function gets called whenever we press or release a mouse button. I want this too to get called repeatedly if I press and hold my mouse button, and that too without jerk. How to do so?

• I've edited your question to replace "OpenGL" with "GLUT" since it's actually nothing to do with OpenGL. – Maximus Minimus Sep 26 '13 at 14:21
• Short tangential answer: games don't use GLUT. – Sean Middleditch Oct 4 '13 at 19:30

glutIgnoreKeyRepeat to ignore auto-repeated keystrokes. (that resolves Questions 1 & 2.)

There, unfortunately, isn't an option to make the mouse button's get called repeatedly. You can, however, create variables recording the mouse button states. And then read those when you need to know if a button is down. Just as good, or better. (Question 3)

Further Description: Recording key-states in variables for repeated use over many frames

Typically in games when you walk forward using a key, they don't rely on the OS's key-repeat. That can be adjusted so the repeat will likely be much slower then your game-loop cycle. That will create jerky movement that could be smoothed out if it was calculated on a per-frame basis.

One of the simplest ways to cut out that jerky movement, is to check that keys state on a per-frame basis. You can do that with function call's, that however will add a bit of unneeded overhead. So instead, you can record the key-state locally in the program. Since GLUT defines a key with char, there are only 255 different key's that you might get. So you only need an array 255 bytes long to store each key's state.

But then there are the 3 mouse buttons. 3 bytes, 1 for each mouse button. The ending result of all this is:

#define BUTTON_UP   0
#define BUTTON_DOWN 1

#define MOUSE_LEFT   0
#define MOUSE_MIDDLE 1
#define MOUSE_RIGHT  2

unsigned char keyState[255];
unsigned char mouseState[3];

void keyboard(unsigned char key, int x, int y)
{
keyState[key] = BUTTON_DOWN;
}

void keyboard_up(unsigned char key, int x, int y)
{
keyState[key] = BUTTON_UP;
}

void mouse(int button, int button_state, int x, int y)
{
#define state ( (button_state == GLUT_DOWN) ? BUTTON_DOWN : BUTTON_UP ) // shortens later code

switch (button)
{
case GLUT_MOUSE_LEFT:
mouseState[MOUSE_LEFT] = state;
break;
case GLUT_MOUSE_MIDDLE:
mouseState[MOUSE_MIDDLE] = state;
break;
case GLUT_MOUSE_RIGHT:
mouseState[MOUSE_RIGHT] = state;
break;
}

#undef state // make sure the defined "state" code above is only used in this function
}

void main()
{
// some fancy code

if (keyState[(unsigned char)'W'] == BUTTON_DOWN) // Walk forward
{
// W is being pressed! Time to walk.
}

if (keyState[(unsigned char)'1'] == BUTTON_DOWN) // render in Wire-Frame
{
// toggle wire-frame rendering

// this key toggles wire-frame mode. We dont want it changing every frame,
// Or it would keep changing to fast for the user to keep track of.
// so we'll just say the key is up. Then it wont switch back before the user
keyState['1'] = BUTTON_UP;
}

// some more fancy code
}

• glutIgnoreKeyRepeat does not allow to repeat key strokes as long as it is pressed. I want it to repeat without that jerk after the first keystroke, which usually happens in dynamic games. – Shashwat Oct 4 '13 at 17:43
• For question 3, we can use glutMouseFunc along with glutMotionFunc or glutPassiveMotionFunc. But still this won't work if the mouse is still. – Shashwat Oct 4 '13 at 17:48
• Made an edit. Should be enough to get you going. – Wolfgang Skyler Oct 4 '13 at 22:15

glutSetKeyRepeat is faster than glutIgnoreKeyRepeat, so says this man page

glutIgnoreKeyRepeat can prevent these auto repeated keystrokes from being reported as keyboard or special callbacks, but there is still some minimal overhead by the X server to continually stream KeyPress events to the GLUT application. The glutSetKeyRepeat routine can be used to actually disable the global sending of auto repeated KeyPress events.

Put this in your init/main

glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);