1
1
Fork 0
mirror of https://github.com/QB64-Phoenix-Edition/QB64pe.git synced 2024-07-04 04:50:22 +00:00

Update FreeGLUT to v2.8.1

This commit is contained in:
Samuel Gomes 2024-01-30 03:01:26 +05:30
parent b5e896384a
commit 3a260f1002
17 changed files with 8108 additions and 4977 deletions

View file

@ -27,7 +27,7 @@ $(PATH_INTERNAL_C)/parts/core/glew/%.o: $(PATH_INTERNAL_C)/parts/core/glew/%.c
$(CC) -O1 $(CFLAGS) $(FREEGLUT_INCLUDE) -DGLEW_STATIC -Wall $< -c -o $@ $(CC) -O1 $(CFLAGS) $(FREEGLUT_INCLUDE) -DGLEW_STATIC -Wall $< -c -o $@
$(PATH_INTERNAL_C)/parts/core/freeglut/%.o: $(PATH_INTERNAL_C)/parts/core/freeglut/%.c $(PATH_INTERNAL_C)/parts/core/freeglut/%.o: $(PATH_INTERNAL_C)/parts/core/freeglut/%.c
$(CC) -O3 $(CFLAGS) $(FREEGLUT_INCLUDE) -DFREEGLUT_STATIC -Wall $< -c -o $@ $(CC) -O3 $(CFLAGS) $(FREEGLUT_INCLUDE) -DFREEGLUT_STATIC -DHAVE_UNISTD_H -DHAVE_FCNTL_H -Wall $< -c -o $@
$(FREEGLUT_LIB): $(FREEGLUT_OBJS) $(FREEGLUT_LIB): $(FREEGLUT_OBJS)
$(AR) rcs $@ $(FREEGLUT_OBJS) $(AR) rcs $@ $(FREEGLUT_OBJS)

View file

@ -159,6 +159,22 @@ static void fghWarpPointer ( int x, int y )
/* Make the warp visible immediately. */ /* Make the warp visible immediately. */
XFlush( fgDisplay.Display ); XFlush( fgDisplay.Display );
} }
void fghGetCursorPos(SFG_XYUse *mouse_pos)
{
/* Get current pointer location in screen coordinates
*/
Window junk_window;
unsigned int junk_mask;
int junk_pos;
XQueryPointer(fgDisplay.Display, fgDisplay.RootWindow,
&junk_window, &junk_window,
&mouse_pos->X, &mouse_pos->Y,
&junk_pos, &junk_pos, &junk_mask);
mouse_pos->Use = GL_TRUE;
}
#endif #endif
@ -205,7 +221,7 @@ static void fghSetCursor ( SFG_Window *window, int cursorID )
{ {
MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW ); MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW );
MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW ); MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW );
MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HAND ); MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HAND ); // QB64-PE: GLUT_CURSOR_INFO -> IDC_HAND per FreeGLUT 3.4.0
MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS ); MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS );
MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP ); MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP );
MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL ); MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL );
@ -244,6 +260,18 @@ static void fghWarpPointer ( int x, int y )
ClientToScreen( fgStructure.CurrentWindow->Window.Handle, &coords ); ClientToScreen( fgStructure.CurrentWindow->Window.Handle, &coords );
SetCursorPos( coords.x, coords.y ); SetCursorPos( coords.x, coords.y );
} }
void fghGetCursorPos(SFG_XYUse *mouse_pos)
{
/* Get current pointer location in screen coordinates
*/
POINT pos;
GetCursorPos(&pos);
mouse_pos->X = pos.x;
mouse_pos->Y = pos.y;
mouse_pos->Use = GL_TRUE;
}
#endif #endif

View file

@ -136,6 +136,8 @@ static GLUTproc fghGetGLUTProcAddress( const char* procName )
CHECK_NAME(glutSolidTorus); CHECK_NAME(glutSolidTorus);
CHECK_NAME(glutWireDodecahedron); CHECK_NAME(glutWireDodecahedron);
CHECK_NAME(glutSolidDodecahedron); CHECK_NAME(glutSolidDodecahedron);
CHECK_NAME(glutWireTeapot);
CHECK_NAME(glutSolidTeapot);
CHECK_NAME(glutWireOctahedron); CHECK_NAME(glutWireOctahedron);
CHECK_NAME(glutSolidOctahedron); CHECK_NAME(glutSolidOctahedron);
CHECK_NAME(glutWireTetrahedron); CHECK_NAME(glutWireTetrahedron);

View file

