From 3c3e3cd234acc4129a114a7b2ee606bd075e3c3f Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:20:57 +0000 Subject: [PATCH 01/20] Initial work on callbacks with user data parameters. -glutCreateMenuUcall -glutTimerFuncUcall -glutIdleFuncUcall git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1808 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/include/GL/freeglut_ext.h | 3 + freeglut/freeglut/include/GL/freeglut_ucall.h | 93 +++++++++++++++++++ freeglut/freeglut/src/fg_callbacks.c | 38 ++++++-- freeglut/freeglut/src/fg_ext.c | 6 ++ freeglut/freeglut/src/fg_init.c | 2 + freeglut/freeglut/src/fg_internal.h | 16 +++- freeglut/freeglut/src/fg_main.c | 4 +- freeglut/freeglut/src/fg_menu.c | 21 ++++- freeglut/freeglut/src/fg_structure.c | 11 ++- 9 files changed, 173 insertions(+), 21 deletions(-) create mode 100644 freeglut/freeglut/include/GL/freeglut_ucall.h diff --git a/freeglut/freeglut/include/GL/freeglut_ext.h b/freeglut/freeglut/include/GL/freeglut_ext.h index 2ef96c2..255edea 100644 --- a/freeglut/freeglut/include/GL/freeglut_ext.h +++ b/freeglut/freeglut/include/GL/freeglut_ext.h @@ -274,6 +274,9 @@ FGAPI void FGAPIENTRY glutAppStatusFunc(void (* callback)(int)); #define GLUT_BORDERLESS 0x0800 #define GLUT_SRGB 0x1000 +/* User-argument callbacks and implementation */ +#include "freeglut_ucall.h" + #ifdef __cplusplus } #endif diff --git a/freeglut/freeglut/include/GL/freeglut_ucall.h b/freeglut/freeglut/include/GL/freeglut_ucall.h new file mode 100644 index 0000000..9cbe82a --- /dev/null +++ b/freeglut/freeglut/include/GL/freeglut_ucall.h @@ -0,0 +1,93 @@ +#ifndef __FREEGLUT_UCALL_H__ +#define __FREEGLUT_UCALL_H__ + +/* + * freeglut_ucall.h + * + * Callbacks with user data arguments. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* + * Menu stuff, see fg_menu.c + */ +FGAPI int FGAPIENTRY glutCreateMenuUcall( void (* callback)( int menu, void* user_data ), void* user_data ); + +/* + * Global callback functions, see fg_callbacks.c + */ +FGAPI void FGAPIENTRY glutTimerFuncUcall( unsigned int time, void (* callback)( int, void* ), int value, void* user_data ); +FGAPI void FGAPIENTRY glutIdleFuncUcall( void (* callback)( void* ), void* user_data ); + +/* + * Window-specific callback functions, see fg_callbacks.c + */ +FGAPI void FGAPIENTRY glutKeyboardFuncUcall( void (* callback)( unsigned char, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpecialFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutReshapeFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutVisibilityFuncUcall( void (* callback)( int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutDisplayFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMouseFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutPassiveMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutEntryFuncUcall( void (* callback)( int, void* ), void* user_data ); + +FGAPI void FGAPIENTRY glutKeyboardUpFuncUcall( void (* callback)( unsigned char, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpecialUpFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutJoystickFuncUcall( void (* callback)( unsigned int, int, int, int, void* ), int pollInterval, void* user_data ); +FGAPI void FGAPIENTRY glutMenuStateFuncUcall( void (* callback)( int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMenuStatusFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutOverlayDisplayFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutWindowStatusFuncUcall( void (* callback)( int, void* ), void* user_data ); + +FGAPI void FGAPIENTRY glutSpaceballMotionFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpaceballRotateFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpaceballButtonFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutButtonBoxFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutDialsFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutTabletMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutTabletButtonFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data ); + +FGAPI void FGAPIENTRY glutMouseWheelFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutPositionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutCloseFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutWMCloseFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMenuDestroyFuncUcall( void (* callback)( void* ), void* user_data ); + +/* + * Multi-touch/multi-pointer extensions + */ +FGAPI void FGAPIENTRY glutMultiEntryFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMultiButtonFuncUcall( void (* callback)( int, int, int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMultiMotionFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMultiPassiveFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); + +/* + * Initialization functions, see fg_init.c + */ +#include +FGAPI void FGAPIENTRY glutInitErrorFuncUcall( void (* callback)( const char *fmt, va_list ap, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutInitWarningFuncUcall( void (* callback)( const char *fmt, va_list ap, void* ), void* user_data ); + +/* Mobile platforms lifecycle */ +FGAPI void FGAPIENTRY glutInitContextFuncUcall(void (* callback)(void*), void* user_data); +FGAPI void FGAPIENTRY glutAppStatusFuncUcall(void (* callback)(int, void*), void* user_data); + +#ifdef __cplusplus + } +#endif + +/*** END OF FILE ***/ + +#endif /* __FREEGLUT_UCALL_H__ */ + diff --git a/freeglut/freeglut/src/fg_callbacks.c b/freeglut/freeglut/src/fg_callbacks.c index 11924b3..b09f421 100644 --- a/freeglut/freeglut/src/fg_callbacks.c +++ b/freeglut/freeglut/src/fg_callbacks.c @@ -35,18 +35,31 @@ * Global callbacks. */ /* Sets the global idle callback */ +void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFuncUcall" ); + fgState.IdleCallback = callback; + fgState.IdleCallbackData = userData; +} + +void glutIdleFuncCallback( void* userData ) +{ + FGCBIdle callback = (FGCBIdle)userData; + callback(); +} + void FGAPIENTRY glutIdleFunc( FGCBIdle callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" ); - fgState.IdleCallback = callback; + glutIdleFuncUcall( glutIdleFuncCallback, (FGCBUserData)callback ); } /* Creates a timer and sets its callback */ -void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID ) +void FGAPIENTRY glutTimerFuncUcall( unsigned int timeOut, FGCBTimerUC callback, int timerID, FGCBUserData userData ) { SFG_Timer *timer, *node; - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFuncUcall" ); if( (timer = fgState.FreeTimers.Last) ) { @@ -59,9 +72,10 @@ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int tim "Memory allocation failure in glutTimerFunc()" ); } - timer->Callback = callback; - timer->ID = timerID; - timer->TriggerTime = fgElapsedTime() + timeOut; + timer->Callback = callback; + timer->CallbackData = userData; + timer->ID = timerID; + timer->TriggerTime = fgElapsedTime() + timeOut; /* Insert such that timers are sorted by end-time */ for( node = fgState.Timers.First; node; node = node->Node.Next ) @@ -73,6 +87,18 @@ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int tim fgListInsert( &fgState.Timers, &node->Node, &timer->Node ); } +void glutTimerFuncCallback( int ID, FGCBUserData userData ) +{ + FGCBTimer callback = (FGCBTimer)userData; + callback( ID ); +} + +void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" ); + glutTimerFuncUcall( timeOut, glutTimerFuncCallback, timerID, (FGCBUserData)callback ); +} + /* Deprecated version of glutMenuStatusFunc callback setting method */ void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback ) { diff --git a/freeglut/freeglut/src/fg_ext.c b/freeglut/freeglut/src/fg_ext.c index d96849a..4c1f9c9 100644 --- a/freeglut/freeglut/src/fg_ext.c +++ b/freeglut/freeglut/src/fg_ext.c @@ -210,6 +210,12 @@ static GLUTproc fghGetGLUTProcAddress( const char* procName ) CHECK_NAME(glutSetVertexAttribCoord3); CHECK_NAME(glutSetVertexAttribNormal); CHECK_NAME(glutSetVertexAttribTexCoord2); + + /* freeglut user callback functions */ + CHECK_NAME(glutCreateMenuUcall); + CHECK_NAME(glutTimerFuncUcall); + CHECK_NAME(glutIdleFuncUcall); + //TODO #undef CHECK_NAME return NULL; diff --git a/freeglut/freeglut/src/fg_init.c b/freeglut/freeglut/src/fg_init.c index ae87212..ffd3f99 100644 --- a/freeglut/freeglut/src/fg_init.c +++ b/freeglut/freeglut/src/fg_init.c @@ -70,6 +70,7 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */ { NULL, NULL }, /* Timers */ { NULL, NULL }, /* FreeTimers */ NULL, /* IdleCallback */ + NULL, /* IdleCallbackData */ 0, /* ActiveMenus */ NULL, /* MenuStateCallback */ NULL, /* MenuStatusCallback */ @@ -299,6 +300,7 @@ void fgDeinitialize( void ) fgListInit( &fgState.FreeTimers ); fgState.IdleCallback = NULL; + fgState.IdleCallbackData = NULL; fgState.MenuStateCallback = ( FGCBMenuState )NULL; fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL; diff --git a/freeglut/freeglut/src/fg_internal.h b/freeglut/freeglut/src/fg_internal.h index 2cecf71..8e27f54 100644 --- a/freeglut/freeglut/src/fg_internal.h +++ b/freeglut/freeglut/src/fg_internal.h @@ -216,6 +216,8 @@ /* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ /* Freeglut callbacks type definitions */ +typedef void* FGCBUserData; + typedef void (* FGCBDisplay )( void ); typedef void (* FGCBReshape )( int, int ); typedef void (* FGCBPosition )( int, int ); @@ -251,12 +253,15 @@ typedef void (* FGCBAppStatus)(int); /* The global callbacks type definitions */ typedef void (* FGCBIdle )( void ); +typedef void (* FGCBIdleUC )( FGCBUserData ); typedef void (* FGCBTimer )( int ); +typedef void (* FGCBTimerUC )( int, FGCBUserData ); typedef void (* FGCBMenuState )( int ); typedef void (* FGCBMenuStatus )( int, int, int ); /* The callback used when creating/using menus */ typedef void (* FGCBMenu )( int ); +typedef void (* FGCBMenuUC )( int, FGCBUserData ); /* The FreeGLUT error/warning handler type definition */ typedef void (* FGError ) ( const char *fmt, va_list ap); @@ -327,7 +332,8 @@ struct tagSFG_State SFG_List Timers; /* The freeglut timer hooks */ SFG_List FreeTimers; /* The unused timer hooks */ - FGCBIdle IdleCallback; /* The global idle callback */ + FGCBIdleUC IdleCallback; /* The global idle callback */ + FGCBUserData IdleCallbackData; /* The global idle callback data */ int ActiveMenus; /* Num. of currently active menus */ FGCBMenuState MenuStateCallback; /* Menu callbacks are global */ @@ -384,7 +390,8 @@ struct tagSFG_Timer { SFG_Node Node; int ID; /* The timer ID integer */ - FGCBTimer Callback; /* The timer callback */ + FGCBTimerUC Callback; /* The timer callback */ + FGCBUserData CallbackData; /* The timer callback user data */ fg_time_t TriggerTime; /* The timer trigger time */ }; @@ -662,7 +669,8 @@ struct tagSFG_Menu void *UserData; /* User data passed back at callback */ int ID; /* The global menu ID */ SFG_List Entries; /* The menu entries list */ - FGCBMenu Callback; /* The menu callback */ + FGCBMenuUC Callback; /* The menu callback */ + FGCBUserData CallbackData; /* The menu callback user data */ FGCBDestroy Destroy; /* Destruction callback */ GLboolean IsActive; /* Is the menu selected? */ void* Font; /* Font to be used for displaying this menu */ @@ -970,7 +978,7 @@ void fgCloseWindows (); void fgDestroyWindow( SFG_Window* window ); /* Menu creation and destruction. Defined in fg_structure.c */ -SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ); +SFG_Menu* fgCreateMenu( FGCBMenuUC menuCallback, FGCBUserData userData ); void fgDestroyMenu( SFG_Menu* menu ); /* Joystick device management functions, defined in fg_joystick.c */ diff --git a/freeglut/freeglut/src/fg_main.c b/freeglut/freeglut/src/fg_main.c index 0f47c8d..6e9ff48 100644 --- a/freeglut/freeglut/src/fg_main.c +++ b/freeglut/freeglut/src/fg_main.c @@ -233,7 +233,7 @@ static void fghCheckTimers( void ) fgListRemove( &fgState.Timers, &timer->Node ); fgListAppend( &fgState.FreeTimers, &timer->Node ); - timer->Callback( timer->ID ); + timer->Callback( timer->ID, timer->CallbackData ); } } @@ -509,7 +509,7 @@ void FGAPIENTRY glutMainLoop( void ) fgStructure.CurrentWindow->IsMenu ) /* fail safe */ fgSetWindow( window ); - fgState.IdleCallback( ); + fgState.IdleCallback( fgState.IdleCallbackData ); } else fghSleepForEvents( ); diff --git a/freeglut/freeglut/src/fg_menu.c b/freeglut/freeglut/src/fg_menu.c index 36b24ce..cad5b83 100644 --- a/freeglut/freeglut/src/fg_menu.c +++ b/freeglut/freeglut/src/fg_menu.c @@ -609,7 +609,7 @@ GLboolean fgCheckActiveMenu ( SFG_Window *window, int button, GLboolean pressed, /* Deactivate menu and then call callback (we don't want menu to stay in view while callback is executing, and user should be able to change menus in callback) */ fgDeactivateMenu( parent_window ); - active_menu->Callback( active_entry->ID ); + active_menu->Callback( active_entry->ID, active_menu->CallbackData ); /* Restore the current window and menu */ fgSetWindow( save_window ); @@ -780,14 +780,27 @@ void fghCalculateMenuBoxSize( void ) /* * Creates a new menu object, adding it to the freeglut structure */ -int FGAPIENTRY glutCreateMenu( FGCBMenu callback ) +int FGAPIENTRY glutCreateMenuUcall( FGCBMenuUC callback, FGCBUserData userData ) { /* The menu object creation code resides in fg_structure.c */ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenuUcall" ); if (fgState.ActiveMenus) fgError("Menu manipulation not allowed while menus in use."); - return fgCreateMenu( callback )->ID; + return fgCreateMenu( callback, userData )->ID; +} + +/* Standard glutCreateMenu */ +void glutCreateMenuCallback( int menu, FGCBUserData userData ) +{ + FGCBMenu callback = (FGCBMenu)userData; + callback( menu ); +} + +int FGAPIENTRY glutCreateMenu( FGCBMenu callback ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" ); + return glutCreateMenuUcall( glutCreateMenuCallback, (FGCBUserData)callback ); } /* diff --git a/freeglut/freeglut/src/fg_structure.c b/freeglut/freeglut/src/fg_structure.c index f0bc9a2..c279b4a 100644 --- a/freeglut/freeglut/src/fg_structure.c +++ b/freeglut/freeglut/src/fg_structure.c @@ -116,7 +116,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, /* * This private function creates a menu and adds it to the menus list */ -SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ) +SFG_Menu* fgCreateMenu( FGCBMenuUC menuCallback, FGCBUserData userData ) { SFG_Window *current_window = fgStructure.CurrentWindow; @@ -134,10 +134,11 @@ SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ) fgSetWindow( current_window ); /* Initialize the object properties: */ - menu->ID = ++fgStructure.MenuID; - menu->Callback = menuCallback; - menu->ActiveEntry = NULL; - menu->Font = fgState.MenuFont; + menu->ID = ++fgStructure.MenuID; + menu->Callback = menuCallback; + menu->CallbackData = userData; + menu->ActiveEntry = NULL; + menu->Font = fgState.MenuFont; fgListInit( &menu->Entries ); fgListAppend( &fgStructure.Menus, &menu->Node ); From 827f593d96c466e182676a78387b55c376220933 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:21:06 +0000 Subject: [PATCH 02/20] Finished implementing all user-data callbacks (GCC-only for now). Updated glutCreateMenu, glutIdleFunc, and glutTimerFunc so they handle NULL callback cases. Removed glutMenuStateFuncUcall (as glutMenuStateFunc is a depreciated function). git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1809 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/include/GL/freeglut_ucall.h | 9 +- freeglut/freeglut/src/fg_callbacks.c | 353 +++++++++++++++--- freeglut/freeglut/src/fg_ext.c | 36 +- freeglut/freeglut/src/fg_init.c | 48 ++- freeglut/freeglut/src/fg_internal.h | 238 +++++++++--- freeglut/freeglut/src/fg_main.c | 4 +- freeglut/freeglut/src/fg_menu.c | 8 +- freeglut/freeglut/src/fg_structure.c | 14 +- 8 files changed, 569 insertions(+), 141 deletions(-) diff --git a/freeglut/freeglut/include/GL/freeglut_ucall.h b/freeglut/freeglut/include/GL/freeglut_ucall.h index 9cbe82a..bbbd32d 100644 --- a/freeglut/freeglut/include/GL/freeglut_ucall.h +++ b/freeglut/freeglut/include/GL/freeglut_ucall.h @@ -45,7 +45,6 @@ FGAPI void FGAPIENTRY glutEntryFuncUcall( void (* callback)( int, void* ), void* FGAPI void FGAPIENTRY glutKeyboardUpFuncUcall( void (* callback)( unsigned char, int, int, void* ), void* user_data ); FGAPI void FGAPIENTRY glutSpecialUpFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); FGAPI void FGAPIENTRY glutJoystickFuncUcall( void (* callback)( unsigned int, int, int, int, void* ), int pollInterval, void* user_data ); -FGAPI void FGAPIENTRY glutMenuStateFuncUcall( void (* callback)( int, void* ), void* user_data ); FGAPI void FGAPIENTRY glutMenuStatusFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); FGAPI void FGAPIENTRY glutOverlayDisplayFuncUcall( void (* callback)( void* ), void* user_data ); FGAPI void FGAPIENTRY glutWindowStatusFuncUcall( void (* callback)( int, void* ), void* user_data ); @@ -76,12 +75,12 @@ FGAPI void FGAPIENTRY glutMultiPassiveFuncUcall( void (* callback)( int, int, in * Initialization functions, see fg_init.c */ #include -FGAPI void FGAPIENTRY glutInitErrorFuncUcall( void (* callback)( const char *fmt, va_list ap, void* ), void* user_data ); -FGAPI void FGAPIENTRY glutInitWarningFuncUcall( void (* callback)( const char *fmt, va_list ap, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutInitErrorFuncUcall( void (* callback)( const char *fmt, va_list ap, void* user_data ), void* user_data ); +FGAPI void FGAPIENTRY glutInitWarningFuncUcall( void (* callback)( const char *fmt, va_list ap, void* user_data ), void* user_data ); /* Mobile platforms lifecycle */ -FGAPI void FGAPIENTRY glutInitContextFuncUcall(void (* callback)(void*), void* user_data); -FGAPI void FGAPIENTRY glutAppStatusFuncUcall(void (* callback)(int, void*), void* user_data); +FGAPI void FGAPIENTRY glutInitContextFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutAppStatusFuncUcall( void (* callback)( int, void* ), void* user_data ); #ifdef __cplusplus } diff --git a/freeglut/freeglut/src/fg_callbacks.c b/freeglut/freeglut/src/fg_callbacks.c index b09f421..5f94b65 100644 --- a/freeglut/freeglut/src/fg_callbacks.c +++ b/freeglut/freeglut/src/fg_callbacks.c @@ -42,7 +42,7 @@ void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData ) fgState.IdleCallbackData = userData; } -void glutIdleFuncCallback( void* userData ) +static void glutIdleFuncCallback( FGCBUserData userData ) { FGCBIdle callback = (FGCBIdle)userData; callback(); @@ -51,7 +51,10 @@ void glutIdleFuncCallback( void* userData ) void FGAPIENTRY glutIdleFunc( FGCBIdle callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" ); - glutIdleFuncUcall( glutIdleFuncCallback, (FGCBUserData)callback ); + if( callback ) + glutIdleFuncUcall( glutIdleFuncCallback, (FGCBUserData)callback ); + else + glutIdleFuncUcall( NULL, NULL ); } /* Creates a timer and sets its callback */ @@ -87,7 +90,7 @@ void FGAPIENTRY glutTimerFuncUcall( unsigned int timeOut, FGCBTimerUC callback, fgListInsert( &fgState.Timers, &node->Node, &timer->Node ); } -void glutTimerFuncCallback( int ID, FGCBUserData userData ) +static void glutTimerFuncCallback( int ID, FGCBUserData userData ) { FGCBTimer callback = (FGCBTimer)userData; callback( ID ); @@ -96,7 +99,10 @@ void glutTimerFuncCallback( int ID, FGCBUserData userData ) void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" ); - glutTimerFuncUcall( timeOut, glutTimerFuncCallback, timerID, (FGCBUserData)callback ); + if( callback ) + glutTimerFuncUcall( timeOut, glutTimerFuncCallback, timerID, (FGCBUserData)callback ); + else + glutTimerFuncUcall( timeOut, NULL, timerID, NULL ); } /* Deprecated version of glutMenuStatusFunc callback setting method */ @@ -107,10 +113,26 @@ void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback ) } /* Sets the global menu status callback for the current window */ +void FGAPIENTRY glutMenuStatusFuncUCall( FGCBMenuStatusUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFuncUCall" ); + fgState.MenuStatusCallback = callback; + fgState.MenuStatusCallbackData = userData; +} + +static void glutMenuStatusFuncCallback( int menuState, int mouseX, int mouseY, FGCBUserData userData ) +{ + FGCBMenuStatus callback = (FGCBMenuStatus)userData; + callback( menuState, mouseX, mouseY ); +} + void FGAPIENTRY glutMenuStatusFunc( FGCBMenuStatus callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" ); - fgState.MenuStatusCallback = callback; + if( callback ) + glutMenuStatusFuncUCall( glutMenuStatusFuncCallback, (FGCBUserData)callback ); + else + glutMenuStatusFuncUCall( NULL, NULL ); } @@ -118,11 +140,29 @@ void FGAPIENTRY glutMenuStatusFunc( FGCBMenuStatus callback ) * Menu specific callbacks. */ /* Callback upon menu destruction */ +void FGAPIENTRY glutMenuDestroyFuncUcall( FGCBDestroyUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFuncUcall" ); + if( fgStructure.CurrentMenu ) + { + fgStructure.CurrentMenu->Destroy = callback; + fgStructure.CurrentMenu->DestroyData = userData; + } +} + +static void glutMenuDestroyFuncCallback( FGCBUserData userData ) +{ + FGCBDestroy callback = (FGCBDestroy)userData; + callback(); +} + void FGAPIENTRY glutMenuDestroyFunc( FGCBDestroy callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" ); - if( fgStructure.CurrentMenu ) - fgStructure.CurrentMenu->Destroy = callback; + if( callback ) + glutMenuDestroyFuncUcall( glutMenuDestroyFuncCallback, (FGCBUserData)callback ); + else + glutMenuDestroyFuncUcall( NULL, NULL ); } @@ -134,73 +174,189 @@ do \ { \ if( fgStructure.CurrentWindow == NULL ) \ return; \ - SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback ); \ + SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback, userData ); \ } while( 0 ) +/* + * Types need to be defined for callbacks. It's not ideal, but it works for this. + */ +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ +static void glut##a##FuncCallback( FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback(); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,b) \ +static void glut##a##FuncCallback( int arg1val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ +static void glut##a##FuncCallback( int arg1val, int arg2val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,arg1,arg2,arg3) \ +static void glut##a##FuncCallback( arg1 arg1val, arg2 arg2val, arg3 arg3val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val, arg3val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b) IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,int,int,int) +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,b) \ +static void glut##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val, arg3val, arg4val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,b) \ +static void glut##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, int arg5val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val, arg3val, arg4val, arg5val ); \ +} /* * And almost every time the callback setter function can be implemented like this: */ -#define IMPLEMENT_CALLBACK_FUNC_2NAME(a,b) \ +#define IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,b) \ +void FGAPIENTRY glut##a##FuncUcall( FGCB##b##UC callback, FGCBUserData userData ) \ +{ \ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"FuncUcall" ); \ + SET_CALLBACK( b ); \ +} \ void FGAPIENTRY glut##a##Func( FGCB##b callback ) \ { \ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"Func" ); \ - SET_CALLBACK( b ); \ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"Func" ); \ + if( callback ) \ + glut##a##FuncUcall( glut##a##FuncCallback, (FGCBUserData)callback ); \ + else \ + glut##a##FuncUcall( NULL, NULL ); \ } -#define IMPLEMENT_CALLBACK_FUNC(a) IMPLEMENT_CALLBACK_FUNC_2NAME(a,a) +/* + * Combine _glut and _cb macros: + */ +#define IMPLEMENT_CALLBACK_FUNC_ARG0(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CALLBACK_FUNC_ARG0_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,b) + +#define IMPLEMENT_CALLBACK_FUNC_ARG1(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CALLBACK_FUNC_ARG2(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CALLBACK_FUNC_ARG2_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,b) + +#define IMPLEMENT_CALLBACK_FUNC_ARG3(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CALLBACK_FUNC_ARG3_USER(a,arg1,arg2,arg3) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,a,arg1,arg2,arg3)\ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CALLBACK_FUNC_ARG4(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CALLBACK_FUNC_ARG5(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) /* Implement all these callback setter functions... */ -IMPLEMENT_CALLBACK_FUNC(Position) -IMPLEMENT_CALLBACK_FUNC(Keyboard) -IMPLEMENT_CALLBACK_FUNC(KeyboardUp) -IMPLEMENT_CALLBACK_FUNC(Special) -IMPLEMENT_CALLBACK_FUNC(SpecialUp) -IMPLEMENT_CALLBACK_FUNC(Mouse) -IMPLEMENT_CALLBACK_FUNC(MouseWheel) -IMPLEMENT_CALLBACK_FUNC(Motion) -IMPLEMENT_CALLBACK_FUNC_2NAME(PassiveMotion,Passive) -IMPLEMENT_CALLBACK_FUNC(Entry) +IMPLEMENT_CALLBACK_FUNC_ARG2(Position) +IMPLEMENT_CALLBACK_FUNC_ARG3_USER(Keyboard,unsigned char,int,int) +IMPLEMENT_CALLBACK_FUNC_ARG3_USER(KeyboardUp,unsigned char,int,int) +IMPLEMENT_CALLBACK_FUNC_ARG3(Special) +IMPLEMENT_CALLBACK_FUNC_ARG3(SpecialUp) +IMPLEMENT_CALLBACK_FUNC_ARG4(Mouse) +IMPLEMENT_CALLBACK_FUNC_ARG4(MouseWheel) +IMPLEMENT_CALLBACK_FUNC_ARG2(Motion) +IMPLEMENT_CALLBACK_FUNC_ARG2_2NAME(PassiveMotion,Passive) +IMPLEMENT_CALLBACK_FUNC_ARG1(Entry) /* glutWMCloseFunc is an alias for glutCloseFunc; both set the window's Destroy callback */ -IMPLEMENT_CALLBACK_FUNC_2NAME(Close,Destroy) -IMPLEMENT_CALLBACK_FUNC_2NAME(WMClose,Destroy) -IMPLEMENT_CALLBACK_FUNC(OverlayDisplay) -IMPLEMENT_CALLBACK_FUNC(WindowStatus) -IMPLEMENT_CALLBACK_FUNC(ButtonBox) -IMPLEMENT_CALLBACK_FUNC(Dials) -IMPLEMENT_CALLBACK_FUNC(TabletMotion) -IMPLEMENT_CALLBACK_FUNC(TabletButton) -IMPLEMENT_CALLBACK_FUNC(MultiEntry) -IMPLEMENT_CALLBACK_FUNC(MultiButton) -IMPLEMENT_CALLBACK_FUNC(MultiMotion) -IMPLEMENT_CALLBACK_FUNC(MultiPassive) -IMPLEMENT_CALLBACK_FUNC(InitContext) -IMPLEMENT_CALLBACK_FUNC(AppStatus) - - +IMPLEMENT_CALLBACK_FUNC_ARG0_2NAME(Close,Destroy) +IMPLEMENT_CALLBACK_FUNC_ARG0_2NAME(WMClose,Destroy) +IMPLEMENT_CALLBACK_FUNC_ARG0(OverlayDisplay) +IMPLEMENT_CALLBACK_FUNC_ARG1(WindowStatus) +IMPLEMENT_CALLBACK_FUNC_ARG2(ButtonBox) +IMPLEMENT_CALLBACK_FUNC_ARG2(Dials) +IMPLEMENT_CALLBACK_FUNC_ARG2(TabletMotion) +IMPLEMENT_CALLBACK_FUNC_ARG4(TabletButton) +IMPLEMENT_CALLBACK_FUNC_ARG2(MultiEntry) +IMPLEMENT_CALLBACK_FUNC_ARG5(MultiButton) +IMPLEMENT_CALLBACK_FUNC_ARG3(MultiMotion) +IMPLEMENT_CALLBACK_FUNC_ARG3(MultiPassive) +IMPLEMENT_CALLBACK_FUNC_ARG0(InitContext) +IMPLEMENT_CALLBACK_FUNC_ARG1(AppStatus) /* * Sets the Display callback for the current window */ -void FGAPIENTRY glutDisplayFunc( FGCBDisplay callback ) +void FGAPIENTRY glutDisplayFuncUcall( FGCBDisplayUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFuncUcall" ); if( !callback ) fgError( "Fatal error in program. NULL display callback not " "permitted in GLUT 3.0+ or freeglut 2.0.1+" ); SET_CALLBACK( Display ); } -void fghDefaultReshape(int width, int height) +static void glutDisplayFuncCallback( FGCBUserData userData ) +{ + FGCBDisplay callback = (FGCBDisplay)userData; + callback(); +} + +void FGAPIENTRY glutDisplayFunc( FGCBDisplay callback ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" ); + if( callback ) + glutDisplayFuncUcall( glutDisplayFuncCallback, (FGCBUserData)callback ); + else + glutDisplayFuncUcall( NULL, NULL ); +} + +void fghDefaultReshape( int width, int height, FGCBUserData userData ) { glViewport( 0, 0, width, height ); } +void FGAPIENTRY glutReshapeFuncUcall( FGCBReshapeUC callback, FGCBUserData userData ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFuncUcall" ); + + if( !callback ) + { + callback = fghDefaultReshape; + userData = NULL; + } + + SET_CALLBACK( Reshape ); +} + +static void glutReshapeFuncCallback( int width, int height, FGCBUserData userData ) +{ + FGCBReshape callback = (FGCBReshape)userData; + callback( width, height ); +} + void FGAPIENTRY glutReshapeFunc( FGCBReshape callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" ); - - if( !callback ) - callback = fghDefaultReshape; - - SET_CALLBACK( Reshape ); + if( callback ) + glutReshapeFuncUcall( glutReshapeFuncCallback, (FGCBUserData)callback ); + else + glutReshapeFuncUcall( NULL, NULL ); } /* @@ -218,7 +374,7 @@ void FGAPIENTRY glutReshapeFunc( FGCBReshape callback ) * http://stackoverflow.com/questions/5445889/get-which-process-window-is-actually-visible-in-c-sharp * for an implementation outline (but it would be polling based, not push based). */ -static void fghVisibility( int status ) +static void fghVisibility( int status, FGCBUserData userData ) { int vis_status; @@ -234,23 +390,44 @@ static void fghVisibility( int status ) INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( vis_status ) ); } -void FGAPIENTRY glutVisibilityFunc( FGCBVisibility callback ) +void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFuncUcall" ); + + if ( !callback ) + { + userData = NULL; + } + SET_CALLBACK( Visibility ); if( callback ) - glutWindowStatusFunc( fghVisibility ); + glutWindowStatusFuncUcall( fghVisibility, NULL ); else - glutWindowStatusFunc( NULL ); + glutWindowStatusFuncUcall( NULL, NULL ); +} + +static void glutVisibilityFuncCallback( int visibility, FGCBUserData userData ) +{ + FGCBVisibility callback = (FGCBVisibility)userData; + callback( visibility ); +} + +void FGAPIENTRY glutVisibilityFunc( FGCBVisibility callback ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" ); + if( callback ) + glutVisibilityFuncUcall( glutVisibilityFuncCallback, (FGCBUserData)callback ); + else + glutVisibilityFuncUcall( NULL, NULL ); } /* * Sets the joystick callback and polling rate for the current window */ -void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval ) +void FGAPIENTRY glutJoystickFuncUcall( FGCBJoystickUC callback, int pollInterval, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFuncUcall" ); fgInitialiseJoysticks (); if ( ( @@ -281,39 +458,97 @@ void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval ) fgStructure.CurrentWindow->State.JoystickLastPoll -= pollInterval; } +static void glutJoystickFuncCallback( unsigned int buttons, int axis0, int axis1, int axis2, FGCBUserData userData ) +{ + FGCBJoystick callback = (FGCBJoystick)userData; + callback( buttons, axis0, axis1, axis2 ); +} +void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" ); + if( callback ) + glutJoystickFuncUcall( glutJoystickFuncCallback, pollInterval, (FGCBUserData)callback ); + else + glutJoystickFuncUcall( NULL, pollInterval, NULL ); +} /* * Sets the spaceball motion callback for the current window */ -void FGAPIENTRY glutSpaceballMotionFunc( FGCBSpaceMotion callback ) +void FGAPIENTRY glutSpaceballMotionFuncUcall( FGCBSpaceMotionUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFuncUcall" ); fgInitialiseSpaceball(); SET_CALLBACK( SpaceMotion ); } +static void glutSpaceballMotionFuncCallback( int x, int y, int z, FGCBUserData userData ) +{ + FGCBSpaceMotion callback = (FGCBSpaceMotion)userData; + callback( x, y, z ); +} + +void FGAPIENTRY glutSpaceballMotionFunc( FGCBSpaceMotion callback ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" ); + if( callback ) + glutSpaceballMotionFuncUcall( glutSpaceballMotionFuncCallback, (FGCBUserData)callback ); + else + glutSpaceballMotionFuncUcall( NULL, NULL ); +} + /* * Sets the spaceball rotate callback for the current window */ -void FGAPIENTRY glutSpaceballRotateFunc( FGCBSpaceRotation callback ) +void FGAPIENTRY glutSpaceballRotateFuncUcall( FGCBSpaceRotationUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFuncUcall" ); fgInitialiseSpaceball(); SET_CALLBACK( SpaceRotation ); } +static void glutSpaceballRotateFuncCallback( int x, int y, int z, FGCBUserData userData ) +{ + FGCBSpaceRotation callback = (FGCBSpaceRotation)userData; + callback( x, y, z ); +} + +void FGAPIENTRY glutSpaceballRotateFunc( FGCBSpaceRotation callback ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" ); + if( callback ) + glutSpaceballRotateFuncUcall( glutSpaceballRotateFuncCallback, (FGCBUserData)callback ); + else + glutSpaceballRotateFuncUcall( NULL, NULL ); +} + /* * Sets the spaceball button callback for the current window */ -void FGAPIENTRY glutSpaceballButtonFunc( FGCBSpaceButton callback ) +void FGAPIENTRY glutSpaceballButtonFuncUcall( FGCBSpaceButtonUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFuncUcall" ); fgInitialiseSpaceball(); SET_CALLBACK( SpaceButton ); } +static void glutSpaceballButtonFuncCallback( int button, int buttonState, FGCBUserData userData ) +{ + FGCBSpaceButton callback = (FGCBSpaceButton)userData; + callback( button, buttonState ); +} + +void FGAPIENTRY glutSpaceballButtonFunc( FGCBSpaceButton callback ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" ); + if( callback ) + glutSpaceballButtonFuncUcall( glutSpaceballButtonFuncCallback, (FGCBUserData)callback ); + else + glutSpaceballButtonFuncUcall( NULL, NULL ); +} + /*** END OF FILE ***/ diff --git a/freeglut/freeglut/src/fg_ext.c b/freeglut/freeglut/src/fg_ext.c index 4c1f9c9..0ddb560 100644 --- a/freeglut/freeglut/src/fg_ext.c +++ b/freeglut/freeglut/src/fg_ext.c @@ -215,7 +215,41 @@ static GLUTproc fghGetGLUTProcAddress( const char* procName ) CHECK_NAME(glutCreateMenuUcall); CHECK_NAME(glutTimerFuncUcall); CHECK_NAME(glutIdleFuncUcall); - //TODO + CHECK_NAME(glutKeyboardFuncUcall); + CHECK_NAME(glutSpecialFuncUcall); + CHECK_NAME(glutReshapeFuncUcall); + CHECK_NAME(glutVisibilityFuncUcall); + CHECK_NAME(glutDisplayFuncUcall); + CHECK_NAME(glutMouseFuncUcall); + CHECK_NAME(glutMotionFuncUcall); + CHECK_NAME(glutPassiveMotionFuncUcall); + CHECK_NAME(glutEntryFuncUcall); + CHECK_NAME(glutKeyboardUpFuncUcall); + CHECK_NAME(glutSpecialUpFuncUcall); + CHECK_NAME(glutJoystickFuncUcall); + CHECK_NAME(glutMenuStatusFuncUcall); + CHECK_NAME(glutOverlayDisplayFuncUcall); + CHECK_NAME(glutWindowStatusFuncUcall); + CHECK_NAME(glutSpaceballMotionFuncUcall); + CHECK_NAME(glutSpaceballRotateFuncUcall); + CHECK_NAME(glutSpaceballButtonFuncUcall); + CHECK_NAME(glutButtonBoxFuncUcall); + CHECK_NAME(glutDialsFuncUcall); + CHECK_NAME(glutTabletMotionFuncUcall); + CHECK_NAME(glutTabletButtonFuncUcall); + CHECK_NAME(glutMouseWheelFuncUcall); + CHECK_NAME(glutPositionFuncUcall); + CHECK_NAME(glutCloseFuncUcall); + CHECK_NAME(glutWMCloseFuncUcall); + CHECK_NAME(glutMenuDestroyFuncUcall); + CHECK_NAME(glutMultiEntryFuncUcall); + CHECK_NAME(glutMultiButtonFuncUcall); + CHECK_NAME(glutMultiMotionFuncUcall); + CHECK_NAME(glutMultiPassiveFuncUcall); + CHECK_NAME(glutInitErrorFuncUcall); + CHECK_NAME(glutInitWarningFuncUcall); + CHECK_NAME(glutInitContextFuncUcall); + CHECK_NAME(glutAppStatusFuncUcall); #undef CHECK_NAME return NULL; diff --git a/freeglut/freeglut/src/fg_init.c b/freeglut/freeglut/src/fg_init.c index ffd3f99..a408bbe 100644 --- a/freeglut/freeglut/src/fg_init.c +++ b/freeglut/freeglut/src/fg_init.c @@ -74,6 +74,7 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */ 0, /* ActiveMenus */ NULL, /* MenuStateCallback */ NULL, /* MenuStatusCallback */ + NULL, /* MenuStatusCallbackData */ FREEGLUT_MENU_FONT, { -1, -1, GL_TRUE }, /* GameModeSize */ -1, /* GameModeDepth */ @@ -96,7 +97,9 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */ 0, /* OpenGL ContextProfile */ 0, /* HasOpenGL20 */ NULL, /* ErrorFunc */ - NULL /* WarningFunc */ + NULL, /* ErrorFuncData */ + NULL, /* WarningFunc */ + NULL /* WarningFuncData */ }; @@ -299,10 +302,11 @@ void fgDeinitialize( void ) fgListInit( &fgState.Timers ); fgListInit( &fgState.FreeTimers ); - fgState.IdleCallback = NULL; - fgState.IdleCallbackData = NULL; - fgState.MenuStateCallback = ( FGCBMenuState )NULL; - fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL; + fgState.IdleCallback = ( FGCBIdleUC )NULL; + fgState.IdleCallbackData = NULL; + fgState.MenuStateCallback = ( FGCBMenuState )NULL; + fgState.MenuStatusCallback = ( FGCBMenuStatusUC )NULL; + fgState.MenuStatusCallbackData = NULL; fgState.SwapCount = 0; fgState.SwapTime = 0; @@ -670,19 +674,49 @@ void FGAPIENTRY glutInitContextProfile( int profile ) /* * Sets the user error handler (note the use of va_list for the args to the fmt) */ -void FGAPIENTRY glutInitErrorFunc( FGError callback ) +void FGAPIENTRY glutInitErrorFuncUcall( FGErrorUC callback, FGCBUserData userData ) { /* This allows user programs to handle freeglut errors */ fgState.ErrorFunc = callback; + fgState.ErrorFuncData = userData; +} + +static void glutInitErrorFuncCallback( const char *fmt, va_list ap, FGCBUserData userData ) +{ + FGError callback = (FGError)userData; + callback( fmt, ap ); +} + +void FGAPIENTRY glutInitErrorFunc( FGError callback ) +{ + if (callback) + glutInitErrorFuncUcall( glutInitErrorFuncCallback, (FGCBUserData)callback ); + else + glutInitErrorFuncUcall( NULL, NULL ); } /* * Sets the user warning handler (note the use of va_list for the args to the fmt) */ -void FGAPIENTRY glutInitWarningFunc( FGWarning callback ) +void FGAPIENTRY glutInitWarningFuncUcall( FGWarningUC callback, FGCBUserData userData ) { /* This allows user programs to handle freeglut warnings */ fgState.WarningFunc = callback; + fgState.WarningFuncData = userData; +} + +static void glutInitWarningFuncCallback( const char *fmt, va_list ap, FGCBUserData userData ) +{ + FGWarning callback = (FGWarning)userData; + callback( fmt, ap ); +} + +void FGAPIENTRY glutInitWarningFunc( FGWarning callback ) +{ + if (callback) + glutInitWarningFuncUcall( glutInitWarningFuncCallback, (FGCBUserData)callback ); + else + glutInitWarningFuncUcall( NULL, NULL ); } /*** END OF FILE ***/ diff --git a/freeglut/freeglut/src/fg_internal.h b/freeglut/freeglut/src/fg_internal.h index 8e27f54..69401d0 100644 --- a/freeglut/freeglut/src/fg_internal.h +++ b/freeglut/freeglut/src/fg_internal.h @@ -218,54 +218,87 @@ /* Freeglut callbacks type definitions */ typedef void* FGCBUserData; -typedef void (* FGCBDisplay )( void ); -typedef void (* FGCBReshape )( int, int ); -typedef void (* FGCBPosition )( int, int ); -typedef void (* FGCBVisibility )( int ); -typedef void (* FGCBKeyboard )( unsigned char, int, int ); -typedef void (* FGCBKeyboardUp )( unsigned char, int, int ); -typedef void (* FGCBSpecial )( int, int, int ); -typedef void (* FGCBSpecialUp )( int, int, int ); -typedef void (* FGCBMouse )( int, int, int, int ); -typedef void (* FGCBMouseWheel )( int, int, int, int ); -typedef void (* FGCBMotion )( int, int ); -typedef void (* FGCBPassive )( int, int ); -typedef void (* FGCBEntry )( int ); -typedef void (* FGCBWindowStatus )( int ); -typedef void (* FGCBJoystick )( unsigned int, int, int, int ); -typedef void (* FGCBOverlayDisplay)( void ); -typedef void (* FGCBSpaceMotion )( int, int, int ); -typedef void (* FGCBSpaceRotation )( int, int, int ); -typedef void (* FGCBSpaceButton )( int, int ); -typedef void (* FGCBDials )( int, int ); -typedef void (* FGCBButtonBox )( int, int ); -typedef void (* FGCBTabletMotion )( int, int ); -typedef void (* FGCBTabletButton )( int, int, int, int ); -typedef void (* FGCBDestroy )( void ); /* Used for both window and menu destroy callbacks */ +typedef void (* FGCBDisplay )( void ); +typedef void (* FGCBDisplayUC )( FGCBUserData ); +typedef void (* FGCBReshape )( int, int ); +typedef void (* FGCBReshapeUC )( int, int, FGCBUserData ); +typedef void (* FGCBPosition )( int, int ); +typedef void (* FGCBPositionUC )( int, int, FGCBUserData ); +typedef void (* FGCBVisibility )( int ); +typedef void (* FGCBVisibilityUC )( int, FGCBUserData ); +typedef void (* FGCBKeyboard )( unsigned char, int, int ); +typedef void (* FGCBKeyboardUC )( unsigned char, int, int, FGCBUserData ); +typedef void (* FGCBKeyboardUp )( unsigned char, int, int ); +typedef void (* FGCBKeyboardUpUC )( unsigned char, int, int, FGCBUserData ); +typedef void (* FGCBSpecial )( int, int, int ); +typedef void (* FGCBSpecialUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBSpecialUp )( int, int, int ); +typedef void (* FGCBSpecialUpUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBMouse )( int, int, int, int ); +typedef void (* FGCBMouseUC )( int, int, int, int, FGCBUserData ); +typedef void (* FGCBMouseWheel )( int, int, int, int ); +typedef void (* FGCBMouseWheelUC )( int, int, int, int, FGCBUserData ); +typedef void (* FGCBMotion )( int, int ); +typedef void (* FGCBMotionUC )( int, int, FGCBUserData ); +typedef void (* FGCBPassive )( int, int ); +typedef void (* FGCBPassiveUC )( int, int, FGCBUserData ); +typedef void (* FGCBEntry )( int ); +typedef void (* FGCBEntryUC )( int, FGCBUserData ); +typedef void (* FGCBWindowStatus )( int ); +typedef void (* FGCBWindowStatusUC )( int, FGCBUserData ); +typedef void (* FGCBJoystick )( unsigned int, int, int, int ); +typedef void (* FGCBJoystickUC )( unsigned int, int, int, int, FGCBUserData ); +typedef void (* FGCBOverlayDisplay )( void ); +typedef void (* FGCBOverlayDisplayUC)( FGCBUserData ); +typedef void (* FGCBSpaceMotion )( int, int, int ); +typedef void (* FGCBSpaceMotionUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBSpaceRotation )( int, int, int ); +typedef void (* FGCBSpaceRotationUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBSpaceButton )( int, int ); +typedef void (* FGCBSpaceButtonUC )( int, int, FGCBUserData ); +typedef void (* FGCBDials )( int, int ); +typedef void (* FGCBDialsUC )( int, int, FGCBUserData ); +typedef void (* FGCBButtonBox )( int, int ); +typedef void (* FGCBButtonBoxUC )( int, int, FGCBUserData ); +typedef void (* FGCBTabletMotion )( int, int ); +typedef void (* FGCBTabletMotionUC )( int, int, FGCBUserData ); +typedef void (* FGCBTabletButton )( int, int, int, int ); +typedef void (* FGCBTabletButtonUC )( int, int, int, int, FGCBUserData ); +typedef void (* FGCBDestroy )( void ); /* Used for both window and menu destroy callbacks */ +typedef void (* FGCBDestroyUC )( FGCBUserData ); -typedef void (* FGCBMultiEntry )( int, int ); -typedef void (* FGCBMultiButton )( int, int, int, int, int ); -typedef void (* FGCBMultiMotion )( int, int, int ); -typedef void (* FGCBMultiPassive )( int, int, int ); +typedef void (* FGCBMultiEntry )( int, int ); +typedef void (* FGCBMultiEntryUC )( int, int, FGCBUserData ); +typedef void (* FGCBMultiButton )( int, int, int, int, int ); +typedef void (* FGCBMultiButtonUC )( int, int, int, int, int, FGCBUserData ); +typedef void (* FGCBMultiMotion )( int, int, int ); +typedef void (* FGCBMultiMotionUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBMultiPassive )( int, int, int ); +typedef void (* FGCBMultiPassiveUC )( int, int, int, FGCBUserData ); -typedef void (* FGCBInitContext)(); -typedef void (* FGCBAppStatus)(int); +typedef void (* FGCBInitContext )( void ); +typedef void (* FGCBInitContextUC )( FGCBUserData ); +typedef void (* FGCBAppStatus )( int ); +typedef void (* FGCBAppStatusUC )( int, FGCBUserData ); /* The global callbacks type definitions */ -typedef void (* FGCBIdle )( void ); -typedef void (* FGCBIdleUC )( FGCBUserData ); -typedef void (* FGCBTimer )( int ); -typedef void (* FGCBTimerUC )( int, FGCBUserData ); -typedef void (* FGCBMenuState )( int ); -typedef void (* FGCBMenuStatus )( int, int, int ); +typedef void (* FGCBIdle )( void ); \ +typedef void (* FGCBIdleUC )( FGCBUserData ); +typedef void (* FGCBTimer )( int ); +typedef void (* FGCBTimerUC )( int, FGCBUserData ); +typedef void (* FGCBMenuState )( int ); +typedef void (* FGCBMenuStatus )( int, int, int ); +typedef void (* FGCBMenuStatusUC )( int, int, int, FGCBUserData ); /* The callback used when creating/using menus */ -typedef void (* FGCBMenu )( int ); -typedef void (* FGCBMenuUC )( int, FGCBUserData ); +typedef void (* FGCBMenu )( int ); +typedef void (* FGCBMenuUC )( int, FGCBUserData ); /* The FreeGLUT error/warning handler type definition */ -typedef void (* FGError ) ( const char *fmt, va_list ap); -typedef void (* FGWarning ) ( const char *fmt, va_list ap); +typedef void (* FGError )( const char *fmt, va_list ap ); +typedef void (* FGErrorUC )( const char *fmt, va_list ap, FGCBUserData userData ); +typedef void (* FGWarning )( const char *fmt, va_list ap ); +typedef void (* FGWarningUC )( const char *fmt, va_list ap, FGCBUserData userData ); /* A list structure */ @@ -337,24 +370,25 @@ struct tagSFG_State int ActiveMenus; /* Num. of currently active menus */ FGCBMenuState MenuStateCallback; /* Menu callbacks are global */ - FGCBMenuStatus MenuStatusCallback; + FGCBMenuStatusUC MenuStatusCallback; + FGCBUserData MenuStatusCallbackData; void* MenuFont; /* Font to be used for newly created menus */ SFG_XYUse GameModeSize; /* Game mode screen's dimensions */ int GameModeDepth; /* The pixel depth for game mode */ int GameModeRefresh; /* The refresh rate for game mode */ - int ActionOnWindowClose; /* Action when user closes window */ + int ActionOnWindowClose; /* Action when user closes window */ - fgExecutionState ExecState; /* Used for GLUT termination */ - char *ProgramName; /* Name of the invoking program */ - GLboolean JoysticksInitialised; /* Only initialize if application calls for them */ - int NumActiveJoysticks; /* Number of active joysticks (callback defined and positive pollrate) -- if zero, don't poll joysticks */ - GLboolean InputDevsInitialised; /* Only initialize if application calls for them */ + fgExecutionState ExecState; /* Used for GLUT termination */ + char *ProgramName; /* Name of the invoking program */ + GLboolean JoysticksInitialised; /* Only initialize if application calls for them */ + int NumActiveJoysticks; /* Number of active joysticks (callback defined and positive pollrate) -- if zero, don't poll joysticks */ + GLboolean InputDevsInitialised; /* Only initialize if application calls for them */ int MouseWheelTicks; /* Number of ticks the mouse wheel has turned */ - int AuxiliaryBufferNumber; /* Number of auxiliary buffers */ + int AuxiliaryBufferNumber;/* Number of auxiliary buffers */ int SampleNumber; /* Number of samples per pixel */ GLboolean SkipStaleMotion; /* skip stale motion events */ @@ -367,8 +401,10 @@ struct tagSFG_State int ContextFlags; /* OpenGL context flags */ int ContextProfile; /* OpenGL context profile */ int HasOpenGL20; /* fgInitGL2 could find all OpenGL 2.0 functions */ - FGError ErrorFunc; /* User defined error handler */ - FGWarning WarningFunc; /* User defined warning handler */ + FGErrorUC ErrorFunc; /* User defined error handler */ + FGCBUserData ErrorFuncData; /* User defined error handler user data */ + FGWarningUC WarningFunc; /* User defined warning handler */ + FGCBUserData WarningFuncData; /* User defined warning handler user data */ }; /* The structure used by display initialization in fg_init.c */ @@ -518,11 +554,12 @@ typedef void (*SFG_Proc)(); /* * SET_WCB() is used as: * - * SET_WCB( window, cbname, func ); + * SET_WCB( window, cbname, func, udata ); * * ...where {window} is the freeglut window to set the callback, * {cbname} is the window-specific callback to set, - * {func} is a function-pointer. + * {func} is a function-pointer, + * {udata} is a void* pointer for user data. * * Originally, {FETCH_WCB( ... ) = func} was rather sloppily used, * but this can cause warnings because the FETCH_WCB() macro type- @@ -532,11 +569,14 @@ typedef void (*SFG_Proc)(); * and for no other reason. Since it's hidden in the macro, the * ugliness is felt to be rather benign. */ -#define SET_WCB(window,cbname,func) \ +#define SET_WCB(window,cbname,func,udata) \ do \ { \ if( FETCH_WCB( window, cbname ) != (SFG_Proc)(func) ) \ + { \ (((window).CallBacks[WCB_ ## cbname]) = (SFG_Proc)(func)); \ + (((window).CallbackDatas[WCB_ ## cbname]) = (udata)); \ + } \ } while( 0 ) /* @@ -553,6 +593,82 @@ do \ #define FETCH_WCB(window,cbname) \ ((window).CallBacks[WCB_ ## cbname]) +/* + * FETCH_USER_DATA_WCB() is used as: + * + * FETCH_USER_DATA_WCB( window, cbname ); + * + * ...where {window} is the freeglut window, + * {cbname} is the window-specific callback to be invoked, + * + * This expects a variable named "window" of type tagSFG_Window to exist. + */ +/* + * FETCH_USER_DATA_WCB() is used as: + * + * FETCH_USER_DATA_WCB( window, cbname ); + * + * ...where {window} is the freeglut window to fetch the callback data from, + * {cbname} is the window-specific callback data to fetch. + * + * The result is the callback data pointer. + */ +#define FETCH_USER_DATA_WCB(window,cbname) \ + ((window).CallbackDatas[WCB_ ## cbname]) + +/* + * EXPAND_WCB() is used as: + * + * EXPAND_WCB arg_list + * + * ... where {(arg_list)} is the parameter list. + * + * This will take the arg_list and extend it by one argument, adding + * the argument "userData" to the end of the list. + * + * All additional args are to get around trailing ',', argument counts, + * and not needing a GCC extension to make this work. + * + * Minor modification of: + * http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946 + * + * Supports up to five arguments + */ +#if TARGET_HOST_MS_WINDOWS + +/* FIXME: Does VC6 support variadic macros? I don't think so (variadic macros came with C99. VC6 came out in 1998) */ + +/* FIXME: VC++ has a greedy preprocessor. + * The preprocessor resolves the macros on use instead of after on argument completion/token usage. + * e.g.: PP_HAS_ARGS_IMPL2(ONE_OR_MORE, ...) -> PP_HAS_ARGS_IMPL2(, ...) -> "Error, not enough tokens for PP_HAS_ARGS_IMPL2" + */ +#define EXPAND_WCB(...) (__VA_ARGS__) + +#else // #if TARGET_HOST_MS_WINDOWS + +#define PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N +#define PP_HAS_ARGS_SOURCE() \ + ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO + +#define PP_HAS_ARGS_IMPL(...) \ + PP_HAS_ARGS_IMPL2(__VA_ARGS__) +#define PP_HAS_ARGS(...) \ + PP_HAS_ARGS_IMPL(NOT_EXIST, ##__VA_ARGS__, PP_HAS_ARGS_SOURCE()) + +#define EXPAND_WCB_ZERO(x) \ + (userData) +#define EXPAND_WCB_ONE_OR_MORE(...) \ + (__VA_ARGS__, userData) + +#define EXPAND_WCB_DISAMBIGUATE2(has_args, ...) \ + EXPAND_WCB_ ## has_args (__VA_ARGS__) +#define EXPAND_WCB_DISAMBIGUATE(has_args, ...) \ + EXPAND_WCB_DISAMBIGUATE2(has_args, __VA_ARGS__) +#define EXPAND_WCB(...) \ + EXPAND_WCB_DISAMBIGUATE(PP_HAS_ARGS(__VA_ARGS__), __VA_ARGS__) + +#endif // #if TARGET_HOST_MS_WINDOWS + /* * INVOKE_WCB() is used as: * @@ -578,9 +694,10 @@ do \ { \ if( FETCH_WCB( window, cbname ) ) \ { \ - FGCB ## cbname func = (FGCB ## cbname)(FETCH_WCB( window, cbname )); \ + FGCB ## cbname ## UC func = (FGCB ## cbname ## UC)(FETCH_WCB( window, cbname )); \ + FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ fgSetWindow( &window ); \ - func arg_list; \ + func EXPAND_WCB arg_list; \ } \ } while( 0 ) #else @@ -590,7 +707,8 @@ do \ if( FETCH_WCB( window, cbname ) ) \ { \ fgSetWindow( &window ); \ - ((FGCB ## cbname)FETCH_WCB( window, cbname )) arg_list; \ + FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ + ((FGCB ## cbname ## UC)FETCH_WCB( window, cbname )) EXPAND_WCB arg_list; \ } \ } while( 0 ) #endif @@ -671,7 +789,8 @@ struct tagSFG_Menu SFG_List Entries; /* The menu entries list */ FGCBMenuUC Callback; /* The menu callback */ FGCBUserData CallbackData; /* The menu callback user data */ - FGCBDestroy Destroy; /* Destruction callback */ + FGCBDestroyUC Destroy; /* Destruction callback */ + FGCBUserData DestroyData; /* Destruction callback user data */ GLboolean IsActive; /* Is the menu selected? */ void* Font; /* Font to be used for displaying this menu */ int Width; /* Menu box width in pixels */ @@ -709,10 +828,11 @@ struct tagSFG_Window SFG_Context Window; /* Window and OpenGL context */ SFG_WindowState State; /* The window state */ SFG_Proc CallBacks[ TOTAL_CALLBACKS ]; /* Array of window callbacks */ + FGCBUserData CallbackDatas[ TOTAL_CALLBACKS ]; /* Array of window callback datas */ void *UserData ; /* For use by user */ - SFG_Menu* Menu[ FREEGLUT_MAX_MENUS ]; /* Menus appended to window */ - SFG_Menu* ActiveMenu; /* The window's active menu */ + SFG_Menu* Menu[ FREEGLUT_MAX_MENUS ]; /* Menus appended to window */ + SFG_Menu* ActiveMenu; /* The window's active menu */ SFG_Window* Parent; /* The parent to this window */ SFG_List Children; /* The subwindows d.l. list */ diff --git a/freeglut/freeglut/src/fg_main.c b/freeglut/freeglut/src/fg_main.c index 6e9ff48..45f13f5 100644 --- a/freeglut/freeglut/src/fg_main.c +++ b/freeglut/freeglut/src/fg_main.c @@ -269,7 +269,7 @@ void fgError( const char *fmt, ... ) va_start( ap, fmt ); /* call user set error handler here */ - fgState.ErrorFunc(fmt, ap); + fgState.ErrorFunc(fmt, ap, fgState.ErrorFuncData); va_end( ap ); @@ -302,7 +302,7 @@ void fgWarning( const char *fmt, ... ) va_start( ap, fmt ); /* call user set warning handler here */ - fgState.WarningFunc(fmt, ap); + fgState.WarningFunc(fmt, ap, fgState.WarningFuncData); va_end( ap ); diff --git a/freeglut/freeglut/src/fg_menu.c b/freeglut/freeglut/src/fg_menu.c index cad5b83..1b07b1a 100644 --- a/freeglut/freeglut/src/fg_menu.c +++ b/freeglut/freeglut/src/fg_menu.c @@ -531,7 +531,7 @@ static void fghActivateMenu( SFG_Window* window, int button ) fgState.MenuStateCallback(GLUT_MENU_IN_USE); if (fgState.MenuStatusCallback) /* window->State.MouseX and window->State.MouseY are relative to client area origin, as needed */ - fgState.MenuStatusCallback(GLUT_MENU_IN_USE, window->State.MouseX, window->State.MouseY); + fgState.MenuStatusCallback(GLUT_MENU_IN_USE, window->State.MouseX, window->State.MouseY, fgState.MenuStatusCallbackData); } fgSetWindow( menu->Window ); @@ -725,7 +725,7 @@ void fgDeactivateMenu( SFG_Window *window ) SFG_XYUse mouse_pos; fghPlatformGetCursorPos(parent_window, GL_TRUE, &mouse_pos); - fgState.MenuStatusCallback(GLUT_MENU_NOT_IN_USE, mouse_pos.X, mouse_pos.Y); + fgState.MenuStatusCallback(GLUT_MENU_NOT_IN_USE, mouse_pos.X, mouse_pos.Y, fgState.MenuStatusCallbackData); } } } @@ -791,7 +791,7 @@ int FGAPIENTRY glutCreateMenuUcall( FGCBMenuUC callback, FGCBUserData userData ) } /* Standard glutCreateMenu */ -void glutCreateMenuCallback( int menu, FGCBUserData userData ) +static void glutCreateMenuCallback( int menu, FGCBUserData userData ) { FGCBMenu callback = (FGCBMenu)userData; callback( menu ); @@ -800,6 +800,8 @@ void glutCreateMenuCallback( int menu, FGCBUserData userData ) int FGAPIENTRY glutCreateMenu( FGCBMenu callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" ); + if (!callback) + return glutCreateMenuUcall( NULL, NULL ); return glutCreateMenuUcall( glutCreateMenuCallback, (FGCBUserData)callback ); } diff --git a/freeglut/freeglut/src/fg_structure.c b/freeglut/freeglut/src/fg_structure.c index c279b4a..4274667 100644 --- a/freeglut/freeglut/src/fg_structure.c +++ b/freeglut/freeglut/src/fg_structure.c @@ -49,7 +49,7 @@ SFG_Structure fgStructure = { { NULL, NULL }, /* The list of windows */ /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ extern void fgPlatformCreateWindow ( SFG_Window *window ); -extern void fghDefaultReshape(int width, int height); +extern void fghDefaultReshape(int width, int height, FGCBUserData userData); static void fghClearCallBacks( SFG_Window *window ) { @@ -57,7 +57,10 @@ static void fghClearCallBacks( SFG_Window *window ) { int i; for( i = 0; i < TOTAL_CALLBACKS; ++i ) + { window->CallBacks[ i ] = NULL; + window->CallbackDatas[ i ] = NULL; + } } } @@ -83,7 +86,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, fgPlatformCreateWindow ( window ); fghClearCallBacks( window ); - SET_WCB( *window, Reshape, fghDefaultReshape); + SET_WCB( *window, Reshape, fghDefaultReshape, NULL); /* Initialize the object properties */ window->ID = ++fgStructure.WindowID; @@ -174,9 +177,10 @@ void fgAddToWindowDestroyList( SFG_Window* window ) * to ensure that they are no longer called after this point. */ { - FGCBDestroy destroy = (FGCBDestroy)FETCH_WCB( *window, Destroy ); + FGCBDestroyUC destroy = (FGCBDestroyUC)FETCH_WCB( *window, Destroy ); + FGCBUserData destroyData = FETCH_USER_DATA_WCB( *window, Destroy ); fghClearCallBacks( window ); - SET_WCB( *window, Destroy, destroy ); + SET_WCB( *window, Destroy, destroy, destroyData ); } } @@ -303,7 +307,7 @@ void fgDestroyMenu( SFG_Menu* menu ) { SFG_Menu *activeMenu=fgStructure.CurrentMenu; fgStructure.CurrentMenu = menu; - menu->Destroy( ); + menu->Destroy( menu->DestroyData ); fgStructure.CurrentMenu = activeMenu; } From da0b7b3369ced228d4953cff9b324d3e564c6722 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:21:14 +0000 Subject: [PATCH 03/20] Changed EXPAND_WCB so it works with MSVC and GCC - Required adding an "argument expansion macro" for each callback (hope to remove eventually) - Fixed MSVC linking error where glutMenuStatusFuncUCall had the incorrect case and should've been glutMenuStatusFuncUcall - Updated formatting of some freeglut_ext.h functions git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1810 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/CMakeLists.txt | 1 + freeglut/freeglut/include/GL/freeglut_ext.h | 10 +-- freeglut/freeglut/src/fg_callbacks.c | 11 ++- freeglut/freeglut/src/fg_internal.h | 77 +++++++++++++++++---- 4 files changed, 75 insertions(+), 24 deletions(-) diff --git a/freeglut/freeglut/CMakeLists.txt b/freeglut/freeglut/CMakeLists.txt index 190964f..17e05b0 100644 --- a/freeglut/freeglut/CMakeLists.txt +++ b/freeglut/freeglut/CMakeLists.txt @@ -68,6 +68,7 @@ ENDIF() SET(FREEGLUT_HEADERS include/GL/freeglut.h + include/GL/freeglut_ucall.h include/GL/freeglut_ext.h include/GL/freeglut_std.h ) diff --git a/freeglut/freeglut/include/GL/freeglut_ext.h b/freeglut/freeglut/include/GL/freeglut_ext.h index 255edea..9b0ac50 100644 --- a/freeglut/freeglut/include/GL/freeglut_ext.h +++ b/freeglut/freeglut/include/GL/freeglut_ext.h @@ -256,13 +256,13 @@ FGAPI void FGAPIENTRY glutInitErrorFunc( void (* callback)( const char *fmt, FGAPI void FGAPIENTRY glutInitWarningFunc( void (* callback)( const char *fmt, va_list ap ) ); /* OpenGL >= 2.0 support */ -FGAPI void FGAPIENTRY glutSetVertexAttribCoord3(GLint attrib); -FGAPI void FGAPIENTRY glutSetVertexAttribNormal(GLint attrib); -FGAPI void FGAPIENTRY glutSetVertexAttribTexCoord2(GLint attrib); +FGAPI void FGAPIENTRY glutSetVertexAttribCoord3( GLint attrib ); +FGAPI void FGAPIENTRY glutSetVertexAttribNormal( GLint attrib ); +FGAPI void FGAPIENTRY glutSetVertexAttribTexCoord2( GLint attrib ); /* Mobile platforms lifecycle */ -FGAPI void FGAPIENTRY glutInitContextFunc(void (* callback)()); -FGAPI void FGAPIENTRY glutAppStatusFunc(void (* callback)(int)); +FGAPI void FGAPIENTRY glutInitContextFunc( void (* callback)( void ) ); +FGAPI void FGAPIENTRY glutAppStatusFunc( void (* callback)( int ) ); /* state flags that can be passed to callback set by glutAppStatusFunc */ #define GLUT_APPSTATUS_PAUSE 0x0001 #define GLUT_APPSTATUS_RESUME 0x0002 diff --git a/freeglut/freeglut/src/fg_callbacks.c b/freeglut/freeglut/src/fg_callbacks.c index 5f94b65..684c934 100644 --- a/freeglut/freeglut/src/fg_callbacks.c +++ b/freeglut/freeglut/src/fg_callbacks.c @@ -113,9 +113,9 @@ void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback ) } /* Sets the global menu status callback for the current window */ -void FGAPIENTRY glutMenuStatusFuncUCall( FGCBMenuStatusUC callback, FGCBUserData userData ) +void FGAPIENTRY glutMenuStatusFuncUcall( FGCBMenuStatusUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFuncUCall" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFuncUcall" ); fgState.MenuStatusCallback = callback; fgState.MenuStatusCallbackData = userData; } @@ -130,12 +130,11 @@ void FGAPIENTRY glutMenuStatusFunc( FGCBMenuStatus callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" ); if( callback ) - glutMenuStatusFuncUCall( glutMenuStatusFuncCallback, (FGCBUserData)callback ); + glutMenuStatusFuncUcall( glutMenuStatusFuncCallback, (FGCBUserData)callback ); else - glutMenuStatusFuncUCall( NULL, NULL ); + glutMenuStatusFuncUcall( NULL, NULL ); } - /* * Menu specific callbacks. */ @@ -180,7 +179,7 @@ do \ * Types need to be defined for callbacks. It's not ideal, but it works for this. */ #define IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ -static void glut##a##FuncCallback( FGCBUserData userData ) \ +static void glut##a##FuncCallback( FGCBUserData userData ) \ { \ FGCB##b callback = (FGCB##b)userData; \ callback(); \ diff --git a/freeglut/freeglut/src/fg_internal.h b/freeglut/freeglut/src/fg_internal.h index 69401d0..7afb400 100644 --- a/freeglut/freeglut/src/fg_internal.h +++ b/freeglut/freeglut/src/fg_internal.h @@ -220,66 +220,96 @@ typedef void* FGCBUserData; typedef void (* FGCBDisplay )( void ); typedef void (* FGCBDisplayUC )( FGCBUserData ); +#define EXPAND_WCB_SUB_Display(args, userData) EXPAND_WCB_ZERO(args, userData) typedef void (* FGCBReshape )( int, int ); typedef void (* FGCBReshapeUC )( int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_Reshape(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBPosition )( int, int ); typedef void (* FGCBPositionUC )( int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_Position(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBVisibility )( int ); typedef void (* FGCBVisibilityUC )( int, FGCBUserData ); +#define EXPAND_WCB_SUB_Visibility(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBKeyboard )( unsigned char, int, int ); typedef void (* FGCBKeyboardUC )( unsigned char, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_Keyboard(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBKeyboardUp )( unsigned char, int, int ); typedef void (* FGCBKeyboardUpUC )( unsigned char, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_KeyboardUp(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBSpecial )( int, int, int ); typedef void (* FGCBSpecialUC )( int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_Special(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBSpecialUp )( int, int, int ); typedef void (* FGCBSpecialUpUC )( int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_SpecialUp(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMouse )( int, int, int, int ); typedef void (* FGCBMouseUC )( int, int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_Mouse(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMouseWheel )( int, int, int, int ); typedef void (* FGCBMouseWheelUC )( int, int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_MouseWheel(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMotion )( int, int ); typedef void (* FGCBMotionUC )( int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_Motion(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBPassive )( int, int ); typedef void (* FGCBPassiveUC )( int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_Passive(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBEntry )( int ); typedef void (* FGCBEntryUC )( int, FGCBUserData ); +#define EXPAND_WCB_SUB_Entry(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBWindowStatus )( int ); typedef void (* FGCBWindowStatusUC )( int, FGCBUserData ); +#define EXPAND_WCB_SUB_WindowStatus(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBJoystick )( unsigned int, int, int, int ); typedef void (* FGCBJoystickUC )( unsigned int, int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_Joystick(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBOverlayDisplay )( void ); typedef void (* FGCBOverlayDisplayUC)( FGCBUserData ); +#define EXPAND_WCB_SUB_OverlayDisplay(args, userData) EXPAND_WCB_ZERO(args, userData) typedef void (* FGCBSpaceMotion )( int, int, int ); typedef void (* FGCBSpaceMotionUC )( int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_SpaceMotion(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBSpaceRotation )( int, int, int ); typedef void (* FGCBSpaceRotationUC )( int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_SpaceRotation(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBSpaceButton )( int, int ); typedef void (* FGCBSpaceButtonUC )( int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_SpaceButton(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBDials )( int, int ); typedef void (* FGCBDialsUC )( int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_Dials(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBButtonBox )( int, int ); typedef void (* FGCBButtonBoxUC )( int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_ButtonBox(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBTabletMotion )( int, int ); typedef void (* FGCBTabletMotionUC )( int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_TabletMotion(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBTabletButton )( int, int, int, int ); typedef void (* FGCBTabletButtonUC )( int, int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_TabletButton(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBDestroy )( void ); /* Used for both window and menu destroy callbacks */ typedef void (* FGCBDestroyUC )( FGCBUserData ); +#define EXPAND_WCB_SUB_Destroy(args, userData) EXPAND_WCB_ZERO(args, userData) typedef void (* FGCBMultiEntry )( int, int ); typedef void (* FGCBMultiEntryUC )( int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_MultiEntry(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMultiButton )( int, int, int, int, int ); typedef void (* FGCBMultiButtonUC )( int, int, int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_MultiButton(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMultiMotion )( int, int, int ); typedef void (* FGCBMultiMotionUC )( int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_MultiMotion(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMultiPassive )( int, int, int ); typedef void (* FGCBMultiPassiveUC )( int, int, int, FGCBUserData ); +#define EXPAND_WCB_SUB_MultiPassive(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBInitContext )( void ); typedef void (* FGCBInitContextUC )( FGCBUserData ); +#define EXPAND_WCB_SUB_InitContext(args, userData) EXPAND_WCB_ZERO(args, userData) typedef void (* FGCBAppStatus )( int ); typedef void (* FGCBAppStatusUC )( int, FGCBUserData ); +#define EXPAND_WCB_SUB_AppStatus(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) /* The global callbacks type definitions */ typedef void (* FGCBIdle )( void ); \ @@ -616,6 +646,7 @@ do \ #define FETCH_USER_DATA_WCB(window,cbname) \ ((window).CallbackDatas[WCB_ ## cbname]) +#if 0 /* * EXPAND_WCB() is used as: * @@ -634,17 +665,8 @@ do \ * * Supports up to five arguments */ -#if TARGET_HOST_MS_WINDOWS -/* FIXME: Does VC6 support variadic macros? I don't think so (variadic macros came with C99. VC6 came out in 1998) */ - -/* FIXME: VC++ has a greedy preprocessor. - * The preprocessor resolves the macros on use instead of after on argument completion/token usage. - * e.g.: PP_HAS_ARGS_IMPL2(ONE_OR_MORE, ...) -> PP_HAS_ARGS_IMPL2(, ...) -> "Error, not enough tokens for PP_HAS_ARGS_IMPL2" - */ -#define EXPAND_WCB(...) (__VA_ARGS__) - -#else // #if TARGET_HOST_MS_WINDOWS +/* GCC-specific design that doesn't require per-callback defines */ #define PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N #define PP_HAS_ARGS_SOURCE() \ @@ -667,7 +689,36 @@ do \ #define EXPAND_WCB(...) \ EXPAND_WCB_DISAMBIGUATE(PP_HAS_ARGS(__VA_ARGS__), __VA_ARGS__) -#endif // #if TARGET_HOST_MS_WINDOWS +#else +/* + * EXPAND_WCB() is used as: + * + * EXPAND_WCB( cbname )( arg_list, userData ) + * + * ... where {(arg_list)} is the parameter list and userData is user + * provided data. + * + * This will take the arg_list and extend it by one argument, adding + * the argument "userData" to the end of the list. + * + * In order for this to work, each callback must have a define that + * properly handles the arguments as needed by the callback. + * This callback is in the format of EXPAND_WCB_SUB_. + * Two helper defines exist: EXPAND_WCB_ZERO and EXPAND_WCB_ONE_OR_MORE, + * each to handle callbacks that take zero-params (but take userData) and + * to take one or more params (along with userData). + * + * An example for the "Entry" callback, where "Entry" is the cbname: + * typedef void (* FGCBEntry )( int ); + * typedef void (* FGCBEntryUC)( int, FGCBUserData ); + * #define EXPAND_WCB_SUB_Entry(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) + */ +#define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ +#define EXPAND_WCB_ZERO(args, userData) ( userData ) +#define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) + +#define EXPAND_WCB(cbname) EXPAND_WCB_SUB_ ## cbname +#endif /* * INVOKE_WCB() is used as: @@ -697,7 +748,7 @@ do \ FGCB ## cbname ## UC func = (FGCB ## cbname ## UC)(FETCH_WCB( window, cbname )); \ FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ fgSetWindow( &window ); \ - func EXPAND_WCB arg_list; \ + func EXPAND_WCB( cbname )( arg_list, userData ); \ } \ } while( 0 ) #else @@ -708,7 +759,7 @@ do \ { \ fgSetWindow( &window ); \ FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ - ((FGCB ## cbname ## UC)FETCH_WCB( window, cbname )) EXPAND_WCB arg_list; \ + ((FGCB ## cbname ## UC)FETCH_WCB( window, cbname )) EXPAND_WCB( cbname )( arg_list, userData ); \ } \ } while( 0 ) #endif From f0150de08d59878468aedba8a039cb6e163a31cf Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:21:21 +0000 Subject: [PATCH 04/20] More explicit argument list for INVOKE_WCB callbacks git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1811 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/fg_internal.h | 15 +++++++++++---- freeglut/freeglut/src/fg_main.c | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/freeglut/freeglut/src/fg_internal.h b/freeglut/freeglut/src/fg_internal.h index 7afb400..93ea3bc 100644 --- a/freeglut/freeglut/src/fg_internal.h +++ b/freeglut/freeglut/src/fg_internal.h @@ -713,7 +713,13 @@ do \ * typedef void (* FGCBEntryUC)( int, FGCBUserData ); * #define EXPAND_WCB_SUB_Entry(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) */ +#define FG_COMPILER_SUPPORTS_VA_ARGS +#ifdef FG_COMPILER_SUPPORTS_VA_ARGS #define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ +#else +#error "Compiler does not support varadic argument macros" +#endif + #define EXPAND_WCB_ZERO(args, userData) ( userData ) #define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) @@ -731,9 +737,10 @@ do \ * * The callback is invoked as: * - * callback( arg_list ); + * callback( arg_list, userData ); * - * ...so the parentheses are REQUIRED in the {arg_list}. + * ...where userData is added to the arg_list, but the parentheses + * are REQUIRED in the {arg_list}. * * NOTE that it does a sanity-check and also sets the * current window. @@ -748,7 +755,7 @@ do \ FGCB ## cbname ## UC func = (FGCB ## cbname ## UC)(FETCH_WCB( window, cbname )); \ FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ fgSetWindow( &window ); \ - func EXPAND_WCB( cbname )( arg_list, userData ); \ + func EXPAND_WCB( cbname )( arg_list, userData ); \ } \ } while( 0 ) #else @@ -759,7 +766,7 @@ do \ { \ fgSetWindow( &window ); \ FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ - ((FGCB ## cbname ## UC)FETCH_WCB( window, cbname )) EXPAND_WCB( cbname )( arg_list, userData ); \ + ((FGCB ## cbname ## UC)FETCH_WCB( window, cbname )) EXPAND_WCB( cbname )( arg_list, userData ); \ } \ } while( 0 ) #endif diff --git a/freeglut/freeglut/src/fg_main.c b/freeglut/freeglut/src/fg_main.c index 45f13f5..97c7a32 100644 --- a/freeglut/freeglut/src/fg_main.c +++ b/freeglut/freeglut/src/fg_main.c @@ -400,7 +400,7 @@ void fgProcessWork(SFG_Window *window) fgPlatformInitWork(window); /* Call init context callback */ - INVOKE_WCB( *window, InitContext, ()); + INVOKE_WCB( *window, InitContext, ( ) ); /* Lastly, check if we have a display callback, error out if not * This is the right place to do it, as the redisplay will be From 658edf902d6d887324c0695399c5bd8cac72cf38 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:21:28 +0000 Subject: [PATCH 05/20] Initial refactoring of callback macros to make sure all compilers are supported git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1812 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/CMakeLists.txt | 1 + freeglut/freeglut/src/fg_callback_macros.h | 226 +++++++++++++++++++++ freeglut/freeglut/src/fg_internal.h | 121 ++--------- 3 files changed, 246 insertions(+), 102 deletions(-) create mode 100644 freeglut/freeglut/src/fg_callback_macros.h diff --git a/freeglut/freeglut/CMakeLists.txt b/freeglut/freeglut/CMakeLists.txt index 17e05b0..55f48ba 100644 --- a/freeglut/freeglut/CMakeLists.txt +++ b/freeglut/freeglut/CMakeLists.txt @@ -91,6 +91,7 @@ SET(FREEGLUT_SRCS src/fg_init.c src/fg_init.h src/fg_internal.h + src/fg_callback_macros.h src/fg_input_devices.c src/fg_joystick.c src/fg_main.c diff --git a/freeglut/freeglut/src/fg_callback_macros.h b/freeglut/freeglut/src/fg_callback_macros.h new file mode 100644 index 0000000..1c70587 --- /dev/null +++ b/freeglut/freeglut/src/fg_callback_macros.h @@ -0,0 +1,226 @@ +/* + * fg_callback_macros.h + * + * The freeglut library callback macro file. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Creation date: Thu Dec 2 1999 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef FREEGLUT_CALLBACK_MACROS_H +#define FREEGLUT_CALLBACK_MACROS_H + +#ifndef FREEGLUT_INTERNAL_H +#error "fg_internal.h needs to be included before this header" +#endif + +#if 0 /* old. Remove once other testing is complete */ +/* + * EXPAND_WCB() is used as: + * + * EXPAND_WCB arg_list + * + * ... where {(arg_list)} is the parameter list. + * + * This will take the arg_list and extend it by one argument, adding + * the argument "userData" to the end of the list. + * + * All additional args are to get around trailing ',', argument counts, + * and not needing a GCC extension to make this work. + * + * Minor modification of: + * http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946 + * + * Supports up to five arguments + */ + +/* GCC-specific design that doesn't require per-callback defines */ + +#define PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N +#define PP_HAS_ARGS_SOURCE() \ + ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO + +#define PP_HAS_ARGS_IMPL(...) \ + PP_HAS_ARGS_IMPL2(__VA_ARGS__) +#define PP_HAS_ARGS(...) \ + PP_HAS_ARGS_IMPL(NOT_EXIST, ##__VA_ARGS__, PP_HAS_ARGS_SOURCE()) + +#define EXPAND_WCB_ZERO(x) \ + (userData) +#define EXPAND_WCB_ONE_OR_MORE(...) \ + (__VA_ARGS__, userData) + +#define EXPAND_WCB_DISAMBIGUATE2(has_args, ...) \ + EXPAND_WCB_ ## has_args (__VA_ARGS__) +#define EXPAND_WCB_DISAMBIGUATE(has_args, ...) \ + EXPAND_WCB_DISAMBIGUATE2(has_args, __VA_ARGS__) +#define EXPAND_WCB(...) \ + EXPAND_WCB_DISAMBIGUATE(PP_HAS_ARGS(__VA_ARGS__), __VA_ARGS__) +#endif + +/* + * Compiler defines: + * FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK: if the compiler supports GCC's varadic macro implementation (AKA, ##__VA_ARGS__) + * FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports varadic macros + */ + +#ifdef FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK + + /* + * EXPAND_WCB() is used as: + * + * EXPAND_WCB arg_list + * + * ... where {(arg_list)} is the parameter list. + * + * This will take the arg_list and extend it by one argument, adding + * the argument "userData" to the end of the list. + * + * All additional args are to get around trailing ',', argument counts, + * and not needing a GCC extension to make this work. + * + * Modification of: + * http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946 + * + * -------------- + * + * GCC-specific design that doesn't require per-callback defines + * + * The naming is terrible... and it's very convuluted and complex, but + * should not require any modification unless additional arguments are to + * be supported. + * + * Supports callbacks up to 5 args (follow the pattern of PP_HAS_ARGS_IMPL2 + * and PP_HAS_ARGS_SOURCE to add more) + * + * Edit with care. + */ + +#define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ + +#define PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N +#define PP_HAS_ARGS_SOURCE() ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO + +#define PP_HAS_ARGS_IMPL(...) PP_HAS_ARGS_IMPL2( __VA_ARGS__ ) +#define PP_HAS_ARGS(...) PP_HAS_ARGS_IMPL( NOT_EXIST, ##__VA_ARGS__, PP_HAS_ARGS_SOURCE() ) + +#define EXPAND_WCB_ZERO(args, userData) ( userData ) +#define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) + +#define EXPAND_WCB_DISAMBIGUATE(has_args, args, userData) EXPAND_WCB_ ## has_args ( args, userData ) + +#define EXPAND_WCB_UNWRAP_ARGS2(args, userData) EXPAND_WCB_DISAMBIGUATE( PP_HAS_ARGS args, args, userData ) +#define EXPAND_WCB_UNWRAP_ARGS(args) EXPAND_WCB_UNWRAP_ARGS2 args + +#define EXPAND_WCB(cbname) EXPAND_WCB_UNWRAP_ARGS + +#else + +/* + * EXPAND_WCB() is used as: + * + * EXPAND_WCB( cbname )(( arg_list, userData )) + * + * ... where {(arg_list)} is the parameter list and userData is user + * provided data. + * + * This will take the arg_list and extend it by one argument, adding + * the argument "userData" to the end of the list. + * + * In order for this to work, each callback must have a define that + * properly handles the arguments as needed by the callback. + * This callback is in the format of EXPAND_WCB_SUB_. + * Helper functions exist for zero to five parameters: EXPAND_WCB_ZERO, + * EXPAND_WCB_ONE, EXPAND_WCB_TWO, EXPAND_WCB_THREE< EXPAND_WCB_FOUR, + * and EXPAND_WCB_FIVE. Each handle the callback argument counts. + * + * An example for the "Entry" callback, where "Entry" is the cbname: + * typedef void (* FGCBEntry )( int ); + * typedef void (* FGCBEntryUC)( int, FGCBUserData ); + * #define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args + */ + +#define FG_COMPILER_SUPPORTS_VA_ARGS //XXX (should be compiler defined) +#ifdef FG_COMPILER_SUPPORTS_VA_ARGS + +#define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ +#define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) + +#define EXPAND_WCB_ONE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_TWO(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_THREE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_FOUR(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_FIVE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) + +#else + +//TODO +#error "Compiler does not support varadic argument macros" + +#endif + +#define EXPAND_WCB_ZERO(args, userData) ( userData ) + +#define EXPAND_WCB(cbname) EXPAND_WCB_SUB_ ## cbname + +/* + * Freeglut callbacks type definitions macros + * + * Every time a callback is updated in fg_internal.h is updated, this needs updated + * if argument counts change, new callbacks are added, or callbacks are removed. + */ + +#define EXPAND_WCB_SUB_Display(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_Reshape(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Position(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Visibility(args) EXPAND_WCB_ONE args +#define EXPAND_WCB_SUB_Keyboard(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_KeyboardUp(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_Special(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_SpecialUp(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_Mouse(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_MouseWheel(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_Motion(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Passive(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args +#define EXPAND_WCB_SUB_WindowStatus(args) EXPAND_WCB_ONE args +#define EXPAND_WCB_SUB_Joystick(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_OverlayDisplay(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_SpaceMotion(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_SpaceRotation(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_SpaceButton(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Dials(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_ButtonBox(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_TabletMotion(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_TabletButton(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_Destroy(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_MultiEntry(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_MultiButton(args) EXPAND_WCB_FIVE args +#define EXPAND_WCB_SUB_MultiMotion(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_MultiPassive(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_InitContext(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_AppStatus(args) EXPAND_WCB_ONE args + +#endif + +#endif /* FREEGLUT_CALLBACK_MACROS_H */ + +/*** END OF FILE ***/ diff --git a/freeglut/freeglut/src/fg_internal.h b/freeglut/freeglut/src/fg_internal.h index 93ea3bc..bce77ca 100644 --- a/freeglut/freeglut/src/fg_internal.h +++ b/freeglut/freeglut/src/fg_internal.h @@ -33,12 +33,14 @@ #endif #include "fg_version.h" +#include "fg_callback_macros.h" /* Freeglut is intended to function under all Unix/X11 and Win32 platforms. */ /* XXX: Don't all MS-Windows compilers (except Cygwin) have _WIN32 defined? * XXX: If so, remove the first set of defined()'s below. */ -#if !defined(TARGET_HOST_POSIX_X11) && !defined(TARGET_HOST_MS_WINDOWS) && !defined(TARGET_HOST_MAC_OSX) && !defined(TARGET_HOST_SOLARIS) +#if !defined(TARGET_HOST_POSIX_X11) && !defined(TARGET_HOST_MS_WINDOWS) && !defined(TARGET_HOST_MAC_OSX) && !defined(TARGET_HOST_SOLARIS) && \ + !defined(TARGET_HOST_ANDROID) && !defined(TARGET_HOST_BLACKBERRY) && !defined(TARGET_HOST_POSIX_WAYLAND) #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__) \ || defined(_WIN32) || defined(_WIN32_WCE) \ || ( defined(__CYGWIN__) && defined(X_DISPLAY_MISSING) ) @@ -215,101 +217,78 @@ /* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ -/* Freeglut callbacks type definitions */ +/* + * Freeglut callbacks type definitions + * + * If anything here is modified or added, update fg_callback_macros.h functions. + * + * This is not ideal, but freeglut needs to either define minimal compiler specs, + * or update header every time this is changed or updated. + */ typedef void* FGCBUserData; typedef void (* FGCBDisplay )( void ); typedef void (* FGCBDisplayUC )( FGCBUserData ); -#define EXPAND_WCB_SUB_Display(args, userData) EXPAND_WCB_ZERO(args, userData) typedef void (* FGCBReshape )( int, int ); typedef void (* FGCBReshapeUC )( int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_Reshape(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBPosition )( int, int ); typedef void (* FGCBPositionUC )( int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_Position(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBVisibility )( int ); typedef void (* FGCBVisibilityUC )( int, FGCBUserData ); -#define EXPAND_WCB_SUB_Visibility(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBKeyboard )( unsigned char, int, int ); typedef void (* FGCBKeyboardUC )( unsigned char, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_Keyboard(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBKeyboardUp )( unsigned char, int, int ); typedef void (* FGCBKeyboardUpUC )( unsigned char, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_KeyboardUp(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBSpecial )( int, int, int ); typedef void (* FGCBSpecialUC )( int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_Special(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBSpecialUp )( int, int, int ); typedef void (* FGCBSpecialUpUC )( int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_SpecialUp(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMouse )( int, int, int, int ); typedef void (* FGCBMouseUC )( int, int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_Mouse(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMouseWheel )( int, int, int, int ); typedef void (* FGCBMouseWheelUC )( int, int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_MouseWheel(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMotion )( int, int ); typedef void (* FGCBMotionUC )( int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_Motion(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBPassive )( int, int ); typedef void (* FGCBPassiveUC )( int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_Passive(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBEntry )( int ); typedef void (* FGCBEntryUC )( int, FGCBUserData ); -#define EXPAND_WCB_SUB_Entry(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBWindowStatus )( int ); typedef void (* FGCBWindowStatusUC )( int, FGCBUserData ); -#define EXPAND_WCB_SUB_WindowStatus(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBJoystick )( unsigned int, int, int, int ); typedef void (* FGCBJoystickUC )( unsigned int, int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_Joystick(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBOverlayDisplay )( void ); typedef void (* FGCBOverlayDisplayUC)( FGCBUserData ); -#define EXPAND_WCB_SUB_OverlayDisplay(args, userData) EXPAND_WCB_ZERO(args, userData) typedef void (* FGCBSpaceMotion )( int, int, int ); typedef void (* FGCBSpaceMotionUC )( int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_SpaceMotion(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBSpaceRotation )( int, int, int ); typedef void (* FGCBSpaceRotationUC )( int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_SpaceRotation(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBSpaceButton )( int, int ); typedef void (* FGCBSpaceButtonUC )( int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_SpaceButton(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBDials )( int, int ); typedef void (* FGCBDialsUC )( int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_Dials(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBButtonBox )( int, int ); typedef void (* FGCBButtonBoxUC )( int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_ButtonBox(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBTabletMotion )( int, int ); typedef void (* FGCBTabletMotionUC )( int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_TabletMotion(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBTabletButton )( int, int, int, int ); typedef void (* FGCBTabletButtonUC )( int, int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_TabletButton(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBDestroy )( void ); /* Used for both window and menu destroy callbacks */ typedef void (* FGCBDestroyUC )( FGCBUserData ); -#define EXPAND_WCB_SUB_Destroy(args, userData) EXPAND_WCB_ZERO(args, userData) typedef void (* FGCBMultiEntry )( int, int ); typedef void (* FGCBMultiEntryUC )( int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_MultiEntry(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMultiButton )( int, int, int, int, int ); typedef void (* FGCBMultiButtonUC )( int, int, int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_MultiButton(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMultiMotion )( int, int, int ); typedef void (* FGCBMultiMotionUC )( int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_MultiMotion(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBMultiPassive )( int, int, int ); typedef void (* FGCBMultiPassiveUC )( int, int, int, FGCBUserData ); -#define EXPAND_WCB_SUB_MultiPassive(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) typedef void (* FGCBInitContext )( void ); typedef void (* FGCBInitContextUC )( FGCBUserData ); -#define EXPAND_WCB_SUB_InitContext(args, userData) EXPAND_WCB_ZERO(args, userData) typedef void (* FGCBAppStatus )( int ); typedef void (* FGCBAppStatusUC )( int, FGCBUserData ); -#define EXPAND_WCB_SUB_AppStatus(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) /* The global callbacks type definitions */ typedef void (* FGCBIdle )( void ); \ @@ -646,54 +625,10 @@ do \ #define FETCH_USER_DATA_WCB(window,cbname) \ ((window).CallbackDatas[WCB_ ## cbname]) -#if 0 /* * EXPAND_WCB() is used as: * - * EXPAND_WCB arg_list - * - * ... where {(arg_list)} is the parameter list. - * - * This will take the arg_list and extend it by one argument, adding - * the argument "userData" to the end of the list. - * - * All additional args are to get around trailing ',', argument counts, - * and not needing a GCC extension to make this work. - * - * Minor modification of: - * http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946 - * - * Supports up to five arguments - */ - -/* GCC-specific design that doesn't require per-callback defines */ - -#define PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N -#define PP_HAS_ARGS_SOURCE() \ - ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO - -#define PP_HAS_ARGS_IMPL(...) \ - PP_HAS_ARGS_IMPL2(__VA_ARGS__) -#define PP_HAS_ARGS(...) \ - PP_HAS_ARGS_IMPL(NOT_EXIST, ##__VA_ARGS__, PP_HAS_ARGS_SOURCE()) - -#define EXPAND_WCB_ZERO(x) \ - (userData) -#define EXPAND_WCB_ONE_OR_MORE(...) \ - (__VA_ARGS__, userData) - -#define EXPAND_WCB_DISAMBIGUATE2(has_args, ...) \ - EXPAND_WCB_ ## has_args (__VA_ARGS__) -#define EXPAND_WCB_DISAMBIGUATE(has_args, ...) \ - EXPAND_WCB_DISAMBIGUATE2(has_args, __VA_ARGS__) -#define EXPAND_WCB(...) \ - EXPAND_WCB_DISAMBIGUATE(PP_HAS_ARGS(__VA_ARGS__), __VA_ARGS__) - -#else -/* - * EXPAND_WCB() is used as: - * - * EXPAND_WCB( cbname )( arg_list, userData ) + * EXPAND_WCB( cbname )(( arg_list, userData )) * * ... where {(arg_list)} is the parameter list and userData is user * provided data. @@ -701,30 +636,12 @@ do \ * This will take the arg_list and extend it by one argument, adding * the argument "userData" to the end of the list. * - * In order for this to work, each callback must have a define that - * properly handles the arguments as needed by the callback. - * This callback is in the format of EXPAND_WCB_SUB_. - * Two helper defines exist: EXPAND_WCB_ZERO and EXPAND_WCB_ONE_OR_MORE, - * each to handle callbacks that take zero-params (but take userData) and - * to take one or more params (along with userData). - * - * An example for the "Entry" callback, where "Entry" is the cbname: - * typedef void (* FGCBEntry )( int ); - * typedef void (* FGCBEntryUC)( int, FGCBUserData ); - * #define EXPAND_WCB_SUB_Entry(args, userData) EXPAND_WCB_ONE_OR_MORE(args, userData) + * All of this is defined in fg_callback_macros.h + * + * See that header for more info. + * + * ------------------------------------------------------------------ */ -#define FG_COMPILER_SUPPORTS_VA_ARGS -#ifdef FG_COMPILER_SUPPORTS_VA_ARGS -#define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ -#else -#error "Compiler does not support varadic argument macros" -#endif - -#define EXPAND_WCB_ZERO(args, userData) ( userData ) -#define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) - -#define EXPAND_WCB(cbname) EXPAND_WCB_SUB_ ## cbname -#endif /* * INVOKE_WCB() is used as: @@ -755,7 +672,7 @@ do \ FGCB ## cbname ## UC func = (FGCB ## cbname ## UC)(FETCH_WCB( window, cbname )); \ FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ fgSetWindow( &window ); \ - func EXPAND_WCB( cbname )( arg_list, userData ); \ + func EXPAND_WCB( cbname )(( arg_list, userData )); \ } \ } while( 0 ) #else @@ -766,7 +683,7 @@ do \ { \ fgSetWindow( &window ); \ FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ - ((FGCB ## cbname ## UC)FETCH_WCB( window, cbname )) EXPAND_WCB( cbname )( arg_list, userData ); \ + ((FGCB ## cbname ## UC)FETCH_WCB( window, cbname )) EXPAND_WCB( cbname )(( arg_list, userData )); \ } \ } while( 0 ) #endif From 0209cd1ef5b1830203793fd2459b00b11b7484b0 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:21:34 +0000 Subject: [PATCH 06/20] Bug fix for GCC compiler usage Removed old/original GCC implementation of EXPAND_WCB git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1813 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/fg_callback_macros.h | 47 +--------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/freeglut/freeglut/src/fg_callback_macros.h b/freeglut/freeglut/src/fg_callback_macros.h index 1c70587..a5fa7b5 100644 --- a/freeglut/freeglut/src/fg_callback_macros.h +++ b/freeglut/freeglut/src/fg_callback_macros.h @@ -32,50 +32,6 @@ #error "fg_internal.h needs to be included before this header" #endif -#if 0 /* old. Remove once other testing is complete */ -/* - * EXPAND_WCB() is used as: - * - * EXPAND_WCB arg_list - * - * ... where {(arg_list)} is the parameter list. - * - * This will take the arg_list and extend it by one argument, adding - * the argument "userData" to the end of the list. - * - * All additional args are to get around trailing ',', argument counts, - * and not needing a GCC extension to make this work. - * - * Minor modification of: - * http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946 - * - * Supports up to five arguments - */ - -/* GCC-specific design that doesn't require per-callback defines */ - -#define PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N -#define PP_HAS_ARGS_SOURCE() \ - ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO - -#define PP_HAS_ARGS_IMPL(...) \ - PP_HAS_ARGS_IMPL2(__VA_ARGS__) -#define PP_HAS_ARGS(...) \ - PP_HAS_ARGS_IMPL(NOT_EXIST, ##__VA_ARGS__, PP_HAS_ARGS_SOURCE()) - -#define EXPAND_WCB_ZERO(x) \ - (userData) -#define EXPAND_WCB_ONE_OR_MORE(...) \ - (__VA_ARGS__, userData) - -#define EXPAND_WCB_DISAMBIGUATE2(has_args, ...) \ - EXPAND_WCB_ ## has_args (__VA_ARGS__) -#define EXPAND_WCB_DISAMBIGUATE(has_args, ...) \ - EXPAND_WCB_DISAMBIGUATE2(has_args, __VA_ARGS__) -#define EXPAND_WCB(...) \ - EXPAND_WCB_DISAMBIGUATE(PP_HAS_ARGS(__VA_ARGS__), __VA_ARGS__) -#endif - /* * Compiler defines: * FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK: if the compiler supports GCC's varadic macro implementation (AKA, ##__VA_ARGS__) @@ -125,7 +81,8 @@ #define EXPAND_WCB_ZERO(args, userData) ( userData ) #define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) -#define EXPAND_WCB_DISAMBIGUATE(has_args, args, userData) EXPAND_WCB_ ## has_args ( args, userData ) +#define EXPAND_WCB_DISAMBIGUATE2(has_args, args, userData) EXPAND_WCB_ ## has_args ( args, userData ) +#define EXPAND_WCB_DISAMBIGUATE(has_args, args, userData) EXPAND_WCB_DISAMBIGUATE2( has_args, args, userData ) #define EXPAND_WCB_UNWRAP_ARGS2(args, userData) EXPAND_WCB_DISAMBIGUATE( PP_HAS_ARGS args, args, userData ) #define EXPAND_WCB_UNWRAP_ARGS(args) EXPAND_WCB_UNWRAP_ARGS2 args From dbbf2e5f08036f0b65a8c957932bebb4bbaf2a26 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:21:40 +0000 Subject: [PATCH 07/20] Implemented pre-C99 support for macro expansion for callbacks. Note: not tested with a pre-C99 compiler as I (the author) don't have any compiler that doesn't C99. Fixed copyright too. git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1814 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/fg_callback_macros.h | 82 ++++++++++++++++++---- 1 file changed, 67 insertions(+), 15 deletions(-) diff --git a/freeglut/freeglut/src/fg_callback_macros.h b/freeglut/freeglut/src/fg_callback_macros.h index a5fa7b5..2406243 100644 --- a/freeglut/freeglut/src/fg_callback_macros.h +++ b/freeglut/freeglut/src/fg_callback_macros.h @@ -3,9 +3,8 @@ * * The freeglut library callback macro file. * - * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. - * Written by Pawel W. Olszta, - * Creation date: Thu Dec 2 1999 + * Copyright (C) 2016 Vincent Simonetti + * Creation date: Sat Jan 16 2016 * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -38,20 +37,65 @@ * FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports varadic macros */ +/* + * Info: + * + * This took a while to figure out, so be sure try to understand what is happening so that you can ensure that whatever you + * change won't break other areas. + * + * If you are just adding a new callback/changing it's argument count, just go to the bottom of the file. + * + * This whole file exists purely for the sake of preventing the need to implement additional parsing logic for each callback + * to pass user arguments. Of course, the necessity to support older compilers means that, as seen in the line above, there + * is still a requirement to add/modify code to handle callbacks. If freeglut ever requires newer compilers (at minimum, ones + * that support C99 or higher), code can very slowly be removed from this file. Even better would be if the C standard eventually + * supports something similar to what GCC has implemented or offers an alternative. Another option is if C++ would be "allowed" by + * project maintaners, as then templates can be used and function overloading. Ironically, the template would probably look worse + * then the GCC macro, so maybe it's good to stay as is. + * + * Onto the different "versions" of macros: + * + * There is one for GCC/Clang(/and supposedly the Intel compiler) which supports the non-standard ##__VA_ARGS__ token. The code may + * look ugly, but the result is, if this was standard, no one would ever need to open this file unless they were curious (or needed + * more then 5 arguments for a callback, but that's trivial to add). It works by adding many fake macros to a "picker" macro + * (PP_HAS_ARGS_IMPL2) which then indictaes which macro counter to use. As we can already use varadic macros (the VA in __VA_ARGS__), + * this just becomes a "reuse the arguments*. + * + * The next is for any non-GCC/Clang/etc. compiler *cough* MSVC/compiler you probably shouldn't be using *cough* that supports C99 + * by default. It requires each callback to have a specific argument count passthrough macro. The only reason there are specific + * count macros is so that (see paraghraph below) don't need have their own set of callback macros. Ideally, there would only be + * ZERO and ONE_OR_MORE. This works by having callback-specific macros call a specific handler macro to return user data (ZERO) or + * return one or more arguments along with userData (ONE_OR_MORE) where, with varadic macros, it just reuses the arguments. + * + * The last set is for the poor individual who has to use a compiler that doesn't support C99 by default, or may not support it at + * all. Stuff like MSVC6... It works by having a specific-count macro that "extracts" each argument to have them reused without the + * parathesis. + * + * A note on parathesis, as earlier mentioned, if the GCC varadic macro element was standard, then instead of needing: + * + * func EXPAND_WCB(Mouse)(( (GLUT_LEFT_BUTTON, GLUT_DOWN, 10, 30), userData)); + * + * ...you can do the following: + * + * func EXPAND_WCB (GLUT_LEFT_BUTTON, GLUT_DOWN, 10, 30); + * + * Wow... so much nice and easier to understand. Sub-note: I have not worked on a version that explicitly takes userData, so for now + * if you can get to that version, look in the version control change history for this file and you'll find that version which + * implicitly passes "userData" and only works on GCC vardiac macro supporting compilers. + */ + #ifdef FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK /* * EXPAND_WCB() is used as: + * + * EXPAND_WCB( cbname )(( arg_list, userData )) + * + * ... where {(arg_list)} is the parameter list and userData is user + * provided data. * - * EXPAND_WCB arg_list - * - * ... where {(arg_list)} is the parameter list. - * - * This will take the arg_list and extend it by one argument, adding - * the argument "userData" to the end of the list. - * - * All additional args are to get around trailing ',', argument counts, - * and not needing a GCC extension to make this work. + * All additional macros are to get around trailing ',' for zero-arg + * callbacks. * * Modification of: * http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946 @@ -115,7 +159,6 @@ * #define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args */ -#define FG_COMPILER_SUPPORTS_VA_ARGS //XXX (should be compiler defined) #ifdef FG_COMPILER_SUPPORTS_VA_ARGS #define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ @@ -129,8 +172,17 @@ #else -//TODO -#error "Compiler does not support varadic argument macros" +#define EXTRACT_ONE_ARGS(arg1) arg1 +#define EXTRACT_TWO_ARGS(arg1, arg2) arg1, arg2 +#define EXTRACT_THREE_ARGS(arg1, arg2, arg3) arg1, arg2, arg3 +#define EXTRACT_FOUR_ARGS(arg1, arg2, arg3, arg4) arg1, arg2, arg3, arg4 +#define EXTRACT_FIVE_ARGS(arg1, arg2, arg3, arg4, arg5) arg1, arg2, arg3, arg4, arg5 + +#define EXPAND_WCB_ONE(args, userData) (EXTRACT_ONE_ARGS args, userData) +#define EXPAND_WCB_TWO(args, userData) (EXTRACT_TWO_ARGS args, userData) +#define EXPAND_WCB_THREE(args, userData) (EXTRACT_THREE_ARGS args, userData) +#define EXPAND_WCB_FOUR(args, userData) (EXTRACT_FOUR_ARGS args, userData) +#define EXPAND_WCB_FIVE(args, userData) (EXTRACT_FIVE_ARGS args, userData) #endif From 16d920d56a7bf9e0989f3774504cd19054c8faee Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:21:46 +0000 Subject: [PATCH 08/20] Added compiler feature detection for __VA_ARGS__ and GCC ##__VA_ARGS__ Made macro names more explicit to prevent name conflicts git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1815 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/fg_callback_macros.h | 73 +++++++++++++--------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/freeglut/freeglut/src/fg_callback_macros.h b/freeglut/freeglut/src/fg_callback_macros.h index 2406243..76c7227 100644 --- a/freeglut/freeglut/src/fg_callback_macros.h +++ b/freeglut/freeglut/src/fg_callback_macros.h @@ -27,16 +27,33 @@ #ifndef FREEGLUT_CALLBACK_MACROS_H #define FREEGLUT_CALLBACK_MACROS_H -#ifndef FREEGLUT_INTERNAL_H -#error "fg_internal.h needs to be included before this header" -#endif - /* * Compiler defines: - * FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK: if the compiler supports GCC's varadic macro implementation (AKA, ##__VA_ARGS__) - * FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports varadic macros + * FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK: if the compiler supports GCC's variadic macro implementation (AKA, ##__VA_ARGS__) + * FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports variadic macros */ +/* What supports variadic macros based off Wikipedia article on it */ +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__GNUC__) && (__GNUC__ >= 3)) || \ + (defined(__clang__)) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1400)) || \ + (defined(__BORLANDC__) && (__BORLANDC__ >= 0x570)) || \ + (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x530)) +#define FG_COMPILER_SUPPORTS_VA_ARGS 1 +#else +#define FG_COMPILER_SUPPORTS_VA_ARGS 0 +#endif + +/* If __VA_ARGS__ is supported, it needs to be GCC(-like) or Clang (since Clang mimics GCC) */ +#if FG_COMPILER_SUPPORTS_VA_ARGS && \ + (defined(__GNUC__)) || \ + (defined(__clang__)) +#define FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK 1 +#else +#define FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK 0 +#endif + /* * Info: * @@ -58,20 +75,20 @@ * There is one for GCC/Clang(/and supposedly the Intel compiler) which supports the non-standard ##__VA_ARGS__ token. The code may * look ugly, but the result is, if this was standard, no one would ever need to open this file unless they were curious (or needed * more then 5 arguments for a callback, but that's trivial to add). It works by adding many fake macros to a "picker" macro - * (PP_HAS_ARGS_IMPL2) which then indictaes which macro counter to use. As we can already use varadic macros (the VA in __VA_ARGS__), + * (PP_HAS_ARGS_IMPL2) which then indictaes which macro counter to use. As we can already use variadic macros (the VA in __VA_ARGS__), * this just becomes a "reuse the arguments*. * * The next is for any non-GCC/Clang/etc. compiler *cough* MSVC/compiler you probably shouldn't be using *cough* that supports C99 * by default. It requires each callback to have a specific argument count passthrough macro. The only reason there are specific * count macros is so that (see paraghraph below) don't need have their own set of callback macros. Ideally, there would only be * ZERO and ONE_OR_MORE. This works by having callback-specific macros call a specific handler macro to return user data (ZERO) or - * return one or more arguments along with userData (ONE_OR_MORE) where, with varadic macros, it just reuses the arguments. + * return one or more arguments along with userData (ONE_OR_MORE) where, with variadic macros, it just reuses the arguments. * * The last set is for the poor individual who has to use a compiler that doesn't support C99 by default, or may not support it at * all. Stuff like MSVC6... It works by having a specific-count macro that "extracts" each argument to have them reused without the * parathesis. * - * A note on parathesis, as earlier mentioned, if the GCC varadic macro element was standard, then instead of needing: + * A note on parathesis, as earlier mentioned, if the GCC variadic macro element was standard, then instead of needing: * * func EXPAND_WCB(Mouse)(( (GLUT_LEFT_BUTTON, GLUT_DOWN, 10, 30), userData)); * @@ -84,7 +101,7 @@ * implicitly passes "userData" and only works on GCC vardiac macro supporting compilers. */ -#ifdef FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK +#if FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK /* * EXPAND_WCB() is used as: @@ -108,19 +125,19 @@ * should not require any modification unless additional arguments are to * be supported. * - * Supports callbacks up to 5 args (follow the pattern of PP_HAS_ARGS_IMPL2 - * and PP_HAS_ARGS_SOURCE to add more) + * Supports callbacks up to 5 args (follow the pattern of + * EXPAND_WCB_PP_HAS_ARGS_IMPL2 and EXPAND_WCB_PP_HAS_ARGS_SOURCE to add more) * * Edit with care. */ #define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ -#define PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N -#define PP_HAS_ARGS_SOURCE() ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO +#define EXPAND_WCB_PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N +#define EXPAND_WCB_PP_HAS_ARGS_SOURCE() ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO -#define PP_HAS_ARGS_IMPL(...) PP_HAS_ARGS_IMPL2( __VA_ARGS__ ) -#define PP_HAS_ARGS(...) PP_HAS_ARGS_IMPL( NOT_EXIST, ##__VA_ARGS__, PP_HAS_ARGS_SOURCE() ) +#define EXPAND_WCB_PP_HAS_ARGS_IMPL(...) EXPAND_WCB_PP_HAS_ARGS_IMPL2( __VA_ARGS__ ) +#define EXPAND_WCB_PP_HAS_ARGS(...) EXPAND_WCB_PP_HAS_ARGS_IMPL( NOT_EXIST, ##__VA_ARGS__, EXPAND_WCB_PP_HAS_ARGS_SOURCE() ) #define EXPAND_WCB_ZERO(args, userData) ( userData ) #define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) @@ -128,7 +145,7 @@ #define EXPAND_WCB_DISAMBIGUATE2(has_args, args, userData) EXPAND_WCB_ ## has_args ( args, userData ) #define EXPAND_WCB_DISAMBIGUATE(has_args, args, userData) EXPAND_WCB_DISAMBIGUATE2( has_args, args, userData ) -#define EXPAND_WCB_UNWRAP_ARGS2(args, userData) EXPAND_WCB_DISAMBIGUATE( PP_HAS_ARGS args, args, userData ) +#define EXPAND_WCB_UNWRAP_ARGS2(args, userData) EXPAND_WCB_DISAMBIGUATE( EXPAND_WCB_PP_HAS_ARGS args, args, userData ) #define EXPAND_WCB_UNWRAP_ARGS(args) EXPAND_WCB_UNWRAP_ARGS2 args #define EXPAND_WCB(cbname) EXPAND_WCB_UNWRAP_ARGS @@ -159,7 +176,7 @@ * #define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args */ -#ifdef FG_COMPILER_SUPPORTS_VA_ARGS +#if FG_COMPILER_SUPPORTS_VA_ARGS #define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ #define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) @@ -172,17 +189,17 @@ #else -#define EXTRACT_ONE_ARGS(arg1) arg1 -#define EXTRACT_TWO_ARGS(arg1, arg2) arg1, arg2 -#define EXTRACT_THREE_ARGS(arg1, arg2, arg3) arg1, arg2, arg3 -#define EXTRACT_FOUR_ARGS(arg1, arg2, arg3, arg4) arg1, arg2, arg3, arg4 -#define EXTRACT_FIVE_ARGS(arg1, arg2, arg3, arg4, arg5) arg1, arg2, arg3, arg4, arg5 +#define EXPAND_WCB_EXTRACT_ONE_ARGS(arg1) arg1 +#define EXPAND_WCB_EXTRACT_TWO_ARGS(arg1, arg2) arg1, arg2 +#define EXPAND_WCB_EXTRACT_THREE_ARGS(arg1, arg2, arg3) arg1, arg2, arg3 +#define EXPAND_WCB_EXTRACT_FOUR_ARGS(arg1, arg2, arg3, arg4) arg1, arg2, arg3, arg4 +#define EXPAND_WCB_EXTRACT_FIVE_ARGS(arg1, arg2, arg3, arg4, arg5) arg1, arg2, arg3, arg4, arg5 -#define EXPAND_WCB_ONE(args, userData) (EXTRACT_ONE_ARGS args, userData) -#define EXPAND_WCB_TWO(args, userData) (EXTRACT_TWO_ARGS args, userData) -#define EXPAND_WCB_THREE(args, userData) (EXTRACT_THREE_ARGS args, userData) -#define EXPAND_WCB_FOUR(args, userData) (EXTRACT_FOUR_ARGS args, userData) -#define EXPAND_WCB_FIVE(args, userData) (EXTRACT_FIVE_ARGS args, userData) +#define EXPAND_WCB_ONE(args, userData) (EXPAND_WCB_EXTRACT_ONE_ARGS args, userData) +#define EXPAND_WCB_TWO(args, userData) (EXPAND_WCB_EXTRACT_TWO_ARGS args, userData) +#define EXPAND_WCB_THREE(args, userData) (EXPAND_WCB_EXTRACT_THREE_ARGS args, userData) +#define EXPAND_WCB_FOUR(args, userData) (EXPAND_WCB_EXTRACT_FOUR_ARGS args, userData) +#define EXPAND_WCB_FIVE(args, userData) (EXPAND_WCB_EXTRACT_FIVE_ARGS args, userData) #endif From da3e00905e1ed7d10464bfdd9f96964c5354ca6b Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:21:53 +0000 Subject: [PATCH 09/20] Fixed issue where setting the same callback with different user pointer wouldn't change the user pointer. Removed extra comment on FETCH_USER_DATA_WCB Renamed helper callbacks from glutXXXCalback to fghXXXCallback git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1816 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/fg_callbacks.c | 58 ++++++++++++++-------------- freeglut/freeglut/src/fg_init.c | 28 +++++++++----- freeglut/freeglut/src/fg_internal.h | 18 +++++---- freeglut/freeglut/src/fg_menu.c | 12 ++++-- 4 files changed, 65 insertions(+), 51 deletions(-) diff --git a/freeglut/freeglut/src/fg_callbacks.c b/freeglut/freeglut/src/fg_callbacks.c index 684c934..4fc0089 100644 --- a/freeglut/freeglut/src/fg_callbacks.c +++ b/freeglut/freeglut/src/fg_callbacks.c @@ -42,7 +42,7 @@ void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData ) fgState.IdleCallbackData = userData; } -static void glutIdleFuncCallback( FGCBUserData userData ) +static void fghIdleFuncCallback( FGCBUserData userData ) { FGCBIdle callback = (FGCBIdle)userData; callback(); @@ -52,7 +52,7 @@ void FGAPIENTRY glutIdleFunc( FGCBIdle callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" ); if( callback ) - glutIdleFuncUcall( glutIdleFuncCallback, (FGCBUserData)callback ); + glutIdleFuncUcall( fghIdleFuncCallback, (FGCBUserData)callback ); else glutIdleFuncUcall( NULL, NULL ); } @@ -90,7 +90,7 @@ void FGAPIENTRY glutTimerFuncUcall( unsigned int timeOut, FGCBTimerUC callback, fgListInsert( &fgState.Timers, &node->Node, &timer->Node ); } -static void glutTimerFuncCallback( int ID, FGCBUserData userData ) +static void fghTimerFuncCallback( int ID, FGCBUserData userData ) { FGCBTimer callback = (FGCBTimer)userData; callback( ID ); @@ -100,7 +100,7 @@ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int tim { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" ); if( callback ) - glutTimerFuncUcall( timeOut, glutTimerFuncCallback, timerID, (FGCBUserData)callback ); + glutTimerFuncUcall( timeOut, fghTimerFuncCallback, timerID, (FGCBUserData)callback ); else glutTimerFuncUcall( timeOut, NULL, timerID, NULL ); } @@ -120,7 +120,7 @@ void FGAPIENTRY glutMenuStatusFuncUcall( FGCBMenuStatusUC callback, FGCBUserData fgState.MenuStatusCallbackData = userData; } -static void glutMenuStatusFuncCallback( int menuState, int mouseX, int mouseY, FGCBUserData userData ) +static void fghMenuStatusFuncCallback( int menuState, int mouseX, int mouseY, FGCBUserData userData ) { FGCBMenuStatus callback = (FGCBMenuStatus)userData; callback( menuState, mouseX, mouseY ); @@ -130,7 +130,7 @@ void FGAPIENTRY glutMenuStatusFunc( FGCBMenuStatus callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" ); if( callback ) - glutMenuStatusFuncUcall( glutMenuStatusFuncCallback, (FGCBUserData)callback ); + glutMenuStatusFuncUcall( fghMenuStatusFuncCallback, (FGCBUserData)callback ); else glutMenuStatusFuncUcall( NULL, NULL ); } @@ -149,7 +149,7 @@ void FGAPIENTRY glutMenuDestroyFuncUcall( FGCBDestroyUC callback, FGCBUserData u } } -static void glutMenuDestroyFuncCallback( FGCBUserData userData ) +static void fghMenuDestroyFuncCallback( FGCBUserData userData ) { FGCBDestroy callback = (FGCBDestroy)userData; callback(); @@ -159,7 +159,7 @@ void FGAPIENTRY glutMenuDestroyFunc( FGCBDestroy callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" ); if( callback ) - glutMenuDestroyFuncUcall( glutMenuDestroyFuncCallback, (FGCBUserData)callback ); + glutMenuDestroyFuncUcall( fghMenuDestroyFuncCallback, (FGCBUserData)callback ); else glutMenuDestroyFuncUcall( NULL, NULL ); } @@ -179,38 +179,38 @@ do \ * Types need to be defined for callbacks. It's not ideal, but it works for this. */ #define IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ -static void glut##a##FuncCallback( FGCBUserData userData ) \ +static void fgh##a##FuncCallback( FGCBUserData userData ) \ { \ FGCB##b callback = (FGCB##b)userData; \ callback(); \ } #define IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,b) \ -static void glut##a##FuncCallback( int arg1val, FGCBUserData userData ) \ +static void fgh##a##FuncCallback( int arg1val, FGCBUserData userData ) \ { \ FGCB##b callback = (FGCB##b)userData; \ callback( arg1val ); \ } #define IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ -static void glut##a##FuncCallback( int arg1val, int arg2val, FGCBUserData userData ) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, FGCBUserData userData ) \ { \ FGCB##b callback = (FGCB##b)userData; \ callback( arg1val, arg2val ); \ } #define IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,arg1,arg2,arg3) \ -static void glut##a##FuncCallback( arg1 arg1val, arg2 arg2val, arg3 arg3val, FGCBUserData userData ) \ +static void fgh##a##FuncCallback( arg1 arg1val, arg2 arg2val, arg3 arg3val, FGCBUserData userData ) \ { \ FGCB##b callback = (FGCB##b)userData; \ callback( arg1val, arg2val, arg3val ); \ } #define IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b) IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,int,int,int) #define IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,b) \ -static void glut##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, FGCBUserData userData ) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, FGCBUserData userData ) \ { \ FGCB##b callback = (FGCB##b)userData; \ callback( arg1val, arg2val, arg3val, arg4val ); \ } #define IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,b) \ -static void glut##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, int arg5val, FGCBUserData userData ) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, int arg5val, FGCBUserData userData ) \ { \ FGCB##b callback = (FGCB##b)userData; \ callback( arg1val, arg2val, arg3val, arg4val, arg5val ); \ @@ -228,7 +228,7 @@ void FGAPIENTRY glut##a##Func( FGCB##b callback ) \ { \ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"Func" ); \ if( callback ) \ - glut##a##FuncUcall( glut##a##FuncCallback, (FGCBUserData)callback ); \ + glut##a##FuncUcall( fgh##a##FuncCallback, (FGCBUserData)callback ); \ else \ glut##a##FuncUcall( NULL, NULL ); \ } @@ -310,7 +310,7 @@ void FGAPIENTRY glutDisplayFuncUcall( FGCBDisplayUC callback, FGCBUserData userD SET_CALLBACK( Display ); } -static void glutDisplayFuncCallback( FGCBUserData userData ) +static void fghDisplayFuncCallback( FGCBUserData userData ) { FGCBDisplay callback = (FGCBDisplay)userData; callback(); @@ -320,7 +320,7 @@ void FGAPIENTRY glutDisplayFunc( FGCBDisplay callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" ); if( callback ) - glutDisplayFuncUcall( glutDisplayFuncCallback, (FGCBUserData)callback ); + glutDisplayFuncUcall( fghDisplayFuncCallback, (FGCBUserData)callback ); else glutDisplayFuncUcall( NULL, NULL ); } @@ -343,7 +343,7 @@ void FGAPIENTRY glutReshapeFuncUcall( FGCBReshapeUC callback, FGCBUserData userD SET_CALLBACK( Reshape ); } -static void glutReshapeFuncCallback( int width, int height, FGCBUserData userData ) +static void fghReshapeFuncCallback( int width, int height, FGCBUserData userData ) { FGCBReshape callback = (FGCBReshape)userData; callback( width, height ); @@ -353,7 +353,7 @@ void FGAPIENTRY glutReshapeFunc( FGCBReshape callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" ); if( callback ) - glutReshapeFuncUcall( glutReshapeFuncCallback, (FGCBUserData)callback ); + glutReshapeFuncUcall( fghReshapeFuncCallback, (FGCBUserData)callback ); else glutReshapeFuncUcall( NULL, NULL ); } @@ -406,7 +406,7 @@ void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData glutWindowStatusFuncUcall( NULL, NULL ); } -static void glutVisibilityFuncCallback( int visibility, FGCBUserData userData ) +static void fghVisibilityFuncCallback( int visibility, FGCBUserData userData ) { FGCBVisibility callback = (FGCBVisibility)userData; callback( visibility ); @@ -416,7 +416,7 @@ void FGAPIENTRY glutVisibilityFunc( FGCBVisibility callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" ); if( callback ) - glutVisibilityFuncUcall( glutVisibilityFuncCallback, (FGCBUserData)callback ); + glutVisibilityFuncUcall( fghVisibilityFuncCallback, (FGCBUserData)callback ); else glutVisibilityFuncUcall( NULL, NULL ); } @@ -457,7 +457,7 @@ void FGAPIENTRY glutJoystickFuncUcall( FGCBJoystickUC callback, int pollInterval fgStructure.CurrentWindow->State.JoystickLastPoll -= pollInterval; } -static void glutJoystickFuncCallback( unsigned int buttons, int axis0, int axis1, int axis2, FGCBUserData userData ) +static void fghJoystickFuncCallback( unsigned int buttons, int axis0, int axis1, int axis2, FGCBUserData userData ) { FGCBJoystick callback = (FGCBJoystick)userData; callback( buttons, axis0, axis1, axis2 ); @@ -467,7 +467,7 @@ void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" ); if( callback ) - glutJoystickFuncUcall( glutJoystickFuncCallback, pollInterval, (FGCBUserData)callback ); + glutJoystickFuncUcall( fghJoystickFuncCallback, pollInterval, (FGCBUserData)callback ); else glutJoystickFuncUcall( NULL, pollInterval, NULL ); } @@ -483,7 +483,7 @@ void FGAPIENTRY glutSpaceballMotionFuncUcall( FGCBSpaceMotionUC callback, FGCBUs SET_CALLBACK( SpaceMotion ); } -static void glutSpaceballMotionFuncCallback( int x, int y, int z, FGCBUserData userData ) +static void fghSpaceballMotionFuncCallback( int x, int y, int z, FGCBUserData userData ) { FGCBSpaceMotion callback = (FGCBSpaceMotion)userData; callback( x, y, z ); @@ -493,7 +493,7 @@ void FGAPIENTRY glutSpaceballMotionFunc( FGCBSpaceMotion callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" ); if( callback ) - glutSpaceballMotionFuncUcall( glutSpaceballMotionFuncCallback, (FGCBUserData)callback ); + glutSpaceballMotionFuncUcall( fghSpaceballMotionFuncCallback, (FGCBUserData)callback ); else glutSpaceballMotionFuncUcall( NULL, NULL ); } @@ -509,7 +509,7 @@ void FGAPIENTRY glutSpaceballRotateFuncUcall( FGCBSpaceRotationUC callback, FGCB SET_CALLBACK( SpaceRotation ); } -static void glutSpaceballRotateFuncCallback( int x, int y, int z, FGCBUserData userData ) +static void fghSpaceballRotateFuncCallback( int x, int y, int z, FGCBUserData userData ) { FGCBSpaceRotation callback = (FGCBSpaceRotation)userData; callback( x, y, z ); @@ -519,7 +519,7 @@ void FGAPIENTRY glutSpaceballRotateFunc( FGCBSpaceRotation callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" ); if( callback ) - glutSpaceballRotateFuncUcall( glutSpaceballRotateFuncCallback, (FGCBUserData)callback ); + glutSpaceballRotateFuncUcall( fghSpaceballRotateFuncCallback, (FGCBUserData)callback ); else glutSpaceballRotateFuncUcall( NULL, NULL ); } @@ -535,7 +535,7 @@ void FGAPIENTRY glutSpaceballButtonFuncUcall( FGCBSpaceButtonUC callback, FGCBUs SET_CALLBACK( SpaceButton ); } -static void glutSpaceballButtonFuncCallback( int button, int buttonState, FGCBUserData userData ) +static void fghSpaceballButtonFuncCallback( int button, int buttonState, FGCBUserData userData ) { FGCBSpaceButton callback = (FGCBSpaceButton)userData; callback( button, buttonState ); @@ -545,7 +545,7 @@ void FGAPIENTRY glutSpaceballButtonFunc( FGCBSpaceButton callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" ); if( callback ) - glutSpaceballButtonFuncUcall( glutSpaceballButtonFuncCallback, (FGCBUserData)callback ); + glutSpaceballButtonFuncUcall( fghSpaceballButtonFuncCallback, (FGCBUserData)callback ); else glutSpaceballButtonFuncUcall( NULL, NULL ); } diff --git a/freeglut/freeglut/src/fg_init.c b/freeglut/freeglut/src/fg_init.c index a408bbe..c3c00e5 100644 --- a/freeglut/freeglut/src/fg_init.c +++ b/freeglut/freeglut/src/fg_init.c @@ -681,7 +681,7 @@ void FGAPIENTRY glutInitErrorFuncUcall( FGErrorUC callback, FGCBUserData userDat fgState.ErrorFuncData = userData; } -static void glutInitErrorFuncCallback( const char *fmt, va_list ap, FGCBUserData userData ) +static void fghInitErrorFuncCallback( const char *fmt, va_list ap, FGCBUserData userData ) { FGError callback = (FGError)userData; callback( fmt, ap ); @@ -689,10 +689,14 @@ static void glutInitErrorFuncCallback( const char *fmt, va_list ap, FGCBUserData void FGAPIENTRY glutInitErrorFunc( FGError callback ) { - if (callback) - glutInitErrorFuncUcall( glutInitErrorFuncCallback, (FGCBUserData)callback ); - else - glutInitErrorFuncUcall( NULL, NULL ); + if (callback) + { + glutInitErrorFuncUcall( fghInitErrorFuncCallback, (FGCBUserData)callback ); + } + else + { + glutInitErrorFuncUcall( NULL, NULL ); + } } /* @@ -705,7 +709,7 @@ void FGAPIENTRY glutInitWarningFuncUcall( FGWarningUC callback, FGCBUserData use fgState.WarningFuncData = userData; } -static void glutInitWarningFuncCallback( const char *fmt, va_list ap, FGCBUserData userData ) +static void fghInitWarningFuncCallback( const char *fmt, va_list ap, FGCBUserData userData ) { FGWarning callback = (FGWarning)userData; callback( fmt, ap ); @@ -713,10 +717,14 @@ static void glutInitWarningFuncCallback( const char *fmt, va_list ap, FGCBUserDa void FGAPIENTRY glutInitWarningFunc( FGWarning callback ) { - if (callback) - glutInitWarningFuncUcall( glutInitWarningFuncCallback, (FGCBUserData)callback ); - else - glutInitWarningFuncUcall( NULL, NULL ); + if (callback) + { + glutInitWarningFuncUcall( fghInitWarningFuncCallback, (FGCBUserData)callback ); + } + else + { + glutInitWarningFuncUcall( NULL, NULL ); + } } /*** END OF FILE ***/ diff --git a/freeglut/freeglut/src/fg_internal.h b/freeglut/freeglut/src/fg_internal.h index bce77ca..c98e520 100644 --- a/freeglut/freeglut/src/fg_internal.h +++ b/freeglut/freeglut/src/fg_internal.h @@ -577,6 +577,12 @@ typedef void (*SFG_Proc)(); * The {if( FETCH_WCB( ... ) != func )} test is to do type-checking * and for no other reason. Since it's hidden in the macro, the * ugliness is felt to be rather benign. + * + * If the function-pointer is the same, the data will be the only + * value updated. If the function-pointer changes, the data will + * be changed as well, preventing stail data from being passed in. + * Just updating the data does nothing unless a function-pointer + * exists, as the data is otherwise already allocated. */ #define SET_WCB(window,cbname,func,udata) \ do \ @@ -586,6 +592,10 @@ do \ (((window).CallBacks[WCB_ ## cbname]) = (SFG_Proc)(func)); \ (((window).CallbackDatas[WCB_ ## cbname]) = (udata)); \ } \ + else if( FETCH_USER_DATA_WCB( window, cbname ) != udata ) \ + { \ + (((window).CallbackDatas[WCB_ ## cbname]) = (udata)); \ + } \ } while( 0 ) /* @@ -611,14 +621,6 @@ do \ * {cbname} is the window-specific callback to be invoked, * * This expects a variable named "window" of type tagSFG_Window to exist. - */ -/* - * FETCH_USER_DATA_WCB() is used as: - * - * FETCH_USER_DATA_WCB( window, cbname ); - * - * ...where {window} is the freeglut window to fetch the callback data from, - * {cbname} is the window-specific callback data to fetch. * * The result is the callback data pointer. */ diff --git a/freeglut/freeglut/src/fg_menu.c b/freeglut/freeglut/src/fg_menu.c index 1b07b1a..ae7405c 100644 --- a/freeglut/freeglut/src/fg_menu.c +++ b/freeglut/freeglut/src/fg_menu.c @@ -784,14 +784,16 @@ int FGAPIENTRY glutCreateMenuUcall( FGCBMenuUC callback, FGCBUserData userData ) { /* The menu object creation code resides in fg_structure.c */ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenuUcall" ); - if (fgState.ActiveMenus) - fgError("Menu manipulation not allowed while menus in use."); + if (fgState.ActiveMenus) + { + fgError( "Menu manipulation not allowed while menus in use." ); + } return fgCreateMenu( callback, userData )->ID; } /* Standard glutCreateMenu */ -static void glutCreateMenuCallback( int menu, FGCBUserData userData ) +static void fghCreateMenuCallback( int menu, FGCBUserData userData ) { FGCBMenu callback = (FGCBMenu)userData; callback( menu ); @@ -801,8 +803,10 @@ int FGAPIENTRY glutCreateMenu( FGCBMenu callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" ); if (!callback) + { return glutCreateMenuUcall( NULL, NULL ); - return glutCreateMenuUcall( glutCreateMenuCallback, (FGCBUserData)callback ); + } + return glutCreateMenuUcall( fghCreateMenuCallback, (FGCBUserData)callback ); } /* From 8ac335fa7ff8a8e99535a07fa5eb1f9a9a716fd0 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:21:59 +0000 Subject: [PATCH 10/20] Removed unneeded line optimization for INVOKE_WCB macro git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1817 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/fg_internal.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/freeglut/freeglut/src/fg_internal.h b/freeglut/freeglut/src/fg_internal.h index c98e520..a61b121 100644 --- a/freeglut/freeglut/src/fg_internal.h +++ b/freeglut/freeglut/src/fg_internal.h @@ -665,7 +665,6 @@ do \ * current window. * */ -#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: also WinCE? */ #define INVOKE_WCB(window,cbname,arg_list) \ do \ { \ @@ -677,18 +676,6 @@ do \ func EXPAND_WCB( cbname )(( arg_list, userData )); \ } \ } while( 0 ) -#else -#define INVOKE_WCB(window,cbname,arg_list) \ -do \ -{ \ - if( FETCH_WCB( window, cbname ) ) \ - { \ - fgSetWindow( &window ); \ - FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ - ((FGCB ## cbname ## UC)FETCH_WCB( window, cbname )) EXPAND_WCB( cbname )(( arg_list, userData )); \ - } \ -} while( 0 ) -#endif /* * The window callbacks the user can supply us with. Should be kept portable. From 9f0eaf1a9269cda21136a352f3f05daa3845714d Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:22:06 +0000 Subject: [PATCH 11/20] Fixed bug where, under c89 mode, callback macros wouldn't work Under c89 (only applies to GCC-like compilers), the variadic macro version would be used and compilation would fail. git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1818 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/fg_callback_macros.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/freeglut/freeglut/src/fg_callback_macros.h b/freeglut/freeglut/src/fg_callback_macros.h index 76c7227..0c574d7 100644 --- a/freeglut/freeglut/src/fg_callback_macros.h +++ b/freeglut/freeglut/src/fg_callback_macros.h @@ -33,10 +33,10 @@ * FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports variadic macros */ -/* What supports variadic macros based off Wikipedia article on it */ -#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - (defined(__GNUC__) && (__GNUC__ >= 3)) || \ - (defined(__clang__)) || \ +/* What supports variadic macros based off Wikipedia article on it (GCC-like must support C99 or higher to use variadic macros) */ +#if (((defined(__GNUC__) && (__GNUC__ >= 3)) || \ + (defined(__clang__))) && \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))) || \ (defined(_MSC_VER) && (_MSC_VER >= 1400)) || \ (defined(__BORLANDC__) && (__BORLANDC__ >= 0x570)) || \ (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x530)) From 1925fca03062b9602ff86529409c9d2b14b626e0 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:22:12 +0000 Subject: [PATCH 12/20] Updated documentation to mention and discuss user-data callbacks. git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1819 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/web-src/docs/api.php | 106 +++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 7 deletions(-) diff --git a/freeglut/web-src/docs/api.php b/freeglut/web-src/docs/api.php index faeb433..e7a6d0f 100644 --- a/freeglut/web-src/docs/api.php +++ b/freeglut/web-src/docs/api.php @@ -301,7 +301,7 @@ and their compatibility with GLUT, are made explicit.

