* Handle a window configuration change. When no reshape
* callback is hooked, the viewport size is updated to
* match the new window size.
- *
- * XXX We can/should make a "unified" window handle type so that
- * XXX the function headers don't need this silly #ifdef junk.
- * XXX Make the type, say, {fgWindow}. On UNIX_X11, this is
- * XXX {Window}. On WIN32, it is {HWND}. Then do the #ifdef
- * XXX junk *once* in "freeglut_internal.h".
*/
-static void fghReshapeWindowByHandle
-#if TARGET_HOST_UNIX_X11
- ( Window handle, int width, int height )
-#elif TARGET_HOST_WIN32
- ( HWND handle, int width, int height )
-#endif
+static void fghReshapeWindowByHandle ( SFG_WindowHandleType handle,
+ int width, int height )
{
SFG_Window *current_window = fgStructure.Window;
XResizeWindow( fgDisplay.Display, window->Window.Handle,
width, height );
XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
- /*
- * XXX REALLY shouldn't be done. GLUT docs state that this
- * XXX isn't even processed immediately, but rather waits
- * XXX for return to the mainloop. "This allows multiple
- * XXX glutReshapeWindow, glutPositionWindow, and glutFullScreen
- * XXX requests to the same window to be coalesced." (This is
- * XXX having some deleterious effect on a sample program of mine.)
- * XXX Not only does GLUT not flush at this point, GLUT doesn't even
- * XXX *do* the reshape at this point! We should probably rip this
- * XXX out and do what GLUT promises. It would be more efficient, and
- * XXX might be more compatible.
- */
#elif TARGET_HOST_WIN32
* Calls a window's redraw method. This is used when
* a redraw is forced by the incoming window messages.
*/
-static void fghRedrawWindowByHandle
-#if TARGET_HOST_UNIX_X11
- ( Window handle )
-#elif TARGET_HOST_WIN32
- ( HWND handle )
-#endif
+static void fghRedrawWindowByHandle ( SFG_WindowHandleType handle )
{
SFG_Window* window = fgWindowByHandle( handle );
- freeglut_return_if_fail( window != NULL );
+ freeglut_return_if_fail( window );
+ freeglut_return_if_fail( FETCH_WCB ( *window, Display ) );
+
+ window->State.Redisplay = GL_FALSE;
- /*
- * XXX Other than clearing the Redisplay flag or not,
- * XXX we may as well rely on the INVOK_WCB() doing this
- * XXX pointer-check.
- * XXX
- * XXX If we do not invoke the display because the pointer
- * XXX is not defined (should never happen, really), then
- * XXX we may enter an infinite busy-loop trying to update
- * XXX the window. Similarly, if we skip because the window
- * XXX is not visible. However, if the window becomes visible
- * XXX at a later time, the window should get its callback
- * XXX invoked. I would recommend removing the first check,
- * XXX and making the second check only affect whether the
- * XXX callback is invoked---but always clear the flag, if
- * XXX the {window} pointer is defined.
- */
- freeglut_return_if_fail( FETCH_WCB( *window, Display ) );
freeglut_return_if_fail( window->State.Visible );
if( window->State.NeedToResize )
fgSetWindow ( current_window );
}
- window->State.Redisplay = GL_FALSE;
INVOKE_WCB( *window, Display, ( ) );
}
static void fghcbDisplayWindow( SFG_Window *window,
SFG_Enumerator *enumerator )
{
- /*
- * XXX Do we need/want to check the callback pointer here?
- * XXX INVOKE_WCB() will check for us. Arguably, the
- * XXX Redisplay status flag should be cleared regardless
- * XXX of any concern but that {window} is a valid pointer
- * XXX (which this function is assuming anyway).
- * XXX Especially since old GLUT wouldn't even enter its main
- * XXX loop if you didn't have a display callback defined...
- */
- if( ( FETCH_WCB( *window, Display ) ) &&
- window->State.Redisplay &&
+ if( window->State.Redisplay &&
window->State.Visible )
{
if( window->State.NeedToResize )
static void fghCheckTimers( void )
{
long checkTime = fgElapsedTime( );
- SFG_Timer *timer, *next;
- SFG_List timedOut;
-
- fgListInit(&timedOut);
+ SFG_Timer *timer;
- for( timer = (SFG_Timer *)fgState.Timers.First;
- timer;
- timer = (SFG_Timer *)next )
+ while( timer = fgState.Timers.First )
{
- next = (SFG_Timer *)timer->Node.Next;
+ if( timer->TriggerTime > checkTime )
+ break;
- if( timer->TriggerTime <= checkTime )
- {
- fgListRemove( &fgState.Timers, &timer->Node );
- fgListAppend( &timedOut, &timer->Node );
- }
- }
+ fgListRemove( &fgState.Timers, &timer->Node );
+ fgListAppend( &fgState.FreeTimers, &timer->Node );
- /*
- * Now feel free to execute all the hooked and timed out timer callbacks
- * And delete the timed out timers...
- */
- while ( (timer = (SFG_Timer *)timedOut.First) )
- {
- if( timer->Callback != NULL )
- timer->Callback( timer->ID );
- fgListRemove( &timedOut, &timer->Node );
- free( timer );
+ timer->Callback( timer->ID );
}
}
-
/*
* Elapsed Time
*/
#if TARGET_HOST_UNIX_X11
struct timeval now;
long elapsed;
-
+
gettimeofday( &now, NULL );
-
+
elapsed = (now.tv_usec - fgState.Time.Value.tv_usec) / 1000;
elapsed += (now.tv_sec - fgState.Time.Value.tv_sec) * 1000;
-
+
return elapsed;
#elif TARGET_HOST_WIN32
return timeGetTime() - fgState.Time.Value;
#if TARGET_HOST_UNIX_X11
gettimeofday( &fgState.Time.Value, NULL );
#elif TARGET_HOST_WIN32
- fgState.Time.Value = timeGetTime () ;
+ fgState.Time.Value = timeGetTime ();
#endif
fgState.Time.Set = GL_TRUE ;
va_end( ap );
if ( fgState.Initialised )
- fgDeinitialize () ;
+ fgDeinitialize ();
exit( 1 );
}
return !!enumerator.data;
}
/*
- * Indicates whether there are any outstanding timers.
- */
-#if 0 /* Not used */
-static int fgHaveTimers( void )
-{
- return !!fgState.Timers.First;
-}
-#endif
-/*
* Returns the number of GLUT ticks (milliseconds) till the next timer event.
*/
static long fgNextTimer( void )
{
- long now = fgElapsedTime();
long ret = INT_MAX;
SFG_Timer *timer;
- for( timer = (SFG_Timer *)fgState.Timers.First;
- timer;
- timer = (SFG_Timer *)timer->Node.Next )
- ret = MIN( ret, MAX( 0, timer->TriggerTime - now ) );
+ if( (timer = fgState.Timers.First) )
+ ret = timer->TriggerTime - fgElapsedTime();
return ret;
}
{
GETWINDOW( xclient );
- fgCloseWindow ( window ) ;
- fgAddToWindowDestroyList ( window, GL_FALSE );
+ fgDestroyWindow ( window );
+
+ if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
+ {
+ fgDeinitialize( );
+ exit( 0 );
+ }
+
+ fgState.ExecState = GLUT_EXEC_STATE_STOP;
+ return;
}
break;
* This is sent to confirm the XDestroyWindow call.
* XXX WHY is this commented out? Should we re-enable it?
*/
- /* fgAddToWindowDestroyList ( window, GL_FALSE ); */
+ /* fgAddToWindowDestroyList ( window ); */
break;
case Expose:
event.xmotion.y_root - window->ActiveMenu->Y;
}
window->ActiveMenu->Window->State.Redisplay = GL_TRUE ;
- fgSetWindow( window->ActiveMenu->ParentWindow ) ;
+ fgSetWindow( window->ActiveMenu->ParentWindow );
break;
}
! FETCH_WCB( *window, MouseWheel ) )
break;
- /*
- * XXX Why don't we use {window}? Other code here does...
- */
fgState.Modifiers = fgGetXModifiers( &event );
/*
while( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) )
{
if( GetMessage( &stMsg, NULL, 0, 0 ) == 0 )
- fgState.ExecState = GLUT_EXEC_STATE_STOP ;
+ {
+ if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
+ {
+ fgDeinitialize( );
+ exit( 0 );
+ }
+ fgState.ExecState = GLUT_EXEC_STATE_STOP;
+ return;
+ }
TranslateMessage( &stMsg );
DispatchMessage( &stMsg );
}
#endif
- fghCheckTimers( );
+ if( fgState.Timers.First )
+ fghCheckTimers( );
fghCheckJoystickPolls( );
fghDisplayAll( );
}
}
- {
- fgExecutionState execState = fgState.ExecState;
-
- /*
- * When this loop terminates, destroy the display, state and structure
- * of a freeglut session, so that another glutInit() call can happen
- */
- fgDeinitialize( );
-
- if( execState == GLUT_ACTION_EXIT )
- exit( 0 ) ;
- }
+ /*
+ * When this loop terminates, destroy the display, state and structure
+ * of a freeglut session, so that another glutInit() call can happen
+ */
+ fgDeinitialize( );
}
/*
LONG lRet = 1;
if ( ( window == NULL ) && ( uMsg != WM_CREATE ) )
- return DefWindowProc( hWnd, uMsg, wParam, lParam ) ;
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
/* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0,
uMsg, wParam, lParam ); */
if( fgStructure.MenuContext )
wglMakeCurrent( window->Window.Device,
fgStructure.MenuContext->Context
- ) ;
+ );
else
{
fgStructure.MenuContext =
wglCreateContext( window->Window.Device );
}
- /* window->Window.Context = wglGetCurrentContext () ; */
+ /* window->Window.Context = wglGetCurrentContext (); */
window->Window.Context = wglCreateContext( window->Window.Device );
}
else
break;
case WM_CLOSE:
- /*
- * Make sure we don't close a window with current context active
- */
- if( fgStructure.Window == window )
- {
- int used = FALSE ;
- SFG_Window *iter ;
-
- wglMakeCurrent( NULL, NULL );
- /*
- * Step through the list of windows. If the rendering context
- * is not being used by another window, then we delete it.
- */
- for( iter = (SFG_Window *)fgStructure.Windows.First;
- iter;
- iter = (SFG_Window *)iter->Node.Next )
- {
- if( ( iter->Window.Context == window->Window.Context ) &&
- ( iter != window ) )
- used = TRUE;
- }
-
- if( ! used )
- wglDeleteContext( window->Window.Context );
- }
-
- /*
- * Put on a linked list of windows to be removed after all the
- * callbacks have returned
- */
- fgAddToWindowDestroyList( window, GL_FALSE );
- DestroyWindow( hWnd );
+ fgDestroyWindow ( window );
+ if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
+ PostQuitMessage(0);
break;
case WM_DESTROY:
if( fgState.IgnoreKeyRepeat && (lParam & KF_REPEAT) )
break;
- /*
- * XXX INVOKE_WCB() takes care of the callback-pointer check.
- * XXX We could just uncoditionally find/trash the Modifiers
- * XXX and get rid of the "if( ... ) {" and "}". Unconditinal
- * XXX code is simpler code. (^&
- */
- if( FETCH_WCB( *window, Keyboard ) )
- {
- fgState.Modifiers = fgGetWin32Modifiers( );
- INVOKE_WCB( *window, Keyboard,
- ( (char)wParam,
- window->State.MouseX, window->State.MouseY )
- );
- fgState.Modifiers = 0xffffffff;
- }
+ fgState.Modifiers = fgGetWin32Modifiers( );
+ INVOKE_WCB( *window, Keyboard,
+ ( (char)wParam,
+ window->State.MouseX, window->State.MouseY )
+ );
+ fgState.Modifiers = 0xffffffff;
}
break;
/* User has finished resizing the window, force a redraw */
INVOKE_WCB( *window, Display, ( ) );
- /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ) ; */
+ /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); */
break;
/*