X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_main.c;h=6375448cc1d5c31aee70f063f7633135ce3ad8a0;hb=acc07c33a660243fece1e72b658c4228a70bea33;hp=f976446a757ac76357c401c4cec8fa9b428a7bde;hpb=2e8c8e1910a0f5a18c6108174bad31f13af38165;p=freeglut diff --git a/src/freeglut_main.c b/src/freeglut_main.c index f976446..6375448 100644 --- a/src/freeglut_main.c +++ b/src/freeglut_main.c @@ -65,72 +65,87 @@ /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ /* - * Calls a window's redraw method. This is used when - * a redraw is forced by the incoming window messages. - * - * 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 fghRedrawWindowByHandle -#if TARGET_HOST_UNIX_X11 - ( Window handle ) -#elif TARGET_HOST_WIN32 - ( HWND handle ) -#endif -{ - SFG_Window* window = fgWindowByHandle( handle ); - freeglut_return_if_fail( window != NULL ); - - /* - * 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 ); - - window->State.Redisplay = GL_FALSE; - INVOKE_WCB( *window, Display, ( ) ); -} - -/* * Handle a window configuration change. When no reshape * callback is hooked, the viewport size is updated to * match the new window size. */ -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; SFG_Window* window = fgWindowByHandle( handle ); freeglut_return_if_fail( window != NULL ); - if( !( FETCH_WCB( *window, Reshape ) ) ) + +#if TARGET_HOST_UNIX_X11 + + XResizeWindow( fgDisplay.Display, window->Window.Handle, + width, height ); + XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ + +#elif TARGET_HOST_WIN32 + + { + RECT rect; + + /* + * For windowed mode, get the current position of the + * window and resize taking the size of the frame + * decorations into account. + */ + + GetWindowRect( window->Window.Handle, &rect ); + rect.right = rect.left + width; + rect.bottom = rect.top + height; + + if ( window->Parent == NULL ) + { + if ( ! window->IsMenu && !window->State.IsGameMode ) + { + rect.right += GetSystemMetrics( SM_CXSIZEFRAME ) * 2; + rect.bottom += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + + GetSystemMetrics( SM_CYCAPTION ); + } + } + else + { + GetWindowRect( window->Parent->Window.Handle, &rect ); + AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | + WS_CLIPCHILDREN, FALSE ); + } + + /* + * SWP_NOACTIVATE Do not activate the window + * SWP_NOOWNERZORDER Do not change position in z-order + * SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message + * SWP_NOZORDER Retains the current Z order (ignore 2nd param) + */ + + SetWindowPos( window->Window.Handle, + HWND_TOP, + rect.left, + rect.top, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | + SWP_NOZORDER + ); + } + + /* + * 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 @@ -146,32 +161,18 @@ static void fghReshapeWindowByHandle } /* - * A static helper function to execute display callback for a window + * Calls a window's redraw method. This is used when + * a redraw is forced by the incoming window messages. */ -static void fghcbDisplayWindow( SFG_Window *window, SFG_Enumerator *enumerator ) +static void fghRedrawWindowByHandle ( SFG_WindowHandleType handle ) { -#if TARGET_HOST_UNIX_X11 - /* - * 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 && - window->State.Visible ) - { - SFG_Window *current_window = fgStructure.Window; + SFG_Window* window = fgWindowByHandle( handle ); + freeglut_return_if_fail( window ); + freeglut_return_if_fail( FETCH_WCB ( *window, Display ) ); - window->State.Redisplay = GL_FALSE; - INVOKE_WCB( *window, Display, ( ) ); - fgSetWindow( current_window ); - } + window->State.Redisplay = GL_FALSE; -#elif TARGET_HOST_WIN32 + freeglut_return_if_fail( window->State.Visible ); if( window->State.NeedToResize ) { @@ -181,30 +182,58 @@ static void fghcbDisplayWindow( SFG_Window *window, SFG_Enumerator *enumerator ) fghReshapeWindowByHandle( window->Window.Handle, - glutGet( GLUT_WINDOW_WIDTH ), - glutGet( GLUT_WINDOW_HEIGHT ) + window->State.Width, + window->State.Height ); window->State.NeedToResize = GL_FALSE; fgSetWindow ( current_window ); } - /* - * XXX See above comment about the Redisplay flag... - */ - if( ( FETCH_WCB( *window, Display ) ) && - window->State.Redisplay && + INVOKE_WCB( *window, Display, ( ) ); +} + +/* + * A static helper function to execute display callback for a window + */ +static void fghcbDisplayWindow( SFG_Window *window, + SFG_Enumerator *enumerator ) +{ + if( window->State.NeedToResize ) + { + SFG_Window *current_window = fgStructure.Window; + + fgSetWindow( window ); + + fghReshapeWindowByHandle( + window->Window.Handle, + window->State.Width, + window->State.Height + ); + + 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 + { + SFG_Window *current_window = fgStructure.Window; + + INVOKE_WCB( *window, Display, ( ) ); + fgSetWindow( current_window ); + } +#elif TARGET_HOST_WIN32 RedrawWindow( window->Window.Handle, NULL, NULL, RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW ); - } - #endif + } fgEnumSubWindows( window, fghcbDisplayWindow, enumerator ); } @@ -217,7 +246,7 @@ static void fghDisplayAll( void ) SFG_Enumerator enumerator; enumerator.found = GL_FALSE; - enumerator.data = NULL; + enumerator.data = NULL; fgEnumWindows( fghcbDisplayWindow, &enumerator ); } @@ -248,7 +277,7 @@ static void fghCheckJoystickPolls( void ) SFG_Enumerator enumerator; enumerator.found = GL_FALSE; - enumerator.data = NULL; + enumerator.data = NULL; fgEnumWindows( fghcbCheckJoystickPolls, &enumerator ); } @@ -259,57 +288,40 @@ static void fghCheckJoystickPolls( void ) static void fghCheckTimers( void ) { long checkTime = fgElapsedTime( ); - SFG_Timer *timer, *next; - SFG_List timedOut; - fgListInit(&timedOut); - - for( timer = (SFG_Timer *)fgState.Timers.First; - timer; - timer = (SFG_Timer *)next ) + while( fgState.Timers.First ) { - next = (SFG_Timer *)timer->Node.Next; + SFG_Timer *timer = fgState.Timers.First; - if( timer->TriggerTime <= checkTime ) - { - fgListRemove( &fgState.Timers, &timer->Node ); - fgListAppend( &timedOut, &timer->Node ); - } - } + if( timer->TriggerTime > checkTime ) + break; - /* - * 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 ); + fgListRemove( &fgState.Timers, &timer->Node ); + fgListAppend( &fgState.FreeTimers, &timer->Node ); + + timer->Callback( timer->ID ); } } - /* * Elapsed Time */ long fgElapsedTime( void ) { - if (fgState.Time.Set) + if ( fgState.Time.Set ) { #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; - + + 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; + return timeGetTime() - fgState.Time.Value; #endif } else @@ -317,9 +329,11 @@ long fgElapsedTime( void ) #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; + fgState.Time.Set = GL_TRUE ; + + return 0 ; } } @@ -332,16 +346,16 @@ void fgError( const char *fmt, ... ) va_start( ap, fmt ); - fprintf( stderr, "freeglut " ); + fprintf( stderr, "freeglut "); if( fgState.ProgramName ) - fprintf( stderr, "(%s): ", fgState.ProgramName ); + fprintf (stderr, "(%s): ", fgState.ProgramName); vfprintf( stderr, fmt, ap ); fprintf( stderr, "\n" ); va_end( ap ); - if ( fgState.Initalized ) - fgDeinitialize( ); + if ( fgState.Initialised ) + fgDeinitialize (); exit( 1 ); } @@ -352,7 +366,7 @@ void fgWarning( const char *fmt, ... ) va_start( ap, fmt ); - fprintf( stderr, "freeglut " ); + fprintf( stderr, "freeglut "); if( fgState.ProgramName ) fprintf( stderr, "(%s): ", fgState.ProgramName ); vfprintf( stderr, fmt, ap ); @@ -381,7 +395,7 @@ void fgWarning( const char *fmt, ... ) * an opaque wall. * */ -static void fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e ) +static void fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e) { if( FETCH_WCB( *w, Joystick ) ) { @@ -398,7 +412,7 @@ static int fgHaveJoystick( void ) fgEnumWindows( fgCheckJoystickCallback, &enumerator ); return !!enumerator.data; } -static void fgHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e ) +static void fgHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e) { if( w->State.Redisplay ) { @@ -407,7 +421,7 @@ static void fgHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e ) } fgEnumSubWindows( w, fgHavePendingRedisplaysCallback, e ); } -static int fgHavePendingRedisplays( void ) +static int fgHavePendingRedisplays (void) { SFG_Enumerator enumerator; enumerator.found = GL_FALSE; @@ -416,25 +430,17 @@ static int fgHavePendingRedisplays( void ) return !!enumerator.data; } /* - * Indicates whether there are any outstanding timers. - */ -static int fgHaveTimers( void ) -{ - return !!fgState.Timers.First; -} -/* * 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; + SFG_Timer *timer = fgState.Timers.First; - for( timer = ( SFG_Timer * )fgState.Timers.First; - timer; - timer = ( SFG_Timer * )timer->Node.Next ) - ret = MIN( ret, MAX( 0, timer->TriggerTime - now ) ); + if( timer ) + ret = timer->TriggerTime - fgElapsedTime(); + if( ret < 0 ) + ret = 0; return ret; } @@ -460,13 +466,13 @@ static void fgSleepForEvents( void ) msec = fgNextTimer( ); if( fgHaveJoystick( ) ) msec = MIN( msec, 10 ); - - wait.tv_sec = msec / 1000; - wait.tv_usec = ( msec % 1000 ) * 1000; + + 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 ); + fgWarning ( "freeglut select() error: %d\n", errno ); #elif TARGET_HOST_WIN32 #endif @@ -531,8 +537,16 @@ void FGAPIENTRY glutMainLoopEvent( void ) { 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; @@ -542,20 +556,38 @@ void FGAPIENTRY glutMainLoopEvent( void ) * (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: - fghReshapeWindowByHandle( - event.xconfigure.window, - event.xconfigure.width, - event.xconfigure.height - ); + GETWINDOW( xconfigure ); + { + 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: @@ -563,16 +595,21 @@ void FGAPIENTRY glutMainLoopEvent( void ) * 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: /* * 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 ); @@ -597,6 +634,9 @@ void FGAPIENTRY glutMainLoopEvent( void ) case VisibilityNotify: { GETWINDOW( xvisibility ); + /* + * XXX INVOKE_WCB() does this check for us. + */ if( ! FETCH_WCB( *window, WindowStatus ) ) break; fgSetWindow( window ); @@ -656,7 +696,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) window->ActiveMenu->Window->State.MouseY = event.xmotion.y_root - window->ActiveMenu->Y; } - window->ActiveMenu->Window->State.Redisplay = GL_TRUE; + window->ActiveMenu->Window->State.Redisplay = GL_TRUE ; fgSetWindow( window->ActiveMenu->ParentWindow ); break; @@ -664,11 +704,13 @@ void FGAPIENTRY glutMainLoopEvent( void ) /* * 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 ) - if( event.xmotion.state & BUTTON_MASK ) + if ( event.xmotion.state & BUTTON_MASK ) INVOKE_WCB( *window, Motion, ( event.xmotion.x, event.xmotion.y ) ); else @@ -684,7 +726,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) int button; if( event.type == ButtonRelease ) - pressed = GL_FALSE; + pressed = GL_FALSE ; /* * A mouse button has been pressed or released. Traditionally, @@ -734,7 +776,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) 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 ) ) @@ -761,12 +803,19 @@ void FGAPIENTRY glutMainLoopEvent( void ) 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; } @@ -779,6 +828,9 @@ void FGAPIENTRY glutMainLoopEvent( void ) ( window->Menu[ button ] ) && pressed ) { + /* + * XXX Posting a requisite Redisplay seems bogus. + */ window->State.Redisplay = GL_TRUE; fgSetWindow( window ); fgActivateMenu( window, button ); @@ -793,15 +845,12 @@ void FGAPIENTRY glutMainLoopEvent( void ) ! FETCH_WCB( *window, MouseWheel ) ) break; - /* - * XXX Why don't we use {window}? Other code here does... - */ fgState.Modifiers = fgGetXModifiers( &event ); /* * 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, @@ -823,7 +872,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) * XXX Note that {button} has already been decremeted * XXX in mapping from X button numbering to GLUT. */ - int wheel_number = ( button - 3 ) / 2; + int wheel_number = (button - 3) / 2; int direction = -1; if( button % 2 ) direction = 1; @@ -942,7 +991,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) * Execute the callback (if one has been specified), * given that the special code seems to be valid... */ - if( special_cb && ( special != -1 ) ) + if( special_cb && (special != -1) ) { fgSetWindow( window ); fgState.Modifiers = fgGetXModifiers( &event ); @@ -958,7 +1007,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) break; /* XXX Should disable this event */ default: - fgWarning( "Unknown X event type: %d", event.type ); + fgWarning ("Unknown X event type: %d", event.type); break; } } @@ -970,14 +1019,23 @@ void FGAPIENTRY glutMainLoopEvent( void ) while( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) ) { if( GetMessage( &stMsg, NULL, 0, 0 ) == 0 ) + { + 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( ); @@ -991,7 +1049,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) void FGAPIENTRY glutMainLoop( void ) { #if TARGET_HOST_WIN32 - SFG_Window *window = (SFG_Window *)fgStructure.Windows.First; + SFG_Window *window = (SFG_Window *)fgStructure.Windows.First ; #endif freeglut_assert_ready; @@ -1008,24 +1066,35 @@ void FGAPIENTRY glutMainLoop( void ) */ while( window ) { - if( FETCH_WCB( *window, Visibility ) ) + if ( FETCH_WCB( *window, Visibility ) ) { - SFG_Window *current_window = fgStructure.Window; + SFG_Window *current_window = fgStructure.Window ; INVOKE_WCB( *window, Visibility, ( window->State.Visible ) ); fgSetWindow( current_window ); } - window = (SFG_Window *)window->Node.Next; + window = (SFG_Window *)window->Node.Next ; } #endif - fgState.ExecState = GLUT_EXEC_STATE_RUNNING; + 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 { @@ -1036,18 +1105,13 @@ void FGAPIENTRY glutMainLoop( void ) } } - { - 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( ); + if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT ) + exit( 0 ); } /* @@ -1055,7 +1119,7 @@ void FGAPIENTRY glutMainLoop( void ) */ void FGAPIENTRY glutLeaveMainLoop( void ) { - fgState.ExecState = GLUT_EXEC_STATE_STOP; + fgState.ExecState = GLUT_EXEC_STATE_STOP ; } @@ -1119,7 +1183,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, wglCreateContext( window->Window.Device ); } - /* window->Window.Context = wglGetCurrentContext( ); */ + /* window->Window.Context = wglGetCurrentContext (); */ window->Window.Context = wglCreateContext( window->Window.Device ); } else @@ -1139,6 +1203,9 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, } window->State.NeedToResize = GL_TRUE; + window->State.Width = fgState.Size.X; + window->State.Height = fgState.Size.Y; + ReleaseDC( window->Window.Handle, window->Window.Device ); break; @@ -1146,16 +1213,18 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* * We got resized... But check if the window has been already added... */ - fghReshapeWindowByHandle( hWnd, LOWORD(lParam), HIWORD(lParam) ); + window->State.NeedToResize = GL_TRUE; + window->State.Width = LOWORD(lParam); + window->State.Height = HIWORD(lParam); break; #if 0 case WM_SETFOCUS: - printf( "WM_SETFOCUS: %p\n", window ); + printf("WM_SETFOCUS: %p\n", window ); lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); break; case WM_ACTIVATE: - if( LOWORD( wParam ) != WA_INACTIVE ) + if (LOWORD(wParam) != WA_INACTIVE) { /* glutSetCursor( fgStructure.Window->State.Cursor ); */ printf("WM_ACTIVATE: glutSetCursor( %p, %d)\n", window, @@ -1167,34 +1236,26 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, break; #endif - case WM_SETCURSOR: /* - * Windows seems to need reminding to erase the cursor for NONE. - */ - - /* - * XXX Is this #if 0 section anything that we need to worry - * XXX about? Can we delete it? If it will ever be used, - * XXX why not re-use some common code with the glutSetCursor() + * XXX Why not re-use some common code with the glutSetCursor() * XXX function (or perhaps invoke glutSetCursor())? + * XXX That is, why are we duplicating code, here, from + * XXX glutSetCursor()? The WIN32 code should be able to just + * XXX call glutSetCurdsor() instead of defining two macros + * XXX and implementing a nested case in-line. */ -#if 0 - if( ( LOWORD( lParam ) == HTCLIENT ) && - ( fgStructure.Window->State.Cursor == GLUT_CURSOR_NONE ) ) - SetCursor( NULL ); -#else - + case WM_SETCURSOR: /* Set the cursor AND change it for this window class. */ -#define MAP_CURSOR(a,b) \ - case a: \ - SetCursor( LoadCursor( NULL, b ) ); \ - break; +#define MAP_CURSOR(a,b) \ + case a: \ + SetCursor( LoadCursor( NULL, b ) ); \ + break; /* Nuke the cursor AND change it for this window class. */ -#define ZAP_CURSOR(a,b) \ - case a: \ - SetCursor( NULL ); \ - break; +#define ZAP_CURSOR(a,b) \ + case a: \ + SetCursor( NULL ); \ + break; if( LOWORD( lParam ) == HTCLIENT ) switch( window->State.Cursor ) @@ -1215,7 +1276,6 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, default: MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_ARROW ); } -#endif else lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); break; @@ -1234,38 +1294,9 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, 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 == FALSE ) - 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: @@ -1314,38 +1345,46 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->State.MouseX = LOWORD( lParam ); window->State.MouseY = HIWORD( lParam ); - /* - * XXX Either these multi-statement lines should be broken - * XXX in the form: - * XXX pressed = GL_TRUE; - * XXX button = GLUT_LEFT_BUTTON; - * XXX break; - * XXX ...or we should use a macro (much as I dislike freeglut's - * XXX preponderance of using macros to "compress" code). - */ switch( uMsg ) { case WM_LBUTTONDOWN: - pressed = GL_TRUE; button = GLUT_LEFT_BUTTON; break; + pressed = GL_TRUE; + button = GLUT_LEFT_BUTTON; + break; case WM_MBUTTONDOWN: - pressed = GL_TRUE; button = GLUT_MIDDLE_BUTTON; break; + pressed = GL_TRUE; + button = GLUT_MIDDLE_BUTTON; + break; case WM_RBUTTONDOWN: - pressed = GL_TRUE; button = GLUT_RIGHT_BUTTON; break; + pressed = GL_TRUE; + button = GLUT_RIGHT_BUTTON; + break; case WM_LBUTTONUP: - pressed = GL_FALSE; button = GLUT_LEFT_BUTTON; break; + pressed = GL_FALSE; + button = GLUT_LEFT_BUTTON; + break; case WM_MBUTTONUP: - pressed = GL_FALSE; button = GLUT_MIDDLE_BUTTON; break; + pressed = GL_FALSE; + button = GLUT_MIDDLE_BUTTON; + break; case WM_RBUTTONUP: - pressed = GL_FALSE; button = GLUT_RIGHT_BUTTON; break; + pressed = GL_FALSE; + button = GLUT_RIGHT_BUTTON; + break; default: - pressed = GL_FALSE; button = -1; break; + pressed = GL_FALSE; + button = -1; + break; } - if( GetSystemMetrics( SM_SWAPBUTTON ) ) - if( button == GLUT_LEFT_BUTTON ) + if ( GetSystemMetrics( SM_SWAPBUTTON ) ) + { + if ( button == GLUT_LEFT_BUTTON ) button = GLUT_RIGHT_BUTTON; - else if( button == GLUT_RIGHT_BUTTON ) + else + if ( button == GLUT_RIGHT_BUTTON ) button = GLUT_LEFT_BUTTON; + } if( button == -1 ) return DefWindowProc( hWnd, uMsg, lParam, wParam ); @@ -1410,7 +1449,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, break; } - if ( window->Menu[ button ] && pressed ) + if( window->Menu[ button ] && pressed ) { window->State.Redisplay = GL_TRUE; fgSetWindow( window ); @@ -1500,13 +1539,13 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, fgState.Modifiers = 0xffffffff; } - break; + break ; case WM_SYSKEYDOWN: case WM_KEYDOWN: { int keypress = -1; - POINT mouse_pos; + POINT mouse_pos ; if( fgState.IgnoreKeyRepeat && (lParam & KF_REPEAT) ) break; @@ -1660,21 +1699,12 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, 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; @@ -1682,7 +1712,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* 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; /* @@ -1734,57 +1764,58 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, */ switch ( lParam ) { - case SC_SIZE: - break; + case SC_SIZE : + break ; - case SC_MOVE: - break; + case SC_MOVE : + break ; - case SC_MINIMIZE: + case SC_MINIMIZE : /* User has clicked on the "-" to minimize the window */ /* Turn off the visibility */ - window->State.Visible = GL_FALSE; - break; + window->State.Visible = GL_FALSE ; - case SC_MAXIMIZE: - break; + break ; - case SC_NEXTWINDOW: - break; + case SC_MAXIMIZE : + break ; - case SC_PREVWINDOW: - break; + case SC_NEXTWINDOW : + break ; - case SC_CLOSE: + case SC_PREVWINDOW : + break ; + + case SC_CLOSE : /* Followed very closely by a WM_CLOSE message */ - break; + break ; - case SC_VSCROLL: - break; + case SC_VSCROLL : + break ; - case SC_HSCROLL: - break; + case SC_HSCROLL : + break ; - case SC_MOUSEMENU: - break; + case SC_MOUSEMENU : + break ; - case SC_KEYMENU: - break; + case SC_KEYMENU : + break ; - case SC_ARRANGE: - break; + case SC_ARRANGE : + break ; - case SC_RESTORE: - break; + case SC_RESTORE : + break ; - case SC_TASKLIST: - break; + case SC_TASKLIST : + break ; - case SC_SCREENSAVE: - break; + case SC_SCREENSAVE : + break ; - case SC_HOTKEY: - break; + case SC_HOTKEY : + break ; } }