now have a default reshape callback function that is used if the user didn't set...
[freeglut] / src / fg_main.c
index 99040af..9acfc31 100644 (file)
@@ -74,13 +74,7 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height )
 
        fgPlatformReshapeWindow ( window, width, height );
 
-    if( FETCH_WCB( *window, Reshape ) )
-        INVOKE_WCB( *window, Reshape, ( width, height ) );
-    else
-    {
-        fgSetWindow( window );
-        glViewport( 0, 0, width, height );
-    }
+    INVOKE_WCB( *window, Reshape, ( width, height ) );
 
     /*
      * Force a window redraw.  In Windows at least this is only a partial
@@ -88,6 +82,7 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height )
      * the already-drawn part does not get drawn again and things look funny.
      * But without this we get this bad behaviour whenever we resize the
      * window.
+     * DN: Hmm.. the above sounds like a concern only in single buffered mode...
      */
     window->State.Redisplay = GL_TRUE;
 
@@ -120,13 +115,17 @@ void fghRedrawWindow ( SFG_Window *window )
 
     if( window->State.NeedToResize )
     {
+        /* Set need to resize to false before calling fghReshapeWindow, otherwise
+           in the case the user's reshape callback calls glutReshapeWindow,
+           his request would get canceled after fghReshapeWindow gets called.
+         */
+        window->State.NeedToResize = GL_FALSE;
+
         fghReshapeWindow(
             window,
             window->State.Width,
             window->State.Height
         );
-
-        window->State.NeedToResize = GL_FALSE;
     }
 
     INVOKE_WCB( *window, Display, ( ) );
@@ -167,15 +166,21 @@ static void fghDisplayAll( void )
 static void fghcbCheckJoystickPolls( SFG_Window *window,
                                      SFG_Enumerator *enumerator )
 {
-    fg_time_t checkTime = fgElapsedTime( );
-
-    if( window->State.JoystickLastPoll + window->State.JoystickPollRate <=
-        checkTime )
+    fg_time_t checkTime;
+    
+    if (window->State.JoystickPollRate > 0 && FETCH_WCB( *window, Joystick ))
     {
+        /* This window has a joystick to be polled (if pollrate <= 0, user needs to poll manually with glutForceJoystickFunc */
+        checkTime= fgElapsedTime( );
+
+        if( window->State.JoystickLastPoll + window->State.JoystickPollRate <=
+            checkTime )
+        {
 #if !defined(_WIN32_WCE)
-        fgJoystickPollWindow( window );
+            fgJoystickPollWindow( window );
 #endif /* !defined(_WIN32_WCE) */
-        window->State.JoystickLastPoll = checkTime;
+            window->State.JoystickLastPoll = checkTime;
+        }
     }
 
     fgEnumSubWindows( window, fghcbCheckJoystickPolls, enumerator );
@@ -183,6 +188,10 @@ static void fghcbCheckJoystickPolls( SFG_Window *window,
 
 /*
  * Check all windows for joystick polling
+ * 
+ * The real way to do this is to make use of the glutTimer() API
+ * to more cleanly re-implement the joystick API.  Then, this code
+ * and all other "joystick timer" code can be yanked.
  */
 static void fghCheckJoystickPolls( void )
 {
@@ -206,6 +215,7 @@ static void fghCheckTimers( void )
         SFG_Timer *timer = fgState.Timers.First;
 
         if( timer->TriggerTime > checkTime )
+            /* XXX: are timers always sorted by triggerTime? If not, this and fghNextTimer are wrong */
             break;
 
         fgListRemove( &fgState.Timers, &timer->Node );
@@ -219,12 +229,8 @@ static void fghCheckTimers( void )
 /* Platform-dependent time in milliseconds, as an unsigned 64-bit integer.
  * This doesn't overflow in any reasonable time, so no need to worry about
  * that. The GLUT API return value will however overflow after 49.7 days,
- * and on Windows we (currently) do not have access to a 64-bit timestamp,
- * which means internal time will still get in trouble when running the
+ * which means you will still get in trouble when running the
  * application for more than 49.7 days.
- * This value wraps every 49.7 days, but integer overflows cancel
- * when subtracting an initial start time, unless the total time exceeds
- * 32-bit, where the GLUT API return value is also overflowed.
  */  
 fg_time_t fgSystemTime(void)
 {
@@ -256,7 +262,7 @@ void fgError( const char *fmt, ... )
         va_end( ap );
 
     } else {
-
+#if FREEGLUT_ERRORS
         va_start( ap, fmt );
 
         fprintf( stderr, "freeglut ");
@@ -266,6 +272,7 @@ void fgError( const char *fmt, ... )
         fprintf( stderr, "\n" );
 
         va_end( ap );
+#endif
 
         if ( fgState.Initialised )
             fgDeinitialize ();
@@ -288,7 +295,7 @@ void fgWarning( const char *fmt, ... )
         va_end( ap );
 
     } else {
-
+#if FREEGLUT_WARNINGS
         va_start( ap, fmt );
 
         fprintf( stderr, "freeglut ");
@@ -298,46 +305,25 @@ void fgWarning( const char *fmt, ... )
         fprintf( stderr, "\n" );
 
         va_end( ap );
+#endif
     }
 }
 
 
 /*
- * Indicates whether Joystick events are being used by ANY window.
+ * Indicates whether a redisplay is pending for ANY window.
  *
  * The current mechanism is to walk all of the windows and ask if
- * there is a joystick callback.  We have a short-circuit early
- * return if we find any joystick handler registered.
- *
- * The real way to do this is to make use of the glutTimer() API
- * to more cleanly re-implement the joystick API.  Then, this code
- * and all other "joystick timer" code can be yanked.
- *
+ * a redisplay is pending. We have a short-circuit early
+ * return if we find any.
  */
-static void fghCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e)
-{
-    if( FETCH_WCB( *w, Joystick ) )
-    {
-        e->found = GL_TRUE;
-        e->data = w;
-    }
-    fgEnumSubWindows( w, fghCheckJoystickCallback, e );
-}
-static int fghHaveJoystick( void )
-{
-    SFG_Enumerator enumerator;
-
-    enumerator.found = GL_FALSE;
-    enumerator.data = NULL;
-    fgEnumWindows( fghCheckJoystickCallback, &enumerator );
-    return !!enumerator.data;
-}
 static void fghHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e)
 {
     if( w->State.Redisplay && w->State.Visible )
     {
         e->found = GL_TRUE;
         e->data = w;
+        return;
     }
     fgEnumSubWindows( w, fghHavePendingRedisplaysCallback, e );
 }