There is considerable confusion about the "right thing to do" concerning -window size and position. GLUT itself is not consistent between +window size and position. GLUT itself is not consistent between Windows and UNIX/X11; since platform independence is a virtue for freeglut, we decided to break with GLUT's behaviour.
Under UNIX/X11, it is apparently not possible to get the window border @@ -327,6 +327,40 @@ area--which is NOT the (x,y) position of the window you specified when you created it.

+

3.2.2 User-data callbacks

+ +

+GLUT was created as a tool to help teach OpenGL programming. To simplify +development, callbacks were used for handling display, input, and other +events. But the time it was developed, the purpose, or for some other +unknown reason, the callbacks lacked any user-provided data argument. +This has caused considerable difficulties for any significantly advanced +usage of GLUT, and now freeglut. This has prevented any attempt to +wrap freeglut in a C++ wrapper, make per-window, per-callback data +structure, and potentially made it undesirable to modern C developers who +tend to be well versed in "don't use globals". To combat these +complaints and issues, many callbacks (with some deprecated +callbacks excluded) support user-data callbacks provided through additional +functions provided in freeglut. All callbacks that support user-data +callbacks are marked as such. +

+ +

+The general rule to follow is to take the freeglut callback function +and append "Ucall" to the end of the function, add an additional void* +argument to the end of the argument list of both the freeglut function +and the callback function. This will pass the user-data to the callback when it's +invoked. +