@ -58,7 +58,7 @@ static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)
/* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and /* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and
* the user actually cares about it (rate > 0) * the user actually cares about it (rate > 0)
*/ */
use_rate = ( rate > 0 ) && ( ( ver_major >= 1 ) || use_rate = ( rate > 0 ) && ( ( ver_major > 1 ) ||
( ( ver_major == 1 ) && ( ver_minor >= 1 ) ) ); ( ( ver_major == 1 ) && ( ver_minor >= 1 ) ) );
/* this loop is only so that the whole thing will be repeated if someone /* this loop is only so that the whole thing will be repeated if someone
@ -105,7 +105,7 @@ static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)
if(res_idx == -1) if(res_idx == -1)
break; /* no matching resolution */ break; /* no matching resolution */
#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) #if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
if(use_rate) { if(use_rate) {
rate = fgState.GameModeRefresh; rate = fgState.GameModeRefresh;
@ -130,7 +130,7 @@ static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)
break; break;
} }
#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) #if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
if(use_rate) if(use_rate)
result = XRRSetScreenConfigAndRate(fgDisplay.Display, xrr_config, result = XRRSetScreenConfigAndRate(fgDisplay.Display, xrr_config,
fgDisplay.RootWindow, res_idx, rot, rate, timestamp); fgDisplay.RootWindow, res_idx, rot, rate, timestamp);
@ -154,6 +154,96 @@ static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)
} }
#endif /* TARGET_HOST_POSIX_X11 */ #endif /* TARGET_HOST_POSIX_X11 */
#if TARGET_HOST_MS_WINDOWS
/*
* Changes to requested devmode, if it doesn't match current mode
*/
GLboolean fghPlatformChangeDisplayMode(GLboolean haveToTest, DEVMODE *devModeRequested)
{
GLboolean success = GL_FALSE;
DEVMODE devModeCurrent;
char *fggmstr = NULL;
char displayMode[300];
/* Get current display mode */
EnumDisplaySettings( fgDisplay.DisplayName, ENUM_CURRENT_SETTINGS, &devModeCurrent );
/* Now see if requested matches current mode, then we're done
* There's only four fields we touch:
* - dmPelsWidth
* - dmPelsHeight
* - dmBitsPerPel
* - dmDisplayFrequency
*/
if (devModeCurrent.dmPelsWidth ==devModeRequested->dmPelsWidth &&
devModeCurrent.dmPelsHeight ==devModeRequested->dmPelsHeight &&
devModeCurrent.dmBitsPerPel ==devModeRequested->dmBitsPerPel &&
devModeCurrent.dmDisplayFrequency==devModeRequested->dmDisplayFrequency)
{
if (!haveToTest)
{
/* update vars in case if actual switch was requested */
EnumDisplaySettings( fgDisplay.DisplayName, ENUM_CURRENT_SETTINGS, &devModeCurrent );
fgState.GameModeSize.X = devModeCurrent.dmPelsWidth;
fgState.GameModeSize.Y = devModeCurrent.dmPelsHeight;
fgState.GameModeDepth = devModeCurrent.dmBitsPerPel;
fgState.GameModeRefresh = devModeCurrent.dmDisplayFrequency;
}
/* We're done */
return GL_TRUE;
}
/* Ok, we do have a mode switch to perform/test */
switch ( ChangeDisplaySettingsEx(fgDisplay.DisplayName, devModeRequested, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) )
{
case DISP_CHANGE_SUCCESSFUL:
success = GL_TRUE;
if (!haveToTest)
{
/* update vars in case if windows switched to proper mode */
EnumDisplaySettings( fgDisplay.DisplayName, ENUM_CURRENT_SETTINGS, &devModeCurrent );
fgState.GameModeSize.X = devModeCurrent.dmPelsWidth;
fgState.GameModeSize.Y = devModeCurrent.dmPelsHeight;
fgState.GameModeDepth = devModeCurrent.dmBitsPerPel;
fgState.GameModeRefresh = devModeCurrent.dmDisplayFrequency;
}
break;
case DISP_CHANGE_RESTART:
fggmstr = "The computer must be restarted for the graphics mode to work.";
break;
case DISP_CHANGE_BADFLAGS:
fggmstr = "An invalid set of flags was passed in.";
break;
case DISP_CHANGE_BADPARAM:
fggmstr = "An invalid parameter was passed in. This can include an invalid flag or combination of flags.";
break;
case DISP_CHANGE_FAILED:
fggmstr = "The display driver failed the specified graphics mode.";
break;
case DISP_CHANGE_BADMODE:
fggmstr = "The graphics mode is not supported.";
break;
default:
fggmstr = "Unknown error in graphics mode???"; /* dunno if it is possible, MSDN does not mention any other error */
break;
}
if ( !success )
{
/* I'd rather get info whats going on in my program than wonder about */
/* what magic happens behind my back, its lib for devels after all ;) */
/* append display mode to error to make things more informative */
sprintf(displayMode,"%s Problem with requested mode: %lux%lu:%lu@%lu", fggmstr, devModeRequested->dmPelsWidth, devModeRequested->dmPelsHeight, devModeRequested->dmBitsPerPel, devModeRequested->dmDisplayFrequency);
fgWarning(displayMode);
}
return success;
}
#endif
/* /*
* Remembers the current visual settings, so that * Remembers the current visual settings, so that
* we can change them and restore later... * we can change them and restore later...
@ -190,7 +280,7 @@ static void fghRememberState( void )
fgDisplay.prev_ysz = ssizes[curr].height; fgDisplay.prev_ysz = ssizes[curr].height;
fgDisplay.prev_refresh = -1; fgDisplay.prev_refresh = -1;
# if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) # if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
if(fgState.GameModeRefresh != -1) { if(fgState.GameModeRefresh != -1) {
fgDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config); fgDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config);
} }
@ -355,7 +445,7 @@ static void fghRestoreState( void )
#elif TARGET_HOST_MS_WINDOWS #elif TARGET_HOST_MS_WINDOWS
/* Restore the previously remembered desktop display settings */ /* Restore the previously remembered desktop display settings */
ChangeDisplaySettingsEx( fgDisplay.DisplayName,&fgDisplay.DisplayMode, 0,0,0 ); fghPlatformChangeDisplayMode(GL_FALSE,&fgDisplay.DisplayMode);
#endif #endif
} }
@ -516,11 +606,10 @@ static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
#elif TARGET_HOST_MS_WINDOWS #elif TARGET_HOST_MS_WINDOWS
DEVMODE devMode; DEVMODE devMode;
char *fggmstr = NULL;
char displayMode[300];
success = GL_FALSE; success = GL_FALSE;
/* Get current display mode */
EnumDisplaySettings( fgDisplay.DisplayName, -1, &devMode ); EnumDisplaySettings( fgDisplay.DisplayName, -1, &devMode );
devMode.dmFields = 0; devMode.dmFields = 0;
@ -545,50 +634,7 @@ static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
devMode.dmFields |= DM_DISPLAYFREQUENCY; devMode.dmFields |= DM_DISPLAYFREQUENCY;
} }
switch ( ChangeDisplaySettingsEx(fgDisplay.DisplayName, &devMode, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) ) success = fghPlatformChangeDisplayMode(haveToTest, &devMode);
{
case DISP_CHANGE_SUCCESSFUL:
success = GL_TRUE;
if (!haveToTest)
{
/* update vars in case if windows switched to proper mode */
EnumDisplaySettings( fgDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS, &devMode );
fgState.GameModeSize.X = devMode.dmPelsWidth;
fgState.GameModeSize.Y = devMode.dmPelsHeight;
fgState.GameModeDepth = devMode.dmBitsPerPel;
fgState.GameModeRefresh = devMode.dmDisplayFrequency;
}
break;
case DISP_CHANGE_RESTART:
fggmstr = "The computer must be restarted for the graphics mode to work.";
break;
case DISP_CHANGE_BADFLAGS:
fggmstr = "An invalid set of flags was passed in.";
break;
case DISP_CHANGE_BADPARAM:
fggmstr = "An invalid parameter was passed in. This can include an invalid flag or combination of flags.";
break;
case DISP_CHANGE_FAILED:
fggmstr = "The display driver failed the specified graphics mode.";
break;
case DISP_CHANGE_BADMODE:
fggmstr = "The graphics mode is not supported.";
break;
default:
fggmstr = "Unknown error in graphics mode???"; /* dunno if it is possible,MSDN does not mention any other error */
break;
}
if ( !success )
{
/* I'd rather get info whats going on in my program than wonder about */
/* magic happenings behind my back, its lib for devels at last ;) */
/* append display mode to error to make things more informative */
sprintf(displayMode,"%s Problem with requested mode: %ix%i:%i@%i", fggmstr, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel, devMode.dmDisplayFrequency);
fgWarning(displayMode);
}
#endif #endif
return success; return success;

View file

@ -391,13 +391,13 @@ void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLi
glBegin(GL_TRIANGLES); glBegin(GL_TRIANGLES);
glNormal3d(cost[0]*sinn, sint[0]*sinn, cosn); glNormal3d(cost[0]*cosn, sint[0]*cosn, sinn);
for (j=0; j<slices; j++) for (j=0; j<slices; j++)
{ {
glVertex3d(cost[j+0]*r0, sint[j+0]*r0, z0 ); glVertex3d(cost[j+0]*r0, sint[j+0]*r0, z0 );
glVertex3d(0, 0, height); glVertex3d(0, 0, height);
glNormal3d(cost[j+1]*sinn, sint[j+1]*sinn, cosn ); glNormal3d(cost[j+1]*cosn, sint[j+1]*cosn, sinn );
glVertex3d(cost[j+1]*r0, sint[j+1]*r0, z0 ); glVertex3d(cost[j+1]*r0, sint[j+1]*r0, z0 );
} }
@ -463,7 +463,7 @@ void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLin
for (j=0; j<slices; j++) for (j=0; j<slices; j++)
{ {
glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn ); glNormal3d(cost[j]*cosn, sint[j]*cosn, sinn );
glVertex3d(cost[j]*r, sint[j]*r, 0.0 ); glVertex3d(cost[j]*r, sint[j]*r, 0.0 );
glVertex3d(0.0, 0.0, height); glVertex3d(0.0, 0.0, height);
} }

View file

