X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_main.c;h=55e033a2788c0ede42f15819854a7915975e282c;hb=fffd18193541999b2b5c00905dea0f1effa0ec07;hp=823087b0129be3537273cbf2075a770c2d1bc2ce;hpb=71f0bb28f82cf739594f4e74fdf128fed11acf6a;p=freeglut diff --git a/src/freeglut_main.c b/src/freeglut_main.c index 823087b..55e033a 100644 --- a/src/freeglut_main.c +++ b/src/freeglut_main.c @@ -65,65 +65,69 @@ /* -- 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 == TRUE ); - - window->State.Redisplay = 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 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 winRect; + int x, y; + + GetWindowRect( window->Window.Handle, &winRect ); + x = winRect.left; + y = winRect.top; + + if ( window->Parent == NULL ) + { + /* + * Adjust the size of the window to allow for the size of the + * frame, if we are not a menu + */ + if ( ! window->IsMenu ) + { + width += GetSystemMetrics( SM_CXSIZEFRAME ) * 2; + height += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + + GetSystemMetrics( SM_CYCAPTION ); + } + } + else + { + GetWindowRect( window->Parent->Window.Handle, + &winRect ); + x -= winRect.left + GetSystemMetrics( SM_CXSIZEFRAME ); + y -= winRect.top + GetSystemMetrics( SM_CYSIZEFRAME ) + + GetSystemMetrics( SM_CYCAPTION ); + } + + MoveWindow( + window->Window.Handle, + x, + y, + width, + height, + TRUE + ); + } + +#endif + if( !( FETCH_WCB( *window, Reshape ) ) ) { fgSetWindow( window ); @@ -139,39 +143,25 @@ static void fghReshapeWindowByHandle * But without this we get this bad behaviour whenever we resize the * window. */ - window->State.Redisplay = TRUE; + window->State.Redisplay = GL_TRUE; if( window->IsMenu ) fgSetWindow( current_window ); } /* - * 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 == TRUE ) && - ( window->State.Visible == TRUE ) ) - { - 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 = 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 +171,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 = FALSE; + window->State.NeedToResize = GL_FALSE; fgSetWindow ( current_window ); } - /* - * XXX See above comment about the Redisplay flag... - */ - if( ( FETCH_WCB( *window, Display ) ) && - ( window->State.Redisplay == TRUE ) && - ( window->State.Visible == TRUE ) ) + 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.Redisplay && + window->State.Visible ) { - window->State.Redisplay = FALSE; + 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 ); + } + + 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 ); } @@ -216,7 +234,7 @@ static void fghDisplayAll( void ) { SFG_Enumerator enumerator; - enumerator.found = FALSE; + enumerator.found = GL_FALSE; enumerator.data = NULL; fgEnumWindows( fghcbDisplayWindow, &enumerator ); @@ -247,7 +265,7 @@ static void fghCheckJoystickPolls( void ) { SFG_Enumerator enumerator; - enumerator.found = FALSE; + enumerator.found = GL_FALSE; enumerator.data = NULL; fgEnumWindows( fghcbCheckJoystickPolls, &enumerator ); @@ -259,56 +277,52 @@ static void fghCheckJoystickPolls( void ) 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 */ long fgElapsedTime( void ) { + 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; - - return elapsed; + 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; + return timeGetTime() - fgState.Time.Value; #endif + } + else + { +#if TARGET_HOST_UNIX_X11 + gettimeofday( &fgState.Time.Value, NULL ); +#elif TARGET_HOST_WIN32 + fgState.Time.Value = timeGetTime (); +#endif + fgState.Time.Set = GL_TRUE ; + + return 0 ; + } } /* @@ -328,6 +342,9 @@ void fgError( const char *fmt, ... ) va_end( ap ); + if ( fgState.Initialised ) + fgDeinitialize (); + exit( 1 ); } @@ -370,7 +387,7 @@ static void fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e) { if( FETCH_WCB( *w, Joystick ) ) { - e->found = TRUE; + e->found = GL_TRUE; e->data = w; } fgEnumSubWindows( w, fgCheckJoystickCallback, e ); @@ -378,7 +395,7 @@ static void fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e) static int fgHaveJoystick( void ) { SFG_Enumerator enumerator; - enumerator.found = FALSE; + enumerator.found = GL_FALSE; enumerator.data = NULL; fgEnumWindows( fgCheckJoystickCallback, &enumerator ); return !!enumerator.data; @@ -387,7 +404,7 @@ static void fgHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e) { if( w->State.Redisplay ) { - e->found = TRUE; + e->found = GL_TRUE; e->data = w; } fgEnumSubWindows( w, fgHavePendingRedisplaysCallback, e ); @@ -395,31 +412,21 @@ static void fgHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e) static int fgHavePendingRedisplays (void) { SFG_Enumerator enumerator; - enumerator.found = FALSE; + enumerator.found = GL_FALSE; enumerator.data = NULL; fgEnumWindows( fgHavePendingRedisplaysCallback, &enumerator ); 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; - 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; } @@ -451,7 +458,7 @@ static void fgSleepForEvents( void ) err = select( socket+1, &fdset, NULL, NULL, &wait ); if( -1 == err ) - printf( "freeglut select() error: %d\n", errno ); + fgWarning ( "freeglut select() error: %d\n", errno ); #elif TARGET_HOST_WIN32 #endif @@ -516,8 +523,16 @@ void FGAPIENTRY glutMainLoopEvent( void ) { GETWINDOW( xclient ); - fgCloseWindow ( window ) ; - fgAddToWindowDestroyList ( window, FALSE ); + fgDestroyWindow ( window ); + + if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT ) + { + fgDeinitialize( ); + exit( 0 ); + } + + fgState.ExecState = GLUT_EXEC_STATE_STOP; + return; } break; @@ -536,11 +551,10 @@ void FGAPIENTRY glutMainLoopEvent( void ) */ case CreateNotify: case ConfigureNotify: - fghReshapeWindowByHandle( - event.xconfigure.window, - event.xconfigure.width, - event.xconfigure.height - ); + GETWINDOW( xconfigure ); + window->State.NeedToResize = GL_TRUE ; + window->State.Width = event.xconfigure.width ; + window->State.Height = event.xconfigure.height; break; case DestroyNotify: @@ -548,7 +562,7 @@ 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, FALSE ); */ + /* fgAddToWindowDestroyList ( window ); */ break; case Expose: @@ -596,18 +610,18 @@ void FGAPIENTRY glutMainLoopEvent( void ) { case VisibilityUnobscured: INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) ); - window->State.Visible = TRUE; + window->State.Visible = GL_TRUE; break; case VisibilityPartiallyObscured: INVOKE_WCB( *window, WindowStatus, ( GLUT_PARTIALLY_RETAINED ) ); - window->State.Visible = TRUE; + window->State.Visible = GL_TRUE; break; case VisibilityFullyObscured: INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_COVERED ) ); - window->State.Visible = FALSE; + window->State.Visible = GL_FALSE; break; default: @@ -641,8 +655,8 @@ void FGAPIENTRY glutMainLoopEvent( void ) window->ActiveMenu->Window->State.MouseY = event.xmotion.y_root - window->ActiveMenu->Y; } - window->ActiveMenu->Window->State.Redisplay = TRUE ; - fgSetWindow( window->ActiveMenu->ParentWindow ) ; + window->ActiveMenu->Window->State.Redisplay = GL_TRUE ; + fgSetWindow( window->ActiveMenu->ParentWindow ); break; } @@ -651,11 +665,9 @@ void FGAPIENTRY glutMainLoopEvent( void ) * XXX For more than 5 buttons, just check {event.xmotion.state}, * XXX rather than a host of bit-masks? */ - if( (event.xmotion.state & Button1Mask) || - (event.xmotion.state & Button2Mask) || - (event.xmotion.state & Button3Mask) || - (event.xmotion.state & Button4Mask) || - (event.xmotion.state & Button5Mask) ) +#define BUTTON_MASK \ + ( Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) + if ( event.xmotion.state & BUTTON_MASK ) INVOKE_WCB( *window, Motion, ( event.xmotion.x, event.xmotion.y ) ); else @@ -667,11 +679,11 @@ void FGAPIENTRY glutMainLoopEvent( void ) case ButtonRelease: case ButtonPress: { - GLboolean pressed = TRUE; + GLboolean pressed = GL_TRUE; int button; if( event.type == ButtonRelease ) - pressed = FALSE ; + pressed = GL_FALSE ; /* * A mouse button has been pressed or released. Traditionally, @@ -724,7 +736,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) /* In the menu, invoke the callback and deactivate the menu*/ if( fgCheckActiveMenu( window->ActiveMenu->Window, - window->ActiveMenu ) == TRUE ) + window->ActiveMenu ) ) { /* * Save the current window and menu and set the current @@ -754,7 +766,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) */ fgDeactivateMenu( window->ActiveMenu->ParentWindow ); - window->State.Redisplay = TRUE; + window->State.Redisplay = GL_TRUE; break; } @@ -762,11 +774,11 @@ void FGAPIENTRY glutMainLoopEvent( void ) * No active menu, let's check whether we need to activate one. */ if( ( 0 <= button ) && - ( 2 >= button ) && + ( FREEGLUT_MAX_MENUS > button ) && ( window->Menu[ button ] ) && pressed ) { - window->State.Redisplay = TRUE; + window->State.Redisplay = GL_TRUE; fgSetWindow( window ); fgActivateMenu( window, button ); break; @@ -780,10 +792,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) ! FETCH_WCB( *window, MouseWheel ) ) break; - /* - * XXX Why don't we use {window}? Other code here does... - */ - fgStructure.Window->State.Modifiers = fgGetXModifiers( &event ); + fgState.Modifiers = fgGetXModifiers( &event ); /* * Finally execute the mouse or mouse wheel callback @@ -826,7 +835,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) /* * Trash the modifiers state */ - fgStructure.Window->State.Modifiers = 0xffffffff; + fgState.Modifiers = 0xffffffff; } break; @@ -864,7 +873,8 @@ void FGAPIENTRY glutMainLoopEvent( void ) * Check for the ASCII/KeySym codes associated with the event: */ len = XLookupString( &event.xkey, asciiCode, sizeof(asciiCode), - &keySym, &composeStatus ); + &keySym, &composeStatus + ); /* * GLUT API tells us to have two separate callbacks... @@ -877,10 +887,11 @@ void FGAPIENTRY glutMainLoopEvent( void ) if( keyboard_cb ) { fgSetWindow( window ); - window->State.Modifiers = fgGetXModifiers( &event ); + fgState.Modifiers = fgGetXModifiers( &event ); keyboard_cb( asciiCode[ 0 ], - event.xkey.x, event.xkey.y ); - window->State.Modifiers = 0xffffffff; + event.xkey.x, event.xkey.y + ); + fgState.Modifiers = 0xffffffff; } } else @@ -930,9 +941,9 @@ void FGAPIENTRY glutMainLoopEvent( void ) if( special_cb && (special != -1) ) { fgSetWindow( window ); - window->State.Modifiers = fgGetXModifiers( &event ); + fgState.Modifiers = fgGetXModifiers( &event ); special_cb( special, event.xkey.x, event.xkey.y ); - window->State.Modifiers = 0xffffffff; + fgState.Modifiers = 0xffffffff; } } } @@ -955,14 +966,23 @@ void FGAPIENTRY glutMainLoopEvent( void ) 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( ); @@ -1021,18 +1041,11 @@ 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( ); } /* @@ -1070,7 +1083,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, 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 ); */ @@ -1085,16 +1098,17 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->Window.Handle = hWnd; window->Window.Device = GetDC( hWnd ); - if( fgState.BuildingAMenu ) + if( window->IsMenu ) { unsigned int current_DisplayMode = fgState.DisplayMode; fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH; - fgSetupPixelFormat( window, FALSE, PFD_MAIN_PLANE ); + fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE ); fgState.DisplayMode = current_DisplayMode; if( fgStructure.MenuContext ) wglMakeCurrent( window->Window.Device, - fgStructure.MenuContext->Context ) ; + fgStructure.MenuContext->Context + ); else { fgStructure.MenuContext = @@ -1103,14 +1117,14 @@ 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 { - fgSetupPixelFormat( window, FALSE, PFD_MAIN_PLANE ); + fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE ); - if( fgState.UseCurrentContext != TRUE ) + if( ! fgState.UseCurrentContext ) window->Window.Context = wglCreateContext( window->Window.Device ); else @@ -1122,7 +1136,10 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, } } - window->State.NeedToResize = TRUE; + 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; @@ -1130,7 +1147,9 @@ 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: @@ -1151,16 +1170,15 @@ 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 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: \ @@ -1192,14 +1210,13 @@ 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; case WM_SHOWWINDOW: - window->State.Visible = TRUE; - window->State.Redisplay = TRUE; + window->State.Visible = GL_TRUE; + window->State.Redisplay = GL_TRUE; break; case WM_PAINT: @@ -1211,38 +1228,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, FALSE ); - DestroyWindow( hWnd ); + fgDestroyWindow ( window ); + if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION ) + PostQuitMessage(0); break; case WM_DESTROY: @@ -1258,12 +1246,12 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, if ( window->ActiveMenu ) { - window->State.Redisplay = TRUE; + window->State.Redisplay = GL_TRUE; fgSetWindow ( window->ActiveMenu->ParentWindow ); break; } - window->State.Modifiers = fgGetWin32Modifiers( ); + fgState.Modifiers = fgGetWin32Modifiers( ); if( ( wParam & MK_LBUTTON ) || ( wParam & MK_MBUTTON ) || @@ -1274,7 +1262,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, INVOKE_WCB( *window, Passive, ( window->State.MouseX, window->State.MouseY ) ); - window->State.Modifiers = 0xffffffff; + fgState.Modifiers = 0xffffffff; } break; @@ -1285,7 +1273,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, case WM_MBUTTONUP: case WM_RBUTTONUP: { - GLboolean pressed = TRUE; + GLboolean pressed = GL_TRUE; int button; window->State.MouseX = LOWORD( lParam ); @@ -1294,19 +1282,33 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, switch( uMsg ) { case WM_LBUTTONDOWN: - pressed = TRUE; button = GLUT_LEFT_BUTTON; break; + pressed = GL_TRUE; + button = GLUT_LEFT_BUTTON; + break; case WM_MBUTTONDOWN: - pressed = TRUE; button = GLUT_MIDDLE_BUTTON; break; + pressed = GL_TRUE; + button = GLUT_MIDDLE_BUTTON; + break; case WM_RBUTTONDOWN: - pressed = TRUE; button = GLUT_RIGHT_BUTTON; break; + pressed = GL_TRUE; + button = GLUT_RIGHT_BUTTON; + break; case WM_LBUTTONUP: - pressed = FALSE; button = GLUT_LEFT_BUTTON; break; + pressed = GL_FALSE; + button = GLUT_LEFT_BUTTON; + break; case WM_MBUTTONUP: - pressed = FALSE; button = GLUT_MIDDLE_BUTTON; break; + pressed = GL_FALSE; + button = GLUT_MIDDLE_BUTTON; + break; case WM_RBUTTONUP: - pressed = FALSE; button = GLUT_RIGHT_BUTTON; break; + pressed = GL_FALSE; + button = GLUT_RIGHT_BUTTON; + break; default: - pressed = FALSE; button = -1; break; + pressed = GL_FALSE; + button = -1; + break; } if( GetSystemMetrics( SM_SWAPBUTTON ) ) @@ -1319,6 +1321,9 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, return DefWindowProc( hWnd, uMsg, lParam, wParam ); /* + * XXX This comment is duplicated in two other spots. + * XXX Can we centralize it? + * * Do not execute the application's mouse callback if a * menu is hooked to this button. * In that case an appropriate private call should be generated. @@ -1338,8 +1343,13 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* Window has an active menu, it absorbs any mouse click */ if( window->ActiveMenu ) { - /* Inside the menu, invoke the callback and deactivate the menu*/ - if( fgCheckActiveMenu( window, window->ActiveMenu ) == TRUE ) + /* Outside the menu, deactivate the menu if it's a downclick */ + if( ! fgCheckActiveMenu( window, window->ActiveMenu ) ) + { + if( pressed ) + fgDeactivateMenu( window->ActiveMenu->ParentWindow ); + } + else /* In menu, invoke the callback and deactivate the menu*/ { /* * Save the current window and menu and set the current @@ -1359,25 +1369,20 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, fgSetWindow( save_window ); fgStructure.Menu = save_menu; } - else /* Out of menu, deactivate the menu if it's a downclick */ - { - if( pressed == TRUE ) - fgDeactivateMenu( window->ActiveMenu->ParentWindow ); - } /* * Let's make the window redraw as a result of the mouse * click and menu activity. */ if( ! window->IsMenu ) - window->State.Redisplay = TRUE; + window->State.Redisplay = GL_TRUE; break; } - if ( ( window->Menu[ button ] ) && ( pressed == TRUE ) ) + if ( window->Menu[ button ] && pressed ) { - window->State.Redisplay = TRUE; + window->State.Redisplay = GL_TRUE; fgSetWindow( window ); fgActivateMenu( window, button ); @@ -1388,28 +1393,30 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, break; fgSetWindow( window ); - fgStructure.Window->State.Modifiers = fgGetWin32Modifiers( ); + fgState.Modifiers = fgGetWin32Modifiers( ); INVOKE_WCB( *window, Mouse, ( button, - pressed == TRUE ? GLUT_DOWN : GLUT_UP, + pressed ? GLUT_DOWN : GLUT_UP, window->State.MouseX, window->State.MouseY ) ); - fgStructure.Window->State.Modifiers = 0xffffffff; + fgState.Modifiers = 0xffffffff; } break; case 0x020a: /* Should be WM_MOUSEWHEEL but my compiler doesn't recognize it */ { + /* + * XXX THIS IS SPECULATIVE -- John Fay, 10/2/03 + * XXX Should use WHEEL_DELTA instead of 120 + */ int wheel_number = LOWORD( wParam ); - /* THIS IS SPECULATIVE -- John Fay, 10/2/03 */ short ticks = ( short )HIWORD( wParam ) / 120; - /* Should be WHEEL_DELTA instead of 120 */ int direction = 1; if( ticks < 0 ) @@ -1431,7 +1438,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, break; fgSetWindow( window ); - fgStructure.Window->State.Modifiers = fgGetWin32Modifiers( ); + fgState.Modifiers = fgGetWin32Modifiers( ); while( ticks-- ) if( FETCH_WCB( *window, MouseWheel ) ) @@ -1461,7 +1468,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, ); } - fgStructure.Window->State.Modifiers = 0xffffffff; + fgState.Modifiers = 0xffffffff; } break ; @@ -1478,7 +1485,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, * Remember the current modifiers state. This is done here in order * to make sure the VK_DELETE keyboard callback is executed properly. */ - window->State.Modifiers = fgGetWin32Modifiers( ); + fgState.Modifiers = fgGetWin32Modifiers( ); GetCursorPos( &mouse_pos ); ScreenToClient( window->Window.Handle, &mouse_pos ); @@ -1530,7 +1537,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->State.MouseX, window->State.MouseY ) ); - window->State.Modifiers = 0xffffffff; + fgState.Modifiers = 0xffffffff; } break; @@ -1544,7 +1551,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, * Remember the current modifiers state. This is done here in order * to make sure the VK_DELETE keyboard callback is executed properly. */ - window->State.Modifiers = fgGetWin32Modifiers( ); + fgState.Modifiers = fgGetWin32Modifiers( ); GetCursorPos( &mouse_pos ); ScreenToClient( window->Window.Handle, &mouse_pos ); @@ -1613,7 +1620,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->State.MouseX, window->State.MouseY ) ); - window->State.Modifiers = 0xffffffff; + fgState.Modifiers = 0xffffffff; } break; @@ -1623,21 +1630,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 ) ) - { - window->State.Modifiers = fgGetWin32Modifiers( ); - INVOKE_WCB( *window, Keyboard, - ( (char)wParam, - window->State.MouseX, window->State.MouseY ) - ); - window->State.Modifiers = 0xffffffff; - } + fgState.Modifiers = fgGetWin32Modifiers( ); + INVOKE_WCB( *window, Keyboard, + ( (char)wParam, + window->State.MouseX, window->State.MouseY ) + ); + fgState.Modifiers = 0xffffffff; } break; @@ -1645,7 +1643,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; /* @@ -1676,7 +1674,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, case WM_SYNCPAINT: /* 0x0088 */ /* Another window has moved, need to update this one */ - window->State.Redisplay = TRUE; + window->State.Redisplay = GL_TRUE; lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); /* Help screen says this message must be passed to "DefWindowProc" */ break;