+ +

Examples

+ +

void glutPositionFunc ( void (* func)( int x, int y ) );
+void glutPositionFuncUcall ( void (* func)( int x, int y, void* user_data ), void* user_data );

+ +

void glutKeyboardUpFunc ( void (* func)( unsigned char key, int x, int y ) );
+void glutKeyboardUpFuncUcall ( void (* func)( unsigned char key, int x, int y, void* user_data ), void* user_data );

+

3.3 Terminology

3.4 Differences from GLUT 3.7

@@ -524,6 +558,8 @@ from the library can be handled by the user.

void glutInitErrorFunc   ( void (* callback)( const char *fmt, va_list ap) );
void glutInitWarningFunc ( void (* callback)( const char *fmt, va_list ap) );

+

These functions have user-data callback functions.

+

Description

The users callback is passed a format string and a variable argument @@ -943,6 +979,8 @@ The glutShowOverlay and glutHideOverlay functions are not impl

10.1 glutCreateMenu

+

Has user-data callback function.

+

10.2 glutDestroyMenu

10.3 glutGetMenu, glutSetMenu

@@ -985,10 +1023,14 @@ stroke font, or an unknown font.

10.11 glutMenuDestroyFunc

+

Has user-data callback function.

+

11. Global Callback Registration Functions