@ -48,7 +48,7 @@
/* -- GLOBAL VARIABLES ----------------------------------------------------- */ /* -- GLOBAL VARIABLES ----------------------------------------------------- */
/* /*
* A structure pointed by g_pDisplay holds all information * A structure fgDisplay holds all information
* regarding the display, screen, root window etc. * regarding the display, screen, root window etc.
*/ */
SFG_Display fgDisplay; SFG_Display fgDisplay;
@ -77,9 +77,9 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
0, /* ActiveMenus */ 0, /* ActiveMenus */
NULL, /* MenuStateCallback */ NULL, /* MenuStateCallback */
NULL, /* MenuStatusCallback */ NULL, /* MenuStatusCallback */
{ 640, 480, GL_TRUE }, /* GameModeSize */ { -1, -1, GL_TRUE }, /* GameModeSize */
16, /* GameModeDepth */ -1, /* GameModeDepth */
72, /* GameModeRefresh */ -1, /* GameModeRefresh */
GLUT_ACTION_EXIT, /* ActionOnWindowClose */ GLUT_ACTION_EXIT, /* ActionOnWindowClose */
GLUT_EXEC_STATE_INIT, /* ExecState */ GLUT_EXEC_STATE_INIT, /* ExecState */
NULL, /* ProgramName */ NULL, /* ProgramName */
@ -89,6 +89,7 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
0, /* MouseWheelTicks */ 0, /* MouseWheelTicks */
1, /* AuxiliaryBufferNumber */ 1, /* AuxiliaryBufferNumber */
4, /* SampleNumber */ 4, /* SampleNumber */
GL_FALSE, /* SkipStaleMotion */
1, /* MajorVersion */ 1, /* MajorVersion */
0, /* MinorVersion */ 0, /* MinorVersion */
0, /* ContextFlags */ 0, /* ContextFlags */
@ -392,7 +393,10 @@ static void fghInitialize( const char* displayName )
fgState.Initialised = GL_TRUE; fgState.Initialised = GL_TRUE;
/* Avoid registering atexit callback on Win32 as it results in an access /* Avoid registering atexit callback on Win32 as it results in an access
* violation due to calling into a module which has been unloaded. */ * violation due to calling into a module which has been unloaded.
* Any cleanup isn't needed on Windows anyway, the OS takes care of it.c
* see: http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx
*/
#if ( TARGET_HOST_MS_WINDOWS == 0 ) #if ( TARGET_HOST_MS_WINDOWS == 0 )
atexit(fgDeinitialize); atexit(fgDeinitialize);
#endif #endif
@ -483,10 +487,10 @@ void fgDeinitialize( void )
fgState.KeyRepeat = GLUT_KEY_REPEAT_ON; fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
fgState.Modifiers = INVALID_MODIFIERS; fgState.Modifiers = INVALID_MODIFIERS;
fgState.GameModeSize.X = 640; fgState.GameModeSize.X = -1;
fgState.GameModeSize.Y = 480; fgState.GameModeSize.Y = -1;
fgState.GameModeDepth = 16; fgState.GameModeDepth = -1;
fgState.GameModeRefresh = 72; fgState.GameModeRefresh = -1;
fgListInit( &fgState.Timers ); fgListInit( &fgState.Timers );
fgListInit( &fgState.FreeTimers ); fgListInit( &fgState.FreeTimers );
@ -1114,6 +1118,7 @@ void FGAPIENTRY glutInitDisplayString( const char* displayMode )
case 35 : /* "borderless": windows should not have borders */ case 35 : /* "borderless": windows should not have borders */
#if TARGET_HOST_POSIX_X11 #if TARGET_HOST_POSIX_X11
#endif #endif
glut_state_flag |= GLUT_BORDERLESS;
break ; break ;
case 36 : /* "aux": some number of aux buffers */ case 36 : /* "aux": some number of aux buffers */

View file

@ -34,8 +34,8 @@
/* XXX Update these for each release! */ /* XXX Update these for each release! */
#define VERSION_MAJOR 2 #define VERSION_MAJOR 2
#define VERSION_MINOR 7 #define VERSION_MINOR 8
#define VERSION_PATCH 0 #define VERSION_PATCH 1
/* Freeglut is intended to function under all Unix/X11 and Win32 platforms. */ /* Freeglut is intended to function under all Unix/X11 and Win32 platforms. */
/* XXX: Don't all MS-Windows compilers (except Cygwin) have _WIN32 defined? /* XXX: Don't all MS-Windows compilers (except Cygwin) have _WIN32 defined?
@ -109,7 +109,7 @@
# include <X11/Xlib.h> # include <X11/Xlib.h>
# include <X11/Xatom.h> # include <X11/Xatom.h>
# include <X11/keysym.h> # include <X11/keysym.h>
# include <X11/extensions/XI.h> # include <X11/extensions/XI.h> // QB64-PE: replaced XInput.h with XI.h
# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H # ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
# include <X11/extensions/xf86vmode.h> # include <X11/extensions/xf86vmode.h>
# endif # endif
@ -138,9 +138,9 @@
#ifdef HAVE_SYS_TYPES_H #ifdef HAVE_SYS_TYPES_H
# include <sys/types.h> # include <sys/types.h>
#endif #endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> # include <unistd.h>
#endif
#ifdef TIME_WITH_SYS_TIME #ifdef TIME_WITH_SYS_TIME
# include <sys/time.h> # include <sys/time.h>
# include <time.h> # include <time.h>
@ -344,6 +344,8 @@ struct tagSFG_State
int AuxiliaryBufferNumber; /* Number of auxiliary buffers */ int AuxiliaryBufferNumber; /* Number of auxiliary buffers */
int SampleNumber; /* Number of samples per pixel */ int SampleNumber; /* Number of samples per pixel */
GLboolean SkipStaleMotion; /* skip stale motion events */
int MajorVersion; /* Major OpenGL context version */ int MajorVersion; /* Major OpenGL context version */
int MinorVersion; /* Minor OpenGL context version */ int MinorVersion; /* Minor OpenGL context version */
int ContextFlags; /* OpenGL context flags */ int ContextFlags; /* OpenGL context flags */
@ -729,7 +731,8 @@ struct tagSFG_Enumerator
GLboolean found; /* Used to terminate search */ GLboolean found; /* Used to terminate search */
void* data; /* Custom data pointer */ void* data; /* Custom data pointer */
}; };
typedef void (* FGCBenumerator )( SFG_Window *, SFG_Enumerator * ); typedef void (* FGCBWindowEnumerator )( SFG_Window *, SFG_Enumerator * );
typedef void (* FGCBMenuEnumerator )( SFG_Menu *, SFG_Enumerator * );
/* The bitmap font structure */ /* The bitmap font structure */
typedef struct tagSFG_Font SFG_Font; typedef struct tagSFG_Font SFG_Font;
@ -928,8 +931,8 @@ void fgSetCursor ( SFG_Window *window, int cursorID );
* and userData is the a custom user-supplied pointer. Functions * and userData is the a custom user-supplied pointer. Functions
* are defined and exported from freeglut_structure.c file. * are defined and exported from freeglut_structure.c file.
*/ */
void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator ); void fgEnumWindows( FGCBWindowEnumerator enumCallback, SFG_Enumerator* enumerator );
void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, void fgEnumSubWindows( SFG_Window* window, FGCBWindowEnumerator enumCallback,
SFG_Enumerator* enumerator ); SFG_Enumerator* enumerator );
#if TARGET_HOST_MS_WINDOWS #if TARGET_HOST_MS_WINDOWS
@ -938,11 +941,11 @@ void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
* and the window rect from the client area given the style of the window * and the window rect from the client area given the style of the window
* (or a valid window pointer from which the style can be queried). * (or a valid window pointer from which the style can be queried).
*/ */
void fghComputeWindowRectFromClientArea_UseStyle ( const DWORD windowStyle , RECT *clientRect, BOOL posIsOutside ); void fghGetDefaultWindowStyle(DWORD *flags);
void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside ); void fghGetStyleFromWindow( const SFG_Window *window, DWORD *windowStyle, DWORD *windowExStyle );
void fghComputeClientAreaFromWindowRect ( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside ); void fghComputeWindowRectFromClientArea_UseStyle( RECT *clientRect, const DWORD windowStyle, const DWORD windowExStyle, BOOL posIsOutside );
RECT fghGetClientArea ( const SFG_Window *window, BOOL wantPosOutside ); void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside );
void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth); void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL wantPosOutside );
#endif #endif
/* /*
@ -965,6 +968,12 @@ SFG_Window* fgWindowByID( int windowID );
*/ */
SFG_Menu* fgMenuByID( int menuID ); SFG_Menu* fgMenuByID( int menuID );
/*
* Returns active menu, if any. Assumption: only one menu active throughout application at any one time.
* This is easier than fgWindowByXXX as all menus are placed in one doubly linked list...
*/
SFG_Menu* fgGetActiveMenu( );
/* /*
* The menu activation and deactivation the code. This is the meat * The menu activation and deactivation the code. This is the meat
* of the menu user interface handling code... * of the menu user interface handling code...
@ -1018,8 +1027,6 @@ SFG_Proc fghGetProcAddress( const char *procName );
extern void (__cdecl *__glutExitFunc)( int return_value ); extern void (__cdecl *__glutExitFunc)( int return_value );
#endif #endif
#include <fcntl.h>
#endif /* FREEGLUT_INTERNAL_H */ #endif /* FREEGLUT_INTERNAL_H */
/*** END OF FILE ***/ /*** END OF FILE ***/

