X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffg_callbacks.c;h=684c93434b11dc61cca5fcc294bbdfe225dc1979;hb=cf2ecefe0a6a352339294c01a5188667f3650496;hp=7e399a9d44438d6cef2cb37474ee7d7789dcd265;hpb=1b5ee849ba61b667aeba474a7e03406196478bee;p=freeglut diff --git a/src/fg_callbacks.c b/src/fg_callbacks.c index 7e399a9..684c934 100644 --- a/src/fg_callbacks.c +++ b/src/fg_callbacks.c @@ -1,5 +1,5 @@ /* - * freeglut_callbacks.c + * fg_callbacks.c * * The callbacks setting methods. * @@ -30,75 +30,39 @@ /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ -/* - * All of the callbacks setting methods can be generalized to this: - */ -#define SET_CALLBACK(a) \ -do \ -{ \ - if( fgStructure.CurrentWindow == NULL ) \ - return; \ - SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback ); \ -} while( 0 ) /* - * Sets the Display callback for the current window + * Global callbacks. */ -void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) ) +/* Sets the global idle callback */ +void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" ); - if( !callback ) - fgError( "Fatal error in program. NULL display callback not " - "permitted in GLUT 3.0+ or freeglut 2.0.1+" ); - SET_CALLBACK( Display ); -} - -/* - * Sets the Reshape callback for the current window - */ -void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" ); - SET_CALLBACK( Reshape ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFuncUcall" ); + fgState.IdleCallback = callback; + fgState.IdleCallbackData = userData; } -/* - * Sets the Keyboard callback for the current window - */ -void FGAPIENTRY glutKeyboardFunc( void (* callback) - ( unsigned char, int, int ) ) +static void glutIdleFuncCallback( FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardFunc" ); - SET_CALLBACK( Keyboard ); + FGCBIdle callback = (FGCBIdle)userData; + callback(); } -/* - * Sets the Special callback for the current window - */ -void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialFunc" ); - SET_CALLBACK( Special ); -} - -/* - * Sets the global idle callback - */ -void FGAPIENTRY glutIdleFunc( void (* callback)( void ) ) +void FGAPIENTRY glutIdleFunc( FGCBIdle callback ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" ); - fgState.IdleCallback = callback; + if( callback ) + glutIdleFuncUcall( glutIdleFuncCallback, (FGCBUserData)callback ); + else + glutIdleFuncUcall( NULL, NULL ); } -/* - * Sets the Timer callback for the current window - */ -void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ), - int timerID ) +/* Creates a timer and sets its callback */ +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) ) { @@ -111,10 +75,12 @@ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ), "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 ) { if( node->TriggerTime > timer->TriggerTime ) @@ -124,289 +90,464 @@ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ), fgListInsert( &fgState.Timers, &node->Node, &timer->Node ); } -/* - * Sets the Visibility callback for the current window. - */ -static void fghVisibility( int status ) +static void glutTimerFuncCallback( int ID, FGCBUserData userData ) { - int glut_status = GLUT_VISIBLE; + FGCBTimer callback = (FGCBTimer)userData; + callback( ID ); +} - FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Visibility Callback" ); - freeglut_return_if_fail( fgStructure.CurrentWindow ); +void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" ); + if( callback ) + glutTimerFuncUcall( timeOut, glutTimerFuncCallback, timerID, (FGCBUserData)callback ); + else + glutTimerFuncUcall( timeOut, NULL, timerID, NULL ); +} - if( ( GLUT_HIDDEN == status ) || ( GLUT_FULLY_COVERED == status ) ) - glut_status = GLUT_NOT_VISIBLE; - INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( glut_status ) ); +/* Deprecated version of glutMenuStatusFunc callback setting method */ +void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" ); + fgState.MenuStateCallback = callback; } -void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) ) +/* Sets the global menu status callback for the current window */ +void FGAPIENTRY glutMenuStatusFuncUcall( FGCBMenuStatusUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" ); - SET_CALLBACK( Visibility ); + 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" ); if( callback ) - glutWindowStatusFunc( fghVisibility ); + glutMenuStatusFuncUcall( glutMenuStatusFuncCallback, (FGCBUserData)callback ); else - glutWindowStatusFunc( NULL ); + glutMenuStatusFuncUcall( NULL, NULL ); } /* - * Sets the keyboard key release callback for the current window + * Menu specific callbacks. */ -void FGAPIENTRY glutKeyboardUpFunc( void (* callback) - ( unsigned char, int, int ) ) +/* Callback upon menu destruction */ +void FGAPIENTRY glutMenuDestroyFuncUcall( FGCBDestroyUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardUpFunc" ); - SET_CALLBACK( KeyboardUp ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFuncUcall" ); + if( fgStructure.CurrentMenu ) + { + fgStructure.CurrentMenu->Destroy = callback; + fgStructure.CurrentMenu->DestroyData = userData; + } } -/* - * Sets the special key release callback for the current window - */ -void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) ) +static void glutMenuDestroyFuncCallback( FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialUpFunc" ); - SET_CALLBACK( SpecialUp ); + FGCBDestroy callback = (FGCBDestroy)userData; + callback(); } -/* - * Sets the joystick callback and polling rate for the current window - */ -void FGAPIENTRY glutJoystickFunc( void (* callback) - ( unsigned int, int, int, int ), - int pollInterval ) +void FGAPIENTRY glutMenuDestroyFunc( FGCBDestroy callback ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" ); - fgInitialiseJoysticks (); - - if ( ( ( fgStructure.CurrentWindow->State.JoystickPollRate < 0 ) || - !FETCH_WCB(*fgStructure.CurrentWindow,Joystick) ) && /* Joystick callback was disabled */ - ( callback && ( pollInterval >= 0 ) ) ) /* but is now enabled */ - ++fgState.NumActiveJoysticks; - else if ( ( ( fgStructure.CurrentWindow->State.JoystickPollRate >= 0 ) && - FETCH_WCB(*fgStructure.CurrentWindow,Joystick) ) && /* Joystick callback was enabled */ - ( !callback || ( pollInterval < 0 ) ) ) /* but is now disabled */ - --fgState.NumActiveJoysticks; - - SET_CALLBACK( Joystick ); - fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval; - - fgStructure.CurrentWindow->State.JoystickLastPoll = - fgElapsedTime() - fgStructure.CurrentWindow->State.JoystickPollRate; - - if( fgStructure.CurrentWindow->State.JoystickLastPoll < 0 ) - fgStructure.CurrentWindow->State.JoystickLastPoll = 0; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" ); + if( callback ) + glutMenuDestroyFuncUcall( glutMenuDestroyFuncCallback, (FGCBUserData)callback ); + else + glutMenuDestroyFuncUcall( NULL, NULL ); } + /* - * Sets the mouse callback for the current window + * All of the window-specific callbacks setting methods can be generalized to this: */ -void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseFunc" ); - SET_CALLBACK( Mouse ); -} - +#define SET_CALLBACK(a) \ +do \ +{ \ + if( fgStructure.CurrentWindow == NULL ) \ + return; \ + SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback, userData ); \ +} while( 0 ) /* - * Sets the mouse wheel callback for the current window + * Types need to be defined for callbacks. It's not ideal, but it works for this. */ -void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseWheelFunc" ); - SET_CALLBACK( MouseWheel ); +#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_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( glut##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 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 mouse motion callback for the current window (one or more buttons - * are pressed) + * Sets the Display callback for the current window */ -void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) ) +void FGAPIENTRY glutDisplayFuncUcall( FGCBDisplayUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMotionFunc" ); - SET_CALLBACK( Motion ); + 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 ); } -/* - * Sets the passive mouse motion callback for the current window (no mouse - * buttons are pressed) - */ -void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) ) +static void glutDisplayFuncCallback( FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPassiveMotionFunc" ); - SET_CALLBACK( Passive ); + FGCBDisplay callback = (FGCBDisplay)userData; + callback(); } -/* - * Window mouse entry/leave callback - */ -void FGAPIENTRY glutEntryFunc( void (* callback)( int ) ) +void FGAPIENTRY glutDisplayFunc( FGCBDisplay callback ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEntryFunc" ); - SET_CALLBACK( Entry ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" ); + if( callback ) + glutDisplayFuncUcall( glutDisplayFuncCallback, (FGCBUserData)callback ); + else + glutDisplayFuncUcall( NULL, NULL ); } -/* - * Window destruction callbacks - */ -void FGAPIENTRY glutCloseFunc( void (* callback)( void ) ) +void fghDefaultReshape( int width, int height, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCloseFunc" ); - SET_CALLBACK( Destroy ); + glViewport( 0, 0, width, height ); } -void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) ) +void FGAPIENTRY glutReshapeFuncUcall( FGCBReshapeUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWMCloseFunc" ); - glutCloseFunc( callback ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFuncUcall" ); + + if( !callback ) + { + callback = fghDefaultReshape; + userData = NULL; + } + + SET_CALLBACK( Reshape ); } -/* A. Donev: Destruction callback for menus */ -void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) ) +static void glutReshapeFuncCallback( int width, int height, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" ); - if( fgStructure.CurrentMenu ) - fgStructure.CurrentMenu->Destroy = callback; + FGCBReshape callback = (FGCBReshape)userData; + callback( width, height ); } -/* - * Deprecated version of glutMenuStatusFunc callback setting method - */ -void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) ) +void FGAPIENTRY glutReshapeFunc( FGCBReshape callback ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" ); - fgState.MenuStateCallback = callback; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" ); + if( callback ) + glutReshapeFuncUcall( glutReshapeFuncCallback, (FGCBUserData)callback ); + else + glutReshapeFuncUcall( NULL, NULL ); } /* - * Sets the global menu status callback for the current window - */ -void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) ) + * Sets the Visibility callback for the current window. + * NB: the Visibility func is deprecated in favor of the WindowStatus func, + * which provides more detail. The visibility func callback is implemented + * as a translation step from the windowStatus func. When the user sets the + * windowStatus func, any visibility func is overwritten. + * DEVELOPER NOTE: in the library, only invoke the window status func, this + * gets automatically translated to the visibility func if thats what the + * user has set. + * window status is kind of anemic on win32 as there are no window messages + * to notify us that the window is covered by other windows or not. + * Should one want to query this, see + * 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, FGCBUserData userData ) +{ + int vis_status; + + FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Visibility Callback" ); + freeglut_return_if_fail( fgStructure.CurrentWindow ); + + /* Translate window status func states to visibility states */ + if( ( GLUT_HIDDEN == status ) || ( GLUT_FULLY_COVERED == status ) ) + vis_status = GLUT_NOT_VISIBLE; + else /* GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED */ + vis_status = GLUT_VISIBLE; + + INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( vis_status ) ); +} + +void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" ); - fgState.MenuStatusCallback = callback; + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFuncUcall" ); + + if ( !callback ) + { + userData = NULL; + } + + SET_CALLBACK( Visibility ); + + if( callback ) + glutWindowStatusFuncUcall( fghVisibility, NULL ); + else + glutWindowStatusFuncUcall( NULL, NULL ); } -/* - * Sets the overlay display callback for the current window - */ -void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) ) +static void glutVisibilityFuncCallback( int visibility, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutOverlayDisplayFunc" ); - SET_CALLBACK( OverlayDisplay ); + FGCBVisibility callback = (FGCBVisibility)userData; + callback( visibility ); } -/* - * Sets the window status callback for the current window - */ -void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) ) +void FGAPIENTRY glutVisibilityFunc( FGCBVisibility callback ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWindowStatusFunc" ); - SET_CALLBACK( WindowStatus ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" ); + if( callback ) + glutVisibilityFuncUcall( glutVisibilityFuncCallback, (FGCBUserData)callback ); + else + glutVisibilityFuncUcall( NULL, NULL ); } /* - * Sets the spaceball motion callback for the current window + * Sets the joystick callback and polling rate for the current window */ -void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) ) +void FGAPIENTRY glutJoystickFuncUcall( FGCBJoystickUC callback, int pollInterval, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" ); - fgInitialiseSpaceball(); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFuncUcall" ); + fgInitialiseJoysticks (); - SET_CALLBACK( SpaceMotion ); + if ( ( + fgStructure.CurrentWindow->State.JoystickPollRate <= 0 || /* Joystick callback was disabled */ + !FETCH_WCB(*fgStructure.CurrentWindow,Joystick) + ) && + ( + callback && ( pollInterval > 0 ) /* but is now enabled */ + ) ) + ++fgState.NumActiveJoysticks; + else if ( ( + fgStructure.CurrentWindow->State.JoystickPollRate > 0 && /* Joystick callback was enabled */ + FETCH_WCB(*fgStructure.CurrentWindow,Joystick) + ) && + ( + !callback || ( pollInterval <= 0 ) /* but is now disabled */ + ) ) + --fgState.NumActiveJoysticks; + + SET_CALLBACK( Joystick ); + fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval; + + /* set last poll time such that joystick will be polled asap */ + fgStructure.CurrentWindow->State.JoystickLastPoll = fgElapsedTime(); + if (fgStructure.CurrentWindow->State.JoystickLastPoll < pollInterval) + fgStructure.CurrentWindow->State.JoystickLastPoll = 0; + else + fgStructure.CurrentWindow->State.JoystickLastPoll -= pollInterval; } -/* - * Sets the spaceball rotate callback for the current window - */ -void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) ) +static void glutJoystickFuncCallback( unsigned int buttons, int axis0, int axis1, int axis2, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" ); - fgInitialiseSpaceball(); + FGCBJoystick callback = (FGCBJoystick)userData; + callback( buttons, axis0, axis1, axis2 ); +} - SET_CALLBACK( SpaceRotation ); +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 button callback for the current window + * Sets the spaceball motion callback for the current window */ -void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) ) +void FGAPIENTRY glutSpaceballMotionFuncUcall( FGCBSpaceMotionUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFuncUcall" ); fgInitialiseSpaceball(); - SET_CALLBACK( SpaceButton ); + SET_CALLBACK( SpaceMotion ); } -/* - * Sets the button box callback for the current window - */ -void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) ) +static void glutSpaceballMotionFuncCallback( int x, int y, int z, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutButtonBoxFunc" ); - SET_CALLBACK( ButtonBox ); + FGCBSpaceMotion callback = (FGCBSpaceMotion)userData; + callback( x, y, z ); } -/* - * Sets the dials box callback for the current window - */ -void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) ) +void FGAPIENTRY glutSpaceballMotionFunc( FGCBSpaceMotion callback ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDialsFunc" ); - SET_CALLBACK( Dials ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" ); + if( callback ) + glutSpaceballMotionFuncUcall( glutSpaceballMotionFuncCallback, (FGCBUserData)callback ); + else + glutSpaceballMotionFuncUcall( NULL, NULL ); } /* - * Sets the tablet motion callback for the current window + * Sets the spaceball rotate callback for the current window */ -void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) ) +void FGAPIENTRY glutSpaceballRotateFuncUcall( FGCBSpaceRotationUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletMotionFunc" ); - SET_CALLBACK( TabletMotion ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFuncUcall" ); + fgInitialiseSpaceball(); + + SET_CALLBACK( SpaceRotation ); } -/* - * Sets the tablet buttons callback for the current window - */ -void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) ) +static void glutSpaceballRotateFuncCallback( int x, int y, int z, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletButtonFunc" ); - SET_CALLBACK( TabletButton ); + FGCBSpaceRotation callback = (FGCBSpaceRotation)userData; + callback( x, y, z ); } -/* - * Sets the multi-pointer entry callback for the current window - */ -void FGAPIENTRY glutMultiEntryFunc( void (* callback)(int, int ) ) +void FGAPIENTRY glutSpaceballRotateFunc( FGCBSpaceRotation callback ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiEntryFunc" ); - SET_CALLBACK( MultiEntry ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" ); + if( callback ) + glutSpaceballRotateFuncUcall( glutSpaceballRotateFuncCallback, (FGCBUserData)callback ); + else + glutSpaceballRotateFuncUcall( NULL, NULL ); } /* - * Sets the multi-pointer button callback for the current window + * Sets the spaceball button callback for the current window */ -void FGAPIENTRY glutMultiButtonFunc( void (* callback)(int, int, int, int, int ) ) +void FGAPIENTRY glutSpaceballButtonFuncUcall( FGCBSpaceButtonUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiButtonFunc" ); - SET_CALLBACK( MultiButton ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFuncUcall" ); + fgInitialiseSpaceball(); + + SET_CALLBACK( SpaceButton ); } -/* - * Sets the multi-pointer motion callback for the current window - */ -void FGAPIENTRY glutMultiMotionFunc( void (* callback)(int, int, int ) ) +static void glutSpaceballButtonFuncCallback( int button, int buttonState, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiMotionFunc" ); - SET_CALLBACK( MultiMotion ); + FGCBSpaceButton callback = (FGCBSpaceButton)userData; + callback( button, buttonState ); } -/* - * Sets the multi-pointer passive motion callback for the current window - */ -void FGAPIENTRY glutMultiPassiveFunc( void (* callback)(int, int, int ) ) +void FGAPIENTRY glutSpaceballButtonFunc( FGCBSpaceButton callback ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiPassiveFunc" ); - SET_CALLBACK( MultiPassive ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" ); + if( callback ) + glutSpaceballButtonFuncUcall( glutSpaceballButtonFuncCallback, (FGCBUserData)callback ); + else + glutSpaceballButtonFuncUcall( NULL, NULL ); } /*** END OF FILE ***/