11.1 glutTimerFunc

+

Has user-data callback function.

+

11.2 glutIdleFunc

@@ -998,11 +1040,11 @@ freeglut calls the idle callback when there are no inputs from the user.

Usage

-

void glutIdleFunc ( void (*func) -( void ) );

+

void glutIdleFunc ( void (*func ) ( void ) );

-

funcThe new -global idle callback function

+

func The new global idle callback function

+ +

Has user-data callback function.

Description

@@ -1042,16 +1084,24 @@ the idle callback.

11.3 glutMenuStatusFunc

+

Has user-data callback function.

+

11.4 glutMenuStateFunc

12. Window-Specific Callback Registration Functions

12.1 glutDisplayFunc

+

Has user-data callback function.

+

12.2 glutOverlayDisplayFunc

+

Has user-data callback function.

+

12.3 glutReshapeFunc

+

Has user-data callback function.

+

12.4 glutPositionFunc

@@ -1065,6 +1115,8 @@ repositioned/moved programatically or by the user.

void glutPositionFunc ( void (* func)( int x, int y) );

+

Has user-data callback function.

+

Description

When freeglut calls this callback, it provides the new @@ -1094,6 +1146,8 @@ about to be destroyed.

func The window's new closure callback function

+

Has user-data callback function.

+