File diff suppressed because it is too large Load diff

View file

@ -84,6 +84,9 @@ static float menu_pen_hfore [4] = {0.0f, 0.0f, 0.0f, 1.0f};
static float menu_pen_hback [4] = {1.0f, 1.0f, 1.0f, 1.0f}; static float menu_pen_hback [4] = {1.0f, 1.0f, 1.0f, 1.0f};
#endif #endif
extern void fghGetCursorPos(SFG_XYUse *mouse_pos);
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
/* /*
@ -532,14 +535,15 @@ void fgDisplayMenu( void )
static void fghActivateMenu( SFG_Window* window, int button ) static void fghActivateMenu( SFG_Window* window, int button )
{ {
int max_x, max_y; int max_x, max_y;
SFG_XYUse mouse_pos;
/* We'll be referencing this menu a lot, so remember its address: */ /* We'll be referencing this menu a lot, so remember its address: */
SFG_Menu* menu = window->Menu[ button ]; SFG_Menu* menu = window->Menu[ button ];
SFG_Window* current_window = fgStructure.CurrentWindow; SFG_Window* current_window = fgStructure.CurrentWindow;
/* If the menu is already active in another window, deactivate it there */ /* If the menu is already active in another window, deactivate it (and any submenus) there */
if ( menu->ParentWindow ) if ( menu->ParentWindow )
menu->ParentWindow->ActiveMenu = NULL ; fgDeactivateMenu(menu->ParentWindow);
/* Mark the menu as active, so that it gets displayed: */ /* Mark the menu as active, so that it gets displayed: */
window->ActiveMenu = menu; window->ActiveMenu = menu;
@ -550,9 +554,17 @@ static void fghActivateMenu( SFG_Window* window, int button )
/* Set up the initial menu position now: */ /* Set up the initial menu position now: */
fghGetVMaxExtent(menu->ParentWindow, &max_x, &max_y); fghGetVMaxExtent(menu->ParentWindow, &max_x, &max_y);
fgSetWindow( window ); fgSetWindow( window );
menu->X = window->State.MouseX + glutGet( GLUT_WINDOW_X ); /* get mouse position on screen (window->State.MouseX and window->State.MouseY
menu->Y = window->State.MouseY + glutGet( GLUT_WINDOW_Y ); * are relative to client area origin), and not easy to correct given that
* glutGet( GLUT_WINDOW_X ) and glutGet( GLUT_WINDOW_Y ) return relative to parent
* origin when looking at a child window
* for parent windows: window->State.MouseX + glutGet( GLUT_WINDOW_X ) == mouse_pos.X
*/
fghGetCursorPos(&mouse_pos);
menu->X = mouse_pos.X;
menu->Y = mouse_pos.Y;
/* Make sure the whole menu is on the screen */
if( menu->X + menu->Width > max_x ) if( menu->X + menu->Width > max_x )
menu->X -=menu->Width; menu->X -=menu->Width;
@ -563,10 +575,21 @@ static void fghActivateMenu( SFG_Window* window, int button )
menu->Y = 0; menu->Y = 0;
} }
menu->Window->State.MouseX = /* Set position of mouse relative to top-left menu in menu's window state (could as well set 0 at creation time...) */
window->State.MouseX + glutGet( GLUT_WINDOW_X ) - menu->X; menu->Window->State.MouseX = mouse_pos.X - menu->X;
menu->Window->State.MouseY = menu->Window->State.MouseY = mouse_pos.Y - menu->Y;
window->State.MouseY + glutGet( GLUT_WINDOW_Y ) - menu->Y;
/* Menu status callback */
if (fgState.MenuStateCallback || fgState.MenuStatusCallback)
{
fgStructure.CurrentMenu = menu;
fgStructure.CurrentWindow = window;
if (fgState.MenuStateCallback)
fgState.MenuStateCallback(GLUT_MENU_IN_USE);
if (fgState.MenuStatusCallback)
/* window->State.MouseX and window->State.MouseY are relative to client area origin, as needed */
fgState.MenuStatusCallback(GLUT_MENU_IN_USE, window->State.MouseX, window->State.MouseY);
}
fgSetWindow( menu->Window ); fgSetWindow( menu->Window );
glutPositionWindow( menu->X, menu->Y ); glutPositionWindow( menu->X, menu->Y );
@ -645,9 +668,8 @@ GLboolean fgCheckActiveMenu ( SFG_Window *window, int button, GLboolean pressed,
/* /*
* Outside the menu, deactivate if it's a downclick * Outside the menu, deactivate if it's a downclick
* *
* XXX This isn't enough. A downclick outside of * A downclick outside of the interior of our freeglut windows
* XXX the interior of our freeglut windows should also * is dealt with in the WM_KILLFOCUS handler of fgPlatformWindowProc
* XXX deactivate the menu. This is more complicated.
*/ */
fgDeactivateMenu( window->ActiveMenu->ParentWindow ); fgDeactivateMenu( window->ActiveMenu->ParentWindow );
@ -684,12 +706,13 @@ GLboolean fgCheckActiveMenu ( SFG_Window *window, int button, GLboolean pressed,
void fgDeactivateMenu( SFG_Window *window ) void fgDeactivateMenu( SFG_Window *window )
{ {
SFG_Window *parent_window = NULL; SFG_Window *parent_window = NULL;
SFG_Menu* menu;
/* Check if there is an active menu attached to this window... */
SFG_Menu* menu = window->ActiveMenu;
SFG_MenuEntry *menuEntry; SFG_MenuEntry *menuEntry;
/* Did we find an active window? */ /* Did we find an active window? */
freeglut_return_if_fail( window );
/* Check if there is an active menu attached to this window... */
menu = window->ActiveMenu;
freeglut_return_if_fail( menu ); freeglut_return_if_fail( menu );
parent_window = menu->ParentWindow; parent_window = menu->ParentWindow;
@ -714,12 +737,32 @@ void fgDeactivateMenu( SFG_Window *window )
{ {
menuEntry->IsActive = GL_FALSE; menuEntry->IsActive = GL_FALSE;
/* Is that an active submenu by any case? */ /* Is that an active submenu by any chance? */
if( menuEntry->SubMenu ) if( menuEntry->SubMenu )
fghDeactivateSubMenu( menuEntry ); fghDeactivateSubMenu( menuEntry );
} }
fgSetWindow ( parent_window ) ; fgSetWindow ( parent_window ) ;
/* Menu status callback */
if (fgState.MenuStateCallback || fgState.MenuStatusCallback)
{
fgStructure.CurrentMenu = menu;
fgStructure.CurrentWindow = parent_window;
if (fgState.MenuStateCallback)
fgState.MenuStateCallback(GLUT_MENU_NOT_IN_USE);
if (fgState.MenuStatusCallback)
{
/* Get cursor position on screen and convert to relative to parent_window's client area */
SFG_XYUse mouse_pos;
fghGetCursorPos(&mouse_pos);
mouse_pos.X -= glutGet( GLUT_WINDOW_X );
mouse_pos.Y -= glutGet( GLUT_WINDOW_Y );
fgState.MenuStatusCallback(GLUT_MENU_NOT_IN_USE, mouse_pos.X, mouse_pos.Y);
}
}
} }
/* /*
@ -766,6 +809,53 @@ void fghCalculateMenuBoxSize( void )
fgStructure.CurrentMenu->Width = width + 4 * FREEGLUT_MENU_BORDER; fgStructure.CurrentMenu->Width = width + 4 * FREEGLUT_MENU_BORDER;
} }
#if TARGET_HOST_MS_WINDOWS
void fgPlatformCheckMenuDeactivate()
{
/* If we have an open menu, see if the open menu should be closed
* when focus was lost because user either switched
* application or FreeGLUT window (if one is running multiple
* windows). If so, close menu the active menu.
*/
SFG_Menu* menu = NULL;
if ( fgStructure.Menus.First )
menu = fgGetActiveMenu();
if ( menu )
{
SFG_Window* wnd = NULL;
HWND hwnd = GetFocus(); /* Get window with current focus - NULL for non freeglut windows */
if (hwnd)
/* See which of our windows it is */
wnd = fgWindowByHandle(hwnd);
if (!hwnd || !wnd)
/* User switched to another application*/
fgDeactivateMenu(menu->ParentWindow);
else if (!wnd->IsMenu) /* Make sure we don't kill the menu when trying to enter a submenu */
{
if (wnd!=menu->ParentWindow)
/* User switched to another FreeGLUT window */
fgDeactivateMenu(menu->ParentWindow);
else
{
/* Check if focus lost because non-client area of
* window was pressed (pressing on client area is
* handled in fgCheckActiveMenu)
*/
POINT mouse_pos;
RECT clientArea;
fghGetClientArea(&clientArea,menu->ParentWindow, GL_FALSE);
GetCursorPos(&mouse_pos);
if ( !PtInRect( &clientArea, mouse_pos ) )
fgDeactivateMenu(menu->ParentWindow);
}
}
}
};
#endif
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
@ -776,6 +866,8 @@ int FGAPIENTRY glutCreateMenu( void(* callback)( int ) )
{ {
/* The menu object creation code resides in freeglut_structure.c */ /* The menu object creation code resides in freeglut_structure.c */
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" ); FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" );
if (fgGetActiveMenu())
fgError("Menu manipulation not allowed while menus in use.");
return fgCreateMenu( callback )->ID; return fgCreateMenu( callback )->ID;
} }
@ -799,6 +891,9 @@ void FGAPIENTRY glutDestroyMenu( int menuID )
freeglut_return_if_fail( menu ); freeglut_return_if_fail( menu );
if (fgGetActiveMenu())
fgError("Menu manipulation not allowed while menus in use.");
/* The menu object destruction code resides in freeglut_structure.c */ /* The menu object destruction code resides in freeglut_structure.c */
fgDestroyMenu( menu ); fgDestroyMenu( menu );
} }
@ -839,7 +934,10 @@ void FGAPIENTRY glutAddMenuEntry( const char* label, int value )
SFG_MenuEntry* menuEntry; SFG_MenuEntry* menuEntry;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAddMenuEntry" ); FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAddMenuEntry" );
menuEntry = (SFG_MenuEntry *)calloc( sizeof(SFG_MenuEntry), 1 ); menuEntry = (SFG_MenuEntry *)calloc( sizeof(SFG_MenuEntry), 1 );
freeglut_return_if_fail( fgStructure.CurrentMenu ); freeglut_return_if_fail( fgStructure.CurrentMenu );
if (fgGetActiveMenu())
fgError("Menu manipulation not allowed while menus in use.");
menuEntry->Text = strdup( label ); menuEntry->Text = strdup( label );
menuEntry->ID = value; menuEntry->ID = value;
@ -863,6 +961,9 @@ void FGAPIENTRY glutAddSubMenu( const char *label, int subMenuID )
subMenu = fgMenuByID( subMenuID ); subMenu = fgMenuByID( subMenuID );
freeglut_return_if_fail( fgStructure.CurrentMenu ); freeglut_return_if_fail( fgStructure.CurrentMenu );
if (fgGetActiveMenu())
fgError("Menu manipulation not allowed while menus in use.");
freeglut_return_if_fail( subMenu ); freeglut_return_if_fail( subMenu );
menuEntry->Text = strdup( label ); menuEntry->Text = strdup( label );
@ -881,7 +982,10 @@ void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value )
SFG_MenuEntry* menuEntry = NULL; SFG_MenuEntry* menuEntry = NULL;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToMenuEntry" ); FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToMenuEntry" );
freeglut_return_if_fail( fgStructure.CurrentMenu ); freeglut_return_if_fail( fgStructure.CurrentMenu );
if (fgGetActiveMenu())
fgError("Menu manipulation not allowed while menus in use.");
/* Get n-th menu entry in the current menu, starting from one: */ /* Get n-th menu entry in the current menu, starting from one: */
menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item ); menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item );
@ -908,10 +1012,15 @@ void FGAPIENTRY glutChangeToSubMenu( int item, const char* label,
SFG_MenuEntry* menuEntry; SFG_MenuEntry* menuEntry;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToSubMenu" ); FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToSubMenu" );
freeglut_return_if_fail( fgStructure.CurrentMenu );
if (fgGetActiveMenu())
fgError("Menu manipulation not allowed while menus in use.");
/* Get handle to sub menu */
subMenu = fgMenuByID( subMenuID ); subMenu = fgMenuByID( subMenuID );
menuEntry = NULL; menuEntry = NULL;
freeglut_return_if_fail( fgStructure.CurrentMenu );
freeglut_return_if_fail( subMenu ); freeglut_return_if_fail( subMenu );
/* Get n-th menu entry in the current menu, starting from one: */ /* Get n-th menu entry in the current menu, starting from one: */
@ -937,7 +1046,10 @@ void FGAPIENTRY glutRemoveMenuItem( int item )
SFG_MenuEntry* menuEntry; SFG_MenuEntry* menuEntry;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutRemoveMenuItem" ); FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutRemoveMenuItem" );
freeglut_return_if_fail( fgStructure.CurrentMenu ); freeglut_return_if_fail( fgStructure.CurrentMenu );
if (fgGetActiveMenu())
fgError("Menu manipulation not allowed while menus in use.");
/* Get n-th menu entry in the current menu, starting from one: */ /* Get n-th menu entry in the current menu, starting from one: */
menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item ); menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item );
@ -960,7 +1072,10 @@ void FGAPIENTRY glutAttachMenu( int button )
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAttachMenu" ); FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAttachMenu" );
freeglut_return_if_fail( fgStructure.CurrentWindow ); freeglut_return_if_fail( fgStructure.CurrentWindow );
freeglut_return_if_fail( fgStructure.CurrentMenu ); freeglut_return_if_fail( fgStructure.CurrentMenu );
if (fgGetActiveMenu())
fgError("Menu manipulation not allowed while menus in use.");
freeglut_return_if_fail( button >= 0 ); freeglut_return_if_fail( button >= 0 );
freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS ); freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS );
@ -976,7 +1091,10 @@ void FGAPIENTRY glutDetachMenu( int button )
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDetachMenu" ); FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDetachMenu" );
freeglut_return_if_fail( fgStructure.CurrentWindow ); freeglut_return_if_fail( fgStructure.CurrentWindow );
freeglut_return_if_fail( fgStructure.CurrentMenu ); freeglut_return_if_fail( fgStructure.CurrentMenu );
if (fgGetActiveMenu())
fgError("Menu manipulation not allowed while menus in use.");
freeglut_return_if_fail( button >= 0 ); freeglut_return_if_fail( button >= 0 );
freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS ); freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS );

View file

@ -124,6 +124,10 @@ void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
fgState.SampleNumber = value; fgState.SampleNumber = value;
break; break;
case GLUT_SKIP_STALE_MOTION_EVENTS:
fgState.SkipStaleMotion = value;
break;
default: default:
fgWarning( "glutSetOption(): missing enum handle %d", eWhat ); fgWarning( "glutSetOption(): missing enum handle %d", eWhat );
break; break;
@ -132,7 +136,7 @@ void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
#if TARGET_HOST_MS_WINDOWS #if TARGET_HOST_MS_WINDOWS
/* The following include file is available from SGI but is not standard: /* The following include file is available from SGI but is not standard:
* #include <wglext.h> * #include <GL/wglext.h>
* So we copy the necessary parts out of it to support the multisampling query * So we copy the necessary parts out of it to support the multisampling query
*/ */
#define WGL_SAMPLES_ARB 0x2042 #define WGL_SAMPLES_ARB 0x2042
@ -434,7 +438,7 @@ int FGAPIENTRY glutGet( GLenum eWhat )
* behaviour, both under Windows and under UNIX/X11: * behaviour, both under Windows and under UNIX/X11:
* - When you create a window with position (x,y) and size * - When you create a window with position (x,y) and size
* (w,h), the upper left hand corner of the outside of the * (w,h), the upper left hand corner of the outside of the
* window is at (x,y) and the size of the drawable area is * window is at (x,y) and the size of the drawable area is
* (w,h). * (w,h).
* - When you query the size and position of the window--as * - When you query the size and position of the window--as
* is happening here for Windows--"freeglut" will return * is happening here for Windows--"freeglut" will return
@ -451,7 +455,20 @@ int FGAPIENTRY glutGet( GLenum eWhat )
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE)
GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect ); GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
#else #else
winRect = fghGetClientArea(fgStructure.CurrentWindow, FALSE); fghGetClientArea(&winRect,fgStructure.CurrentWindow, FALSE);
if (fgStructure.CurrentWindow->Parent && (eWhat==GLUT_WINDOW_X || eWhat==GLUT_WINDOW_Y))
{
/* For child window, we should return relative to upper-left
* of parent's client area.
*/
POINT topleft;
topleft.x = winRect.left;
topleft.y = winRect.top;
ScreenToClient(fgStructure.CurrentWindow->Parent->Window.Handle,&topleft);
winRect.left = topleft.x;
winRect.top = topleft.y;
}
#endif /* defined(_WIN32_WCE) */ #endif /* defined(_WIN32_WCE) */
switch( eWhat ) switch( eWhat )
@ -465,30 +482,47 @@ int FGAPIENTRY glutGet( GLenum eWhat )
break; break;
case GLUT_WINDOW_BORDER_WIDTH : case GLUT_WINDOW_BORDER_WIDTH :
case GLUT_WINDOW_HEADER_HEIGHT : case GLUT_WINDOW_BORDER_HEIGHT :
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE)
return 0; return 0;
#else #else
{ {
DWORD windowStyle; /* We can't get the border width or header height in the simple way
* with some calls to GetSystemMetrics. We'd then have to assume which
* elements are present for a given decoration, and such calculations
* wouldn't be valid for every version of Windows. The below should be
* robust. */
int borderWidth, captionHeight;
DWORD windowStyle, windowExStyle;
RECT clientRect, winRect;
/* Get style of window, or default style */
fghGetStyleFromWindow( fgStructure.CurrentWindow, &windowStyle, &windowExStyle );
/* Get client area if any window */
if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle) if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle)
windowStyle = GetWindowLong(fgStructure.CurrentWindow->Window.Handle, GWL_STYLE); fghGetClientArea(&clientRect,fgStructure.CurrentWindow,FALSE);
else else
/* If no window, return sizes for a default window with title bar and border */ SetRect(&clientRect,0,0,200,200);
windowStyle = WS_OVERLAPPEDWINDOW;
/* Compute window rect (including non-client area) */
CopyRect(&winRect,&clientRect);
fghComputeWindowRectFromClientArea_UseStyle(&winRect,windowStyle,windowExStyle,FALSE);
/* Calculate border width by taking width of whole window minus width of client area and divide by two
* NB: we assume horizontal and vertical borders have the same size, which should always be the case
* unless the user bypassed FreeGLUT and messed with the windowstyle himself.
* Once borderwidth is known, account for it when comparing height of window to height of client area.
* all other extra pixels are assumed to be atop the window, forming the caption.
*/
borderWidth = ((winRect.right-winRect.left)-(clientRect.right-clientRect.left))/2;
captionHeight = (winRect.bottom-winRect.top)-(clientRect.bottom-clientRect.top)-borderWidth*2;
switch( eWhat ) switch( eWhat )
{ {
case GLUT_WINDOW_BORDER_WIDTH: case GLUT_WINDOW_BORDER_WIDTH:
{ return borderWidth;
int xBorderWidth, yBorderWidth; case GLUT_WINDOW_BORDER_HEIGHT:
fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth); return captionHeight;
return xBorderWidth;
}
case GLUT_WINDOW_HEADER_HEIGHT:
/* Need to query for WS_SYSMENU to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
return (windowStyle & WS_SYSMENU)? GetSystemMetrics( SM_CYCAPTION ) : 0;
} }
} }
#endif /* defined(_WIN32_WCE) */ #endif /* defined(_WIN32_WCE) */
@ -554,6 +588,9 @@ int FGAPIENTRY glutGet( GLenum eWhat )
case GLUT_MULTISAMPLE: case GLUT_MULTISAMPLE:
return fgState.SampleNumber; return fgState.SampleNumber;
case GLUT_SKIP_STALE_MOTION_EVENTS:
return fgState.SkipStaleMotion;
default: default:
fgWarning( "glutGet(): missing enum handle %d", eWhat ); fgWarning( "glutGet(): missing enum handle %d", eWhat );
break; break;

View file

@ -380,7 +380,7 @@ void fgDestroyStructure( void )
/* /*
* Helper function to enumerate through all registered top-level windows * Helper function to enumerate through all registered top-level windows
*/ */
void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator ) void fgEnumWindows( FGCBWindowEnumerator enumCallback, SFG_Enumerator* enumerator )
{ {
SFG_Window *window; SFG_Window *window;
@ -399,11 +399,33 @@ void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
} }
} }
/*
* Helper function to enumerate through all registered top-level windows
*/
void fgEnumMenus( FGCBMenuEnumerator enumCallback, SFG_Enumerator* enumerator )
{
SFG_Menu *menu;
FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator,
"Enumerator or callback missing from window enumerator call",
"fgEnumWindows" );
/* It's enough to check all entries in fgStructure.Menus... */
for( menu = (SFG_Menu *)fgStructure.Menus.First;
menu;
menu = (SFG_Menu *)menu->Node.Next )
{
enumCallback( menu, enumerator );
if( enumerator->found )
return;
}
}
/* /*
* Helper function to enumerate through all a window's subwindows * Helper function to enumerate through all a window's subwindows
* (single level descent) * (single level descent)
*/ */
void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, void fgEnumSubWindows( SFG_Window* window, FGCBWindowEnumerator enumCallback,
SFG_Enumerator* enumerator ) SFG_Enumerator* enumerator )
{ {
SFG_Window *child; SFG_Window *child;
@ -487,7 +509,7 @@ static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator )
} }
/* /*
* This function is similiar to the previous one, except it is * This function is similar to the previous one, except it is
* looking for a specified (sub)window identifier. The function * looking for a specified (sub)window identifier. The function
* is defined in freeglut_structure.c file. * is defined in freeglut_structure.c file.
*/ */
@ -495,7 +517,7 @@ SFG_Window* fgWindowByID( int windowID )
{ {
SFG_Enumerator enumerator; SFG_Enumerator enumerator;
/* Uses a method very similiar for fgWindowByHandle... */ /* Uses a method very similar for fgWindowByHandle... */
enumerator.found = GL_FALSE; enumerator.found = GL_FALSE;
enumerator.data = ( void * )&windowID; enumerator.data = ( void * )&windowID;
fgEnumWindows( fghcbWindowByID, &enumerator ); fgEnumWindows( fghcbWindowByID, &enumerator );
@ -506,18 +528,75 @@ SFG_Window* fgWindowByID( int windowID )
/* /*
* Looks up a menu given its ID. This is easier that fgWindowByXXX * Looks up a menu given its ID. This is easier that fgWindowByXXX
* A static helper function to look for a menu given its ID
*/
static void fghcbMenuByID( SFG_Menu *menu, SFG_Enumerator *enumerator )
{
if ( enumerator->found )
return;
/* Check the menu's ID. */
if( menu->ID == (int)(enumerator->data) )
{
enumerator->found = GL_TRUE;
enumerator->data = menu;
return;
}
}
/*
* Looks up a menu given its ID. This is easier than fgWindowByXXX
* as all menus are placed in one doubly linked list... * as all menus are placed in one doubly linked list...
*/ */
SFG_Menu* fgMenuByID( int menuID ) SFG_Menu* fgMenuByID( int menuID )
{ {
SFG_Menu *menu = NULL; SFG_Enumerator enumerator;
/* It's enough to check all entries in fgStructure.Menus... */ /* This is easy and makes use of the menus enumeration defined above */
for( menu = (SFG_Menu *)fgStructure.Menus.First; enumerator.found = GL_FALSE;
menu; enumerator.data = (void *)menuID;
menu = (SFG_Menu *)menu->Node.Next ) fgEnumMenus( fghcbMenuByID, &enumerator );
if( menu->ID == menuID )
return menu; if( enumerator.found )
return( SFG_Menu *) enumerator.data;
return NULL;
}
/*
* A static helper function to look for an active menu
*/
static void fghcbGetActiveMenu( SFG_Menu *menu, SFG_Enumerator *enumerator )
{
if ( enumerator->found )
return;
/* Check the menu's ID. */
if( menu->IsActive )
{
enumerator->found = GL_TRUE;
enumerator->data = menu;
return;
}
}
/*
* Returns active menu, if any. Assumption: only one menu active throughout application at any one time.
* This is easier than fgWindowByXXX as all menus are placed in one doubly linked list...
*/
SFG_Menu* fgGetActiveMenu( )
{
SFG_Enumerator enumerator;
/* This is easy and makes use of the menus enumeration defined above */
enumerator.found = GL_FALSE;
fgEnumMenus( fghcbGetActiveMenu, &enumerator );
if( enumerator.found )
return( SFG_Menu *) enumerator.data;
return NULL; return NULL;
} }

View file

@ -0,0 +1,200 @@
/*
* freeglut_teapot.c
*
* Teapot(tm) rendering code.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Fri Dec 24 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Original teapot code copyright follows:
*/
/*
* (c) Copyright 1993, Silicon Graphics, Inc.
*
* ALL RIGHTS RESERVED
*
* Permission to use, copy, modify, and distribute this software
* for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that
* both the copyright notice and this permission notice appear in
* supporting documentation, and that the name of Silicon
* Graphics, Inc. not be used in advertising or publicity
* pertaining to distribution of the software without specific,
* written prior permission.
*
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
* "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
* OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
* EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
* ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
* INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
* SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
* NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* US Government Users Restricted Rights
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
* (c)(1)(ii) of the Rights in Technical Data and Computer
* Software clause at DFARS 252.227-7013 and/or in similar or
* successor clauses in the FAR or the DOD or NASA FAR
* Supplement. Unpublished-- rights reserved under the copyright
* laws of the United States. Contractor/manufacturer is Silicon
* Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
* 94039-7311.
*
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
#include "freeglut_teapot_data.h"
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
static void fghTeapot( GLint grid, GLdouble scale, GLenum type )
{
#if defined(_WIN32_WCE)
int i, numV=sizeof(strip_vertices)/4, numI=sizeof(strip_normals)/4;
#else
double p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
long i, j, k, l;
#endif
glPushAttrib( GL_ENABLE_BIT | GL_EVAL_BIT );
glEnable( GL_AUTO_NORMAL );
glEnable( GL_NORMALIZE );
glEnable( GL_MAP2_VERTEX_3 );
glEnable( GL_MAP2_TEXTURE_COORD_2 );
glPushMatrix();
glRotated( 270.0, 1.0, 0.0, 0.0 );
glScaled( 0.5 * scale, 0.5 * scale, 0.5 * scale );
glTranslated( 0.0, 0.0, -1.5 );
#if defined(_WIN32_WCE)
glRotated( 90.0, 1.0, 0.0, 0.0 );
glBegin( GL_TRIANGLE_STRIP );
for( i = 0; i < numV-1; i++ )
{
int vidx = strip_vertices[i],
nidx = strip_normals[i];
if( vidx != -1 )
{
glNormal3fv( normals[nidx] );
glVertex3fv( vertices[vidx] );
}
else
{
glEnd();
glBegin( GL_TRIANGLE_STRIP );
}
}
glEnd();
#else
for (i = 0; i < 10; i++) {
for (j = 0; j < 4; j++) {
for (k = 0; k < 4; k++) {
for (l = 0; l < 3; l++) {
p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
if (l == 1)
q[j][k][l] *= -1.0;
if (i < 6) {
r[j][k][l] =
cpdata[patchdata[i][j * 4 + (3 - k)]][l];
if (l == 0)
r[j][k][l] *= -1.0;
s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
if (l == 0)
s[j][k][l] *= -1.0;
if (l == 1)
s[j][k][l] *= -1.0;
}
}
}
}
glMap2d(GL_MAP2_TEXTURE_COORD_2, 0.0, 1.0, 2, 2, 0.0, 1.0, 4, 2,
&tex[0][0][0]);
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
&p[0][0][0]);
glMapGrid2d(grid, 0.0, 1.0, grid, 0.0, 1.0);
glEvalMesh2(type, 0, grid, 0, grid);
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
&q[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
if (i < 6) {
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
&r[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
&s[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
}
}
#endif /* defined(_WIN32_WCE) */
glPopMatrix();
glPopAttrib();
}
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
* Renders a beautiful wired teapot...
*/
void FGAPIENTRY glutWireTeapot( GLdouble size )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTeapot" );
/* We will use the general teapot rendering code */
fghTeapot( 10, size, GL_LINE );
}
/*
* Renders a beautiful filled teapot...
*/
void FGAPIENTRY glutSolidTeapot( GLdouble size )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTeapot" );
/* We will use the general teapot rendering code */
fghTeapot( 7, size, GL_FILL );
}
/*** END OF FILE ***/

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -13,6 +13,9 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/extensions/XInput2.h> #include <X11/extensions/XInput2.h>
/* convert the XInput button state mask to the regular X mouse event button mask */
#define BUTTON_MASK(xistate) ((xistate) << 8)
/* import function from freeglut_main.c */ /* import function from freeglut_main.c */
int fghGetXModifiers( int state ); int fghGetXModifiers( int state );
@ -112,9 +115,9 @@ void fgPrintXIDeviceEvent(XIDeviceEvent* event)
printf(" device: %d (%d)\n", event->deviceid, event->sourceid); printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
printf(" detail: %d\n", event->detail); printf(" detail: %d\n", event->detail);
printf(" buttons:"); printf(" buttons:");
for (i = 0; i < event->buttons.mask_len * 8; i++) for (i = 0; i < event->buttons.mask_len * 8; i++)
if (XIMaskIsSet(event->buttons.mask, i)) if (XIMaskIsSet(event->buttons.mask, i))
printf(" %d", i); printf(" %d", i);
printf("\n"); printf("\n");
printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n", printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
@ -143,76 +146,124 @@ void fgPrintXIDeviceEvent(XIDeviceEvent* event)
* \brief This function is called when an Extension Event is received * \brief This function is called when an Extension Event is received
* and calls the corresponding callback functions for these events. * and calls the corresponding callback functions for these events.
*/ */
void fgHandleExtensionEvents( XEvent* base_ev ) { void fgHandleExtensionEvents( XEvent* base_ev )
{
XEvent std_ev; /* standard single-pointer event to be added to the event queue */
int i, button = 0;
XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie);
int i, button = 0; /* initialize the generic fields from base_ev */
XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie); std_ev.xany = base_ev->xany;
if ( XGetEventData( fgDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) { if ( XGetEventData( fgDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) {
XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data); XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data);
/*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/ XIEnterEvent *evcross;
/*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/
SFG_Window* window = fgWindowByHandle( event->event ); SFG_Window* window = fgWindowByHandle( event->event );
if (!window) return; if (!window) return;
switch (cookie->evtype) { switch (cookie->evtype) {
case XI_Enter:
case XI_Leave:
evcross = (XIEnterEvent*)event;
case XI_Enter: fgState.Modifiers = fghGetXModifiers( evcross->mods.base );
case XI_Leave: INVOKE_WCB( *window, MultiEntry, (
fgState.Modifiers = fghGetXModifiers( ((XIEnterEvent*)event)->mods.base ); event->deviceid,
INVOKE_WCB( *window, MultiEntry, ( (event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT)
event->deviceid, ));
(event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT) #if _DEBUG
)); fgPrintXILeaveEvent((XILeaveEvent*)event);
#if _DEBUG #endif
fgPrintXILeaveEvent((XILeaveEvent*)event);
#endif
break;
case XI_ButtonPress: /* Also process the standard crossing event */
case XI_ButtonRelease: std_ev.type = evcross->evtype == XI_Enter ? EnterNotify : LeaveNotify;
fgState.Modifiers = fghGetXModifiers( event->mods.base ); std_ev.xcrossing.window = evcross->event;
INVOKE_WCB( *window, MultiButton, ( std_ev.xcrossing.root = evcross->root;
event->deviceid, std_ev.xcrossing.subwindow = evcross->child;
event->event_x, std_ev.xcrossing.x = evcross->event_x;
event->event_y, std_ev.xcrossing.y = evcross->event_y;
(event->detail)-1, std_ev.xcrossing.x_root = evcross->root_x;
(event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP) std_ev.xcrossing.y_root = evcross->root_y;
)); std_ev.xcrossing.mode = evcross->mode;
INVOKE_WCB( *window, Mouse, ( std_ev.xcrossing.detail = evcross->detail;
(event->detail)-1, std_ev.xcrossing.same_screen = evcross->same_screen;
(event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP), std_ev.xcrossing.focus = evcross->focus;
event->event_x, std_ev.xcrossing.state = BUTTON_MASK(*(unsigned int*)evcross->buttons.mask);
event->event_y
));
break;
case XI_Motion: XPutBackEvent(fgDisplay.Display, &std_ev);
fgState.Modifiers = fghGetXModifiers( event->mods.base ); break;
for (i = 0; i < event->buttons.mask_len; i++) if (event->buttons.mask[i]) button = 1;
if (button) {
INVOKE_WCB( *window, MultiMotion, ( event->deviceid, event->event_x, event->event_y ) );
INVOKE_WCB( *window, Motion, ( event->event_x, event->event_y ) );
} else {
INVOKE_WCB( *window, MultiPassive, ( event->deviceid, event->event_x, event->event_y ) );
INVOKE_WCB( *window, Passive, ( event->event_x, event->event_y ) );
}
#if _DEBUG
fgPrintXIDeviceEvent(event);
#endif
break;
default: case XI_ButtonPress:
#if _DEBUG case XI_ButtonRelease:
fgWarning( "Unknown XI2 device event:" ); fgState.Modifiers = fghGetXModifiers( event->mods.base );
fgPrintXIDeviceEvent( event ); INVOKE_WCB( *window, MultiButton, (
#endif event->deviceid,
break; event->event_x,
} event->event_y,
fgState.Modifiers = INVALID_MODIFIERS; event->detail-1,
} (event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP)
XFreeEventData( fgDisplay.Display, cookie ); ));
/* Also process the standard button event */
std_ev.type = event->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease;
std_ev.xbutton.window = event->event;
std_ev.xbutton.root = event->root;
std_ev.xbutton.subwindow = event->child;
std_ev.xbutton.x = event->event_x;
std_ev.xbutton.y = event->event_y;
std_ev.xbutton.x_root = event->root_x;
std_ev.xbutton.y_root = event->root_y;
std_ev.xbutton.state = event->mods.base;
std_ev.xbutton.button = event->detail;
XPutBackEvent(fgDisplay.Display, &std_ev);
break;
case XI_Motion:
fgState.Modifiers = fghGetXModifiers( event->mods.base );
for (i = 0; i < event->buttons.mask_len; i++) {
if (event->buttons.mask[i]) {
button = 1;
}
}
if (button) {
INVOKE_WCB( *window, MultiMotion, ( event->deviceid, event->event_x, event->event_y ) );
} else {
INVOKE_WCB( *window, MultiPassive, ( event->deviceid, event->event_x, event->event_y ) );
}
#if _DEBUG
fgPrintXIDeviceEvent(event);
#endif
/* Also process the standard motion event */
std_ev.type = MotionNotify;
std_ev.xmotion.window = event->event;
std_ev.xmotion.root = event->root;
std_ev.xmotion.subwindow = event->child;
std_ev.xmotion.time = event->time;
std_ev.xmotion.x = event->event_x;
std_ev.xmotion.y = event->event_y;
std_ev.xmotion.x_root = event->root_x;
std_ev.xmotion.y_root = event->root_y;
std_ev.xmotion.state = BUTTON_MASK(*(unsigned int*)event->buttons.mask);
std_ev.xmotion.is_hint = NotifyNormal;
XPutBackEvent(fgDisplay.Display, &std_ev);
break;
default:
#if _DEBUG
fgWarning( "Unknown XI2 device event:" );
fgPrintXIDeviceEvent( event );
#endif
break;
}
fgState.Modifiers = INVALID_MODIFIERS;
}
XFreeEventData( fgDisplay.Display, cookie );
} }
#endif #endif