@@ -350,6 +336,7 @@ static int fghHavePendingRedisplays (void)
     fgEnumWindows( fghHavePendingRedisplaysCallback, &enumerator );
     return !!enumerator.data;
 }
+
 /*
  * Returns the number of GLUT ticks (milliseconds) till the next timer event.
  */
@@ -371,13 +358,13 @@ static void fghSleepForEvents( void )
 {
     fg_time_t msec;
 
-    if( fgState.IdleCallback || fghHavePendingRedisplays( ) )
+    if( fghHavePendingRedisplays( ) )
         return;
 
     msec = fghNextTimer( );
-    /* XXX Use GLUT timers for joysticks... */
+    /* XXX Should use GLUT timers for joysticks... */
     /* XXX Dumb; forces granularity to .01sec */
-    if( fghHaveJoystick( ) && ( msec > 10 ) )     
+    if( fgState.NumActiveJoysticks>0 && ( msec > 10 ) )     
         msec = 10;
 
        fgPlatformSleepForEvents ( msec );
@@ -395,7 +382,8 @@ void FGAPIENTRY glutMainLoopEvent( void )
 
     if( fgState.Timers.First )
         fghCheckTimers( );
-    fghCheckJoystickPolls( );
+    if (fgState.NumActiveJoysticks>0)   /* If zero, don't poll joysticks */
+        fghCheckJoystickPolls( );
     fghDisplayAll( );
 
     fgCloseWindows( );
@@ -411,6 +399,9 @@ void FGAPIENTRY glutMainLoop( void )
 
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoop" );
 
+    if (!fgStructure.Windows.First)
+        fgError(" ERROR:  glutMainLoop called with no windows created.");
+
        fgPlatformMainLoopPreliminaryWork ();
 
     fgState.ExecState = GLUT_EXEC_STATE_RUNNING ;
@@ -441,8 +432,8 @@ void FGAPIENTRY glutMainLoop( void )
                     fgSetWindow( window );
                 fgState.IdleCallback( );
             }
-
-            fghSleepForEvents( );
+            else
+                fghSleepForEvents( );
         }
     }