Description

@@ -1121,6 +1175,8 @@ alias to glutCloseFunc.

12.6 glutKeyboardFunc

+

Has user-data callback function.

+

12.7 glutSpecialFunc

@@ -1145,6 +1201,8 @@ to the window at the time the key is pressed
The y-coordinate of the mouse relative to the window at the time the key is pressed

+

Has user-data callback function.

+

Description

@@ -1200,6 +1258,8 @@ to the window at the time the key is released
The y-coordinate of the mouse relative to the window at the time the key is released

+

Has user-data callback function.

+

Description

@@ -1252,6 +1312,8 @@ to the window at the time the key is released
The y-coordinate of the mouse relative to the window at the time the key is released

+

Has user-data callback function.

+

Description

@@ -1289,8 +1351,12 @@ have them fixed.

12.10 glutMotionFunc, glutPassiveMotionFunc

+

Both functions have user-data callback functions.

+

12.11 glutMouseFunc

+

Has user-data callback function.

+

12.12 glutMouseWheelFunc

@@ -1304,6 +1370,8 @@ spins the mouse wheel.

void glutMouseWheelFunc ( void( *callback )( int wheel, int direction, int x, int y ));

+

Has user-data callback function.

+

Description

If the mouse wheel is spun over your (sub)window, freeglut @@ -1320,8 +1388,12 @@ as mouse buttons.

