Many updates from John Fay.

git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@31 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
dheyse 2002-11-28 23:26:17 +00:00
parent c00890a4b5
commit 5e1ec95e4c
14 changed files with 2685 additions and 1783 deletions

View File

@ -182,8 +182,8 @@ void FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int
fgStructure.Window->State.JoystickLastPoll = fgStructure.Window->State.JoystickLastPoll =
fgElapsedTime() - fgStructure.Window->State.JoystickPollRate; fgElapsedTime() - fgStructure.Window->State.JoystickPollRate;
if( fgStructure.Window->State.JoystickLastPoll < 0.0 ) if( fgStructure.Window->State.JoystickLastPoll < 0 )
fgStructure.Window->State.JoystickLastPoll = 0.0; fgStructure.Window->State.JoystickLastPoll = 0;
} }
/* /*
@ -218,6 +218,19 @@ void FGAPIENTRY glutEntryFunc( void (* callback)( int ) )
SET_CALLBACK( Entry ); SET_CALLBACK( Entry );
} }
/*
* Window destruction callbacks
*/
void FGAPIENTRY glutCloseFunc( void (* callback)( void ) )
{
SET_CALLBACK( Destroy );
}
void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) )
{
glutCloseFunc( callback );
}
/* /*
* Deprecated version of glutMenuStatusFunc callback setting method * Deprecated version of glutMenuStatusFunc callback setting method
*/ */

View File

@ -43,7 +43,6 @@
* *
* fgDisplayCursor() -- this waits for better times * fgDisplayCursor() -- this waits for better times
* glutSetCursor() -- both X and Win32 mappings are incomplete * glutSetCursor() -- both X and Win32 mappings are incomplete
* glutWarpPointer() -- check the Win32 version
* *
* It would be good to use custom mouse cursor shapes, and introduce * It would be good to use custom mouse cursor shapes, and introduce
* an option to display them using glBitmap() and/or texture mapping, * an option to display them using glBitmap() and/or texture mapping,
@ -112,7 +111,14 @@ void FGAPIENTRY glutSetCursor( int cursorID )
/* /*
* This is a temporary solution only... * This is a temporary solution only...
*/ */
# define MAP_CURSOR(a,b) case a: SetCursor( LoadCursor( NULL, b ) ); break; // Set the cursor AND change it for this window class.
# define MAP_CURSOR(a,b) case a: SetCursor( LoadCursor( NULL, b ) ); \
SetClassLong(fgStructure.Window->Window.Handle,GCL_HCURSOR,(LONG)LoadCursor(NULL,b)); \
break;
// Nuke the cursor AND change it for this window class.
# define ZAP_CURSOR(a,b) case a: SetCursor( NULL ); \
SetClassLong(fgStructure.Window->Window.Handle,GCL_HCURSOR,(LONG)NULL); \
break;
switch( cursorID ) switch( cursorID )
{ {
@ -126,10 +132,11 @@ void FGAPIENTRY glutSetCursor( int cursorID )
MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT ); MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT );
MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_UPARROW ); MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_UPARROW );
MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS ); MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS );
MAP_CURSOR( GLUT_CURSOR_NONE, IDC_NO ); //MAP_CURSOR( GLUT_CURSOR_NONE, IDC_NO );
ZAP_CURSOR( GLUT_CURSOR_NONE, NULL );
default: default:
MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_UPARROW ); MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_ARROW );
} }
#endif #endif

View File

