X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;ds=sidebyside;f=src%2Ffg_callbacks.c;h=b09f421021d9a5bd3214bf574976d00fca852c4f;hb=76bb5e2f2b60a3cb15fe7fa0142d80a89065cf30;hp=16519c7291fa20a84ecb4c22f09888fead41af32;hpb=aee00443ad278d5a51f17261b4f2f2d87be73ad3;p=freeglut diff --git a/src/fg_callbacks.c b/src/fg_callbacks.c index 16519c7..b09f421 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. * @@ -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,10 +72,12 @@ 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 ) { if( node->TriggerTime > timer->TriggerTime ) @@ -72,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 ) { @@ -109,6 +136,45 @@ do \ return; \ SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback ); \ } while( 0 ) +/* + * 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 ) \ +{ \ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"Func" ); \ + SET_CALLBACK( b ); \ +} +#define IMPLEMENT_CALLBACK_FUNC(a) IMPLEMENT_CALLBACK_FUNC_2NAME(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) + + /* * Sets the Display callback for the current window @@ -122,64 +188,50 @@ void FGAPIENTRY glutDisplayFunc( FGCBDisplay callback ) SET_CALLBACK( Display ); } -/* - * Sets the Reshape callback for the current window - */ -void FGAPIENTRY glutReshapeFunc( FGCBReshape callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" ); - SET_CALLBACK( Reshape ); -} - -/* - * Sets the Keyboard callback for the current window - */ -void FGAPIENTRY glutKeyboardFunc( FGCBKeyboard callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardFunc" ); - SET_CALLBACK( Keyboard ); -} - -/* - * Sets the keyboard key release callback for the current window - */ -void FGAPIENTRY glutKeyboardUpFunc( FGCBKeyboardUp callback ) +void fghDefaultReshape(int width, int height) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardUpFunc" ); - SET_CALLBACK( KeyboardUp ); + glViewport( 0, 0, width, height ); } -/* - * Sets the Special callback for the current window - */ -void FGAPIENTRY glutSpecialFunc( FGCBSpecial callback ) +void FGAPIENTRY glutReshapeFunc( FGCBReshape callback ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialFunc" ); - SET_CALLBACK( Special ); -} + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" ); + + if( !callback ) + callback = fghDefaultReshape; -/* - * Sets the special key release callback for the current window - */ -void FGAPIENTRY glutSpecialUpFunc( FGCBSpecialUp callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialUpFunc" ); - SET_CALLBACK( SpecialUp ); + SET_CALLBACK( Reshape ); } /* * 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 ) { - int glut_status = GLUT_VISIBLE; + 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 ) ) - glut_status = GLUT_NOT_VISIBLE; - INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( glut_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 glutVisibilityFunc( FGCBVisibility callback ) @@ -201,104 +253,35 @@ void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval ) 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 */ + 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 ) && - FETCH_WCB(*fgStructure.CurrentWindow,Joystick) ) && /* Joystick callback was enabled */ - ( !callback || ( pollInterval < 0 ) ) ) /* but is now disabled */ + 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; - fgStructure.CurrentWindow->State.JoystickLastPoll = - fgElapsedTime() - fgStructure.CurrentWindow->State.JoystickPollRate; - - if( fgStructure.CurrentWindow->State.JoystickLastPoll < 0 ) + /* 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 mouse callback for the current window - */ -void FGAPIENTRY glutMouseFunc( FGCBMouse callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseFunc" ); - SET_CALLBACK( Mouse ); -} - -/* - * Sets the mouse wheel callback for the current window - */ -void FGAPIENTRY glutMouseWheelFunc( FGCBMouseWheel callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseWheelFunc" ); - SET_CALLBACK( MouseWheel ); -} - -/* - * Sets the mouse motion callback for the current window (one or more buttons - * are pressed) - */ -void FGAPIENTRY glutMotionFunc( FGCBMotion callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMotionFunc" ); - SET_CALLBACK( Motion ); -} - -/* - * Sets the passive mouse motion callback for the current window (no mouse - * buttons are pressed) - */ -void FGAPIENTRY glutPassiveMotionFunc( FGCBPassive callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPassiveMotionFunc" ); - SET_CALLBACK( Passive ); -} - -/* - * Window mouse entry/leave callback - */ -void FGAPIENTRY glutEntryFunc( FGCBEntry callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEntryFunc" ); - SET_CALLBACK( Entry ); -} - -/* - * Window destruction callbacks - */ -void FGAPIENTRY glutCloseFunc( FGCBDestroy callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCloseFunc" ); - SET_CALLBACK( Destroy ); -} -void FGAPIENTRY glutWMCloseFunc( FGCBDestroy callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWMCloseFunc" ); - glutCloseFunc( callback ); -} - -/* - * Sets the overlay display callback for the current window - */ -void FGAPIENTRY glutOverlayDisplayFunc( FGCBOverlayDisplay callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutOverlayDisplayFunc" ); - SET_CALLBACK( OverlayDisplay ); -} - -/* - * Sets the window status callback for the current window - */ -void FGAPIENTRY glutWindowStatusFunc( FGCBWindowStatus callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWindowStatusFunc" ); - SET_CALLBACK( WindowStatus ); -} /* * Sets the spaceball motion callback for the current window @@ -333,103 +316,4 @@ void FGAPIENTRY glutSpaceballButtonFunc( FGCBSpaceButton callback ) SET_CALLBACK( SpaceButton ); } -/* - * Sets the button box callback for the current window - */ -void FGAPIENTRY glutButtonBoxFunc( FGCBButtonBox callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutButtonBoxFunc" ); - SET_CALLBACK( ButtonBox ); -} - -/* - * Sets the dials box callback for the current window - */ -void FGAPIENTRY glutDialsFunc( FGCBDials callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDialsFunc" ); - SET_CALLBACK( Dials ); -} - -/* - * Sets the tablet motion callback for the current window - */ -void FGAPIENTRY glutTabletMotionFunc( FGCBTabletMotion callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletMotionFunc" ); - SET_CALLBACK( TabletMotion ); -} - -/* - * Sets the tablet buttons callback for the current window - */ -void FGAPIENTRY glutTabletButtonFunc( FGCBTabletButton callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletButtonFunc" ); - SET_CALLBACK( TabletButton ); -} - -/* - * Sets the multi-pointer entry callback for the current window - */ -void FGAPIENTRY glutMultiEntryFunc( FGCBMultiEntry callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiEntryFunc" ); - SET_CALLBACK( MultiEntry ); -} - -/* - * Sets the multi-pointer button callback for the current window - */ -void FGAPIENTRY glutMultiButtonFunc( FGCBMultiButton callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiButtonFunc" ); - SET_CALLBACK( MultiButton ); -} - -/* - * Sets the multi-pointer motion callback for the current window - */ -void FGAPIENTRY glutMultiMotionFunc( FGCBMultiMotion callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiMotionFunc" ); - SET_CALLBACK( MultiMotion ); -} - -/* - * Sets the multi-pointer passive motion callback for the current window - */ -void FGAPIENTRY glutMultiPassiveFunc( FGCBMultiPassive callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiPassiveFunc" ); - SET_CALLBACK( MultiPassive ); -} - -/* - * Sets the context reload callback for the current window - */ -void FGAPIENTRY glutInitContextFunc( FGCBInitContext callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutInitContextFunc" ); - SET_CALLBACK( InitContext ); -} - -/* - * Sets the pause callback for the current window - */ -void FGAPIENTRY glutPauseFunc( FGCBPause callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPauseFunc" ); - SET_CALLBACK( Pause ); -} - -/* - * Sets the resume callback for the current window - */ -void FGAPIENTRY glutResumeFunc( FGCBResume callback ) -{ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutResumeFunc" ); - SET_CALLBACK( Resume ); -} - /*** END OF FILE ***/