All changes are from John, except for:
(a) I re-inserted the meat of a comment that I still feel is relavent. (b) I fixed a compile-time error in the UNIX_X11 code where a variable is declared after executable code in a block without creating a new sub-block for the declaration. Changes from John include: (a) Style revision. (b) Changes to postpone the handling of window resizes. Lots of lines were changed, but I think that thos two cover the ground that he hit. See the diffs for details. git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@360 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
parent
1c7454b49d
commit
7e7ff3191d
@ -219,7 +219,7 @@ struct tagSFG_State
|
||||
SFG_XYUse Size; /* The default windows' size */
|
||||
unsigned int DisplayMode; /* Display mode for new windows */
|
||||
|
||||
GLboolean Initialised; /* Freeglut has been initialised */
|
||||
GLboolean Initialised; /* freeglut has been initialised */
|
||||
|
||||
GLboolean ForceDirectContext; /* Force direct rendering? */
|
||||
GLboolean TryDirectContext; /* What about giving a try to? */
|
||||
@ -352,9 +352,7 @@ struct tagSFG_WindowState
|
||||
|
||||
GLboolean IsGameMode; /* Is this the game mode window? */
|
||||
|
||||
#if TARGET_HOST_WIN32
|
||||
GLboolean NeedToResize; /* Do we need to explicitly resize? */
|
||||
#endif
|
||||
GLboolean NeedToResize; /* Do we need to resize the window? */
|
||||
};
|
||||
|
||||
|
||||
|
@ -65,8 +65,9 @@
|
||||
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Calls a window's redraw method. This is used when
|
||||
* a redraw is forced by the incoming window messages.
|
||||
* Handle a window configuration change. When no reshape
|
||||
* callback is hooked, the viewport size is updated to
|
||||
* match the new window size.
|
||||
*
|
||||
* XXX We can/should make a "unified" window handle type so that
|
||||
* XXX the function headers don't need this silly #ifdef junk.
|
||||
@ -74,6 +75,106 @@
|
||||
* XXX {Window}. On WIN32, it is {HWND}. Then do the #ifdef
|
||||
* XXX junk *once* in "freeglut_internal.h".
|
||||
*/
|
||||
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
|
||||
{
|
||||
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 */
|
||||
/*
|
||||
* XXX REALLY shouldn't be done. GLUT docs state that this
|
||||
* XXX isn't even processed immediately, but rather waits
|
||||
* XXX for return to the mainloop. "This allows multiple
|
||||
* XXX glutReshapeWindow, glutPositionWindow, and glutFullScreen
|
||||
* XXX requests to the same window to be coalesced." (This is
|
||||
* XXX having some deleterious effect on a sample program of mine.)
|
||||
* XXX Not only does GLUT not flush at this point, GLUT doesn't even
|
||||
* XXX *do* the reshape at this point! We should probably rip this
|
||||
* XXX out and do what GLUT promises. It would be more efficient, and
|
||||
* XXX might be more compatible.
|
||||
*/
|
||||
|
||||
#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 );
|
||||
glViewport( 0, 0, width, height );
|
||||
}
|
||||
else
|
||||
INVOKE_WCB( *window, Reshape, ( width, height ) );
|
||||
|
||||
/*
|
||||
* Force a window redraw. In Windows at least this is only a partial
|
||||
* solution: if the window is increasing in size in either dimension,
|
||||
* the already-drawn part does not get drawn again and things look funny.
|
||||
* But without this we get this bad behaviour whenever we resize the
|
||||
* window.
|
||||
*/
|
||||
window->State.Redisplay = GL_TRUE;
|
||||
|
||||
if( window->IsMenu )
|
||||
fgSetWindow( current_window );
|
||||
}
|
||||
|
||||
/*
|
||||
* Calls a window's redraw method. This is used when
|
||||
* a redraw is forced by the incoming window messages.
|
||||
*/
|
||||
static void fghRedrawWindowByHandle
|
||||
#if TARGET_HOST_UNIX_X11
|
||||
( Window handle )
|
||||
@ -103,54 +204,32 @@ static void fghRedrawWindowByHandle
|
||||
freeglut_return_if_fail( FETCH_WCB( *window, Display ) );
|
||||
freeglut_return_if_fail( window->State.Visible );
|
||||
|
||||
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;
|
||||
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
|
||||
{
|
||||
SFG_Window *current_window = fgStructure.Window;
|
||||
|
||||
SFG_Window* window = fgWindowByHandle( handle );
|
||||
freeglut_return_if_fail( window != NULL );
|
||||
|
||||
if( !( FETCH_WCB( *window, Reshape ) ) )
|
||||
{
|
||||
fgSetWindow( window );
|
||||
glViewport( 0, 0, width, height );
|
||||
}
|
||||
else
|
||||
INVOKE_WCB( *window, Reshape, ( width, height ) );
|
||||
|
||||
/*
|
||||
* Force a window redraw. In Windows at least this is only a partial
|
||||
* solution: if the window is increasing in size in either dimension,
|
||||
* the already-drawn part does not get drawn again and things look funny.
|
||||
* But without this we get this bad behaviour whenever we resize the
|
||||
* window.
|
||||
*/
|
||||
window->State.Redisplay = GL_TRUE;
|
||||
|
||||
if( window->IsMenu )
|
||||
fgSetWindow( current_window );
|
||||
}
|
||||
|
||||
/*
|
||||
* A static helper function to execute display callback for a window
|
||||
*/
|
||||
static void fghcbDisplayWindow( SFG_Window *window, SFG_Enumerator *enumerator )
|
||||
static void fghcbDisplayWindow( SFG_Window *window,
|
||||
SFG_Enumerator *enumerator )
|
||||
{
|
||||
#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
|
||||
@ -164,15 +243,6 @@ static void fghcbDisplayWindow( SFG_Window *window, SFG_Enumerator *enumerator )
|
||||
window->State.Redisplay &&
|
||||
window->State.Visible )
|
||||
{
|
||||
SFG_Window *current_window = fgStructure.Window;
|
||||
|
||||
window->State.Redisplay = GL_FALSE;
|
||||
INVOKE_WCB( *window, Display, ( ) );
|
||||
fgSetWindow( current_window );
|
||||
}
|
||||
|
||||
#elif TARGET_HOST_WIN32
|
||||
|
||||
if( window->State.NeedToResize )
|
||||
{
|
||||
SFG_Window *current_window = fgStructure.Window;
|
||||
@ -181,30 +251,30 @@ 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 &&
|
||||
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 );
|
||||
}
|
||||
@ -555,11 +625,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:
|
||||
@ -1143,6 +1212,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;
|
||||
|
||||
@ -1150,7 +1222,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:
|
||||
@ -1171,23 +1245,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 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: \
|
||||
@ -1219,7 +1285,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;
|
||||
@ -1318,31 +1383,36 @@ 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 ) )
|
||||
@ -1748,6 +1818,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
||||
/* User has clicked on the "-" to minimize the window */
|
||||
/* Turn off the visibility */
|
||||
window->State.Visible = GL_FALSE ;
|
||||
|
||||
break ;
|
||||
|
||||
case SC_MAXIMIZE :
|
||||
|
@ -793,68 +793,9 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
|
||||
freeglut_assert_ready;
|
||||
freeglut_assert_window;
|
||||
|
||||
#if TARGET_HOST_UNIX_X11
|
||||
|
||||
XResizeWindow( fgDisplay.Display, fgStructure.Window->Window.Handle,
|
||||
width, height );
|
||||
XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
|
||||
/*
|
||||
* XXX REALLY shouldn't be done. GLUT docs state that this
|
||||
* XXX isn't even processed immediately, but rather waits
|
||||
* XXX for return to the mainloop. "This allows multiple
|
||||
* XXX glutReshapeWindow, glutPositionWindow, and glutFullScreen
|
||||
* XXX requests to the same window to be coalesced." (This is
|
||||
* XXX having some deleterious effect on a sample program of mine.)
|
||||
* XXX Not only does GLUT not flush at this point, GLUT doesn't even
|
||||
* XXX *do* the reshape at this point! We should probably rip this
|
||||
* XXX out and do what GLUT promises. It would be more efficient, and
|
||||
* XXX might be more compatible.
|
||||
*/
|
||||
|
||||
#elif TARGET_HOST_WIN32
|
||||
|
||||
{
|
||||
RECT winRect;
|
||||
int x, y;
|
||||
|
||||
GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
|
||||
x = winRect.left;
|
||||
y = winRect.top;
|
||||
|
||||
if ( fgStructure.Window->Parent == NULL )
|
||||
{
|
||||
/*
|
||||
* Adjust the size of the window to allow for the size of the
|
||||
* frame, if we are not a menu
|
||||
*/
|
||||
if ( ! fgStructure.Window->IsMenu )
|
||||
{
|
||||
width += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
|
||||
height += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 +
|
||||
GetSystemMetrics( SM_CYCAPTION );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetWindowRect( fgStructure.Window->Parent->Window.Handle,
|
||||
&winRect );
|
||||
x -= winRect.left + GetSystemMetrics( SM_CXSIZEFRAME );
|
||||
y -= winRect.top + GetSystemMetrics( SM_CYSIZEFRAME ) +
|
||||
GetSystemMetrics( SM_CYCAPTION );
|
||||
}
|
||||
|
||||
MoveWindow(
|
||||
fgStructure.Window->Window.Handle,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
TRUE
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
fgStructure.Window->State.NeedToResize = GL_TRUE;
|
||||
fgStructure.Window->State.Width = width ;
|
||||
fgStructure.Window->State.Height = height;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user