X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_main.c;h=b42f9a05a362bd42d6d6f88262395717f9965570;hb=1c4676845beb10386f4f58320b05b000efc47ae1;hp=144453db842c801e12b7082a356c0a7c3e214bba;hpb=5efc7f1ec295474817dd1ed99c04180f8f19c8d9;p=freeglut diff --git a/src/freeglut_main.c b/src/freeglut_main.c index 144453d..b42f9a0 100644 --- a/src/freeglut_main.c +++ b/src/freeglut_main.c @@ -87,45 +87,56 @@ static void fghReshapeWindowByHandle ( SFG_WindowHandleType handle, #elif TARGET_HOST_WIN32 { - RECT winRect; - int x, y; + RECT rect; - GetWindowRect( window->Window.Handle, &winRect ); - x = winRect.left; - y = winRect.top; + /* + * 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 ) { - /* - * Adjust the size of the window to allow for the size of the - * frame, if we are not a menu - */ - if ( ! window->IsMenu ) + if ( ! window->IsMenu && !window->State.IsGameMode ) { - width += GetSystemMetrics( SM_CXSIZEFRAME ) * 2; - height += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + - GetSystemMetrics( SM_CYCAPTION ); + rect.right += GetSystemMetrics( SM_CXSIZEFRAME ) * 2; + rect.bottom += 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 ); + GetWindowRect( window->Parent->Window.Handle, &rect ); + AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | + WS_CLIPCHILDREN, FALSE ); } - MoveWindow( - window->Window.Handle, - x, - y, - width, - height, - TRUE + /* + * 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 @@ -559,12 +570,15 @@ 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: @@ -573,13 +587,19 @@ void FGAPIENTRY glutMainLoopEvent( void ) int width = event.xconfigure.width; int height = event.xconfigure.height; - GETWINDOW( xconfigure ); - if( FETCH_WCB( *window, Reshape ) ) - INVOKE_WCB( *window, Reshape, ( width, height ) ); - else + if( ( width != window->State.OldWidth ) || + ( height != window->State.OldHeight ) ) { - fgSetWindow( window ); - glViewport( 0, 0, width, height ); + 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; @@ -595,10 +615,15 @@ void FGAPIENTRY glutMainLoopEvent( void ) 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 ); @@ -623,6 +648,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 ); @@ -690,7 +718,9 @@ 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 ) @@ -760,7 +790,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 ) ) @@ -787,12 +817,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; } @@ -805,6 +842,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 ); @@ -824,7 +864,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) /* * 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, @@ -1055,16 +1095,27 @@ void FGAPIENTRY glutMainLoop( void ) 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( ); } } @@ -1073,6 +1124,8 @@ void FGAPIENTRY glutMainLoop( void ) * of a freeglut session, so that another glutInit() call can happen */ fgDeinitialize( ); + if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT ) + exit( 0 ); } /* @@ -1407,7 +1460,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 );