@ -37,8 +37,7 @@
/* /*
* TODO BEFORE THE STABLE RELEASE: * TODO BEFORE THE STABLE RELEASE:
* *
* glutStrokeCharacter() -- stroke fonts not implemented, uses a bitmap font instead * Test things out ...
* glutStrokeWidth() -- stroke fonts not implemented, uses a bitmap font instead
*/ */
/* -- IMPORT DECLARATIONS -------------------------------------------------- */ /* -- IMPORT DECLARATIONS -------------------------------------------------- */
@ -164,8 +163,8 @@ void FGAPIENTRY glutBitmapCharacter( void* fontID, int character )
*/ */
glBitmap( glBitmap(
face[ 0 ], font->Height, /* The bitmap's width and height */ face[ 0 ], font->Height, /* The bitmap's width and height */
0, 0, /* The origin -- what the hell? */ font->xorig, font->yorig, /* The origin -- what on earth? */
face[ 0 ] + 1, 0, /* The raster advance -- inc. x */ (float)(face[ 0 ] + 1), 0.0, /* The raster advance -- inc. x */
(face + 1) /* The packed bitmap data... */ (face + 1) /* The packed bitmap data... */
); );
@ -177,10 +176,67 @@ void FGAPIENTRY glutBitmapCharacter( void* fontID, int character )
void FGAPIENTRY glutBitmapString( void* fontID, const char *string ) void FGAPIENTRY glutBitmapString( void* fontID, const char *string )
{ {
int i; int c;
int numchar = strlen ( string ) ;
for( i=0; i<strlen( string ); i++ ) /*
glutBitmapCharacter( fontID, string[ i ] ); * First of all we'll need a font to use
*/
SFG_Font* font = fghFontByID( fontID );
float raster_position[4] ;
glGetFloatv ( GL_CURRENT_RASTER_POSITION, raster_position ) ;
/*
* Save the old pixel store settings
*/
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
/*
* Set up the pixel unpacking ways
*/
glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
/*
* Step through the string, drawing each character.
* A carriage return will simply translate the next character's insertion point back to the
* start of the line and down one line.
*/
for( c = 0; c < numchar; c++ )
{
if ( ( string[ c ] >= 0 ) && ( string[ c ] < 256 ) )
{
if ( string[c] == '\n' )
{
raster_position[1] -= (float)font->Height ;
glRasterPos4fv ( raster_position ) ;
}
else /* Not a carriage return, draw the bitmap character */
{
const GLubyte* face = font->Characters[ string[ c ] - 1 ] ;
/*
* We'll use a glBitmap call to draw the font.
*/
glBitmap(
face[ 0 ], font->Height, /* The bitmap's width and height */
font->xorig, font->yorig, /* The origin -- what on earth? */
(float)(face[ 0 ] + 1), 0.0, /* The raster advance -- inc. x */
(face + 1) /* The packed bitmap data... */
) ;
}
}
}
/*
* Restore the old pixel store settings
*/
glPopClientAttrib();
} }
/* /*
@ -204,6 +260,60 @@ int FGAPIENTRY glutBitmapWidth( void* fontID, int character )
return( *(font->Characters[ character - 1 ]) + 1 ); return( *(font->Characters[ character - 1 ]) + 1 );
} }
/*
* Return the width of a string drawn using a bitmap font
*/
int FGAPIENTRY glutBitmapLength( void* fontID, const char* string )
{
int c, length = 0, this_line_length = 0;
/*
* First of all, grab the font we need
*/
SFG_Font* font = fghFontByID( fontID );
/*
* Step through the characters in the string, adding up the width of each one
*/
int numchar = strlen ( string ) ;
for( c = 0; c < numchar; c++ )
{
if ( ( string[ c ] >= 0 ) && ( string[ c ] < 256 ) )
{
if ( string[ c ] == '\n' ) /* Carriage return, reset the length of this line */
{
if ( length < this_line_length ) length = this_line_length ;
this_line_length = 0 ;
}
else /* Not a carriage return, increment the length of this line */
this_line_length += *(font->Characters[ string[ c ] - 1 ]) + 1 ;
}
}
if ( length < this_line_length ) length = this_line_length ;
/*
* Return the result now
*/
return( length );
}
/*
* Returns the height of a bitmap font
*/
int FGAPIENTRY glutBitmapHeight( void* fontID )
{
/*
* See which font are we queried about
*/
SFG_Font* font = fghFontByID( fontID );
/*
* Return the character set's height
*/
return( font->Height );
}
/* /*
* Draw a stroke character * Draw a stroke character
*/ */
@ -241,6 +351,55 @@ void FGAPIENTRY glutStrokeCharacter( void* fontID, int character )
glTranslatef(schar->Right, 0.0, 0.0); glTranslatef(schar->Right, 0.0, 0.0);
} }
void FGAPIENTRY glutStrokeString( void* fontID, const char *string )
{
int c, i, j;
int numchar = strlen ( string ) ;
float length = 0.0 ;
/*
* First of all we'll need a font to use
*/
SFG_StrokeFont* font = fghStrokeByID( fontID );
/*
* Step through the string, drawing each character.
* A carriage return will simply translate the next character's insertion point back to the
* start of the line and down one line.
*/
for( c = 0; c < numchar; c++ )
{
if ( ( string[ c ] >= 0 ) && ( string[ c ] < font->Quantity ) )
{
if ( string[c] == '\n' )
{
glTranslatef ( -length, -(float)(font->Height), 0.0 ) ;
length = 0.0 ;
}
else /* Not a carriage return, draw the bitmap character */
{
const SFG_StrokeChar *schar = font->Characters[string[c]];
if ( schar != NULL )
{
const SFG_StrokeStrip *strip = schar->Strips;
for (i = 0; i < schar->Number; i++, strip++)
{
glBegin(GL_LINE_STRIP);
for(j = 0; j < strip->Number; j++)
glVertex2f(strip->Vertices[j].X, strip->Vertices[j].Y);
glEnd();
}
length += schar->Right ;
glTranslatef(schar->Right, 0.0, 0.0);
}
}
}
}
}
/* /*
* Return the width in pixels of a stroke character * Return the width in pixels of a stroke character
*/ */
@ -255,32 +414,13 @@ int FGAPIENTRY glutStrokeWidth( void* fontID, int character )
/* /*
* Make sure the character we want to output is valid * Make sure the character we want to output is valid
*/ */
freeglut_return_if_fail( character >= 0 && character < font->Quantity ); freeglut_return_val_if_fail( character >= 0 && character < font->Quantity, 0 );
schar = font->Characters[character]; schar = font->Characters[character];
freeglut_return_if_fail( schar ); freeglut_return_val_if_fail( schar, 0 );
return (schar->Right); return ((int)(schar->Right + 0.5));
}
/*
* Return the width of a string drawn using a bitmap font
*/
int FGAPIENTRY glutBitmapLength( void* fontID, const char* string )
{
int i, length = 0;
/*
* Using glutBitmapWidth() function to calculate the result
*/
for( i=0; i<strlen( string ); i++ )
length += glutBitmapWidth( fontID, string[ i ] );
/*
* Return the result now
*/
return( length );
} }
/* /*
@ -288,34 +428,43 @@ int FGAPIENTRY glutBitmapLength( void* fontID, const char* string )
*/ */
int FGAPIENTRY glutStrokeLength( void* fontID, const char* string ) int FGAPIENTRY glutStrokeLength( void* fontID, const char* string )
{ {
int i, length = 0; int c;
float length = 0.0;
float this_line_length = 0.0 ;
/* /*
* Using glutStrokeWidth() function to calculate the result * First of all we'll need a font to use
*/ */
for( i=0; i<strlen( string ); i++ ) SFG_StrokeFont* font = fghStrokeByID( fontID );
length += glutStrokeWidth( fontID, string[ i ] );
/*
* Step through the characters in the string, adding up the width of each one
*/
int numchar = strlen ( string ) ;
for( c = 0; c < numchar; c++ )
{
if ( ( string[ c ] >= 0 ) && ( string[ c ] < font->Quantity ) )
{
if ( string[ c ] == '\n' ) /* Carriage return, reset the length of this line */
{
if ( length < this_line_length ) length = this_line_length ;
this_line_length = 0.0 ;
}
else /* Not a carriage return, increment the length of this line */
{
const SFG_StrokeChar *schar = font->Characters[string[c]];
if ( schar != NULL )
this_line_length += schar->Right ;
}
}
}
if ( length < this_line_length ) length = this_line_length ;
/* /*
* Return the result now * Return the result now
*/ */
return( length ); return( (int)(length+0.5) );
}
/*
* Returns the height of a bitmap font
*/
int FGAPIENTRY glutBitmapHeight( void* fontID )
{
/*
* See which font are we queried about
*/
SFG_Font* font = fghFontByID( fontID );
/*
* Return the character set's height
*/
return( font->Height );
} }
/* /*

File diff suppressed because one or more lines are too long

View File

@ -82,9 +82,9 @@ void fghRememberState( void )
*/ */
/* hack to get around my stupid cross-gcc headers */ /* hack to get around my stupid cross-gcc headers */
#define ENUM_CURRENT_SETTINGS -1 #define FREEGLUT_ENUM_CURRENT_SETTINGS -1
EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &fgDisplay.DisplayMode ); EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS, &fgDisplay.DisplayMode );
/* /*
* Make sure we will be restoring all settings needed * Make sure we will be restoring all settings needed
@ -254,7 +254,7 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
devMode.dmBitsPerPel, fgState.GameModeRefresh ) ) devMode.dmBitsPerPel, fgState.GameModeRefresh ) )
{ {
/* /*
* OKi, we've found a matching display mode, remember it's number and break * OKi, we've found a matching display mode, remember its number and break
*/ */
mode = displayModes; mode = displayModes;
break; break;
@ -355,7 +355,7 @@ int FGAPIENTRY glutEnterGameMode( void )
/* /*
* ...if so, delete it before proceeding... * ...if so, delete it before proceeding...
*/ */
fgDestroyWindow( fgStructure.GameMode, TRUE ); fgAddToWindowDestroyList( fgStructure.GameMode, TRUE );
} }
else else
{ {
@ -434,9 +434,9 @@ void FGAPIENTRY glutLeaveGameMode( void )
freeglut_return_if_fail( fgStructure.GameMode != NULL ); freeglut_return_if_fail( fgStructure.GameMode != NULL );
/* /*
* First of all, have the game mode window created * First of all, have the game mode window destroyed
*/ */
fgDestroyWindow( fgStructure.GameMode, TRUE ); fgAddToWindowDestroyList( fgStructure.GameMode, TRUE );
#if TARGET_HOST_UNIX_X11 #if TARGET_HOST_UNIX_X11

View File

@ -55,7 +55,14 @@ SFG_Display fgDisplay;
/* /*
* The settings for the current freeglut session * The settings for the current freeglut session
*/ */
SFG_State fgState; SFG_State fgState = { { -1, -1, FALSE }, { 300, 300, TRUE }, GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH,
FALSE, TRUE, FALSE, FALSE, FALSE, TRUE,
#ifdef TARGET_HOST_WIN32
{ 0, FALSE },
#else
{ { 0, 0 }, FALSE },
#endif
{ NULL, NULL }, NULL, NULL, NULL, { 640, 480, TRUE }, 16, 72, GLUT_ACTION_EXIT, GLUT_EXEC_STATE_INIT } ;
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
@ -163,15 +170,13 @@ void fgInitialize( const char* displayName )
*/ */
if( atom == 0 ) if( atom == 0 )
{ {
GLboolean retval;
/* /*
* Make sure the unitialized fields are reset to zero * Make sure the unitialized fields are reset to zero
*/ */
ZeroMemory( &wc, sizeof(WNDCLASS) ); ZeroMemory( &wc, sizeof(WNDCLASS) );
/* /*
* Each of the windows should have it's own device context... * Each of the windows should have its own device context...
*/ */
wc.style = CS_OWNDC; wc.style = CS_OWNDC;
wc.lpfnWndProc = fgWindowProc; wc.lpfnWndProc = fgWindowProc;
@ -187,8 +192,8 @@ void fgInitialize( const char* displayName )
/* /*
* Register the window class * Register the window class
*/ */
retval = RegisterClass( &wc ); atom = RegisterClass( &wc );
assert( retval != FALSE ); assert( atom != 0 );
} }
/* /*
@ -259,6 +264,51 @@ void fgDeinitialize( void )
*/ */
fgJoystickClose(); fgJoystickClose();
/*
* Reset the state structure
*/
fgState.Position.X = -1 ;
fgState.Position.Y = -1 ;
fgState.Position.Use = FALSE ;
fgState.Size.X = 300 ;
fgState.Size.Y = 300 ;
fgState.Size.Use = TRUE ;
/*
* The default display mode to be used
*/
fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
fgState.ForceDirectContext = FALSE;
fgState.TryDirectContext = TRUE;
fgState.ForceIconic = FALSE;
fgState.GLDebugSwitch = FALSE;
fgState.XSyncSwitch = FALSE;
fgState.ActionOnWindowClose = GLUT_ACTION_EXIT ;
fgState.ExecState = GLUT_EXEC_STATE_INIT ;
/*
* Assume we want to ignore the automatic key repeat
*/
fgState.IgnoreKeyRepeat = TRUE;
/*
* Set the default game mode settings
*/
fgState.GameModeSize.X = 640;
fgState.GameModeSize.Y = 480;
fgState.GameModeDepth = 16;
fgState.GameModeRefresh = 72;
fgState.Time.Set = FALSE ;
fgState.Timers.First = fgState.Timers.Last = NULL ;
fgState.IdleCallback = NULL ;
fgState.MenuStateCallback = (FGCBmenuState)NULL ;
fgState.MenuStatusCallback = (FGCBmenuStatus)NULL ;
#if TARGET_HOST_UNIX_X11 #if TARGET_HOST_UNIX_X11
/* /*
@ -283,7 +333,6 @@ void fgDeinitialize( void )
*/ */
void FGAPIENTRY glutInit( int* pargc, char** argv ) void FGAPIENTRY glutInit( int* pargc, char** argv )
{ {
char* geometrySettings = NULL;
char* displayName = NULL; char* displayName = NULL;
int i, j, argc = *pargc; int i, j, argc = *pargc;
@ -303,55 +352,12 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
*/ */
fgCreateStructure(); fgCreateStructure();
/*
* Fill in the default values that have not been passed in yet.
*/
if( fgState.Position.Use == FALSE )
{
fgState.Position.X = -1;
fgState.Position.Y = -1;
}
if( fgState.Size.Use == FALSE )
{
fgState.Size.X = 300;
fgState.Size.Y = 300;
fgState.Size.Use = TRUE;
}
/*
* Some more settings to come
*/
fgState.ForceDirectContext = FALSE;
fgState.TryDirectContext = TRUE;
fgState.ForceIconic = FALSE;
fgState.GLDebugSwitch = FALSE;
fgState.XSyncSwitch = FALSE;
/*
* Assume we want to ignore the automatic key repeat
*/
fgState.IgnoreKeyRepeat = TRUE;
/*
* The default display mode to be used
*/
fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
/*
* Set the default game mode settings
*/
fgState.GameModeSize.X = 640;
fgState.GameModeSize.Y = 480;
fgState.GameModeDepth = 16;
fgState.GameModeRefresh = 72;
/* /*
* Remember the function's call time * Remember the function's call time
*/ */
#ifndef WIN32 #if TARGET_HOST_UNIX_X11
gettimeofday(&fgState.Time.Value, NULL); gettimeofday(&fgState.Time.Value, NULL);
#else #elif TARGET_HOST_WIN32
fgState.Time.Value = timeGetTime(); fgState.Time.Value = timeGetTime();
#endif #endif
fgState.Time.Set = TRUE; fgState.Time.Set = TRUE;
@ -401,6 +407,9 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
*/ */
else if( strcmp( argv[ i ], "-geometry" ) == 0 ) else if( strcmp( argv[ i ], "-geometry" ) == 0 )
{ {
int result, x, y;
unsigned int w, h;
/* /*
* Again, check if there is at least one more argument * Again, check if there is at least one more argument
*/ */
@ -408,9 +417,34 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
fgError( "-geometry parameter must be followed by window geometry settings" ); fgError( "-geometry parameter must be followed by window geometry settings" );
/* /*
* Otherwise make a duplicate of the geometry settings... * Otherwise scan the geometry settings...
*/ */
geometrySettings = strdup( argv[ i ] ); result = sscanf ( argv[i], "%dx%d+%d+%d", &x, &y, &w, &h );
/*
* Check what we have been supplied with...
*/
if ( result > 3 )
fgState.Size.Y = h ;
if ( result > 2 )
fgState.Size.X = w ;
if( result > 1 )
{
if( y < 0 )
fgState.Position.Y = fgDisplay.ScreenHeight + y - fgState.Size.Y;
else
fgState.Position.Y = y;
}
if( result > 0 )
{
if( x < 0 )
fgState.Position.X = fgDisplay.ScreenWidth + x - fgState.Size.X;
else
fgState.Position.X = x;
}
/* /*
* Have both arguments removed * Have both arguments removed
@ -483,18 +517,13 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
/* /*
* Have the arguments list compacted now * Have the arguments list compacted now
*/ */
for( i=1; i<argc; i++ ) j = 2 ;
for( i = 1; i < *pargc; i++, j++ )
{ {
if( argv[ i ] == NULL ) if( argv[ i ] == NULL )
{ {
for( j=i; j<argc; j++ ) while ( argv[j] == NULL ) j++ ; /* Guaranteed to end because there are "*pargc" arguments left */
{
if( argv[ j ] != NULL )
{
argv[i] = argv[j] ; argv[i] = argv[j] ;
argv[ j ] = NULL;
}
}
} }
} }
@ -505,55 +534,6 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
*/ */
fgInitialize( displayName ); fgInitialize( displayName );
#if TARGET_HOST_UNIX_X11
/*
* We can process the default window geometry settings safely now
*
* WARNING: have this rewritten to be portable. That won't be hard.
*/
if( geometrySettings != NULL )
{
int result, x, y;
unsigned int w, h;
/*
* Have the settings parsed now. This is easy.
* We will use the XParseGeometry function.
*/
result = XParseGeometry( geometrySettings, &x, &y, &w, &h );
/*
* Check what we have been supplied with...
*/
if( (result & WidthValue) && (w >= 0) )
fgState.Size.X = w;
if( (result & HeightValue) && (h >= 0) )
fgState.Size.Y = h;
if( result & XValue )
{
if( result & XNegative )
fgState.Position.X = fgDisplay.ScreenWidth + x - fgState.Size.X;
else
fgState.Position.X = x;
}
if( result & YValue )
{
if( result & YNegative )
fgState.Position.Y = fgDisplay.ScreenHeight + y - fgState.Size.Y;
else
fgState.Position.Y = y;
}
/*
* Free the geometry settings string
*/
free( geometrySettings );
}
#endif
/* /*
* Check for the minus one settings for both position and size... * Check for the minus one settings for both position and size...
*/ */
@ -605,7 +585,7 @@ void FGAPIENTRY glutInitWindowSize( int width, int height )
/* /*
* The settings can be disables when both values are negative * The settings can be disables when both values are negative
*/ */
if( (width >= 0) && (height >= 0) ) if( (width > 0) && (height > 0) )
{ {
/* /*
* We want to specify the initial size of each of the windows * We want to specify the initial size of each of the windows
@ -617,7 +597,7 @@ void FGAPIENTRY glutInitWindowSize( int width, int height )
else else
{ {
/* /*
* The initial size of each of the windows is specified by the wm * The initial size of each of the windows is specified by the wm (officially this is an error condition)
*/ */
fgState.Size.X = -1; fgState.Size.X = -1;
fgState.Size.Y = -1; fgState.Size.Y = -1;
@ -845,7 +825,7 @@ void FGAPIENTRY glutInitDisplayString( char* displayMode )
value = strtol( valueString, NULL, 0 ); value = strtol( valueString, NULL, 0 );
/* /*
* Now we need to match the capability string and it's ID * Now we need to match the capability string and its ID
*/ */
for( i=0; g_Tokens[ i ]!=NULL; i++ ) for( i=0; g_Tokens[ i ]!=NULL; i++ )
{ {
@ -921,8 +901,175 @@ void FGAPIENTRY glutInitDisplayString( char* displayMode )
} }
#endif #endif
#define NUM_TOKENS 28
static char* Tokens[] =
{
"alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double", "green",
"index", "num", "red", "rgba", "rgb", "luminance", "stencil", "single", "stereo", "samples",
"slow", "win32pdf", "xvisual", "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
"xtruecolor", "xdirectcolor"
};
static int TokenLengths[] =
{
5, 4, 3, 4, 6, 10, 5, 6, 5,
5, 3, 3, 4, 3, 9, 7, 6, 6, 7,
4, 8, 7, 11, 10, 12, 12,
10, 12
};
void FGAPIENTRY glutInitDisplayString( char* displayMode ) void FGAPIENTRY glutInitDisplayString( char* displayMode )
{ {
int glut_state_flag = 0 ;
/*
* Unpack a lot of options from a character string. The options are delimited by blanks or tabs.
*/
char *token ;
int len = strlen ( displayMode ) ;
char *buffer = malloc ( (len+1) * sizeof(char) ) ;
memcpy ( buffer, displayMode, len ) ;
buffer[len] = '\0' ;
token = strtok ( buffer, " \t" ) ;
while ( token )
{
/*
* Process this token
*/
int i ;
for ( i = 0; i < NUM_TOKENS; i++ )
{
if ( strncmp ( token, Tokens[i], TokenLengths[i] ) == 0 ) break ;
}
switch ( i )
{
case 0 : /* "alpha": Alpha color buffer precision in bits */
glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
break ;
case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer precision in bits */
break ;
case 2 : /* "acc": Red, green, and blue accumulation buffer precision in bits with zero bits alpha */
glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
break ;
case 3 : /* "blue": Blue color buffer precision in bits */
break ;
case 4 : /* "buffer": Number of bits in the color index color buffer */
break ;
case 5 : /* "conformant": Boolean indicating if the frame buffer configuration is conformant or not */
break ;
case 6 : /* "depth": Number of bits of precsion in the depth buffer */
glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
break ;
case 7 : /* "double": Boolean indicating if the color buffer is double buffered */
glut_state_flag |= GLUT_DOUBLE ;
break ;
case 8 : /* "green": Green color buffer precision in bits */
break ;
case 9 : /* "index": Boolean if the color model is color index or not */
glut_state_flag |= GLUT_INDEX ;
break ;
case 10 : /* "num": A special capability name indicating where the value represents the Nth frame buffer configuration matching the description string */
break ;
case 11 : /* "red": Red color buffer precision in bits */
break ;
case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in the RGBA color buffer */
glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
break ;
case 13 : /* "rgb": Number of bits of red, green, and blue in the RGBA color buffer with zero bits alpha */
glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
break ;
case 14 : /* "luminance": Number of bits of red in the RGBA and zero bits of green, blue (alpha not specified) of color buffer precision */
glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
break ;
case 15 : /* "stencil": Number of bits in the stencil buffer */
glut_state_flag |= GLUT_STENCIL ; /* Somebody fix this for me! */
break ;
case 16 : /* "single": Boolean indicate the color buffer is single buffered */
glut_state_flag |= GLUT_SINGLE ;
break ;
case 17 : /* "stereo": Boolean indicating the color buffer supports OpenGL-style stereo */
glut_state_flag |= GLUT_STEREO ;
break ;
case 18 : /* "samples": Indicates the number of multisamples to use based on GLX's SGIS_multisample extension (for antialiasing) */
glut_state_flag |= GLUT_MULTISAMPLE ; /* Somebody fix this for me! */
break ;
case 19 : /* "slow": Boolean indicating if the frame buffer configuration is slow or not */
break ;
case 20 : /* "win32pdf": matches the Win32 Pixel Format Descriptor by number */
#ifdef TARGET_HOST_WIN32
#endif
break ;
case 21 : /* "xvisual": matches the X visual ID by number */
#ifdef TARGET_HOST_UNIX_X11
#endif
break ;
case 22 : /* "xstaticgray": boolean indicating if the frame buffer configuration's X visual is of type StaticGray */
#ifdef TARGET_HOST_UNIX_X11
#endif
break ;
case 23 : /* "xgrayscale": boolean indicating if the frame buffer configuration's X visual is of type GrayScale */
#ifdef TARGET_HOST_UNIX_X11
#endif
break ;
case 24 : /* "xstaticcolor": boolean indicating if the frame buffer configuration's X visual is of type StaticColor */
#ifdef TARGET_HOST_UNIX_X11
#endif
break ;
case 25 : /* "xpseudocolor": boolean indicating if the frame buffer configuration's X visual is of type PseudoColor */
#ifdef TARGET_HOST_UNIX_X11
#endif
break ;
case 26 : /* "xtruecolor": boolean indicating if the frame buffer configuration's X visual is of type TrueColor */
#ifdef TARGET_HOST_UNIX_X11
#endif
break ;
case 27 : /* "xdirectcolor": boolean indicating if the frame buffer configuration's X visual is of type DirectColor */
#ifdef TARGET_HOST_UNIX_X11
#endif
break ;
case 28 : /* Unrecognized */
printf ( "WARNING - Display string token not recognized: %s\n", token ) ;
break ;
}
token = strtok ( NULL, " \t" ) ;
}
free ( buffer ) ;
/*
* We will make use of this value when creating a new OpenGL context...
*/
fgState.DisplayMode = glut_state_flag;
} }
/*** END OF FILE ***/ /*** END OF FILE ***/

View File

@ -80,11 +80,17 @@ static void fghRedrawWindowByHandle
*/ */
glutSetWindow( window->ID ); glutSetWindow( window->ID );
/*
* Do not exagerate with the redisplaying
*/
window->State.Redisplay = FALSE;
/* /*
* Have the callback executed now. The buffers should * Have the callback executed now. The buffers should
* be swapped by the glutSwapBuffers() execution inside * be swapped by the glutSwapBuffers() execution inside
* the callback itself. * the callback itself.
*/ */
window->Callbacks.Display(); window->Callbacks.Display();
} }
@ -128,6 +134,14 @@ static void fghReshapeWindowByHandle
*/ */
glViewport( 0, 0, width, height ); glViewport( 0, 0, 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 = TRUE ;
} }
/* /*
@ -183,10 +197,20 @@ static void fghcbDisplayWindow( SFG_Window *window, SFG_Enumerator *enumerator )
/* /*
* This is done in a bit different way under Windows * This is done in a bit different way under Windows
*/ */
if( (window->Callbacks.Display != NULL) &&
(window->State.Redisplay == TRUE) &&
(window->State.Visible == TRUE) )
{
/*
* Do not exagerate with the redisplaying
*/
window->State.Redisplay = FALSE;
RedrawWindow( RedrawWindow(
window->Window.Handle, NULL, NULL, window->Window.Handle, NULL, NULL,
RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE
); );
}
#endif #endif
@ -220,7 +244,7 @@ static void fghDisplayAll( void )
*/ */
static void fghcbCheckJoystickPolls( SFG_Window *window, SFG_Enumerator *enumerator ) static void fghcbCheckJoystickPolls( SFG_Window *window, SFG_Enumerator *enumerator )
{ {
double checkTime = fgElapsedTime(); long int checkTime = fgElapsedTime();
/* /*
* Check if actually need to do the poll for the currently enumerated window: * Check if actually need to do the poll for the currently enumerated window:
@ -307,12 +331,13 @@ static void fghCheckTimers( void )
} }
} }
/* /*
* Elapsed Time * Elapsed Time
*/ */
long fgElapsedTime( void ) long fgElapsedTime( void )
{ {
#ifndef WIN32 #if TARGET_HOST_UNIX_X11
struct timeval now; struct timeval now;
long elapsed; long elapsed;
@ -322,7 +347,7 @@ long fgElapsedTime( void )
elapsed += (now.tv_sec - fgState.Time.Value.tv_sec) * 1000; elapsed += (now.tv_sec - fgState.Time.Value.tv_sec) * 1000;
return( elapsed ); return( elapsed );
#else #elif TARGET_HOST_WIN32
return (timeGetTime() - fgState.Time.Value); return (timeGetTime() - fgState.Time.Value);
#endif #endif
} }
@ -358,12 +383,73 @@ void fgWarning( const char *fmt, ... )
va_end( ap ); va_end( ap );
} }
/*
* Clean up on exit
*/
static void fgCleanUpGlutsMess( void )
{
int i;
i = 0;
if ( fgStructure.Windows.First != NULL )
{
SFG_Window *win = fgStructure.Windows.First ;
glEnd();
glFinish();
glFlush();
while ( win != NULL )
{
SFG_Window *temp_win = win->Node.Next ;
fgDestroyWindow ( win, FALSE ) ;
win = temp_win ;
}
}
#if 0
/* these are pointers to external handles */
__glutWindowListSize = 0;
__glutStaleWindowList = NULL;
__glutWindowList = NULL;
__glutCurrentWindow = NULL;
/* make sure we no longer have a GL context */
if ( wglGetCurrentContext() != NULL )
{
wglDeleteContext( wglGetCurrentContext() );
}
hInstance = GetModuleHandle(NULL);
UnregisterClass( classname, hInstance );
/* clean up allocated timer memory */
tList = __glutTimerList;
i = 0;
while ( __glutTimerList )
{
i++;
tList = __glutTimerList;
if ( __glutTimerList )
__glutTimerList = __glutTimerList->next;
if ( tList )
free( tList );
}
#endif
}
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/* /*
* Enters the FreeGLUT processing loop. Never returns. * Executes a single iteration in the FreeGLUT processing loop.
*/ */
void FGAPIENTRY glutMainLoop( void ) void FGAPIENTRY glutMainLoopEvent( void )
{ {
#if TARGET_HOST_UNIX_X11 #if TARGET_HOST_UNIX_X11
SFG_Window* window; SFG_Window* window;
@ -381,12 +467,6 @@ void FGAPIENTRY glutMainLoop( void )
*/ */
freeglut_assert_ready; freeglut_assert_ready;
/*
* Enter the loop. Iterate as long as there are
* any windows in the freeglut structure.
*/
while( fgStructure.Windows.First != NULL )
{
/* /*
* Do we have any event messages pending? * Do we have any event messages pending?
*/ */
@ -410,8 +490,13 @@ void FGAPIENTRY glutMainLoop( void )
case DestroyNotify: case DestroyNotify:
/* /*
* This is sent to confirm the XDestroyWindow call. Ignore it. * This is sent to confirm the XDestroyWindow call.
*/ */
/*
* Call the window closure callback, remove from the structure, etc.
*/
fgAddToWindowDestroyList ( window, FALSE );
break; break;
case ClientMessage: case ClientMessage:
@ -420,10 +505,6 @@ void FGAPIENTRY glutMainLoop( void )
*/ */
if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.DeleteWindow ) if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.DeleteWindow )
{ {
/*
* I wonder if the window still exists ;-)
*/
fgDestroyWindow( fgWindowByHandle( event.xclient.window ), TRUE );
} }
break; break;
@ -597,8 +678,11 @@ void FGAPIENTRY glutMainLoop( void )
case ButtonRelease: case ButtonRelease:
case ButtonPress: case ButtonPress:
{ {
GLboolean pressed = TRUE ;
int button; int button;
if ( event.type == ButtonRelease ) pressed = FALSE ;
/* /*
* A mouse button has been pressed or released. Traditionally, * A mouse button has been pressed or released. Traditionally,
* break if the window was found within the freeglut structures. * break if the window was found within the freeglut structures.
@ -627,34 +711,51 @@ void FGAPIENTRY glutMainLoop( void )
break; break;
/* /*
* Do not execute the callback if a menu is hooked to this key. * 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 * In that case an appropriate private call should be generated.
* Near as I can tell, this is the menu behaviour:
* - Down-click the menu button, menu not active: activate the menu with its upper left-hand corner at the mouse location.
* - Down-click any button outside the menu, menu active: deactivate the menu
* - Down-click any button inside the menu, menu active: select the menu entry and deactivate the menu
* - Up-click the menu button, menu not active: nothing happens
* - Up-click the menu button outside the menu, menu active: nothing happens
* - Up-click the menu button inside the menu, menu active: select the menu entry and deactivate the menu
*/ */
if( window->Menu[ button ] != NULL ) if ( window->ActiveMenu != NULL ) /* Window has an active menu, it absorbs any mouse click */
{
if ( fgCheckActiveMenu ( window, window->ActiveMenu ) == TRUE ) /* Inside the menu, invoke the callback and deactivate the menu*/
{
fgExecuteMenuCallback ( window->ActiveMenu ) ;
fgDeactivateMenu ( window ) ;
}
else /* Outside the menu, deactivate the menu if it's a downclick */
{
if ( pressed == TRUE ) fgDeactivateMenu ( window ) ;
}
/*
* Let's make the window redraw as a result of the mouse click and menu activity.
*/
window->State.Redisplay = TRUE ;
break ;
}
/*
* No active menu, let's check whether we need to activate one.
*/
if ( ( window->Menu[ button ] != NULL ) && ( pressed == TRUE ) )
{ {
/* /*
* Set the current window * Let's make the window redraw as a result of the mouse click.
*/ */
glutSetWindow( window->ID ); window->State.Redisplay = TRUE ;
if( event.type == ButtonPress )
{
/* /*
* Activate the appropriate menu structure... * Activate the appropriate menu structure...
*/ */
fgActivateMenu( button ); fgActivateMenu( window, button );
}
else
{
/*
* There are two general cases generated when a menu button
* is released -- it can provoke a menu call (when released
* over a menu area) or just deactivate the menu (when released
* somewhere else). Unfortunately, both cases must be checked
* recursively due to the submenu possibilities.
*/
fgDeactivateMenu( button );
}
break; break;
} }
@ -873,25 +974,21 @@ void FGAPIENTRY glutMainLoop( void )
*/ */
fghDisplayAll(); fghDisplayAll();
} }
}
#elif TARGET_HOST_WIN32 #elif TARGET_HOST_WIN32
GLboolean bLoop = TRUE;
MSG stMsg; MSG stMsg;
/* /*
* The windows main loop is considerably smaller * The windows processing is considerably smaller
*/ */
while( bLoop )
{
if( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) ) if( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) )
{ {
/* /*
* Grab the message now, checking for WM_QUIT * Grab the message now, checking for WM_QUIT
*/ */
if( GetMessage( &stMsg, NULL, 0, 0 ) == 0 ) if( GetMessage( &stMsg, NULL, 0, 0 ) == 0 )
bLoop = FALSE; fgState.ExecState = GLUT_EXEC_STATE_STOP ;
/* /*
* Translate virtual-key messages and send them to the window... * Translate virtual-key messages and send them to the window...
@ -922,15 +1019,77 @@ void FGAPIENTRY glutMainLoop( void )
* been marked for a redisplay (possibly in the idle call): * been marked for a redisplay (possibly in the idle call):
*/ */
fghDisplayAll(); fghDisplayAll();
}
#endif
}
/* /*
* We need to terminate the main loop if no windows are left * Enters the FreeGLUT processing loop. Stays until the "ExecState" changes to "GLUT_EXEC_STATE_STOP".
*/ */
bLoop = (fgStructure.Windows.First != NULL); void FGAPIENTRY glutMainLoop( void )
{
#if TARGET_HOST_WIN32
SFG_Window *window = fgStructure.Windows.First ;
#endif
/*
* Make sure the display has been created etc.
*/
freeglut_assert_ready;
#if TARGET_HOST_WIN32
/*
* Processing before the main loop: If there is a window which is open and which
* has a visibility callback, call it. I know this is an ugly hack, but I'm not sure
* what else to do about it. Ideally we should leave something uninitialized in the
* create window code and initialize it in the main loop, and have that initialization
* create a "WM_ACTIVATE" message. Then we would put the visibility callback code in
* the "case WM_ACTIVATE" block below. - John Fay -- 10/24/02
*/
while ( window != NULL )
{
if ( window->Callbacks.Visibility != NULL )
window->Callbacks.Visibility ( window->State.Visible ) ;
window = window->Node.Next ;
} }
#endif
/*
* Set freeglut to be running
*/
fgState.ExecState = GLUT_EXEC_STATE_RUNNING ;
/*
* Enter the main loop itself. Inside the loop, process events and check for loop exit.
*/
while ( fgState.ExecState == GLUT_EXEC_STATE_RUNNING )
{
glutMainLoopEvent () ;
/*
* If an event caused a window to be closed, do the actual closing here
*/
fgCloseWindows () ;
/*
* If there are no more windows open, stop execution
*/
if ( fgStructure.Windows.First == NULL )
fgState.ExecState = GLUT_EXEC_STATE_STOP ;
} }
#endif
/*
* If we got here by the user closing a window or by the application closing down, there may still be windows open.
*/
fgCleanUpGlutsMess () ;
/*
* Check whether we return to the calling program or simply exit
*/
if ( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
exit ( 0 ) ;
/* /*
* When this loop terminates, destroy the display, state and structure * When this loop terminates, destroy the display, state and structure
@ -939,6 +1098,14 @@ void FGAPIENTRY glutMainLoop( void )
fgDeinitialize(); fgDeinitialize();
} }
/*
* Leaves the FreeGLUT processing loop.
*/
void FGAPIENTRY glutLeaveMainLoop( void )
{
fgState.ExecState = GLUT_EXEC_STATE_STOP ;
}
/* /*
* The window procedure for handling Win32 events * The window procedure for handling Win32 events
*/ */
@ -949,8 +1116,10 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
PAINTSTRUCT ps; PAINTSTRUCT ps;
LONG lRet = 1; LONG lRet = 1;
# define assert_window_registered if( window == NULL ) return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ); if ( ( window == NULL ) && ( uMsg != WM_CREATE ) )
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) );
/* if ( uMsg != 0x000f ) printf ( "message <%x>\n", uMsg ) ; */
/* /*
* Check what type of message are we receiving * Check what type of message are we receiving
*/ */
@ -1000,11 +1169,78 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
*/ */
fghReshapeWindowByHandle( hWnd, LOWORD(lParam), HIWORD(lParam) ); fghReshapeWindowByHandle( hWnd, LOWORD(lParam), HIWORD(lParam) );
break; break;
#if 0
case WM_SETFOCUS:
printf("WM_SETFOCUS: %p\n", window );
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
break;
case WM_ACTIVATE:
if (LOWORD(wParam) != WA_INACTIVE)
{
//glutSetCursor( fgStructure.Window->State.Cursor );
printf("WM_ACTIVATE: glutSetCursor( %p, %d)\n", window, window->State.Cursor );
glutSetCursor( window->State.Cursor );
}
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
break;
#endif
case WM_SETCURSOR:
/*
* Windows seems to need reminding to erase the cursor for NONE.
*/
#if 0
if ((LOWORD(lParam) == HTCLIENT) &&
(fgStructure.Window->State.Cursor == GLUT_CURSOR_NONE))
SetCursor( NULL );
#else
// Set the cursor AND change it for this window class.
# 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;
if (LOWORD(lParam) == HTCLIENT)
switch( window->State.Cursor )
{
MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW );
MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW );
MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HELP );
MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS );
MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP );
MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL );
MAP_CURSOR( GLUT_CURSOR_SPRAY, IDC_CROSS );
MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT );
MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_UPARROW );
MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS );
//MAP_CURSOR( GLUT_CURSOR_NONE, IDC_NO );
ZAP_CURSOR( GLUT_CURSOR_NONE, NULL );
default:
MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_ARROW );
}
#endif
else
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
break;
case WM_SHOWWINDOW:
/*
* We are now Visible!
*/
window->State.Visible = TRUE;
window->State.Redisplay = TRUE;
break;
case WM_PAINT: case WM_PAINT:
/* /*
* Start the painting job * Start the painting job
*/ */
BeginPaint( hWnd, &ps ); BeginPaint( hWnd, &ps );
/* /*
@ -1028,23 +1264,25 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
wglDeleteContext( window->Window.Context ); wglDeleteContext( window->Window.Context );
} }
/*
* Put on a linked list of windows to be removed after all the callbacks have returned
*/
fgAddToWindowDestroyList ( window, FALSE ) ;
/* /*
* Proceed with the window destruction * Proceed with the window destruction
*/ */
DestroyWindow( window->Window.Handle ); DestroyWindow( hWnd );
break; break;
case WM_DESTROY: case WM_DESTROY:
/* /*
* The window already got destroyed, so forget about it's existence: * The window already got destroyed, so don't bother with it.
*/ */
fgDestroyWindow( window, FALSE );
return( 0 ); return( 0 );
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
{ {
assert_window_registered;
/* /*
* The mouse cursor has moved. Remember the new mouse cursor's position * The mouse cursor has moved. Remember the new mouse cursor's position
*/ */
@ -1054,16 +1292,23 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
/* /*
* Fallback if there's an active menu hooked to this window * Fallback if there's an active menu hooked to this window
*/ */
if( window->MenuActive[ 0 ] || window->MenuActive[ 1 ] || window->MenuActive[ 2 ] ) if( window->ActiveMenu != NULL )
{
/*
* Let's make the window redraw as a result of the mouse motion.
*/
window->State.Redisplay = TRUE ;
break; break;
}
/* /*
* Remember the current modifiers state. * Remember the current modifiers state.
*/ */
window->State.Modifiers = window->State.Modifiers =
(GetKeyState( VK_LSHIFT ) || GetKeyState( VK_RSHIFT )) ? GLUT_ACTIVE_SHIFT : 0 | ( ( (GetKeyState( VK_LSHIFT ) < 0 ) || ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
(GetKeyState( VK_LCONTROL ) || GetKeyState( VK_RCONTROL )) ? GLUT_ACTIVE_CTRL : 0 | ( ( (GetKeyState( VK_LCONTROL ) < 0 ) || ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
(GetKeyState( VK_LMENU ) || GetKeyState( VK_RMENU )) ? GLUT_ACTIVE_ALT : 0; ( ( (GetKeyState( VK_LMENU ) < 0 ) || ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
/* /*
* Check if any of the mouse buttons is pressed... * Check if any of the mouse buttons is pressed...
@ -1122,12 +1367,6 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
GLboolean pressed = TRUE; GLboolean pressed = TRUE;
int button; int button;
/*
* A mouse button has been pressed *or* released. Again, break off
* if the message was not directed towards a freeglut window...
*/
assert_window_registered;
/* /*
* The mouse cursor has moved. Remember the new mouse cursor's position * The mouse cursor has moved. Remember the new mouse cursor's position
*/ */
@ -1162,34 +1401,51 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
return( DefWindowProc( hWnd, uMsg, lParam, wParam ) ); return( DefWindowProc( hWnd, uMsg, lParam, wParam ) );
/* /*
* Do not execute the callback if a menu is hooked to this key. * 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 * In that case an appropriate private call should be generated.
* Near as I can tell, this is the menu behaviour:
* - Down-click the menu button, menu not active: activate the menu with its upper left-hand corner at the mouse location.
* - Down-click any button outside the menu, menu active: deactivate the menu
* - Down-click any button inside the menu, menu active: select the menu entry and deactivate the menu
* - Up-click the menu button, menu not active: nothing happens
* - Up-click the menu button outside the menu, menu active: nothing happens
* - Up-click the menu button inside the menu, menu active: select the menu entry and deactivate the menu
*/ */
if( window->Menu[ button ] != NULL ) if ( window->ActiveMenu != NULL ) /* Window has an active menu, it absorbs any mouse click */
{
if ( fgCheckActiveMenu ( window, window->ActiveMenu ) == TRUE ) /* Inside the menu, invoke the callback and deactivate the menu*/
{
fgExecuteMenuCallback ( window->ActiveMenu ) ;
fgDeactivateMenu ( window ) ;
}
else /* Outside the menu, deactivate the menu if it's a downclick */
{
if ( pressed == TRUE ) fgDeactivateMenu ( window ) ;
}
/*
* Let's make the window redraw as a result of the mouse click and menu activity.
*/
window->State.Redisplay = TRUE ;
break ;
}
/*
* No active menu, let's check whether we need to activate one.
*/
if ( ( window->Menu[ button ] != NULL ) && ( pressed == TRUE ) )
{ {
/* /*
* Set the current window * Let's make the window redraw as a result of the mouse click.
*/ */
glutSetWindow( window->ID ); window->State.Redisplay = TRUE ;
if( pressed == TRUE )
{
/* /*
* Activate the appropriate menu structure... * Activate the appropriate menu structure...
*/ */
fgActivateMenu( button ); fgActivateMenu( window, button );
}
else
{
/*
* There are two general cases generated when a menu button
* is released -- it can provoke a menu call (when released
* over a menu area) or just deactivate the menu (when released
* somewhere else). Unfortunately, both cases must be checked
* recursively due to the submenu possibilities.
*/
fgDeactivateMenu( button );
}
break; break;
} }
@ -1208,9 +1464,9 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
* Remember the current modifiers state. * Remember the current modifiers state.
*/ */
window->State.Modifiers = window->State.Modifiers =
(GetKeyState( VK_LSHIFT ) || GetKeyState( VK_RSHIFT )) ? GLUT_ACTIVE_SHIFT : 0 | ( ( (GetKeyState( VK_LSHIFT ) < 0 ) || ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
(GetKeyState( VK_LCONTROL ) || GetKeyState( VK_RCONTROL )) ? GLUT_ACTIVE_CTRL : 0 | ( ( (GetKeyState( VK_LCONTROL ) < 0 ) || ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
(GetKeyState( VK_LMENU ) || GetKeyState( VK_RMENU )) ? GLUT_ACTIVE_ALT : 0; ( ( (GetKeyState( VK_LMENU ) < 0 ) || ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
/* /*
* Finally execute the mouse callback * Finally execute the mouse callback
@ -1234,25 +1490,25 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
{ {
int keypress = -1; int keypress = -1;
/*
* First of all, make sure that there is a window to be notified of this
*/
assert_window_registered;
/* /*
* Ignore the automatic key repetition if needed: * Ignore the automatic key repetition if needed:
*/ */
if( fgState.IgnoreKeyRepeat && (lParam & KF_REPEAT) ) if( fgState.IgnoreKeyRepeat && (lParam & KF_REPEAT) )
break; break;
/*
* Set the current window
*/
glutSetWindow( window->ID );
/* /*
* Remember the current modifiers state. This is done here in order * Remember the current modifiers state. This is done here in order
* to make sure the VK_DELETE keyboard callback is executed properly. * to make sure the VK_DELETE keyboard callback is executed properly.
*/ */
window->State.Modifiers = window->State.Modifiers =
(GetKeyState( VK_LSHIFT ) || GetKeyState( VK_RSHIFT )) ? GLUT_ACTIVE_SHIFT : 0 | ( ( (GetKeyState( VK_LSHIFT ) < 0 ) || ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
(GetKeyState( VK_LCONTROL ) || GetKeyState( VK_RCONTROL )) ? GLUT_ACTIVE_CTRL : 0 | ( ( (GetKeyState( VK_LCONTROL ) < 0 ) || ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
(GetKeyState( VK_LMENU ) || GetKeyState( VK_RMENU )) ? GLUT_ACTIVE_ALT : 0; ( ( (GetKeyState( VK_LMENU ) < 0 ) || ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
/* /*
* Convert the Win32 keystroke codes to GLUTtish way * Convert the Win32 keystroke codes to GLUTtish way
@ -1305,14 +1561,84 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
} }
break; break;
case WM_SYSKEYUP:
case WM_KEYUP:
{
int keypress = -1;
/*
* Set the current window
*/
glutSetWindow( window->ID );
/*
* 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 =
( ( (GetKeyState( VK_LSHIFT ) < 0 ) || ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
( ( (GetKeyState( VK_LCONTROL ) < 0 ) || ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
( ( (GetKeyState( VK_LMENU ) < 0 ) || ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
/*
* Convert the Win32 keystroke codes to GLUTtish way. "KEY(a,b)" was defined under "WM_KEYDOWN"
*/
switch( wParam )
{
/*
* Most of the special characters can be handled automagically...
*/
KEY( VK_F1, GLUT_KEY_F1 ); KEY( VK_F2, GLUT_KEY_F2 );
KEY( VK_F3, GLUT_KEY_F3 ); KEY( VK_F4, GLUT_KEY_F4 );
KEY( VK_F5, GLUT_KEY_F5 ); KEY( VK_F6, GLUT_KEY_F6 );
KEY( VK_F7, GLUT_KEY_F7 ); KEY( VK_F8, GLUT_KEY_F8 );
KEY( VK_F9, GLUT_KEY_F9 ); KEY( VK_F10, GLUT_KEY_F10 );
KEY( VK_F11, GLUT_KEY_F11 ); KEY( VK_F12, GLUT_KEY_F12 );
KEY( VK_PRIOR, GLUT_KEY_PAGE_UP ); KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
KEY( VK_HOME, GLUT_KEY_HOME ); KEY( VK_END, GLUT_KEY_END );
KEY( VK_LEFT, GLUT_KEY_LEFT ); KEY( VK_UP, GLUT_KEY_UP );
KEY( VK_RIGHT, GLUT_KEY_RIGHT ); KEY( VK_DOWN, GLUT_KEY_DOWN );
KEY( VK_INSERT, GLUT_KEY_INSERT );
/*
* ...yet there is a small exception we need to have handled...
*/
case VK_DELETE:
/*
* The delete key should be treated as an ASCII keypress:
*/
if( window->Callbacks.KeyboardUp != NULL )
window->Callbacks.KeyboardUp( 127, window->State.MouseX, window->State.MouseY );
default:
/*
* Call the KeyboardUp callback for a regular character if there is one.
*/
if( window->Callbacks.KeyboardUp != NULL )
window->Callbacks.KeyboardUp( wParam, window->State.MouseX, window->State.MouseY );
}
/*
* Execute the special callback, if present, given the conversion was a success:
*/
if( (keypress != -1) && (window->Callbacks.SpecialUp != NULL) )
{
/*
* Have the special callback executed:
*/
window->Callbacks.SpecialUp( keypress, window->State.MouseX, window->State.MouseY );
}
/*
* Thrash the modifiers register now
*/
window->State.Modifiers = 0xffffffff;
}
break;
case WM_SYSCHAR: case WM_SYSCHAR:
case WM_CHAR: case WM_CHAR:
{ {
/*
* First of all, make sure that there is a window to be notified of this
*/
assert_window_registered;
/* /*
* Ignore the automatic key repetition if needed: * Ignore the automatic key repetition if needed:
*/ */
@ -1328,9 +1654,9 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
* Remember the current modifiers state * Remember the current modifiers state
*/ */
window->State.Modifiers = window->State.Modifiers =
(GetKeyState( VK_LSHIFT ) || GetKeyState( VK_RSHIFT )) ? GLUT_ACTIVE_SHIFT : 0 | ( ( (GetKeyState( VK_LSHIFT ) < 0 ) || ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
(GetKeyState( VK_LCONTROL ) || GetKeyState( VK_RCONTROL )) ? GLUT_ACTIVE_CTRL : 0 | ( ( (GetKeyState( VK_LCONTROL ) < 0 ) || ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
(GetKeyState( VK_LMENU ) || GetKeyState( VK_RMENU )) ? GLUT_ACTIVE_ALT : 0; ( ( (GetKeyState( VK_LMENU ) < 0 ) || ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
/* /*
* Have the special callback executed: * Have the special callback executed:
@ -1345,6 +1671,13 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
} }
break; break;
case WM_CAPTURECHANGED : /* User has finished resizing the window, force a redraw */
if ( window->Callbacks.Display )
window->Callbacks.Display () ;
// lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ) ;
break ;
default: default:
/* /*
* Handle unhandled messages * Handle unhandled messages

View File

@ -49,6 +49,7 @@
*/ */
#define FREEGLUT_MENU_FONT GLUT_BITMAP_8_BY_13 #define FREEGLUT_MENU_FONT GLUT_BITMAP_8_BY_13
#define FREEGLUT_MENU_HEIGHT 15 #define FREEGLUT_MENU_HEIGHT 15
#define FREEGLUT_MENU_BORDER 8
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
@ -74,9 +75,8 @@ static SFG_MenuEntry *fghFindMenuEntry( SFG_Menu* menu, int index )
/* /*
* Private static function to check for the current menu/sub menu activity state * Private static function to check for the current menu/sub menu activity state
*/ */
static GLboolean fghCheckMenuStatus( SFG_Menu* menu ) static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
{ {
SFG_Window* window = fgStructure.Window;
SFG_MenuEntry* menuEntry; SFG_MenuEntry* menuEntry;
int x, y; int x, y;
@ -92,11 +92,11 @@ static GLboolean fghCheckMenuStatus( SFG_Menu* menu )
if( menuEntry->SubMenu != NULL && menuEntry->IsActive == TRUE ) if( menuEntry->SubMenu != NULL && menuEntry->IsActive == TRUE )
{ {
/* /*
* OKi, have the sub-menu checked, too. If it returns TRUE, it will mean * OK, have the sub-menu checked, too. If it returns TRUE, it will mean
* that it caught the mouse cursor and we do not need to regenerate * that it caught the mouse cursor and we do not need to regenerate
* the activity list, and so our parents do... * the activity list, and so our parents do...
*/ */
if( fghCheckMenuStatus( menuEntry->SubMenu ) == TRUE ) if( fghCheckMenuStatus( window, menuEntry->SubMenu ) == TRUE )
return( TRUE ); return( TRUE );
} }
} }
@ -147,30 +147,37 @@ static GLboolean fghCheckMenuStatus( SFG_Menu* menu )
/* /*
* OKi, we have marked that entry as active, but it would be also * OKi, we have marked that entry as active, but it would be also
* nice to have it's contents updated, in case it's a sub menu. * nice to have its contents updated, in case it's a sub menu.
* Also, ignore the return value of the check function: * Also, ignore the return value of the check function:
*/ */
if( menuEntry->SubMenu != NULL ) if( menuEntry->SubMenu != NULL )
{ {
int x = window->State.MouseX;
int y = window->State.MouseY;
/* /*
* Set up the initial menu position now... * Set up the initial menu position now...
*/ */
if( x > 15 ) menuEntry->SubMenu->X = x - 15; else menuEntry->SubMenu->X = 15; menuEntry->SubMenu->X = menu->X + menu->Width ;
if( y > 15 ) menuEntry->SubMenu->Y = y - 15; else menuEntry->SubMenu->Y = 15; menuEntry->SubMenu->Y = menu->Y + menuEntry->Ordinal * FREEGLUT_MENU_HEIGHT ;
if( x > (glutGet( GLUT_WINDOW_WIDTH ) - menuEntry->SubMenu->Width - 15) ) /*
menuEntry->SubMenu->X = glutGet( GLUT_WINDOW_WIDTH ) - menuEntry->SubMenu->Width - 15; * Make sure the submenu stays within the window
if( y > (glutGet( GLUT_WINDOW_HEIGHT ) - menuEntry->SubMenu->Height - 15) ) */
menuEntry->SubMenu->Y = glutGet( GLUT_WINDOW_HEIGHT ) - menuEntry->SubMenu->Height - 15; if ( menuEntry->SubMenu->X + menuEntry->SubMenu->Width > glutGet ( GLUT_WINDOW_WIDTH ) )
{
menuEntry->SubMenu->X = menu->X - menuEntry->SubMenu->Width ;
if ( menuEntry->SubMenu->X < 0 )
menuEntry->SubMenu->X = glutGet ( GLUT_WINDOW_WIDTH ) - menuEntry->SubMenu->Width ;
}
/* /*
* ...then check the submenu's state: * ...then check the submenu's state:
*/ */
fghCheckMenuStatus( menuEntry->SubMenu ); fghCheckMenuStatus( window, menuEntry->SubMenu );
/*
* Even if the submenu turned up inactive, activate it because its parent entry is active
*/
menuEntry->SubMenu->IsActive = TRUE ;
} }
/* /*
@ -186,7 +193,7 @@ static GLboolean fghCheckMenuStatus( SFG_Menu* menu )
} }
/* /*
* Displays a menu box and all of it's submenus (if they are active) * Displays a menu box and all of its submenus (if they are active)
*/ */
static void fghDisplayMenuBox( SFG_Menu* menu ) static void fghDisplayMenuBox( SFG_Menu* menu )
{ {
@ -199,18 +206,18 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
*/ */
glColor4f( 0.0, 0.0, 0.0, 1.0 ); glColor4f( 0.0, 0.0, 0.0, 1.0 );
glBegin( GL_QUADS ); glBegin( GL_QUADS );
glVertex2f( menu->X - 8 , menu->Y - 1 ); glVertex2f( menu->X , menu->Y - 1 );
glVertex2f( menu->X + 8 + menu->Width, menu->Y - 1 ); glVertex2f( menu->X + menu->Width, menu->Y - 1 );
glVertex2f( menu->X + 8 + menu->Width, menu->Y + 4 + menu->Height ); glVertex2f( menu->X + menu->Width, menu->Y + 4 + menu->Height );
glVertex2f( menu->X - 8 , menu->Y + 4 + menu->Height ); glVertex2f( menu->X , menu->Y + 4 + menu->Height );
glEnd(); glEnd();
glColor4f( 0.3, 0.4, 0.5, 1.0 ); glColor4f( 0.3, 0.4, 0.5, 1.0 );
glBegin( GL_QUADS ); glBegin( GL_QUADS );
glVertex2f( menu->X - 6 , menu->Y + 1 ); glVertex2f( menu->X - 2 , menu->Y + 1 );
glVertex2f( menu->X + 6 + menu->Width, menu->Y + 1 ); glVertex2f( menu->X - 2 + menu->Width, menu->Y + 1 );
glVertex2f( menu->X + 6 + menu->Width, menu->Y + 2 + menu->Height ); glVertex2f( menu->X - 2 + menu->Width, menu->Y + 2 + menu->Height );
glVertex2f( menu->X - 6 , menu->Y + 2 + menu->Height ); glVertex2f( menu->X - 2 , menu->Y + 2 + menu->Height );
glEnd(); glEnd();
/* /*
@ -236,10 +243,10 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
*/ */
glColor4f( 0.2, 0.3, 0.4, 1.0 ); glColor4f( 0.2, 0.3, 0.4, 1.0 );
glBegin( GL_QUADS ); glBegin( GL_QUADS );
glVertex2f( menu->X - 6 , menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 ); glVertex2f( menu->X - 2 , menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
glVertex2f( menu->X + 6 + menu->Width, menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 ); glVertex2f( menu->X - 2 + menu->Width, menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
glVertex2f( menu->X + 6 + menu->Width, menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 ); glVertex2f( menu->X - 2 + menu->Width, menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
glVertex2f( menu->X - 6 , menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 ); glVertex2f( menu->X - 2 , menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
glEnd(); glEnd();
} }
} }
@ -256,7 +263,7 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
* Move the raster into position... * Move the raster into position...
*/ */
glRasterPos2i( glRasterPos2i(
menu->X, menu->X + FREEGLUT_MENU_BORDER,
menu->Y + (i + 1)*FREEGLUT_MENU_HEIGHT menu->Y + (i + 1)*FREEGLUT_MENU_HEIGHT
); );
@ -264,6 +271,32 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
* Have the label drawn, character after character: * Have the label drawn, character after character:
*/ */
glutBitmapString( FREEGLUT_MENU_FONT, menuEntry->Text); glutBitmapString( FREEGLUT_MENU_FONT, menuEntry->Text);
/*
* If it's a submenu, draw a right arrow
*/
if ( menuEntry->SubMenu != NULL )
{
GLubyte arrow_char [] = { 0, 0, 32, 48, 56, 60, 62, 63, 62, 60, 56, 48, 32, 0, 0 } ;
int width = glutBitmapWidth ( FREEGLUT_MENU_FONT, ' ' ) ;
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
/*
* Set up the pixel unpacking ways
*/
glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
glRasterPos2i ( menu->X + menu->Width - 2 - width,
menu->Y + (i + 1)*FREEGLUT_MENU_HEIGHT ) ;
glBitmap ( width, FREEGLUT_MENU_HEIGHT, 0, 0, 0.0, 0.0, arrow_char ) ;
glPopClientAttrib();
}
} }
/* /*
@ -292,7 +325,6 @@ void fgDisplayMenu( void )
{ {
SFG_Window* window = fgStructure.Window; SFG_Window* window = fgStructure.Window;
SFG_Menu* menu = NULL; SFG_Menu* menu = NULL;
int i;
/* /*
* Make sure there is a current window available * Make sure there is a current window available
@ -302,17 +334,12 @@ void fgDisplayMenu( void )
/* /*
* Check if there is an active menu attached to this window... * Check if there is an active menu attached to this window...
*/ */
for( i=0; i<FREEGLUT_MAX_MENUS; i++ ) menu = window->ActiveMenu;
{
if( window->Menu[ i ] != NULL && window->MenuActive[ i ] == TRUE )
menu = window->Menu[ i ];
};
/* /*
* Did we find an active window? * Did we find an active window?
*/ */
freeglut_return_if_fail( menu != NULL ); freeglut_return_if_fail( menu != NULL );
/* /*
* Prepare the OpenGL state to do the rendering first: * Prepare the OpenGL state to do the rendering first:
*/ */
@ -345,7 +372,7 @@ void fgDisplayMenu( void )
/* /*
* First of all, have the exact menu status check: * First of all, have the exact menu status check:
*/ */
fghCheckMenuStatus( menu ); fghCheckMenuStatus( window, menu );
/* /*
* The status has been updated and we're ready to have the menu drawn now: * The status has been updated and we're ready to have the menu drawn now:
@ -357,32 +384,29 @@ void fgDisplayMenu( void )
*/ */
glPopAttrib(); glPopAttrib();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
glMatrixMode( GL_PROJECTION ); glMatrixMode( GL_PROJECTION );
glPopMatrix(); glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
} }
/* /*
* Activates a menu pointed by the function argument * Activates a menu pointed by the function argument
*/ */
void fgActivateMenu( int button ) void fgActivateMenu( SFG_Window* window, int button )
{ {
SFG_Window* window = fgStructure.Window;
SFG_Menu* menu = NULL;
int x, y; int x, y;
freeglut_assert_window; /*
* We'll be referencing this menu a lot, so remember its address:
*/
SFG_Menu* menu = window->Menu[ button ];
/* /*
* Mark the menu as active, so that it gets displayed: * Mark the menu as active, so that it gets displayed:
*/ */
window->MenuActive[ button ] = TRUE; window->ActiveMenu = menu;
menu->IsActive = TRUE ;
/*
* We'll be referencing this menu a lot, so remember it's address:
*/
menu = window->Menu[ button ];
/* /*
* Grab the mouse cursor position respective to the current window * Grab the mouse cursor position respective to the current window
@ -393,8 +417,10 @@ void fgActivateMenu( int button )
/* /*
* Set up the initial menu position now: * Set up the initial menu position now:
*/ */
if( x > 10 ) menu->X = x - 10; else menu->X = 5; menu->X = x ;
if( y > 10 ) menu->Y = y - 10; else menu->Y = 5; menu->Y = y ;
glutSetWindow ( window->ID ) ;
if( x > ( glutGet( GLUT_WINDOW_WIDTH ) - menu->Width ) ) if( x > ( glutGet( GLUT_WINDOW_WIDTH ) - menu->Width ) )
menu->X = glutGet( GLUT_WINDOW_WIDTH ) - menu->Width; menu->X = glutGet( GLUT_WINDOW_WIDTH ) - menu->Width;
@ -403,17 +429,32 @@ void fgActivateMenu( int button )
} }
/* /*
* Private static function to check for menu entry selection on menu deactivation * Check whether an active menu absorbs a mouse click
*/ */
static void fghCheckMenuSelect( SFG_Menu* menu ) GLboolean fgCheckActiveMenu ( SFG_Window *window, SFG_Menu *menu )
{
/*
* Near as I can tell, this is the active menu behaviour:
* - Down-click any button outside the menu, menu active: deactivate the menu
* - Down-click any button inside the menu, menu active: select the menu entry and deactivate the menu
* - Up-click the menu button outside the menu, menu active: nothing happens
* - Up-click the menu button inside the menu, menu active: select the menu entry and deactivate the menu
* Since menus can have submenus, we need to check this recursively.
*/
return fghCheckMenuStatus ( window, menu ) ;
}
/*
* Function to check for menu entry selection on menu deactivation
*/
void fgExecuteMenuCallback( SFG_Menu* menu )
{ {
SFG_MenuEntry *menuEntry; SFG_MenuEntry *menuEntry;
/* /*
* First of all check any of the active sub menus... * First of all check any of the active sub menus...
*/ */
for( menuEntry = menu->Entries.First; menuEntry; for( menuEntry = menu->Entries.First; menuEntry; menuEntry = menuEntry->Node.Next)
menuEntry = menuEntry->Node.Next)
{ {
/* /*
* Is this menu entry active? * Is this menu entry active?
@ -421,7 +462,7 @@ static void fghCheckMenuSelect( SFG_Menu* menu )
if( menuEntry->IsActive == TRUE ) if( menuEntry->IsActive == TRUE )
{ {
/* /*
* If this is not a sub menu, execute the menu callback and return... * If there is not a sub menu, execute the menu callback and return...
*/ */
if( menuEntry->SubMenu == NULL ) if( menuEntry->SubMenu == NULL )
{ {
@ -437,7 +478,7 @@ static void fghCheckMenuSelect( SFG_Menu* menu )
/* /*
* Otherwise recurse into the submenu. * Otherwise recurse into the submenu.
*/ */
fghCheckMenuSelect( menuEntry->SubMenu ); fgExecuteMenuCallback( menuEntry->SubMenu );
/* /*
* There is little sense in dwelling the search on * There is little sense in dwelling the search on
@ -450,41 +491,23 @@ static void fghCheckMenuSelect( SFG_Menu* menu )
/* /*
* Deactivates a menu pointed by the function argument. * Deactivates a menu pointed by the function argument.
*/ */
void fgDeactivateMenu( int button ) void fgDeactivateMenu( SFG_Window *window )
{ {
SFG_Window* window = fgStructure.Window;
SFG_Menu* menu = NULL;
int i;
/*
* Make sure there is a current window available...
*/
freeglut_assert_window;
/* /*
* Check if there is an active menu attached to this window... * Check if there is an active menu attached to this window...
*/ */
for( i=0; i<FREEGLUT_MAX_MENUS; i++ ) SFG_Menu* menu = window->ActiveMenu;
{
if( window->Menu[ i ] != NULL && window->MenuActive[ i ] == TRUE )
menu = window->Menu[ i ];
};
/* /*
* Did we find an active window? * Did we find an active window?
*/ */
freeglut_return_if_fail( menu != NULL ); freeglut_return_if_fail( menu != NULL );
/*
* Check if there was any menu entry active. This would
* mean the user has selected a menu entry...
*/
fghCheckMenuSelect( menu );
/* /*
* Forget about having that menu active anymore, now: * Forget about having that menu active anymore, now:
*/ */
fgStructure.Window->MenuActive[ button ] = FALSE; window->ActiveMenu = NULL;
menu->IsActive = FALSE ;
} }
/* /*
@ -524,7 +547,7 @@ void fghCalculateMenuBoxSize( void )
* Store the menu's box size now: * Store the menu's box size now:
*/ */
fgStructure.Menu->Height = height; fgStructure.Menu->Height = height;
fgStructure.Menu->Width = width; fgStructure.Menu->Width = width + 2 * FREEGLUT_MENU_BORDER ;
} }
@ -581,7 +604,7 @@ int FGAPIENTRY glutGetMenu( void )
} }
/* /*
* Sets the current menu given it's menu ID * Sets the current menu given its menu ID
*/ */
void FGAPIENTRY glutSetMenu( int menuID ) void FGAPIENTRY glutSetMenu( int menuID )
{ {

View File

@ -52,7 +52,7 @@ int FGAPIENTRY glutExtensionSupported( const char* extension )
{ {
const char *extensions; const char *extensions;
const char *ptr; const char *ptr;
int i; int len = strlen ( extension ) ;
/* /*
* Make sure there is a current window, and thus -- a current context available * Make sure there is a current window, and thus -- a current context available
@ -61,7 +61,7 @@ int FGAPIENTRY glutExtensionSupported( const char* extension )
freeglut_return_val_if_fail( fgStructure.Window != NULL, 0 ); freeglut_return_val_if_fail( fgStructure.Window != NULL, 0 );
/* /*
* Not it is safe to query the extenstions * Note it is safe to query the extensions
*/ */
extensions = glGetString(GL_EXTENSIONS); extensions = glGetString(GL_EXTENSIONS);
@ -70,8 +70,7 @@ int FGAPIENTRY glutExtensionSupported( const char* extension )
/* /*
* Check if the extension itself looks valid * Check if the extension itself looks valid
*/ */
for( i=0; i<strlen( extension ); i++ ) if ( strchr ( extension, ' ' ) != NULL )
if( extension[ i ] == ' ' )
return( 0 ); return( 0 );
/* /*
@ -79,20 +78,22 @@ int FGAPIENTRY glutExtensionSupported( const char* extension )
*/ */
for (ptr = extensions; *ptr;) for (ptr = extensions; *ptr;)
{ {
const char *str = extension; /*
char c; * Is it the current extension?
*/
while ( (c = *(str++)) ) if ( strncmp ( extension, extensions, len ) == 0 )
{
if (*ptr != c)
goto next;
ptr++;
}
if ( !(c = *ptr) || c == ' ' )
return 1 ; return 1 ;
next:
while ( (c = *ptr) && c != ' ' ) /*
ptr++; * No, go find the next extension. They are separated from each other by one or more blank spaces.
*/
ptr = strchr ( ptr + len, ' ' ) ;
/*
* If we ran off the end of the "extensions" character string, we didn't find it. Return failure.
*/
if ( !ptr ) return 0 ;
while ( *ptr == ' ' ) while ( *ptr == ' ' )
ptr++ ; ptr++ ;
} }
@ -101,7 +102,7 @@ int FGAPIENTRY glutExtensionSupported( const char* extension )
} }
/* /*
* This function reports all the errors that happened till now * This function reports all the OpenGL errors that happened till now
*/ */
void FGAPIENTRY glutReportErrors( void ) void FGAPIENTRY glutReportErrors( void )
{ {
@ -133,10 +134,10 @@ void FGAPIENTRY glutReportErrors( void )
/* /*
* Turns the ignore key auto repeat feature on and off * Turns the ignore key auto repeat feature on and off
*/ */
void FGAPIENTRY glutIgnoreKeyRepeat( int ignore ) void FGAPIENTRY glutIgnoreKeyRepeat( int ignore ) /* DEPRECATED 11/4/02 - Do not use */
{ {
/* /*
* This is simple and not demanging... * This is simple and not damaging...
*/ */
fgState.IgnoreKeyRepeat = ignore ? TRUE : FALSE; fgState.IgnoreKeyRepeat = ignore ? TRUE : FALSE;
} }

View File

@ -47,32 +47,9 @@
/* -- LOCAL DEFINITIONS ---------------------------------------------------- */ /* -- LOCAL DEFINITIONS ---------------------------------------------------- */
/*
* Those are definitions introduced to make the glutGet() more easy,
* however they might introduce errors if someone ports GLX to Win32 :)
*
* Btw. this is not that a bad idea (wrapping WGL around GLX)...
*/
#if TARGET_HOST_WIN32
# define GLX_RGBA 0x01
# define GLX_DOUBLEBUFFER 0x02
# define GLX_BUFFER_SIZE 0x03
# define GLX_STENCIL_SIZE 0x04
# define GLX_DEPTH_SIZE 0x05
# define GLX_RED_SIZE 0x06
# define GLX_GREEN_SIZE 0x07
# define GLX_BLUE_SIZE 0x08
# define GLX_ALPHA_SIZE 0x09
# define GLX_ACCUM_RED_SIZE 0x0A
# define GLX_ACCUM_GREEN_SIZE 0x0B
# define GLX_ACCUM_BLUE_SIZE 0x0C
# define GLX_ACCUM_ALPHA_SIZE 0x0D
# define GLX_STEREO 0x0E
#endif
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
#if TARGET_HOST_UNIX_X11
/* /*
* Queries the GL context about some attributes * Queries the GL context about some attributes
*/ */
@ -86,57 +63,67 @@ static int fghGetConfig( int attribute )
if( fgStructure.Window == NULL ) if( fgStructure.Window == NULL )
return( 0 ); return( 0 );
#if TARGET_HOST_UNIX_X11
/* /*
* glXGetConfig should work fine * glXGetConfig should work fine
*/ */
glXGetConfig( fgDisplay.Display, fgStructure.Window->Window.VisualInfo, attribute, &returnValue ); glXGetConfig( fgDisplay.Display, fgStructure.Window->Window.VisualInfo, attribute, &returnValue );
#elif TARGET_HOST_WIN32
/*
* This is going to be a bit harder than the X11 version...
*/
# pragma message( "freeglut_state.c::fghGetConfig() says hello world my name is not implemented!" )
switch( attribute )
{
case GLX_RGBA:
case GLX_DOUBLEBUFFER:
case GLX_BUFFER_SIZE:
case GLX_RED_SIZE:
case GLX_GREEN_SIZE:
case GLX_BLUE_SIZE:
case GLX_DEPTH_SIZE:
return( 1 );
case GLX_STENCIL_SIZE:
case GLX_ALPHA_SIZE:
case GLX_ACCUM_RED_SIZE:
case GLX_ACCUM_GREEN_SIZE:
case GLX_ACCUM_BLUE_SIZE:
case GLX_ACCUM_ALPHA_SIZE:
case GLX_STEREO:
default:
/*
* Well, this looks like not implemented to me :)
*/
return( 0 );
}
#endif
/* /*
* Have the query results returned * Have the query results returned
*/ */
return ( returnValue ) ; return ( returnValue ) ;
} }
#endif
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
* General settings assignment method
*/
void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
{
freeglut_assert_ready;
/*
* Check what is the caller querying for. In chronological code add order.
*/
switch( eWhat )
{
case GLUT_INIT_WINDOW_X: fgState.Position.X = (GLint)value ;
break ;
case GLUT_INIT_WINDOW_Y: fgState.Position.Y = (GLint)value ;
break ;
case GLUT_INIT_WINDOW_WIDTH: fgState.Size.X = (GLint)value ;
break ;
case GLUT_INIT_WINDOW_HEIGHT: fgState.Size.Y = (GLint)value ;
break ;
case GLUT_INIT_DISPLAY_MODE: fgState.DisplayMode = (unsigned int)value ;
break ;
case GLUT_ACTION_ON_WINDOW_CLOSE: fgState.ActionOnWindowClose = value ;
break ;
case GLUT_WINDOW_CURSOR:
if( fgStructure.Window != NULL ) fgStructure.Window->State.Cursor = value ;
break ;
default:
/*
* Just have it reported, so that we can see what needs to be implemented
*/
fgWarning( "glutSetOption(): missing enum handle %i\n", eWhat );
break;
}
}
/* /*
* General settings query method * General settings query method
*/ */
int FGAPIENTRY glutGet( GLenum eWhat ) int FGAPIENTRY glutGet( GLenum eWhat )
{ {
int returnValue ;
GLboolean boolValue ;
freeglut_assert_ready; freeglut_assert_ready;
/* /*
@ -172,8 +159,9 @@ int FGAPIENTRY glutGet( GLenum eWhat )
*/ */
return( 0 ); return( 0 );
#if TARGET_HOST_UNIX_X11
/* /*
* The rest of GLX queries is general enough to use a macro to check them * The rest of GLX queries under X are general enough to use a macro to check them
*/ */
# define GLX_QUERY(a,b) case a: return( fghGetConfig( b ) ); # define GLX_QUERY(a,b) case a: return( fghGetConfig( b ) );
@ -194,7 +182,6 @@ int FGAPIENTRY glutGet( GLenum eWhat )
# undef GLX_QUERY # undef GLX_QUERY
#if TARGET_HOST_UNIX_X11
/* /*
* Colormap size is handled in a bit different way than all the rest * Colormap size is handled in a bit different way than all the rest
*/ */
@ -314,6 +301,60 @@ int FGAPIENTRY glutGet( GLenum eWhat )
#elif TARGET_HOST_WIN32 #elif TARGET_HOST_WIN32
/*
* Handle the OpenGL inquiries
*/
case GLUT_WINDOW_RGBA:
glGetBooleanv ( GL_RGBA_MODE, &boolValue ) ; /* True if color buffers store RGBA */
returnValue = boolValue ? 1 : 0 ;
return ( returnValue ) ;
case GLUT_WINDOW_DOUBLEBUFFER:
glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue ) ; /* True if front and back buffers exist */
returnValue = boolValue ? 1 : 0 ;
return ( returnValue ) ;
case GLUT_WINDOW_STEREO:
glGetBooleanv ( GL_STEREO, &boolValue ) ; /* True if left and right buffers exist */
returnValue = boolValue ? 1 : 0 ;
return ( returnValue ) ;
case GLUT_WINDOW_RED_SIZE:
glGetIntegerv ( GL_RED_BITS, &returnValue ) ; /* Number of bits per red component in color buffers */
return ( returnValue ) ;
case GLUT_WINDOW_GREEN_SIZE:
glGetIntegerv ( GL_GREEN_BITS, &returnValue ) ; /* Number of bits per green component in color buffers */
return ( returnValue ) ;
case GLUT_WINDOW_BLUE_SIZE:
glGetIntegerv ( GL_BLUE_BITS, &returnValue ) ; /* Number of bits per blue component in color buffers */
return ( returnValue ) ;
case GLUT_WINDOW_ALPHA_SIZE:
glGetIntegerv ( GL_ALPHA_BITS, &returnValue ) ; /* Number of bits per alpha component in color buffers */
return ( returnValue ) ;
case GLUT_WINDOW_ACCUM_RED_SIZE:
glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue ) ; /* Number of bits per red component in the accumulation buffer */
return ( returnValue ) ;
case GLUT_WINDOW_ACCUM_GREEN_SIZE:
glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue ) ; /* Number of bits per green component in the accumulation buffer */
return ( returnValue ) ;
case GLUT_WINDOW_ACCUM_BLUE_SIZE:
glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue ) ; /* Number of bits per blue component in the accumulation buffer */
return ( returnValue ) ;
case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue ) ; /* Number of bits per alpha component in the accumulation buffer */
return ( returnValue ) ;
case GLUT_WINDOW_DEPTH_SIZE:
glGetIntegerv ( GL_DEPTH_BITS, &returnValue ) ; /* Number of depth-buffer bitplanes */
return ( returnValue ) ;
case GLUT_WINDOW_BUFFER_SIZE:
returnValue = 1 ; /* ????? */
return ( returnValue ) ;
case GLUT_WINDOW_STENCIL_SIZE:
returnValue = 0 ; /* ????? */
return ( returnValue ) ;
/*
* Window position and size
*/
case GLUT_WINDOW_X: case GLUT_WINDOW_X:
case GLUT_WINDOW_Y: case GLUT_WINDOW_Y:
case GLUT_WINDOW_WIDTH: case GLUT_WINDOW_WIDTH:
@ -411,6 +452,8 @@ int FGAPIENTRY glutGet( GLenum eWhat )
return( fgListLength( &fgStructure.Menu->Entries ) ); return( fgListLength( &fgStructure.Menu->Entries ) );
case GLUT_ACTION_ON_WINDOW_CLOSE: return ( fgState.ActionOnWindowClose ) ;
default: default:
/* /*
* Just have it reported, so that we can see what needs to be implemented * Just have it reported, so that we can see what needs to be implemented

View File

@ -2,11 +2,14 @@
/* This file has been automatically generated by the genstroke utility. */ /* This file has been automatically generated by the genstroke utility. */
#include "../include/GL/freeglut_internal.h" #include "../include/GL/freeglut_internal.h"
#ifdef TARGET_HOST_WIN32
#pragma warning ( once:4305 )
#endif
/* char: 0x20 */ /* char: 0x20 */
static const SFG_StrokeStrip ch32st[] = static const SFG_StrokeStrip ch32st[] =
{ {
{ 0, NULL }
}; };
static const SFG_StrokeChar ch32 = {104.762,0,ch32st}; static const SFG_StrokeChar ch32 = {104.762,0,ch32st};

View File

@ -2,11 +2,15 @@
/* This file has been automatically generated by the genstroke utility. */ /* This file has been automatically generated by the genstroke utility. */
#include "../include/GL/freeglut_internal.h" #include "../include/GL/freeglut_internal.h"
#ifdef TARGET_HOST_WIN32
#pragma warning ( once:4305 )
#endif
/* char: 0x20 */ /* char: 0x20 */
static const SFG_StrokeStrip ch32st[] = static const SFG_StrokeStrip ch32st[] =
{ {
{ 0, NULL }
}; };
static const SFG_StrokeChar ch32 = {104.762,0,ch32st}; static const SFG_StrokeChar ch32 = {104.762,0,ch32st};

View File

@ -106,7 +106,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, int x, int y,
* Open the window now. The fgOpenWindow() function is system * Open the window now. The fgOpenWindow() function is system
* dependant, and resides in freeglut_window.c. Uses fgState. * dependant, and resides in freeglut_window.c. Uses fgState.
*/ */
fgOpenWindow( window, title, x, y, w, h, gameMode ); fgOpenWindow( window, title, x, y, w, h, gameMode, (parent != NULL) ? TRUE : FALSE );
/* /*
* Return a pointer to the newly created window * Return a pointer to the newly created window
@ -160,7 +160,67 @@ SFG_Menu* fgCreateMenu( FGCBmenu menuCallback )
} }
/* /*
* This function destroys a window and all of it's subwindows. Actually, * Linked list of windows to destroy ... this is so we don't destroy a window from the middle of
* its callback. Some C compilers take an extremely dim view of this.
*/
static SFG_WindowList* WindowsToDestroy = (SFG_WindowList*)NULL ;
/*
* Function to add a window to the linked list of windows to destroy. Subwindows are automatically
* added because they hang from the window structure.
*/
void fgAddToWindowDestroyList ( SFG_Window* window, GLboolean needToClose )
{
SFG_WindowList *new_list_entry = (SFG_WindowList*)malloc ( sizeof(SFG_WindowList) ) ;
new_list_entry->window = window ;
new_list_entry->needToClose = needToClose ;
new_list_entry->next = WindowsToDestroy ;
WindowsToDestroy = new_list_entry ;
/*
* Check the execution state. If this has been called from "glutDestroyWindow",
* a statement in that function will reset the "ExecState" after this function returns.
*/
if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
{
/*
* Set the execution state flag to drop out of the main loop.
*/
if ( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
fgState.ExecState = GLUT_EXEC_STATE_STOP ;
}
}
/*
* Function to close down all the windows in the "WindowsToDestroy" list
*/
void fgCloseWindows ()
{
fgExecutionState ExecState = fgState.ExecState ;
SFG_WindowList *window_ptr = WindowsToDestroy ;
WindowsToDestroy = (SFG_WindowList*)NULL ; // In case the destroy callbacks cause more windows to be closed
while ( window_ptr )
{
SFG_WindowList *next = window_ptr->next ;
fgDestroyWindow ( window_ptr->window, window_ptr->needToClose ) ;
free ( window_ptr ) ;
window_ptr = next ;
if ( !window_ptr ) window_ptr = WindowsToDestroy ;
}
/*
* Since the "fgDestroyWindow" function could easily have set the "ExecState" to stop,
* let's set it back to what it was.
*/
fgState.ExecState = ExecState ;
}
/*
* This function destroys a window and all of its subwindows. Actually,
* another function, defined in freeglut_window.c is called, but this is * another function, defined in freeglut_window.c is called, but this is
* a whole different story... * a whole different story...
*/ */
@ -174,17 +234,23 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose )
/* /*
* Does this window have any subwindows? * Does this window have any subwindows?
*/ */
if( (subWindow = window->Children.First) != NULL ) while ( (subWindow = window->Children.First) != NULL )
{ {
/* /*
* Destroy the first window in the list (possibly destroying * Destroy the first window in the list (possibly destroying
* it's subwindows too). This is not very effective, but works * its subwindows too). This is not very effective, but works
*/ */
fgDestroyWindow( subWindow, TRUE ); fgDestroyWindow( subWindow, needToClose );
} }
/* /*
* Now we should remove the reference to this window from it's parent * If the programmer defined a destroy callback, call it
*/
if ( window->Callbacks.Destroy != NULL )
window->Callbacks.Destroy () ;
/*
* Now we should remove the reference to this window from its parent
*/ */
if ( window->Parent != NULL ) if ( window->Parent != NULL )
fgListRemove( &window->Parent->Children, &window->Node ); fgListRemove( &window->Parent->Children, &window->Node );
@ -212,7 +278,7 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose )
} }
/* /*
* This is a helper static function that removes a menu (given it's pointer) * This is a helper static function that removes a menu (given its pointer)
* from any windows that can be accessed from a given parent... * from any windows that can be accessed from a given parent...
*/ */
static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu ) static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu )
@ -273,8 +339,7 @@ void fgDestroyMenu( SFG_Menu* menu )
/* /*
* First of all, have all references to this menu removed from all windows: * First of all, have all references to this menu removed from all windows:
*/ */
for( window = fgStructure.Windows.First; window; for( window = fgStructure.Windows.First; window; window = window->Node.Next )
window = window->Node.Next )
{ {
fghRemoveMenuFromWindow( window, menu ); fghRemoveMenuFromWindow( window, menu );
} }
@ -289,7 +354,7 @@ void fgDestroyMenu( SFG_Menu* menu )
/* /*
* Now we are pretty sure the menu is not used anywhere * Now we are pretty sure the menu is not used anywhere
* and that we can remove all of it's entries * and that we can remove all of its entries
*/ */
while( (entry = menu->Entries.First) != NULL ) while( (entry = menu->Entries.First) != NULL )
{ {
@ -423,7 +488,7 @@ void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, SFG_Enum
} }
/* /*
* A static helper function to look for a window given it's handle * A static helper function to look for a window given its handle
*/ */
static void fghcbWindowByHandle( SFG_Window *window, SFG_Enumerator *enumerator ) static void fghcbWindowByHandle( SFG_Window *window, SFG_Enumerator *enumerator )
{ {
@ -495,7 +560,7 @@ SFG_Window* fgWindowByHandle
} }
/* /*
* A static helper function to look for a window given it's ID * A static helper function to look for a window given its ID
*/ */
static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator ) static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator )
{ {
@ -554,7 +619,7 @@ SFG_Window* fgWindowByID( int windowID )
} }
/* /*
* Looks up a menu given it's ID. This is easier that fgWindowByXXX * Looks up a menu given its ID. This is easier that fgWindowByXXX
* as all menus are placed in a single doubly linked list... * as all menus are placed in a single doubly linked list...
*/ */
SFG_Menu* fgMenuByID( int menuID ) SFG_Menu* fgMenuByID( int menuID )

View File

@ -258,8 +258,13 @@ GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly )
pfd.cAccumGreenBits = 0; pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0; pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0; pfd.cAccumAlphaBits = 0;
#if 0
pfd.cDepthBits = 32; pfd.cDepthBits = 32;
pfd.cStencilBits = 0; pfd.cStencilBits = 0;
#else
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
#endif
pfd.cAuxBuffers = 0; pfd.cAuxBuffers = 0;
pfd.iLayerType = PFD_MAIN_PLANE; pfd.iLayerType = PFD_MAIN_PLANE;
pfd.bReserved = 0; pfd.bReserved = 0;
@ -300,7 +305,7 @@ GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly )
* Opens a window. Requires a SFG_Window object created and attached * Opens a window. Requires a SFG_Window object created and attached
* to the freeglut structure. OpenGL context is created here. * to the freeglut structure. OpenGL context is created here.
*/ */
void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, int h, GLboolean gameMode ) void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, int h, GLboolean gameMode, int isSubWindow )
{ {
#if TARGET_HOST_UNIX_X11 #if TARGET_HOST_UNIX_X11
XSetWindowAttributes winAttr; XSetWindowAttributes winAttr;
@ -471,7 +476,6 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
WNDCLASS wc; WNDCLASS wc;
int flags; int flags;
ATOM atom; ATOM atom;
HWND hWnd;
freeglut_assert_ready; freeglut_assert_ready;
@ -482,14 +486,19 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
assert( atom != 0 ); assert( atom != 0 );
if( gameMode == FALSE ) if( gameMode == FALSE )
{
if ( !isSubWindow )
{ {
/* /*
* Update the window position and dimensions, taking account of window decorations * Update the window position and dimensions, taking account of window decorations
*/ */
x -= (GetSystemMetrics( SM_CXSIZEFRAME ) - 1);
y -= (GetSystemMetrics( SM_CYSIZEFRAME ) - 1); x -= (GetSystemMetrics( SM_CXSIZEFRAME ) );
w += (GetSystemMetrics( SM_CXSIZEFRAME ) - 1)*2; y -= (GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ) );
h += (GetSystemMetrics( SM_CYSIZEFRAME ) - 1)*2 + GetSystemMetrics( SM_CYCAPTION ); if ( y < 0 ) y = 0 ;
w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 + GetSystemMetrics( SM_CYCAPTION );
}
/* /*
* Check if the user wants us to use the default position/size * Check if the user wants us to use the default position/size
@ -600,7 +609,7 @@ void fgCloseWindow( SFG_Window* window )
int FGAPIENTRY glutCreateWindow( const char* title ) int FGAPIENTRY glutCreateWindow( const char* title )
{ {
/* /*
* Create a new window and return it's unique ID number * Create a new window and return its unique ID number
*/ */
return( fgCreateWindow( NULL, title, fgState.Position.X, fgState.Position.Y, return( fgCreateWindow( NULL, title, fgState.Position.X, fgState.Position.Y,
fgState.Size.X, fgState.Size.Y, FALSE )->ID ); fgState.Size.X, fgState.Size.Y, FALSE )->ID );
@ -638,7 +647,7 @@ int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
} }
/* /*
* Destroys a window and all of it's subwindows * Destroys a window and all of its subwindows
*/ */
void FGAPIENTRY glutDestroyWindow( int windowID ) void FGAPIENTRY glutDestroyWindow( int windowID )
{ {
@ -652,7 +661,7 @@ void FGAPIENTRY glutDestroyWindow( int windowID )
* There is a function that performs all needed steps * There is a function that performs all needed steps
* defined in freeglut_structure.c. Let's use it: * defined in freeglut_structure.c. Let's use it:
*/ */
fgDestroyWindow( window, TRUE ); fgAddToWindowDestroyList( window, TRUE );
} }
/* /*
@ -955,19 +964,37 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
#elif TARGET_HOST_WIN32 #elif TARGET_HOST_WIN32
{ {
RECT winRect; RECT winRect;
int x, y ;
/* /*
* First off, grab the current window's position * First off, grab the current window's position
*/ */
GetWindowRect( fgStructure.Window->Window.Handle, &winRect ); GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
x = winRect.left ;
y = winRect.top ;
if ( fgStructure.Window->Parent == NULL ) /* If this is not a subwindow ... */
{
/*
* Adjust the size of the window to allow for the size of the frame
*/
width += (GetSystemMetrics( SM_CXSIZEFRAME ) - 1)*2;
height += (GetSystemMetrics( SM_CYSIZEFRAME ) - 1)*2 + GetSystemMetrics( SM_CYCAPTION );
}
else /* This is a subwindow, get the parent window's position and subtract it off */
{
GetWindowRect ( fgStructure.Window->Parent->Window.Handle, &winRect ) ;
x -= winRect.left + GetSystemMetrics( SM_CXSIZEFRAME ) ;
y -= winRect.top + GetSystemMetrics( SM_CXSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ) ;
}
/* /*
* Resize the window, forcing a redraw to happen * Resize the window, forcing a redraw to happen
*/ */
MoveWindow( MoveWindow(
fgStructure.Window->Window.Handle, fgStructure.Window->Window.Handle,
winRect.left, x,
winRect.top, y,
width, width,
height, height,
TRUE TRUE
@ -999,6 +1026,16 @@ void FGAPIENTRY glutPositionWindow( int x, int y )
*/ */
GetWindowRect( fgStructure.Window->Window.Handle, &winRect ); GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
if ( fgStructure.Window->Parent == NULL ) /* If this is not a subwindow ... */
{
/*
* Adjust the position of the window to allow for the size of the frame
*/
x -= (GetSystemMetrics( SM_CXSIZEFRAME ) - 1);
y -= (GetSystemMetrics( SM_CYSIZEFRAME ) - 1 + GetSystemMetrics( SM_CYCAPTION ));
if ( y < 0 ) y = 0 ;
}
/* /*
* Reposition the window, forcing a redraw to happen * Reposition the window, forcing a redraw to happen
*/ */