#include "config.h"
#endif
-#include "../include/GL/freeglut.h"
+#include <GL/freeglut.h>
#include "freeglut_internal.h"
#include <limits.h>
);
window->State.NeedToResize = GL_FALSE;
- fgSetWindow ( current_window );
+ fgSetWindow( current_window );
}
INVOKE_WCB( *window, Display, ( ) );
static void fghcbDisplayWindow( SFG_Window *window,
SFG_Enumerator *enumerator )
{
- if( window->State.Redisplay &&
- window->State.Visible )
+ if( window->State.NeedToResize )
{
- /*
- * 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;
+ SFG_Window *current_window = fgStructure.Window;
- fgSetWindow( window );
+ fgSetWindow( window );
- fghReshapeWindowByHandle(
- window->Window.Handle,
- window->State.Width,
- window->State.Height
- );
+ fghReshapeWindowByHandle(
+ window->Window.Handle,
+ window->State.Width,
+ window->State.Height
+ );
- window->State.NeedToResize = GL_FALSE;
- fgSetWindow ( current_window );
- }
+ window->State.NeedToResize = GL_FALSE;
+ fgSetWindow ( current_window );
+ }
+ if( window->State.Redisplay &&
+ window->State.Visible )
+ {
window->State.Redisplay = GL_FALSE;
#if TARGET_HOST_UNIX_X11
* Indicates whether Joystick events are being used by ANY window.
*
* The current mechanism is to walk all of the windows and ask if
- * there is a joystick callback. Certainly in some cases, maybe
- * in all cases, the joystick is attached to the system and accessed
- * from ONE point by GLUT/freeglut, so this is not the right way,
- * in general, to do this. However, the Joystick code is segregated
- * in its own little world, so we can't access the information that
- * we need in order to do that nicely.
+ * there is a joystick callback. We have a short-circuit early
+ * return if we find any joystick handler registered.
*
- * Some alternatives:
- * * Store Joystick data into freeglut global state.
- * * Provide NON-static functions or data from Joystick *.c file.
- *
- * Basically, the RIGHT way to do this requires knowing something
- * about the Joystick. Right now, the Joystick code is behind
- * an opaque wall.
+ * 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 fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e)
*/
static void fgSleepForEvents( void )
{
-#if TARGET_HOST_UNIX_X11
- fd_set fdset;
- int err;
- int socket;
- struct timeval wait;
- long msec;
-
+ long msec;
+
if( fgState.IdleCallback || fgHavePendingRedisplays( ) )
return;
- socket = ConnectionNumber( fgDisplay.Display );
- FD_ZERO( &fdset );
- FD_SET( socket, &fdset );
-
- 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 );
+ msec = fgNextTimer( );
+ if( fgHaveJoystick( ) ) /* XXX Use GLUT timers for joysticks... */
+ msec = MIN( msec, 10 ); /* XXX Dumb; forces granularity to .01sec */
- if( -1 == err )
- fgWarning ( "freeglut select() error: %d\n", errno );
-
+#if TARGET_HOST_UNIX_X11
+ /*
+ * Possibly due to aggressive use of XFlush() and friends,
+ * it is possible to have our socket drained but still have
+ * unprocessed events. (Or, this may just be normal with
+ * X, anyway?) We do non-trivial processing of X events
+ * after tham in event-reading loop, in any case, so we
+ * need to allow that we may have an empty socket but non-
+ * empty event queue.
+ */
+ if( ! XPending( fgDisplay.Display ) )
+ {
+ fd_set fdset;
+ int err;
+ int socket;
+ struct timeval wait;
+
+ socket = ConnectionNumber( fgDisplay.Display );
+ FD_ZERO( &fdset );
+ FD_SET( socket, &fdset );
+ wait.tv_sec = msec / 1000;
+ wait.tv_usec = (msec % 1000) * 1000;
+ err = select( socket+1, &fdset, NULL, NULL, &wait );
+
+ if( -1 == err )
+ fgWarning ( "freeglut select() error: %d\n", errno );
+ }
#elif TARGET_HOST_WIN32
+ MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLEVENTS );
#endif
}
case DestroyNotify:
/*
* This is sent to confirm the XDestroyWindow call.
+ *
* XXX WHY is this commented out? Should we re-enable it?
*/
/* fgAddToWindowDestroyList ( window ); */
* 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 );
+ {
+ GETWINDOW( xexpose );
+ fgSetWindow( window );
+ glutPostRedisplay( );
+ }
break;
case MapNotify:
*/
void FGAPIENTRY glutMainLoop( void )
{
+ int action;
+
#if TARGET_HOST_WIN32
SFG_Window *window = (SFG_Window *)fgStructure.Windows.First ;
#endif
/*
* When this loop terminates, destroy the display, state and structure
* of a freeglut session, so that another glutInit() call can happen
+ *
+ * Save the "ActionOnWindowClose" because "fgDeinitialize" resets it.
*/
+ action = fgState.ActionOnWindowClose;
fgDeinitialize( );
- if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
+ if( action == GLUT_ACTION_EXIT )
exit( 0 );
}
case WM_SIZE:
/*
- * We got resized... But check if the window has been already added...
+ * If the window is visible, then it is the user manually resizing it.
+ * If it is not, then it is the system sending us a dummy resize with
+ * zero dimensions on a "glutIconifyWindow" call.
*/
- window->State.NeedToResize = GL_TRUE;
- window->State.Width = LOWORD(lParam);
- window->State.Height = HIWORD(lParam);
+ if( window->State.Visible )
+ {
+ window->State.NeedToResize = GL_TRUE;
+ window->State.Width = LOWORD(lParam);
+ window->State.Height = HIWORD(lParam);
+ }
+
break;
#if 0
case WM_SETFOCUS:
}
if( GetSystemMetrics( SM_SWAPBUTTON ) )
+ {
if( button == GLUT_LEFT_BUTTON )
button = GLUT_RIGHT_BUTTON;
- else if( button == GLUT_RIGHT_BUTTON )
- button = GLUT_LEFT_BUTTON;
+ else
+ if( button == GLUT_RIGHT_BUTTON )
+ button = GLUT_LEFT_BUTTON;
+ }
if( button == -1 )
return DefWindowProc( hWnd, uMsg, lParam, wParam );
int keypress = -1;
POINT mouse_pos ;
- if( fgState.IgnoreKeyRepeat && (lParam & KF_REPEAT) )
+ if( fgState.IgnoreKeyRepeat && (HIWORD(lParam) & KF_REPEAT) )
break;
/*
case WM_SYSCHAR:
case WM_CHAR:
{
- if( fgState.IgnoreKeyRepeat && (lParam & KF_REPEAT) )
+ if( fgState.IgnoreKeyRepeat && (HIWORD(lParam) & KF_REPEAT) )
break;
fgState.Modifiers = fgGetWin32Modifiers( );