12.13 glutEntryFunc

+

Has user-data callback function.

+

12.14 glutJoystickFunc

+

Has user-data callback function.

+

12.15 glutSpaceballMotionFunc

@@ -1337,6 +1409,8 @@ provided so that GLUT-based programs can compile and link against

void glutSpaceballMotionFunc ( void (* callback)( int x, int y, int z ) );

+

Has user-data callback function.

+

Description

The x, y, and z arguments indicate the amount of translation in integer along x, y, and z axis respectively.

@@ -1357,6 +1431,8 @@ provided so that GLUT-based programs can compile and link against

void glutSpaceballRotateFunc ( void (* callback)( int rx, int ry, int rz ) );

+

Has user-data callback function.

+

Description

The rx, ry, and rz arguments indicate the amount of rotation in integer with respect to x, y, and z axis respectively.

@@ -1379,6 +1455,8 @@ The glutSpaceballButtonFunc function sets the window's Spaceball button

void glutSpaceballButtonFunc ( void (* callback)( int button, int updown ) );

+

Has user-data callback function.

+

Description

The button argument may take one of the following defined @@ -1418,6 +1496,8 @@ The glutDialsFunc function sets the global dials&buttons box callback. void glutButtonBoxFunc ( void (* callback)( int button, int updown ) );

