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 );
* Initialization functions, see fg_init.c
*/
#include <stdarg.h>
-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
}
fgState.IdleCallbackData = userData;
}
-void glutIdleFuncCallback( void* userData )
+static void glutIdleFuncCallback( FGCBUserData userData )
{
FGCBIdle callback = (FGCBIdle)userData;
callback();
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 */
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 );
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 */
}
/* 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 );
}
* Menu specific callbacks.
*/
/* Callback upon menu destruction */
-void FGAPIENTRY glutMenuDestroyFunc( FGCBDestroy callback )
+void FGAPIENTRY glutMenuDestroyFuncUcall( FGCBDestroyUC callback, FGCBUserData userData )
{
- FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" );
+ 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( callback )
+ glutMenuDestroyFuncUcall( glutMenuDestroyFuncCallback, (FGCBUserData)callback );
+ else
+ glutMenuDestroyFuncUcall( NULL, NULL );
}
{ \
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) \
-void FGAPIENTRY glut##a##Func( FGCB##b callback ) \
+#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"Func" ); \
+ 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( 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)
-/* 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)
-/* 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)
+#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_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_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 glutReshapeFunc( FGCBReshape callback )
+void FGAPIENTRY glutReshapeFuncUcall( FGCBReshapeUC callback, FGCBUserData userData )
{
- FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" );
+ 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 )
+ glutReshapeFuncUcall( glutReshapeFuncCallback, (FGCBUserData)callback );
+ else
+ glutReshapeFuncUcall( NULL, NULL );
+}
+
/*
* Sets the Visibility callback for the current window.
* NB: the Visibility func is deprecated in favor of the WindowStatus func,
* 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;
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 ( (
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 ***/
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;
0, /* ActiveMenus */
NULL, /* MenuStateCallback */
NULL, /* MenuStatusCallback */
+ NULL, /* MenuStatusCallbackData */
FREEGLUT_MENU_FONT,
{ -1, -1, GL_TRUE }, /* GameModeSize */
-1, /* GameModeDepth */
0, /* OpenGL ContextProfile */
0, /* HasOpenGL20 */
NULL, /* ErrorFunc */
- NULL /* WarningFunc */
+ NULL, /* ErrorFuncData */
+ NULL, /* WarningFunc */
+ NULL /* WarningFuncData */
};
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;
/*
* 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 ***/
/* 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 (* 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 (* FGCBInitContext)();
-typedef void (* FGCBAppStatus)(int);
+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 (* 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 )( 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 */
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 */
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 */
/*
* 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-
* 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 )
/*
((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:
*
* INVOKE_WCB( window, cbname, ( arg_list ) );
{ \
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
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
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 */
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 */
va_start( ap, fmt );
/* call user set error handler here */
- fgState.ErrorFunc(fmt, ap);
+ fgState.ErrorFunc(fmt, ap, fgState.ErrorFuncData);
va_end( ap );
va_start( ap, fmt );
/* call user set warning handler here */
- fgState.WarningFunc(fmt, ap);
+ fgState.WarningFunc(fmt, ap, fgState.WarningFuncData);
va_end( ap );
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 );
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);
}
}
}
}
/* Standard glutCreateMenu */
-void glutCreateMenuCallback( int menu, FGCBUserData userData )
+static void glutCreateMenuCallback( int menu, FGCBUserData userData )
{
FGCBMenu callback = (FGCBMenu)userData;
callback( menu );
int FGAPIENTRY glutCreateMenu( FGCBMenu callback )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" );
+ if (!callback)
+ return glutCreateMenuUcall( NULL, NULL );
return glutCreateMenuUcall( glutCreateMenuCallback, (FGCBUserData)callback );
}
/* -- 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 )
{
{
int i;
for( i = 0; i < TOTAL_CALLBACKS; ++i )
+ {
window->CallBacks[ i ] = NULL;
+ window->CallbackDatas[ i ] = NULL;
+ }
}
}
fgPlatformCreateWindow ( window );
fghClearCallBacks( window );
- SET_WCB( *window, Reshape, fghDefaultReshape);
+ SET_WCB( *window, Reshape, fghDefaultReshape, NULL);
/* Initialize the object properties */
window->ID = ++fgStructure.WindowID;
* 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 );
}
}
{
SFG_Menu *activeMenu=fgStructure.CurrentMenu;
fgStructure.CurrentMenu = menu;
- menu->Destroy( );
+ menu->Destroy( menu->DestroyData );
fgStructure.CurrentMenu = activeMenu;
}