Initial work on callbacks with user data parameters.
[freeglut] / src / fg_callbacks.c
index c62d37c..b09f421 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * freeglut_callbacks.c
+ * fg_callbacks.c
  *
  * The callbacks setting methods.
  *
  * 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 )
 {
@@ -121,32 +148,31 @@ void FGAPIENTRY glut##a##Func( FGCB##b callback )               \
 #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);
+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(Pause);
-IMPLEMENT_CALLBACK_FUNC(Resume);
+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)
 
 
 
@@ -247,11 +273,12 @@ void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval )
     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;
 }