);
}
-#endif
-
- if( !( FETCH_WCB( *window, Reshape ) ) )
+ /*
+ * XXX Should update {window->State.OldWidth, window->State.OldHeight}
+ * XXX to keep in lockstep with UNIX_X11 code.
+ */
+ if( FETCH_WCB( *window, Reshape ) )
+ INVOKE_WCB( *window, Reshape, ( width, height ) );
+ else
{
fgSetWindow( window );
glViewport( 0, 0, width, height );
}
- else
- INVOKE_WCB( *window, Reshape, ( width, height ) );
+
+#endif
/*
* Force a window redraw. In Windows at least this is only a partial
if( window->State.Redisplay &&
window->State.Visible )
{
+ /*
+ * XXX Resizing should *not* depend upon whether there
+ * XXX is a pending redisplay flag, as far as I can tell.
+ * XXX
+ * XXX Note, too, that the {NeedToResize} flag is a little
+ * XXX fuzzy in its meaning, since for WIN32, this also
+ * XXX means "we need to tell the application that the window has
+ * XXX changed size", while in X11, it only means "we need
+ * XXX to ask the window system to resize the window.
+ * XXX Splitting the flag's meaning might be desirable, but
+ * XXX that could complicate the code more. (On X11, the
+ * XXX user callback is called as soon as the event is
+ * XXX discovered, but resizing the window is postponed
+ * XXX until after other events.)
+ */
if( window->State.NeedToResize )
{
SFG_Window *current_window = fgStructure.Window;
static long fgNextTimer( void )
{
long ret = INT_MAX;
- SFG_Timer *timer;
+ SFG_Timer *timer = fgState.Timers.First;
- if( (timer = fgState.Timers.First) )
+ if( timer )
ret = timer->TriggerTime - fgElapsedTime();
+ if( ret < 0 )
+ ret = 0;
return ret;
}
msec = fgNextTimer( );
if( fgHaveJoystick( ) )
msec = MIN( msec, 10 );
-
+
wait.tv_sec = msec / 1000;
wait.tv_usec = (msec % 1000) * 1000;
err = select( socket+1, &fdset, NULL, NULL, &wait );
* (in freeglut only) will not get an initial reshape event,
* which can break things.
*
- * XXX NOTE that it is possible that you will more than one Reshape
- * XXX event for your top-level window, but something like this
- * XXX appears to be required for compatbility.
- *
* GLUT presumably does this because it generally tries to treat
* sub-windows the same as windows.
+ *
+ * XXX Technically, GETWINDOW( xconfigure ) and
+ * XXX {event.xconfigure} may not be legit ways to get at
+ * XXX data for CreateNotify events. In practice, the data
+ * XXX is in a union which is laid out much the same either
+ * XXX way. But if you want to split hairs, this isn't legit,
+ * XXX and we should instead duplicate some code.
*/
case CreateNotify:
case ConfigureNotify:
GETWINDOW( xconfigure );
- window->State.NeedToResize = GL_TRUE ;
- window->State.Width = event.xconfigure.width ;
- window->State.Height = event.xconfigure.height;
+ {
+ int width = event.xconfigure.width;
+ int height = event.xconfigure.height;
+
+ if( ( width != window->State.OldWidth ) ||
+ ( height != window->State.OldHeight ) )
+ {
+ window->State.OldWidth = width;
+ window->State.OldHeight = height;
+ if( FETCH_WCB( *window, Reshape ) )
+ INVOKE_WCB( *window, Reshape, ( width, height ) );
+ else
+ {
+ fgSetWindow( window );
+ glViewport( 0, 0, width, height );
+ }
+ glutPostRedisplay( );
+ }
+ }
break;
case DestroyNotify:
case Expose:
/*
* We are too dumb to process partial exposes...
+ *
* XXX Well, we could do it. However, it seems to only
* XXX be potentially useful for single-buffered (since
* XXX double-buffered does not respect viewport when we
* XXX do a buffer-swap).
+ *
+ * XXX GETWINDOW( xexpose );
+ * XXX fgSetWindow( window );
+ * XXX glutPostRedisplay( );
*/
if( event.xexpose.count == 0 )
fghRedrawWindowByHandle( event.xexpose.window );
case VisibilityNotify:
{
GETWINDOW( xvisibility );
+ /*
+ * XXX INVOKE_WCB() does this check for us.
+ */
if( ! FETCH_WCB( *window, WindowStatus ) )
break;
fgSetWindow( window );
/*
* XXX For more than 5 buttons, just check {event.xmotion.state},
- * XXX rather than a host of bit-masks?
+ * XXX rather than a host of bit-masks? Or maybe we need to
+ * XXX track ButtonPress/ButtonRelease events in our own
+ * XXX bit-mask?
*/
#define BUTTON_MASK \
( Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
window->ActiveMenu->Window->State.MouseY =
event.xbutton.y_root - window->ActiveMenu->Y;
}
-
+
/* In the menu, invoke the callback and deactivate the menu*/
if( fgCheckActiveMenu( window->ActiveMenu->Window,
window->ActiveMenu ) )
else if( pressed )
/*
* Outside the menu, deactivate if it's a downclick
+ *
* XXX This isn't enough. A downclick outside of
* XXX the interior of our freeglut windows should also
* XXX deactivate the menu. This is more complicated.
*/
fgDeactivateMenu( window->ActiveMenu->ParentWindow );
-
+
+ /*
+ * XXX Why does an active menu require a redisplay at
+ * XXX this point? If this can come out cleanly, then
+ * XXX it probably should do so; if not, a comment should
+ * XXX explain it.
+ */
window->State.Redisplay = GL_TRUE;
break;
}
( window->Menu[ button ] ) &&
pressed )
{
+ /*
+ * XXX Posting a requisite Redisplay seems bogus.
+ */
window->State.Redisplay = GL_TRUE;
fgSetWindow( window );
fgActivateMenu( window, button );
/*
* Finally execute the mouse or mouse wheel callback
*
- * XXX Use a symbolic constant, *not* "4"!
+ * XXX Use a symbolic constant, *not* "4"! ("3, sire!")
*/
if( ( button < 3 ) || ( ! FETCH_WCB( *window, MouseWheel ) ) )
INVOKE_WCB( *window, Mouse, ( button,
fgState.ExecState = GLUT_EXEC_STATE_RUNNING ;
while( fgState.ExecState == GLUT_EXEC_STATE_RUNNING )
{
- glutMainLoopEvent( );
+ SFG_Window *window;
- if( fgStructure.Windows.First == NULL )
+ glutMainLoopEvent( );
+ /*
+ * Step through the list of windows, seeing if there are any
+ * that are not menus
+ */
+ for( window = ( SFG_Window * )fgStructure.Windows.First;
+ window;
+ window = ( SFG_Window * )window->Node.Next )
+ if ( ! ( window->IsMenu ) )
+ break;
+
+ if( ! window )
fgState.ExecState = GLUT_EXEC_STATE_STOP;
else
{
if( fgState.IdleCallback )
fgState.IdleCallback( );
- fgSleepForEvents();
+ fgSleepForEvents( );
}
}
* of a freeglut session, so that another glutInit() call can happen
*/
fgDeinitialize( );
+ if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
+ exit( 0 );
}
/*
break;
}
- if ( window->Menu[ button ] && pressed )
+ if( window->Menu[ button ] && pressed )
{
window->State.Redisplay = GL_TRUE;
fgSetWindow( window );