View file

@ -74,7 +74,8 @@
#define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9 #define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9
#define GLUT_WINDOW_BORDER_WIDTH 0x01FA #define GLUT_WINDOW_BORDER_WIDTH 0x01FA
#define GLUT_WINDOW_HEADER_HEIGHT 0x01FB #define GLUT_WINDOW_BORDER_HEIGHT 0x01FB
#define GLUT_WINDOW_HEADER_HEIGHT 0x01FB /* Docs say it should always have been GLUT_WINDOW_BORDER_HEIGHT, keep this for backward compatibility */
#define GLUT_VERSION 0x01FC #define GLUT_VERSION 0x01FC
@ -83,6 +84,8 @@
#define GLUT_FULL_SCREEN 0x01FF #define GLUT_FULL_SCREEN 0x01FF
#define GLUT_SKIP_STALE_MOTION_EVENTS 0x0204
/* /*
* New tokens for glutInitDisplayMode. * New tokens for glutInitDisplayMode.
* Only one GLUT_AUXn bit may be used at a time. * Only one GLUT_AUXn bit may be used at a time.

View file

@ -113,14 +113,21 @@
*/ */
#define FREEGLUT 1 #define FREEGLUT 1
#define GLUT_API_VERSION 4 #define GLUT_API_VERSION 4
#define FREEGLUT_VERSION_2_0 1
#define GLUT_XLIB_IMPLEMENTATION 13 #define GLUT_XLIB_IMPLEMENTATION 13
/* Deprecated:
cf. http://sourceforge.net/mailarchive/forum.php?thread_name=CABcAi1hw7cr4xtigckaGXB5X8wddLfMcbA_rZ3NAuwMrX_zmsw%40mail.gmail.com&forum_name=freeglut-developer */
#define FREEGLUT_VERSION_2_0 1
/* /*
* Always include OpenGL and GLU headers * Always include OpenGL and GLU headers
*/ */
#include <GL/gl.h> #if __APPLE__
#include <GL/glu.h> # include <OpenGL/gl.h>
# include <OpenGL/glu.h>
#else
# include <GL/gl.h>
# include <GL/glu.h>
#endif
/* /*
* GLUT API macro definitions -- the special key codes: * GLUT API macro definitions -- the special key codes:
@ -531,6 +538,13 @@ FGAPI void FGAPIENTRY glutSolidTetrahedron( void );
FGAPI void FGAPIENTRY glutWireIcosahedron( void ); FGAPI void FGAPIENTRY glutWireIcosahedron( void );
FGAPI void FGAPIENTRY glutSolidIcosahedron( void ); FGAPI void FGAPIENTRY glutSolidIcosahedron( void );
/*
* Teapot rendering functions, found in freeglut_teapot.c
* NB: front facing polygons have clockwise winding, not counter clockwise
*/
FGAPI void FGAPIENTRY glutWireTeapot( GLdouble size );
FGAPI void FGAPIENTRY glutSolidTeapot( GLdouble size );
/* /*
* Game mode functions, see freeglut_gamemode.c * Game mode functions, see freeglut_gamemode.c
*/ */