+

Has user-data callback function.

+

Description

@@ -1442,6 +1522,8 @@ The glutDialsFunc function sets the global dials&buttons box callback.

void glutDialsFunc ( void (* callback)( int dial, int value ) );

+

Has user-data callback function.

+

Description

@@ -1469,6 +1551,8 @@ that a call to the function will not produce an error.. void glutTabletMotionFunc ( void (* callback)( int x, int y ) );

+

Has user-data callback function.

+

Description

The glutTabletMotionFunc function @@ -1491,6 +1575,8 @@ that a call to the function will not produce an error..

void glutTabletButtonFunc ( void (* callback)( int button, int updown, int x, int y ) );

+

Has user-data callback function.

+

Description

@@ -1517,6 +1603,8 @@ these callbacks when the visibility status of a window changes.
void glutWindowStatusFunc ( void( *callback )( int state ));

+

Both functions have user-data callback functions.

+

Description

@@ -2701,6 +2789,8 @@ Currently, under windows, the first (oldest) touch point also controls the mouse cursor, which triggers the non-multi callbacks as usual.
+All these functions have user-data callback functions. +
Limitation: currently on the cursor id is provided. It may be @@ -2729,9 +2819,11 @@ whether/how to implement it.

  • glutInitContextFunc ← void : called when the context -is initialized or re-initialized (e.g. after a pause)
  • +is initialized or re-initialized (e.g. after a pause). Has user-data callback +function.
  • glutAppStatusFunc ← event : called when the -application's status changes, with event identifying the state entered. +application's status changes, with event identifying the state entered. Has +user-data callback function. Possible states:
    • application goes on a pause (or a stop) → GLUT_APPSTATUS_PAUSE
    • From 2646c0c9f8ecfb9d1ca62eb7af6bd609ef8b1879 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:22:19 +0000 Subject: [PATCH 13/20] Moved as many callback setters as possible to macro function generators Moved macro function generators to fg_callback_macros.h git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1820 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/fg_callback_macros.h | 160 +++++++++++ freeglut/freeglut/src/fg_callbacks.c | 314 +++------------------ 2 files changed, 203 insertions(+), 271 deletions(-) diff --git a/freeglut/freeglut/src/fg_callback_macros.h b/freeglut/freeglut/src/fg_callback_macros.h index 0c574d7..2aa6ccd 100644 --- a/freeglut/freeglut/src/fg_callback_macros.h +++ b/freeglut/freeglut/src/fg_callback_macros.h @@ -27,6 +27,12 @@ #ifndef FREEGLUT_CALLBACK_MACROS_H #define FREEGLUT_CALLBACK_MACROS_H +/* + * ---------------------------------------------------------------------------------------------------------------------- + * There are two sets of macros here. One is for executing window callbacks, the others are for setting window callbacks. + * ---------------------------------------------------------------------------------------------------------------------- + */ + /* * Compiler defines: * FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK: if the compiler supports GCC's variadic macro implementation (AKA, ##__VA_ARGS__) @@ -55,6 +61,10 @@ #endif /* + * -------------------------- + * Executing window callbacks + * -------------------------- + * * Info: * * This took a while to figure out, so be sure try to understand what is happening so that you can ensure that whatever you @@ -247,6 +257,156 @@ #endif +/* + * ------------------------ + * Setting window callbacks + * ------------------------ + * + * These originally existed in fg_callbacks.c + */ + +/* + * All of the window-specific callbacks setting methods can be generalized to this: + */ +#define SET_CURRENT_WINDOW_CALLBACK(a) \ +do \ +{ \ + if( fgStructure.CurrentWindow == NULL ) \ + return; \ + SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback, userData ); \ +} while( 0 ) + +/* + * Types need to be defined for callbacks. It's not ideal, but it works for this. + */ +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ +static void fgh##a##FuncCallback( FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback(); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,b) \ +static void fgh##a##FuncCallback( int arg1val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,arg1,arg2,arg3) \ +static void fgh##a##FuncCallback( arg1 arg1val, arg2 arg2val, arg3 arg3val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val, arg3val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b) IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,int,int,int) +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,b) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val, arg3val, arg4val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,b) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, int arg5val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val, arg3val, arg4val, arg5val ); \ +} + +/* + * And almost every time the callback setter function can be implemented with these: + */ +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT_UCALL(a,b) \ +void FGAPIENTRY glut##a##FuncUcall( FGCB##b##UC callback, FGCBUserData userData ) \ +{ \ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"FuncUcall" ); \ + SET_CURRENT_WINDOW_CALLBACK( b ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) \ +void FGAPIENTRY glut##a##Func( FGCB##b callback ) \ +{ \ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"Func" ); \ + if( callback ) \ + glut##a##FuncUcall( fgh##a##FuncCallback, (FGCBUserData)callback ); \ + else \ + glut##a##FuncUcall( NULL, NULL ); \ +} + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT_UCALL(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +/* + * Combine _glut and _cb macros: + */ +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG1(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(a,arg1,arg2,arg3) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,a,arg1,arg2,arg3) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG5(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + #endif /* FREEGLUT_CALLBACK_MACROS_H */ /*** END OF FILE ***/ diff --git a/freeglut/freeglut/src/fg_callbacks.c b/freeglut/freeglut/src/fg_callbacks.c index 4fc0089..0e656a8 100644 --- a/freeglut/freeglut/src/fg_callbacks.c +++ b/freeglut/freeglut/src/fg_callbacks.c @@ -30,10 +30,10 @@ /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ - /* * Global callbacks. */ + /* Sets the global idle callback */ void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData ) { @@ -42,20 +42,7 @@ void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData ) fgState.IdleCallbackData = userData; } -static void fghIdleFuncCallback( FGCBUserData userData ) -{ - FGCBIdle callback = (FGCBIdle)userData; - callback(); -} - -void FGAPIENTRY glutIdleFunc( FGCBIdle callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" ); - if( callback ) - glutIdleFuncUcall( fghIdleFuncCallback, (FGCBUserData)callback ); - else - glutIdleFuncUcall( NULL, NULL ); -} +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Idle) /* Creates a timer and sets its callback */ void FGAPIENTRY glutTimerFuncUcall( unsigned int timeOut, FGCBTimerUC callback, int timerID, FGCBUserData userData ) @@ -90,11 +77,7 @@ void FGAPIENTRY glutTimerFuncUcall( unsigned int timeOut, FGCBTimerUC callback, fgListInsert( &fgState.Timers, &node->Node, &timer->Node ); } -static void fghTimerFuncCallback( int ID, FGCBUserData userData ) -{ - FGCBTimer callback = (FGCBTimer)userData; - callback( ID ); -} +IMPLEMENT_CALLBACK_FUNC_CB_ARG1(Timer, Timer) void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID ) { @@ -120,20 +103,7 @@ void FGAPIENTRY glutMenuStatusFuncUcall( FGCBMenuStatusUC callback, FGCBUserData fgState.MenuStatusCallbackData = userData; } -static void fghMenuStatusFuncCallback( int menuState, int mouseX, int mouseY, FGCBUserData userData ) -{ - FGCBMenuStatus callback = (FGCBMenuStatus)userData; - callback( menuState, mouseX, mouseY ); -} - -void FGAPIENTRY glutMenuStatusFunc( FGCBMenuStatus callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" ); - if( callback ) - glutMenuStatusFuncUcall( fghMenuStatusFuncCallback, (FGCBUserData)callback ); - else - glutMenuStatusFuncUcall( NULL, NULL ); -} +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3(MenuStatus) /* * Menu specific callbacks. @@ -149,154 +119,34 @@ void FGAPIENTRY glutMenuDestroyFuncUcall( FGCBDestroyUC callback, FGCBUserData u } } -static void fghMenuDestroyFuncCallback( FGCBUserData userData ) -{ - FGCBDestroy callback = (FGCBDestroy)userData; - callback(); -} - -void FGAPIENTRY glutMenuDestroyFunc( FGCBDestroy callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" ); - if( callback ) - glutMenuDestroyFuncUcall( fghMenuDestroyFuncCallback, (FGCBUserData)callback ); - else - glutMenuDestroyFuncUcall( NULL, NULL ); -} - - -/* - * All of the window-specific callbacks setting methods can be generalized to this: - */ -#define SET_CALLBACK(a) \ -do \ -{ \ - if( fgStructure.CurrentWindow == NULL ) \ - return; \ - SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback, userData ); \ -} while( 0 ) -/* - * Types need to be defined for callbacks. It's not ideal, but it works for this. - */ -#define IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ -static void fgh##a##FuncCallback( FGCBUserData userData ) \ -{ \ - FGCB##b callback = (FGCB##b)userData; \ - callback(); \ -} -#define IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,b) \ -static void fgh##a##FuncCallback( int arg1val, FGCBUserData userData ) \ -{ \ - FGCB##b callback = (FGCB##b)userData; \ - callback( arg1val ); \ -} -#define IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ -static void fgh##a##FuncCallback( int arg1val, int arg2val, FGCBUserData userData ) \ -{ \ - FGCB##b callback = (FGCB##b)userData; \ - callback( arg1val, arg2val ); \ -} -#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,arg1,arg2,arg3) \ -static void fgh##a##FuncCallback( arg1 arg1val, arg2 arg2val, arg3 arg3val, FGCBUserData userData ) \ -{ \ - FGCB##b callback = (FGCB##b)userData; \ - callback( arg1val, arg2val, arg3val ); \ -} -#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b) IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,int,int,int) -#define IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,b) \ -static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, FGCBUserData userData ) \ -{ \ - FGCB##b callback = (FGCB##b)userData; \ - callback( arg1val, arg2val, arg3val, arg4val ); \ -} -#define IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,b) \ -static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, int arg5val, FGCBUserData userData ) \ -{ \ - FGCB##b callback = (FGCB##b)userData; \ - callback( arg1val, arg2val, arg3val, arg4val, arg5val ); \ -} -/* - * And almost every time the callback setter function can be implemented like this: - */ -#define IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,b) \ -void FGAPIENTRY glut##a##FuncUcall( FGCB##b##UC callback, FGCBUserData userData ) \ -{ \ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"FuncUcall" ); \ - SET_CALLBACK( b ); \ -} \ -void FGAPIENTRY glut##a##Func( FGCB##b callback ) \ -{ \ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"Func" ); \ - if( callback ) \ - glut##a##FuncUcall( fgh##a##FuncCallback, (FGCBUserData)callback ); \ - else \ - glut##a##FuncUcall( NULL, NULL ); \ -} -/* - * Combine _glut and _cb macros: - */ -#define IMPLEMENT_CALLBACK_FUNC_ARG0(a) \ - IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a) \ - IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) - -#define IMPLEMENT_CALLBACK_FUNC_ARG0_2NAME(a,b) \ - IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ - IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,b) - -#define IMPLEMENT_CALLBACK_FUNC_ARG1(a) \ - IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a) \ - IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) - -#define IMPLEMENT_CALLBACK_FUNC_ARG2(a) \ - IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a) \ - IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) - -#define IMPLEMENT_CALLBACK_FUNC_ARG2_2NAME(a,b) \ - IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ - IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,b) - -#define IMPLEMENT_CALLBACK_FUNC_ARG3(a) \ - IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a) \ - IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) - -#define IMPLEMENT_CALLBACK_FUNC_ARG3_USER(a,arg1,arg2,arg3) \ - IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,a,arg1,arg2,arg3)\ - IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) - -#define IMPLEMENT_CALLBACK_FUNC_ARG4(a) \ - IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,a) \ - IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) - -#define IMPLEMENT_CALLBACK_FUNC_ARG5(a) \ - IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,a) \ - IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT(a,a) +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0_2NAME(MenuDestroy, Destroy) /* Implement all these callback setter functions... */ -IMPLEMENT_CALLBACK_FUNC_ARG2(Position) -IMPLEMENT_CALLBACK_FUNC_ARG3_USER(Keyboard,unsigned char,int,int) -IMPLEMENT_CALLBACK_FUNC_ARG3_USER(KeyboardUp,unsigned char,int,int) -IMPLEMENT_CALLBACK_FUNC_ARG3(Special) -IMPLEMENT_CALLBACK_FUNC_ARG3(SpecialUp) -IMPLEMENT_CALLBACK_FUNC_ARG4(Mouse) -IMPLEMENT_CALLBACK_FUNC_ARG4(MouseWheel) -IMPLEMENT_CALLBACK_FUNC_ARG2(Motion) -IMPLEMENT_CALLBACK_FUNC_ARG2_2NAME(PassiveMotion,Passive) -IMPLEMENT_CALLBACK_FUNC_ARG1(Entry) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Position) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(Keyboard,unsigned char,int,int) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(KeyboardUp,unsigned char,int,int) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(Special) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(SpecialUp) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(Mouse) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(MouseWheel) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Motion) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2_2NAME(PassiveMotion,Passive) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(Entry) /* glutWMCloseFunc is an alias for glutCloseFunc; both set the window's Destroy callback */ -IMPLEMENT_CALLBACK_FUNC_ARG0_2NAME(Close,Destroy) -IMPLEMENT_CALLBACK_FUNC_ARG0_2NAME(WMClose,Destroy) -IMPLEMENT_CALLBACK_FUNC_ARG0(OverlayDisplay) -IMPLEMENT_CALLBACK_FUNC_ARG1(WindowStatus) -IMPLEMENT_CALLBACK_FUNC_ARG2(ButtonBox) -IMPLEMENT_CALLBACK_FUNC_ARG2(Dials) -IMPLEMENT_CALLBACK_FUNC_ARG2(TabletMotion) -IMPLEMENT_CALLBACK_FUNC_ARG4(TabletButton) -IMPLEMENT_CALLBACK_FUNC_ARG2(MultiEntry) -IMPLEMENT_CALLBACK_FUNC_ARG5(MultiButton) -IMPLEMENT_CALLBACK_FUNC_ARG3(MultiMotion) -IMPLEMENT_CALLBACK_FUNC_ARG3(MultiPassive) -IMPLEMENT_CALLBACK_FUNC_ARG0(InitContext) -IMPLEMENT_CALLBACK_FUNC_ARG1(AppStatus) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(Close,Destroy) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(WMClose,Destroy) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(OverlayDisplay) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(WindowStatus) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(ButtonBox) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Dials) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(TabletMotion) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(TabletButton) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(MultiEntry) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG5(MultiButton) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiMotion) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiPassive) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(InitContext) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(AppStatus) /* * Sets the Display callback for the current window @@ -307,23 +157,10 @@ void FGAPIENTRY glutDisplayFuncUcall( FGCBDisplayUC callback, FGCBUserData userD if( !callback ) fgError( "Fatal error in program. NULL display callback not " "permitted in GLUT 3.0+ or freeglut 2.0.1+" ); - SET_CALLBACK( Display ); + SET_CURRENT_WINDOW_CALLBACK( Display ); } -static void fghDisplayFuncCallback( FGCBUserData userData ) -{ - FGCBDisplay callback = (FGCBDisplay)userData; - callback(); -} - -void FGAPIENTRY glutDisplayFunc( FGCBDisplay callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" ); - if( callback ) - glutDisplayFuncUcall( fghDisplayFuncCallback, (FGCBUserData)callback ); - else - glutDisplayFuncUcall( NULL, NULL ); -} +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Display) void fghDefaultReshape( int width, int height, FGCBUserData userData ) { @@ -340,23 +177,10 @@ void FGAPIENTRY glutReshapeFuncUcall( FGCBReshapeUC callback, FGCBUserData userD userData = NULL; } - SET_CALLBACK( Reshape ); + SET_CURRENT_WINDOW_CALLBACK( Reshape ); } -static void fghReshapeFuncCallback( int width, int height, FGCBUserData userData ) -{ - FGCBReshape callback = (FGCBReshape)userData; - callback( width, height ); -} - -void FGAPIENTRY glutReshapeFunc( FGCBReshape callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" ); - if( callback ) - glutReshapeFuncUcall( fghReshapeFuncCallback, (FGCBUserData)callback ); - else - glutReshapeFuncUcall( NULL, NULL ); -} +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2(Reshape) /* * Sets the Visibility callback for the current window. @@ -381,7 +205,7 @@ static void fghVisibility( int status, FGCBUserData userData ) freeglut_return_if_fail( fgStructure.CurrentWindow ); /* Translate window status func states to visibility states */ - if( ( GLUT_HIDDEN == status ) || ( GLUT_FULLY_COVERED == status ) ) + if( ( status == GLUT_HIDDEN) || ( status == GLUT_FULLY_COVERED) ) vis_status = GLUT_NOT_VISIBLE; else /* GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED */ vis_status = GLUT_VISIBLE; @@ -398,7 +222,7 @@ void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData userData = NULL; } - SET_CALLBACK( Visibility ); + SET_CURRENT_WINDOW_CALLBACK( Visibility ); if( callback ) glutWindowStatusFuncUcall( fghVisibility, NULL ); @@ -406,20 +230,7 @@ void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData glutWindowStatusFuncUcall( NULL, NULL ); } -static void fghVisibilityFuncCallback( int visibility, FGCBUserData userData ) -{ - FGCBVisibility callback = (FGCBVisibility)userData; - callback( visibility ); -} - -void FGAPIENTRY glutVisibilityFunc( FGCBVisibility callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" ); - if( callback ) - glutVisibilityFuncUcall( fghVisibilityFuncCallback, (FGCBUserData)callback ); - else - glutVisibilityFuncUcall( NULL, NULL ); -} +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG1(Visibility) /* * Sets the joystick callback and polling rate for the current window @@ -446,7 +257,7 @@ void FGAPIENTRY glutJoystickFuncUcall( FGCBJoystickUC callback, int pollInterval ) ) --fgState.NumActiveJoysticks; - SET_CALLBACK( Joystick ); + SET_CURRENT_WINDOW_CALLBACK( Joystick ); fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval; /* set last poll time such that joystick will be polled asap */ @@ -480,23 +291,10 @@ void FGAPIENTRY glutSpaceballMotionFuncUcall( FGCBSpaceMotionUC callback, FGCBUs FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFuncUcall" ); fgInitialiseSpaceball(); - SET_CALLBACK( SpaceMotion ); + SET_CURRENT_WINDOW_CALLBACK( SpaceMotion ); } -static void fghSpaceballMotionFuncCallback( int x, int y, int z, FGCBUserData userData ) -{ - FGCBSpaceMotion callback = (FGCBSpaceMotion)userData; - callback( x, y, z ); -} - -void FGAPIENTRY glutSpaceballMotionFunc( FGCBSpaceMotion callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" ); - if( callback ) - glutSpaceballMotionFuncUcall( fghSpaceballMotionFuncCallback, (FGCBUserData)callback ); - else - glutSpaceballMotionFuncUcall( NULL, NULL ); -} +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballMotion, SpaceMotion) /* * Sets the spaceball rotate callback for the current window @@ -506,23 +304,10 @@ void FGAPIENTRY glutSpaceballRotateFuncUcall( FGCBSpaceRotationUC callback, FGCB FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFuncUcall" ); fgInitialiseSpaceball(); - SET_CALLBACK( SpaceRotation ); + SET_CURRENT_WINDOW_CALLBACK( SpaceRotation ); } -static void fghSpaceballRotateFuncCallback( int x, int y, int z, FGCBUserData userData ) -{ - FGCBSpaceRotation callback = (FGCBSpaceRotation)userData; - callback( x, y, z ); -} - -void FGAPIENTRY glutSpaceballRotateFunc( FGCBSpaceRotation callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" ); - if( callback ) - glutSpaceballRotateFuncUcall( fghSpaceballRotateFuncCallback, (FGCBUserData)callback ); - else - glutSpaceballRotateFuncUcall( NULL, NULL ); -} +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballRotate, SpaceRotation) /* * Sets the spaceball button callback for the current window @@ -532,22 +317,9 @@ void FGAPIENTRY glutSpaceballButtonFuncUcall( FGCBSpaceButtonUC callback, FGCBUs FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFuncUcall" ); fgInitialiseSpaceball(); - SET_CALLBACK( SpaceButton ); + SET_CURRENT_WINDOW_CALLBACK( SpaceButton ); } -static void fghSpaceballButtonFuncCallback( int button, int buttonState, FGCBUserData userData ) -{ - FGCBSpaceButton callback = (FGCBSpaceButton)userData; - callback( button, buttonState ); -} - -void FGAPIENTRY glutSpaceballButtonFunc( FGCBSpaceButton callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" ); - if( callback ) - glutSpaceballButtonFuncUcall( fghSpaceballButtonFuncCallback, (FGCBUserData)callback ); - else - glutSpaceballButtonFuncUcall( NULL, NULL ); -} +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2_2NAME(SpaceballButton, SpaceButton) /*** END OF FILE ***/ From deaa5b843ab5e6ceaf80dfe334178f8f12cb1375 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:22:26 +0000 Subject: [PATCH 14/20] Added "hack" function for glutCreateMenuUcall Not desired, but potentially needed as with the other "hack" functions git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1821 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/include/GL/freeglut_ucall.h | 21 +++++++++++++++++++ freeglut/freeglut/src/mswin/fg_menu_mswin.c | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/freeglut/freeglut/include/GL/freeglut_ucall.h b/freeglut/freeglut/include/GL/freeglut_ucall.h index bbbd32d..f6fc99a 100644 --- a/freeglut/freeglut/include/GL/freeglut_ucall.h +++ b/freeglut/freeglut/include/GL/freeglut_ucall.h @@ -82,6 +82,27 @@ FGAPI void FGAPIENTRY glutInitWarningFuncUcall( void (* callback)( const char *f FGAPI void FGAPIENTRY glutInitContextFuncUcall( void (* callback)( void* ), void* user_data ); FGAPI void FGAPIENTRY glutAppStatusFuncUcall( void (* callback)( int, void* ), void* user_data ); +/* + * Continued "hack" from GLUT applied to Ucall functions. + * For more info, see bottom of freeglut_std.h + */ + +/* to get the prototype for exit() */ +#include + +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__) +FGAPI int FGAPIENTRY __glutCreateMenuUcallWithExit(void(*func)(int, void*), void(__cdecl *exitfunc)(int), void* user_data); +#ifndef FREEGLUT_BUILDING_LIB +#if defined(__GNUC__) +#define FGUNUSED __attribute__((unused)) +#else +#define FGUNUSED +#endif +static int FGAPIENTRY FGUNUSED glutCreateMenuUcall_ATEXIT_HACK(void(*func)(int, void*), void* user_data) { return __glutCreateMenuUcallWithExit(func, exit, user_data); } +#define glutCreateMenuUcall glutCreateMenuUcall_ATEXIT_HACK +#endif +#endif + #ifdef __cplusplus } #endif diff --git a/freeglut/freeglut/src/mswin/fg_menu_mswin.c b/freeglut/freeglut/src/mswin/fg_menu_mswin.c index 27bc356..42d056b 100644 --- a/freeglut/freeglut/src/mswin/fg_menu_mswin.c +++ b/freeglut/freeglut/src/mswin/fg_menu_mswin.c @@ -106,3 +106,8 @@ int FGAPIENTRY __glutCreateMenuWithExit( void(* callback)( int ), void (__cdecl return glutCreateMenu( callback ); } +int FGAPIENTRY __glutCreateMenuUcallWithExit(void(*callback)(int, void*), void(__cdecl *exit_function)(int), void* user_data) +{ + __glutExitFunc = exit_function; + return glutCreateMenuUcall(callback, user_data); +} From 850d80554a2e0952bbe2918b2380e32d083aae56 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:22:39 +0000 Subject: [PATCH 15/20] Added timer_callback sample for user callbacks git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1822 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/CMakeLists.txt | 1 + .../progs/demos/timer_callback/timer.c | 174 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 freeglut/freeglut/progs/demos/timer_callback/timer.c diff --git a/freeglut/freeglut/CMakeLists.txt b/freeglut/freeglut/CMakeLists.txt index 55f48ba..58b1b46 100644 --- a/freeglut/freeglut/CMakeLists.txt +++ b/freeglut/freeglut/CMakeLists.txt @@ -551,6 +551,7 @@ IF(UNIX) ENDIF() ADD_DEMO(subwin progs/demos/subwin/subwin.c) ADD_DEMO(timer progs/demos/timer/timer.c) +ADD_DEMO(timer_callback progs/demos/timer_callback/timer.c) diff --git a/freeglut/freeglut/progs/demos/timer_callback/timer.c b/freeglut/freeglut/progs/demos/timer_callback/timer.c new file mode 100644 index 0000000..03acd40 --- /dev/null +++ b/freeglut/freeglut/progs/demos/timer_callback/timer.c @@ -0,0 +1,174 @@ +/* Timer (callback) demo + * + * Written by John Tsiombikas + * Modified by Vincent Simonetti + * + * A modification of the timer sample, but with this + * offering a use of the user-data callback. + */ +#include +#include + +struct display_index_s +{ + /* color index will be advanced every time the timer expires */ + int surround_color_index; + int center_color_index; +}; +typedef struct display_index_s display_index_t; + +struct timer_state_s +{ + int* color_index_ptr; + int* timer_time_ptr; +}; +typedef struct timer_state_s timer_state_t; + +struct menu_state_s +{ + int* timer_time_ptr; + int menu_id; +}; +typedef struct menu_state_s menu_state_t; + +void disp(void* uptr); +void timer_func(int which, void* uptr); + +const float color[][3] = { + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + {1, 1, 0}, + {0, 1, 1}, + {1, 0, 1} +}; +const int timerInts[] = { + 250, + 500, + 1000 +}; + +void createMenuEntries(menu_state_t* menuState) +{ + int i; + for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++) + { + char temp[10] = {'\0'}; + /* flag current value */ + if ((*menuState->timer_time_ptr) == timerInts[i]) + temp[0] = '+'; + else + temp[0] = '-'; + + sprintf(temp + 1, " %4d ms", timerInts[i]); + + glutAddMenuEntry(temp, timerInts[i]); + } +} + +void updateMenuEntries(menu_state_t* menuState) +{ + int i; + for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++) + { + char temp[10] = { '\0' }; + /* flag current value */ + if ((*menuState->timer_time_ptr) == timerInts[i]) + temp[0] = '+'; + else + temp[0] = '-'; + + sprintf(temp + 1, " %4d ms", timerInts[i]); + + glutChangeToMenuEntry(i+1, temp, timerInts[i]); + } +} + +void MenuHandler(int timerInt, void* user_ptr) +{ + menu_state_t* menuState; + + if (!user_ptr) + { + /* In case main menu is selected somehow */ + return; + } + + menuState = (menu_state_t*)user_ptr; + + *menuState->timer_time_ptr = timerInt; + glutSetMenu(menuState->menu_id); + updateMenuEntries(menuState); +} + +int main(int argc, char **argv) +{ + int timerSurroundInt = 1000, timerCenterInt = 500; + display_index_t displayIndex = { 0, 2 }; + timer_state_t surroundTimerState = { &displayIndex.surround_color_index, &timerSurroundInt }; + timer_state_t centerTimerState = { &displayIndex.center_color_index, &timerCenterInt }; + menu_state_t surroundMenuState = { &timerSurroundInt, 0 }; + menu_state_t centerMenuState = { &timerCenterInt, 0 }; + + glutInit(&argc, argv); + glutInitWindowSize(128, 128); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("timer test"); + + glutDisplayFuncUcall(disp, &displayIndex); + + /* get timer started, its reset in the timer function itself */ + glutTimerFuncUcall(timerSurroundInt, timer_func, 1, &surroundTimerState); + glutTimerFuncUcall(timerCenterInt, timer_func, 2, ¢erTimerState); + + /* menus for setting timing */ + surroundMenuState.menu_id = glutCreateMenuUcall(MenuHandler, &surroundMenuState); + createMenuEntries(&surroundMenuState); + + centerMenuState.menu_id = glutCreateMenuUcall(MenuHandler, ¢erMenuState); + createMenuEntries(¢erMenuState); + + glutCreateMenuUcall(MenuHandler, NULL); /* doesn't matter, no clickable entries in this menu */ + glutAddSubMenu("Center", centerMenuState.menu_id); + glutAddSubMenu("Surround", surroundMenuState.menu_id); + glutAttachMenu(GLUT_RIGHT_BUTTON); + + glutMainLoop(); + return 0; +} + +void disp(void* user_ptr) +{ + const display_index_t* displayIndex; + int cidx, pcidx; + + displayIndex = (display_index_t*)user_ptr; + + cidx = displayIndex->surround_color_index; + glClearColor(color[cidx][0], color[cidx][1], color[cidx][2], 1); + glClear(GL_COLOR_BUFFER_BIT); + + pcidx = displayIndex->center_color_index; + glPointSize(10.f); + glColor3f(color[pcidx][0], color[pcidx][1], color[pcidx][2]); + glBegin(GL_POINTS); + glVertex2i(0,0); + glEnd(); + + glutSwapBuffers(); +} + +void timer_func(int which, void* user_ptr) +{ + const timer_state_t* timerState; + + timerState = (timer_state_t*)user_ptr; + + /* advance the color index and trigger a redisplay */ + *timerState->color_index_ptr = (*timerState->color_index_ptr + 1) % (sizeof color / sizeof *color); + + glutPostRedisplay(); + + /* (re)set the timer callback and ask glut to call it in x ms */ + glutTimerFuncUcall(*timerState->timer_time_ptr, timer_func, which, user_ptr); +} From cc6830131a14f14d72c2c0a29e27a7bbc93d51be Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:22:45 +0000 Subject: [PATCH 16/20] Fixed x11 and Wayland not using INVOKE_WCB ...since INVOKE_WCB handled user data. Now they handle user data. git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1823 7f0cb862-5218-0410-a997-914c9d46530a --- .../src/wayland/fg_input_devices_wl.c | 22 +++++++++++------- freeglut/freeglut/src/x11/fg_main_x11.c | 23 ++++++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/freeglut/freeglut/src/wayland/fg_input_devices_wl.c b/freeglut/freeglut/src/wayland/fg_input_devices_wl.c index 0aaa91e..bb32f98 100644 --- a/freeglut/freeglut/src/wayland/fg_input_devices_wl.c +++ b/freeglut/freeglut/src/wayland/fg_input_devices_wl.c @@ -71,8 +71,10 @@ void fghKeyboardInterpretKeysym( SFG_Window* window, xkb_keysym_t sym, uint32_t state ) { - FGCBKeyboard keyboard_cb; - FGCBSpecial special_cb; + FGCBKeyboardUC keyboard_cb; + FGCBSpecialUC special_cb; + FGCBUserData keyboard_ud; + FGCBUserData special_ud; char string[16]; int special = -1; @@ -81,13 +83,17 @@ void fghKeyboardInterpretKeysym( SFG_Window* window, * others, which need to be translated to GLUT_KEY_Xs... */ if( state ) { - keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, Keyboard )); - special_cb = (FGCBSpecial) ( FETCH_WCB( *window, Special )); + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, Keyboard )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, Special )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, Keyboard ); + special_ud = FETCH_USER_DATA_WCB( *window, Special ); } else { - keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, KeyboardUp )); - special_cb = (FGCBSpecial) ( FETCH_WCB( *window, SpecialUp )); + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, KeyboardUp )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, SpecialUp )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, KeyboardUp ); + special_ud = FETCH_USER_DATA_WCB( *window, SpecialUp ); } switch( sym ) @@ -127,13 +133,13 @@ void fghKeyboardInterpretKeysym( SFG_Window* window, if( special_cb && (special != -1) ) { fgSetWindow( window ); - special_cb( special, window->State.MouseX, window->State.MouseY ); + special_cb( special, window->State.MouseX, window->State.MouseY, special_ud ); } else if( keyboard_cb && (special == -1) ) { fgSetWindow( window ); xkb_keysym_to_utf8( sym, string, sizeof( string ) ); - keyboard_cb( string[0], window->State.MouseX, window->State.MouseY ); + keyboard_cb( string[0], window->State.MouseX, window->State.MouseY, keyboard_ud ); } } diff --git a/freeglut/freeglut/src/x11/fg_main_x11.c b/freeglut/freeglut/src/x11/fg_main_x11.c index 0e54253..80fd2c8 100644 --- a/freeglut/freeglut/src/x11/fg_main_x11.c +++ b/freeglut/freeglut/src/x11/fg_main_x11.c @@ -890,8 +890,10 @@ void fgPlatformProcessSingleEvent ( void ) case KeyRelease: case KeyPress: { - FGCBKeyboard keyboard_cb; - FGCBSpecial special_cb; + FGCBKeyboardUC keyboard_cb; + FGCBSpecialUC special_cb; + FGCBUserData keyboard_ud; + FGCBUserData special_ud; GETWINDOW( xkey ); GETMOUSE( xkey ); @@ -932,13 +934,17 @@ void fgPlatformProcessSingleEvent ( void ) if( event.type == KeyPress ) { - keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, Keyboard )); - special_cb = (FGCBSpecial) ( FETCH_WCB( *window, Special )); + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, Keyboard )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, Special )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, Keyboard ); + special_ud = FETCH_USER_DATA_WCB( *window, Special ); } else { - keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, KeyboardUp )); - special_cb = (FGCBSpecial) ( FETCH_WCB( *window, SpecialUp )); + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, KeyboardUp )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, SpecialUp )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, KeyboardUp ); + special_ud = FETCH_USER_DATA_WCB( *window, SpecialUp ); } /* Is there a keyboard/special callback hooked for this window? */ @@ -963,7 +969,8 @@ void fgPlatformProcessSingleEvent ( void ) fgSetWindow( window ); fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state ); keyboard_cb( asciiCode[ 0 ], - event.xkey.x, event.xkey.y + event.xkey.x, event.xkey.y, + keyboard_ud ); fgState.Modifiers = INVALID_MODIFIERS; } @@ -1031,7 +1038,7 @@ void fgPlatformProcessSingleEvent ( void ) { fgSetWindow( window ); fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state ); - special_cb( special, event.xkey.x, event.xkey.y ); + special_cb( special, event.xkey.x, event.xkey.y, special_ud ); fgState.Modifiers = INVALID_MODIFIERS; } } From 1fec35a406a210f9eb4b73accf8d03e7e2b986ab Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:22:52 +0000 Subject: [PATCH 17/20] Corrected phrasing in docs and unneeded \ in code git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1824 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/fg_internal.h | 2 +- freeglut/web-src/docs/api.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/freeglut/freeglut/src/fg_internal.h b/freeglut/freeglut/src/fg_internal.h index a61b121..a95027b 100644 --- a/freeglut/freeglut/src/fg_internal.h +++ b/freeglut/freeglut/src/fg_internal.h @@ -291,7 +291,7 @@ typedef void (* FGCBAppStatus )( int ); typedef void (* FGCBAppStatusUC )( int, FGCBUserData ); /* The global callbacks type definitions */ -typedef void (* FGCBIdle )( void ); \ +typedef void (* FGCBIdle )( void ); typedef void (* FGCBIdleUC )( FGCBUserData ); typedef void (* FGCBTimer )( int ); typedef void (* FGCBTimerUC )( int, FGCBUserData ); diff --git a/freeglut/web-src/docs/api.php b/freeglut/web-src/docs/api.php index e7a6d0f..8603eb2 100644 --- a/freeglut/web-src/docs/api.php +++ b/freeglut/web-src/docs/api.php @@ -332,7 +332,7 @@ when you created it.

    GLUT was created as a tool to help teach OpenGL programming. To simplify development, callbacks were used for handling display, input, and other -events. But the time it was developed, the purpose, or for some other +events. But at the time it was developed, the purpose, or for some other unknown reason, the callbacks lacked any user-provided data argument. This has caused considerable difficulties for any significantly advanced usage of GLUT, and now freeglut. This has prevented any attempt to From 47fb7d5f28545d0f22438b6e580a5248096a9136 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:22:59 +0000 Subject: [PATCH 18/20] Removed "hack" macro set git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1825 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/fg_callback_macros.h | 101 +++------------------ 1 file changed, 11 insertions(+), 90 deletions(-) diff --git a/freeglut/freeglut/src/fg_callback_macros.h b/freeglut/freeglut/src/fg_callback_macros.h index 2aa6ccd..76d76b1 100644 --- a/freeglut/freeglut/src/fg_callback_macros.h +++ b/freeglut/freeglut/src/fg_callback_macros.h @@ -34,9 +34,7 @@ */ /* - * Compiler defines: - * FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK: if the compiler supports GCC's variadic macro implementation (AKA, ##__VA_ARGS__) - * FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports variadic macros + * Compiler define: FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports variadic macros */ /* What supports variadic macros based off Wikipedia article on it (GCC-like must support C99 or higher to use variadic macros) */ @@ -51,15 +49,6 @@ #define FG_COMPILER_SUPPORTS_VA_ARGS 0 #endif -/* If __VA_ARGS__ is supported, it needs to be GCC(-like) or Clang (since Clang mimics GCC) */ -#if FG_COMPILER_SUPPORTS_VA_ARGS && \ - (defined(__GNUC__)) || \ - (defined(__clang__)) -#define FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK 1 -#else -#define FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK 0 -#endif - /* * -------------------------- * Executing window callbacks @@ -82,86 +71,20 @@ * * Onto the different "versions" of macros: * - * There is one for GCC/Clang(/and supposedly the Intel compiler) which supports the non-standard ##__VA_ARGS__ token. The code may - * look ugly, but the result is, if this was standard, no one would ever need to open this file unless they were curious (or needed - * more then 5 arguments for a callback, but that's trivial to add). It works by adding many fake macros to a "picker" macro - * (PP_HAS_ARGS_IMPL2) which then indictaes which macro counter to use. As we can already use variadic macros (the VA in __VA_ARGS__), - * this just becomes a "reuse the arguments*. - * - * The next is for any non-GCC/Clang/etc. compiler *cough* MSVC/compiler you probably shouldn't be using *cough* that supports C99 - * by default. It requires each callback to have a specific argument count passthrough macro. The only reason there are specific - * count macros is so that (see paraghraph below) don't need have their own set of callback macros. Ideally, there would only be - * ZERO and ONE_OR_MORE. This works by having callback-specific macros call a specific handler macro to return user data (ZERO) or - * return one or more arguments along with userData (ONE_OR_MORE) where, with variadic macros, it just reuses the arguments. + * The first is for any compiler that supports C99 by default. It requires each callback to have a specific argument count + * passthrough macro. The only reason there are specific count macros is so that (see paraghraph below) don't need have their own + * set of callback macros. Ideally, there would only be ZERO and ONE_OR_MORE. This works by having callback-specific macros call a + * specific handler macro to return user data (ZERO) or return one or more arguments along with userData (ONE_OR_MORE) where, with + * variadic macros, it just reuses the arguments. * - * The last set is for the poor individual who has to use a compiler that doesn't support C99 by default, or may not support it at - * all. Stuff like MSVC6... It works by having a specific-count macro that "extracts" each argument to have them reused without the - * parathesis. + * The last macro set is for the poor individual who has to use a compiler that doesn't support C99 by default, or may not support + * it at all. Stuff like MSVC6... It works by having a specific-count macro that "extracts" each argument to have them reused without + * the parathesis. * - * A note on parathesis, as earlier mentioned, if the GCC variadic macro element was standard, then instead of needing: - * - * func EXPAND_WCB(Mouse)(( (GLUT_LEFT_BUTTON, GLUT_DOWN, 10, 30), userData)); - * - * ...you can do the following: - * - * func EXPAND_WCB (GLUT_LEFT_BUTTON, GLUT_DOWN, 10, 30); - * - * Wow... so much nice and easier to understand. Sub-note: I have not worked on a version that explicitly takes userData, so for now - * if you can get to that version, look in the version control change history for this file and you'll find that version which - * implicitly passes "userData" and only works on GCC vardiac macro supporting compilers. + * There is a 3rd macro set that only worked on GCC/Clang, and thus was removed (last seen in revision e9676fc of the GIT mirror. + * Not sure at this time what the SVN number is.) as it's a non-standard functionality. */ -#if FG_COMPILER_SUPPORTS_GCC_VA_ARGS_HACK - - /* - * EXPAND_WCB() is used as: - * - * EXPAND_WCB( cbname )(( arg_list, userData )) - * - * ... where {(arg_list)} is the parameter list and userData is user - * provided data. - * - * All additional macros are to get around trailing ',' for zero-arg - * callbacks. - * - * Modification of: - * http://stackoverflow.com/questions/5355241/generating-function-declaration-using-a-macro-iteration/5355946#5355946 - * - * -------------- - * - * GCC-specific design that doesn't require per-callback defines - * - * The naming is terrible... and it's very convuluted and complex, but - * should not require any modification unless additional arguments are to - * be supported. - * - * Supports callbacks up to 5 args (follow the pattern of - * EXPAND_WCB_PP_HAS_ARGS_IMPL2 and EXPAND_WCB_PP_HAS_ARGS_SOURCE to add more) - * - * Edit with care. - */ - -#define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ - -#define EXPAND_WCB_PP_HAS_ARGS_IMPL2(_0, _1, _2, _3, _4, _5, N, ...) N -#define EXPAND_WCB_PP_HAS_ARGS_SOURCE() ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ONE_OR_MORE, ZERO - -#define EXPAND_WCB_PP_HAS_ARGS_IMPL(...) EXPAND_WCB_PP_HAS_ARGS_IMPL2( __VA_ARGS__ ) -#define EXPAND_WCB_PP_HAS_ARGS(...) EXPAND_WCB_PP_HAS_ARGS_IMPL( NOT_EXIST, ##__VA_ARGS__, EXPAND_WCB_PP_HAS_ARGS_SOURCE() ) - -#define EXPAND_WCB_ZERO(args, userData) ( userData ) -#define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) - -#define EXPAND_WCB_DISAMBIGUATE2(has_args, args, userData) EXPAND_WCB_ ## has_args ( args, userData ) -#define EXPAND_WCB_DISAMBIGUATE(has_args, args, userData) EXPAND_WCB_DISAMBIGUATE2( has_args, args, userData ) - -#define EXPAND_WCB_UNWRAP_ARGS2(args, userData) EXPAND_WCB_DISAMBIGUATE( EXPAND_WCB_PP_HAS_ARGS args, args, userData ) -#define EXPAND_WCB_UNWRAP_ARGS(args) EXPAND_WCB_UNWRAP_ARGS2 args - -#define EXPAND_WCB(cbname) EXPAND_WCB_UNWRAP_ARGS - -#else - /* * EXPAND_WCB() is used as: * @@ -255,8 +178,6 @@ #define EXPAND_WCB_SUB_InitContext(args) EXPAND_WCB_ZERO args #define EXPAND_WCB_SUB_AppStatus(args) EXPAND_WCB_ONE args -#endif - /* * ------------------------ * Setting window callbacks From 5df98e73df94020bf7f3a3db616e9d8bc5fd29d4 Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:23:05 +0000 Subject: [PATCH 19/20] CMake produces an error if XInput.h is not found git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1826 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/freeglut/freeglut/CMakeLists.txt b/freeglut/freeglut/CMakeLists.txt index 58b1b46..b4db0fd 100644 --- a/freeglut/freeglut/CMakeLists.txt +++ b/freeglut/freeglut/CMakeLists.txt @@ -326,6 +326,8 @@ IF(UNIX AND NOT(ANDROID OR BLACKBERRY OR FREEGLUT_WAYLAND)) # Needed for multi-touch: CHECK_INCLUDE_FILES("${X11_Xinput_INCLUDE_PATH}/X11/extensions/XInput2.h" HAVE_X11_EXTENSIONS_XINPUT2_H) LIST(APPEND LIBS ${X11_Xinput_LIB}) + ELSE() + MESSAGE(FATAL_ERROR, "Missing X11's XInput.h (X11/extensions/XInput.h)") ENDIF() ENDIF() IF(ANDROID) From fbd61be1ddb2004c6ac793cc13a7fddec550ccdb Mon Sep 17 00:00:00 2001 From: dcnieho Date: Fri, 30 Jun 2017 23:23:11 +0000 Subject: [PATCH 20/20] Fixed incorrect MESSAGE usage git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1827 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freeglut/freeglut/CMakeLists.txt b/freeglut/freeglut/CMakeLists.txt index b4db0fd..c86d4ce 100644 --- a/freeglut/freeglut/CMakeLists.txt +++ b/freeglut/freeglut/CMakeLists.txt @@ -327,7 +327,7 @@ IF(UNIX AND NOT(ANDROID OR BLACKBERRY OR FREEGLUT_WAYLAND)) CHECK_INCLUDE_FILES("${X11_Xinput_INCLUDE_PATH}/X11/extensions/XInput2.h" HAVE_X11_EXTENSIONS_XINPUT2_H) LIST(APPEND LIBS ${X11_Xinput_LIB}) ELSE() - MESSAGE(FATAL_ERROR, "Missing X11's XInput.h (X11/extensions/XInput.h)") + MESSAGE(FATAL_ERROR "Missing X11's XInput.h (X11/extensions/XInput.h)") ENDIF() ENDIF() IF(ANDROID)