From 4f58e4f75c3d57437da215f4119e9991b77272e0 Mon Sep 17 00:00:00 2001 From: Nigel Stewart Date: Sun, 14 Mar 2004 04:36:02 +0000 Subject: [PATCH] Resolution of X11 key-repeat handling glutSetKeyRepeat is global to all FreeGLUT windows in the application glutIgnoreKeyRepeat is a per-window over-ride To avoid nasty global X11 state interaction, or GLUT-style event queue filtering - the approach in FreeGLUT is to use the current key state XQueryKeymap to detect and ignore KeyRelease/KeyPress pairs that are auto-generated. See also: http://pyopengl.sourceforge.net/documentation/manual/glutSetKeyRepeat.3GLUT.xml http://pyopengl.sourceforge.net/documentation/manual/glutIgnoreKeyRepeat.3GLUT.xml git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@476 7f0cb862-5218-0410-a997-914c9d46530a --- src/freeglut_init.c | 4 ++-- src/freeglut_internal.h | 7 +++++-- src/freeglut_main.c | 28 ++++++++++++++++++++++++++++ src/freeglut_misc.c | 40 +++++++++++++++++----------------------- src/freeglut_state.c | 2 +- src/freeglut_structure.c | 3 +++ 6 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/freeglut_init.c b/src/freeglut_init.c index e25404f..8fce87f 100644 --- a/src/freeglut_init.c +++ b/src/freeglut_init.c @@ -65,7 +65,7 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */ GL_FALSE, /* UseCurrentContext */ GL_FALSE, /* GLDebugSwitch */ GL_FALSE, /* XSyncSwitch */ - GL_FALSE, /* IgnoreKeyRepeat */ + GL_TRUE, /* KeyRepeat */ 0xffffffff, /* Modifiers */ 0, /* FPSInterval */ 0, /* SwapCount */ @@ -272,7 +272,7 @@ void fgDeinitialize( void ) fgState.ActionOnWindowClose = GLUT_ACTION_EXIT; fgState.ExecState = GLUT_EXEC_STATE_INIT; - fgState.IgnoreKeyRepeat = GL_TRUE; + fgState.KeyRepeat = GL_FALSE; fgState.Modifiers = 0xffffffff; fgState.GameModeSize.X = 640; diff --git a/src/freeglut_internal.h b/src/freeglut_internal.h index 23ff6b6..0427784 100644 --- a/src/freeglut_internal.h +++ b/src/freeglut_internal.h @@ -233,7 +233,7 @@ struct tagSFG_State GLboolean GLDebugSwitch; /* OpenGL state debugging switch */ GLboolean XSyncSwitch; /* X11 sync protocol switch */ - GLboolean IgnoreKeyRepeat; /* Whether to ignore key repeat. */ + int KeyRepeat; /* Global key repeat mode. */ int Modifiers; /* Current ALT/SHIFT/CTRL state */ GLuint FPSInterval; /* Interval between FPS printfs */ @@ -367,10 +367,13 @@ struct tagSFG_WindowState int Cursor; /* The currently selected cursor */ long JoystickPollRate; /* The joystick polling rate */ - long JoystickLastPoll; /* When the last poll has happened */ + long JoystickLastPoll; /* When the last poll happened */ int MouseX, MouseY; /* The most recent mouse position */ + GLboolean IgnoreKeyRepeat; /* Whether to ignore key repeat. */ + GLboolean KeyRepeating; /* Currently in repeat mode */ + GLboolean IsGameMode; /* Is this the game mode window? */ GLboolean NeedToResize; /* Do we need to resize the window? */ GLboolean IsOffscreen; /* Tags a `window' as on/offscreen. */ diff --git a/src/freeglut_main.c b/src/freeglut_main.c index fb75654..1763461 100644 --- a/src/freeglut_main.c +++ b/src/freeglut_main.c @@ -908,6 +908,34 @@ void FGAPIENTRY glutMainLoopEvent( void ) GETWINDOW( xkey ); GETMOUSE( xkey ); + /* Detect auto repeated keys, if configured globally or per-window */ + + if ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) + { + if (event.type==KeyRelease) + { + /* + * Look at X11 keystate to detect repeat mode. + * While X11 says the key is actually held down, we'll ignore KeyRelease/KeyPress pairs. + */ + + char keys[32]; + XQueryKeymap( fgDisplay.Display, keys ); /* Look at X11 keystate to detect repeat mode */ + + if ( keys[event.xkey.keycode>>3] & (1<<(event.xkey.keycode%8)) ) + window->State.KeyRepeating = GL_TRUE; + else + window->State.KeyRepeating = GL_FALSE; + } + } + else + window->State.KeyRepeating = GL_FALSE; + + /* Cease processing this event if it is auto repeated */ + + if (window->State.KeyRepeating) + break; + if( event.type == KeyPress ) { keyboard_cb = FETCH_WCB( *window, Keyboard ); diff --git a/src/freeglut_misc.c b/src/freeglut_misc.c index bbef626..e232d6d 100644 --- a/src/freeglut_misc.c +++ b/src/freeglut_misc.c @@ -93,49 +93,43 @@ void FGAPIENTRY glutReportErrors( void ) } /* - * Turns the ignore key auto repeat feature on and off - * - * DEPRECATED 11/4/02 - Do not use + * Control the auto-repeat of keystrokes to the current window */ void FGAPIENTRY glutIgnoreKeyRepeat( int ignore ) { - fgState.IgnoreKeyRepeat = ignore ? GL_TRUE : GL_FALSE; + freeglut_assert_ready; + freeglut_assert_window; + + fgStructure.Window->State.IgnoreKeyRepeat = ignore ? GL_TRUE : GL_FALSE; } /* - * Hints the window system whether to generate key auto repeat, or not. - * This is evil. + * Set global auto-repeat of keystrokes * - * XXX Is this also deprecated as of 20021104? + * RepeatMode should be either: + * GLUT_KEY_REPEAT_OFF + * GLUT_KEY_REPEAT_ON + * GLUT_KEY_REPEAT_DEFAULT */ void FGAPIENTRY glutSetKeyRepeat( int repeatMode ) { -#if TARGET_HOST_UNIX_X11 - freeglut_assert_ready; switch( repeatMode ) { - case GLUT_KEY_REPEAT_OFF: XAutoRepeatOff( fgDisplay.Display ); break; - case GLUT_KEY_REPEAT_ON: XAutoRepeatOn( fgDisplay.Display ); break; + case GLUT_KEY_REPEAT_OFF: + case GLUT_KEY_REPEAT_ON: + fgState.KeyRepeat = repeatMode; + break; + case GLUT_KEY_REPEAT_DEFAULT: - { - XKeyboardState keyboardState; - - XGetKeyboardControl( fgDisplay.Display, &keyboardState ); - glutSetKeyRepeat( - keyboardState.global_auto_repeat == AutoRepeatModeOn ? - GLUT_KEY_REPEAT_ON : GLUT_KEY_REPEAT_OFF - ); - } - break; + fgState.KeyRepeat = GLUT_KEY_REPEAT_ON; + break; default: fgError ("Invalid glutSetKeyRepeat mode: %d", repeatMode); break; } - -#endif } /* diff --git a/src/freeglut_state.c b/src/freeglut_state.c index 2adf2a7..0ea47a4 100644 --- a/src/freeglut_state.c +++ b/src/freeglut_state.c @@ -542,7 +542,7 @@ int FGAPIENTRY glutDeviceGet( GLenum eWhat ) return 0; case GLUT_DEVICE_IGNORE_KEY_REPEAT: - return fgState.IgnoreKeyRepeat; + return fgStructure.Window ? fgStructure.Window->State.IgnoreKeyRepeat : 0; case GLUT_DEVICE_KEY_REPEAT: /* diff --git a/src/freeglut_structure.c b/src/freeglut_structure.c index fe172d1..498dad3 100644 --- a/src/freeglut_structure.c +++ b/src/freeglut_structure.c @@ -110,6 +110,9 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, window->IsMenu = isMenu; + window->State.IgnoreKeyRepeat = GL_FALSE; + window->State.KeyRepeating = GL_FALSE; + /* * Open the window now. The fgOpenWindow() function is system * dependant, and resides in freeglut_window.c. Uses fgState. -- 1.7.10.4