mirror of
https://github.com/QB64-Phoenix-Edition/QB64pe.git
synced 2024-07-04 06:00:23 +00:00
Update FreeGLUT to v2.8.1
This commit is contained in:
parent
b5e896384a
commit
3a260f1002
|
@ -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 $@
|
||||
|
||||
$(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)
|
||||
$(AR) rcs $@ $(FREEGLUT_OBJS)
|
||||
|
|
|
@ -159,6 +159,22 @@ static void fghWarpPointer ( int x, int y )
|
|||
/* Make the warp visible immediately. */
|
||||
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
|
||||
|
||||
|
||||
|
@ -205,7 +221,7 @@ static void fghSetCursor ( SFG_Window *window, int cursorID )
|
|||
{
|
||||
MAP_CURSOR( GLUT_CURSOR_RIGHT_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_HELP, IDC_HELP );
|
||||
MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL );
|
||||
|
@ -244,6 +260,18 @@ static void fghWarpPointer ( int x, int y )
|
|||
ClientToScreen( fgStructure.CurrentWindow->Window.Handle, &coords );
|
||||
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
|
||||
|
||||
|
||||
|
|
|
@ -136,6 +136,8 @@ static GLUTproc fghGetGLUTProcAddress( const char* procName )
|
|||
CHECK_NAME(glutSolidTorus);
|
||||
CHECK_NAME(glutWireDodecahedron);
|
||||
CHECK_NAME(glutSolidDodecahedron);
|
||||
CHECK_NAME(glutWireTeapot);
|
||||
CHECK_NAME(glutSolidTeapot);
|
||||
CHECK_NAME(glutWireOctahedron);
|
||||
CHECK_NAME(glutSolidOctahedron);
|
||||
CHECK_NAME(glutWireTetrahedron);
|
||||
|
|
|
@ -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
|
||||
* 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 ) ) );
|
||||
|
||||
/* 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)
|
||||
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) {
|
||||
rate = fgState.GameModeRefresh;
|
||||
|
||||
|
@ -130,7 +130,7 @@ static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)
|
|||
break;
|
||||
}
|
||||
|
||||
#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
|
||||
#if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
|
||||
if(use_rate)
|
||||
result = XRRSetScreenConfigAndRate(fgDisplay.Display, xrr_config,
|
||||
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 */
|
||||
|
||||
#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
|
||||
* we can change them and restore later...
|
||||
|
@ -190,7 +280,7 @@ static void fghRememberState( void )
|
|||
fgDisplay.prev_ysz = ssizes[curr].height;
|
||||
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) {
|
||||
fgDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config);
|
||||
}
|
||||
|
@ -355,7 +445,7 @@ static void fghRestoreState( void )
|
|||
#elif TARGET_HOST_MS_WINDOWS
|
||||
|
||||
/* Restore the previously remembered desktop display settings */
|
||||
ChangeDisplaySettingsEx( fgDisplay.DisplayName,&fgDisplay.DisplayMode, 0,0,0 );
|
||||
fghPlatformChangeDisplayMode(GL_FALSE,&fgDisplay.DisplayMode);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -516,11 +606,10 @@ static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
|
|||
#elif TARGET_HOST_MS_WINDOWS
|
||||
|
||||
DEVMODE devMode;
|
||||
char *fggmstr = NULL;
|
||||
char displayMode[300];
|
||||
|
||||
success = GL_FALSE;
|
||||
|
||||
/* Get current display mode */
|
||||
EnumDisplaySettings( fgDisplay.DisplayName, -1, &devMode );
|
||||
devMode.dmFields = 0;
|
||||
|
||||
|
@ -545,50 +634,7 @@ static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
|
|||
devMode.dmFields |= DM_DISPLAYFREQUENCY;
|
||||
}
|
||||
|
||||
switch ( ChangeDisplaySettingsEx(fgDisplay.DisplayName, &devMode, 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, 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);
|
||||
}
|
||||
success = fghPlatformChangeDisplayMode(haveToTest, &devMode);
|
||||
#endif
|
||||
|
||||
return success;
|
||||
|
|
|
@ -391,13 +391,13 @@ void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLi
|
|||
|
||||
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++)
|
||||
{
|
||||
glVertex3d(cost[j+0]*r0, sint[j+0]*r0, z0 );
|
||||
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 );
|
||||
}
|
||||
|
||||
|
@ -463,7 +463,7 @@ void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLin
|
|||
|
||||
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(0.0, 0.0, height);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
/* -- GLOBAL VARIABLES ----------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* A structure pointed by g_pDisplay holds all information
|
||||
* A structure fgDisplay holds all information
|
||||
* regarding the display, screen, root window etc.
|
||||
*/
|
||||
SFG_Display fgDisplay;
|
||||
|
@ -77,9 +77,9 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
|
|||
0, /* ActiveMenus */
|
||||
NULL, /* MenuStateCallback */
|
||||
NULL, /* MenuStatusCallback */
|
||||
{ 640, 480, GL_TRUE }, /* GameModeSize */
|
||||
16, /* GameModeDepth */
|
||||
72, /* GameModeRefresh */
|
||||
{ -1, -1, GL_TRUE }, /* GameModeSize */
|
||||
-1, /* GameModeDepth */
|
||||
-1, /* GameModeRefresh */
|
||||
GLUT_ACTION_EXIT, /* ActionOnWindowClose */
|
||||
GLUT_EXEC_STATE_INIT, /* ExecState */
|
||||
NULL, /* ProgramName */
|
||||
|
@ -89,6 +89,7 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
|
|||
0, /* MouseWheelTicks */
|
||||
1, /* AuxiliaryBufferNumber */
|
||||
4, /* SampleNumber */
|
||||
GL_FALSE, /* SkipStaleMotion */
|
||||
1, /* MajorVersion */
|
||||
0, /* MinorVersion */
|
||||
0, /* ContextFlags */
|
||||
|
@ -392,7 +393,10 @@ static void fghInitialize( const char* displayName )
|
|||
fgState.Initialised = GL_TRUE;
|
||||
|
||||
/* 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 )
|
||||
atexit(fgDeinitialize);
|
||||
#endif
|
||||
|
@ -483,10 +487,10 @@ void fgDeinitialize( void )
|
|||
fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
|
||||
fgState.Modifiers = INVALID_MODIFIERS;
|
||||
|
||||
fgState.GameModeSize.X = 640;
|
||||
fgState.GameModeSize.Y = 480;
|
||||
fgState.GameModeDepth = 16;
|
||||
fgState.GameModeRefresh = 72;
|
||||
fgState.GameModeSize.X = -1;
|
||||
fgState.GameModeSize.Y = -1;
|
||||
fgState.GameModeDepth = -1;
|
||||
fgState.GameModeRefresh = -1;
|
||||
|
||||
fgListInit( &fgState.Timers );
|
||||
fgListInit( &fgState.FreeTimers );
|
||||
|
@ -1114,6 +1118,7 @@ void FGAPIENTRY glutInitDisplayString( const char* displayMode )
|
|||
case 35 : /* "borderless": windows should not have borders */
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
#endif
|
||||
glut_state_flag |= GLUT_BORDERLESS;
|
||||
break ;
|
||||
|
||||
case 36 : /* "aux": some number of aux buffers */
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
|
||||
/* XXX Update these for each release! */
|
||||
#define VERSION_MAJOR 2
|
||||
#define VERSION_MINOR 7
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_MINOR 8
|
||||
#define VERSION_PATCH 1
|
||||
|
||||
/* Freeglut is intended to function under all Unix/X11 and Win32 platforms. */
|
||||
/* XXX: Don't all MS-Windows compilers (except Cygwin) have _WIN32 defined?
|
||||
|
@ -109,7 +109,7 @@
|
|||
# include <X11/Xlib.h>
|
||||
# include <X11/Xatom.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
|
||||
# include <X11/extensions/xf86vmode.h>
|
||||
# endif
|
||||
|
@ -138,9 +138,9 @@
|
|||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
|
@ -344,6 +344,8 @@ struct tagSFG_State
|
|||
int AuxiliaryBufferNumber; /* Number of auxiliary buffers */
|
||||
int SampleNumber; /* Number of samples per pixel */
|
||||
|
||||
GLboolean SkipStaleMotion; /* skip stale motion events */
|
||||
|
||||
int MajorVersion; /* Major OpenGL context version */
|
||||
int MinorVersion; /* Minor OpenGL context version */
|
||||
int ContextFlags; /* OpenGL context flags */
|
||||
|
@ -729,7 +731,8 @@ struct tagSFG_Enumerator
|
|||
GLboolean found; /* Used to terminate search */
|
||||
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 */
|
||||
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
|
||||
* are defined and exported from freeglut_structure.c file.
|
||||
*/
|
||||
void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator );
|
||||
void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
|
||||
void fgEnumWindows( FGCBWindowEnumerator enumCallback, SFG_Enumerator* enumerator );
|
||||
void fgEnumSubWindows( SFG_Window* window, FGCBWindowEnumerator enumCallback,
|
||||
SFG_Enumerator* enumerator );
|
||||
|
||||
#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
|
||||
* (or a valid window pointer from which the style can be queried).
|
||||
*/
|
||||
void fghComputeWindowRectFromClientArea_UseStyle ( const DWORD windowStyle , RECT *clientRect, BOOL posIsOutside );
|
||||
void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside );
|
||||
void fghComputeClientAreaFromWindowRect ( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside );
|
||||
RECT fghGetClientArea ( const SFG_Window *window, BOOL wantPosOutside );
|
||||
void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth);
|
||||
void fghGetDefaultWindowStyle(DWORD *flags);
|
||||
void fghGetStyleFromWindow( const SFG_Window *window, DWORD *windowStyle, DWORD *windowExStyle );
|
||||
void fghComputeWindowRectFromClientArea_UseStyle( RECT *clientRect, const DWORD windowStyle, const DWORD windowExStyle, BOOL posIsOutside );
|
||||
void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside );
|
||||
void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL wantPosOutside );
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -965,6 +968,12 @@ SFG_Window* fgWindowByID( int windowID );
|
|||
*/
|
||||
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
|
||||
* of the menu user interface handling code...
|
||||
|
@ -1018,8 +1027,6 @@ SFG_Proc fghGetProcAddress( const char *procName );
|
|||
extern void (__cdecl *__glutExitFunc)( int return_value );
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#endif /* FREEGLUT_INTERNAL_H */
|
||||
|
||||
/*** END OF FILE ***/
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
# define VFPRINTF(s,f,a)
|
||||
#endif
|
||||
|
||||
// QB64-PE Custom Code
|
||||
// QB64-PE: custom code begin
|
||||
#include "../../../libqb/include/keyhandler.h"
|
||||
|
||||
#define QB64_EVENT_CLOSE 1
|
||||
|
@ -53,6 +53,7 @@ void qb64_os_event_linux(XEvent *event, Display *display, int *qb64_os_event_inf
|
|||
#else
|
||||
LRESULT qb64_os_event_windows(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, int *qb64_os_event_info);
|
||||
#endif
|
||||
// QB64-PE: custom code end
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
|
||||
|
@ -85,11 +86,23 @@ struct GXKeyList gxKeyList;
|
|||
# define MIN(a,b) (((a)<(b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#if TARGET_HOST_POSIX_X11
|
||||
/* used in the event handling code to match and discard stale mouse motion events */
|
||||
static Bool match_motion(Display *dpy, XEvent *xev, XPointer arg)
|
||||
{
|
||||
return xev->type == MotionNotify;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WM_TOUCH
|
||||
typedef BOOL (WINAPI *pGetTouchInputInfo)(HTOUCHINPUT,UINT,PTOUCHINPUT,int);
|
||||
typedef BOOL (WINAPI *pCloseTouchInputHandle)(HTOUCHINPUT);
|
||||
static pGetTouchInputInfo fghGetTouchInputInfo = (pGetTouchInputInfo)0xDEADBEEF;
|
||||
static pCloseTouchInputHandle fghCloseTouchInputHandle = (pCloseTouchInputHandle)0xDEADBEEF;
|
||||
static pGetTouchInputInfo fghGetTouchInputInfo = (pGetTouchInputInfo)0xDEADBEEF;
|
||||
static pCloseTouchInputHandle fghCloseTouchInputHandle = (pCloseTouchInputHandle)0xDEADBEEF;
|
||||
#endif
|
||||
|
||||
#if TARGET_HOST_MS_WINDOWS
|
||||
extern void fgPlatformCheckMenuDeactivate();
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -130,6 +143,16 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height )
|
|||
* For windowed mode, get the current position of the
|
||||
* window and resize taking the size of the frame
|
||||
* decorations into account.
|
||||
*
|
||||
* Note on maximizing behavior of Windows: the resize borders are off
|
||||
* the screen such that the client area extends all the way from the
|
||||
* leftmost corner to the rightmost corner to maximize screen real
|
||||
* estate. A caption is still shown however to allow interaction with
|
||||
* the window controls. This is default behavior of Windows that
|
||||
* FreeGLUT sticks with. To alter, one would have to check if
|
||||
* WS_MAXIMIZE style is set when a resize event is triggered, and
|
||||
* then manually correct the windowRect to put the borders back on
|
||||
* screen.
|
||||
*/
|
||||
|
||||
/* "GetWindowRect" returns the pixel coordinates of the outside of the window */
|
||||
|
@ -141,7 +164,7 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height )
|
|||
|
||||
if (window->Parent == NULL)
|
||||
/* get the window rect from this to feed to SetWindowPos, correct for window decorations */
|
||||
fghComputeWindowRectFromClientArea_QueryWindow(window,&windowRect,TRUE);
|
||||
fghComputeWindowRectFromClientArea_QueryWindow(&windowRect,window,TRUE);
|
||||
else
|
||||
{
|
||||
/* correct rect for position client area of parent window
|
||||
|
@ -151,11 +174,8 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height )
|
|||
* for them.
|
||||
*/
|
||||
RECT parentRect;
|
||||
parentRect = fghGetClientArea( window->Parent, FALSE );
|
||||
windowRect.left -= parentRect.left;
|
||||
windowRect.right -= parentRect.left;
|
||||
windowRect.top -= parentRect.top;
|
||||
windowRect.bottom -= parentRect.top;
|
||||
fghGetClientArea( &parentRect, window->Parent, FALSE );
|
||||
OffsetRect(&windowRect,-parentRect.left,-parentRect.top);
|
||||
}
|
||||
|
||||
/* Do the actual resizing */
|
||||
|
@ -184,6 +204,7 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height )
|
|||
* 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.
|
||||
* DN: Hmm.. the above sounds like a concern only in single buffered mode...
|
||||
*/
|
||||
window->State.Redisplay = GL_TRUE;
|
||||
|
||||
|
@ -210,13 +231,17 @@ static void fghRedrawWindow ( SFG_Window *window )
|
|||
|
||||
if( window->State.NeedToResize )
|
||||
{
|
||||
/* Set need to resize to false before calling fghReshapeWindow, otherwise
|
||||
in the case the user's reshape callback calls glutReshapeWindow,
|
||||
his request would get canceled after fghReshapeWindow gets called.
|
||||
*/
|
||||
window->State.NeedToResize = GL_FALSE;
|
||||
|
||||
fghReshapeWindow(
|
||||
window,
|
||||
window->State.Width,
|
||||
window->State.Height
|
||||
);
|
||||
|
||||
window->State.NeedToResize = GL_FALSE;
|
||||
}
|
||||
|
||||
INVOKE_WCB( *window, Display, ( ) );
|
||||
|
@ -323,16 +348,22 @@ static void fghCheckTimers( void )
|
|||
* 32-bit, where the GLUT API return value is also overflowed.
|
||||
*/
|
||||
unsigned long fgSystemTime(void) {
|
||||
#if TARGET_HOST_SOLARIS || HAVE_GETTIMEOFDAY
|
||||
struct timeval now;
|
||||
gettimeofday( &now, NULL );
|
||||
return now.tv_usec/1000 + now.tv_sec*1000;
|
||||
#elif TARGET_HOST_MS_WINDOWS
|
||||
#if TARGET_HOST_MS_WINDOWS
|
||||
# if defined(_WIN32_WCE)
|
||||
return GetTickCount();
|
||||
# else
|
||||
return timeGetTime();
|
||||
# endif
|
||||
#else
|
||||
# ifdef CLOCK_MONOTONIC
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
return now.tv_nsec/1000000 + now.tv_sec*1000;
|
||||
# elif HAVE_GETTIMEOFDAY
|
||||
struct timeval now;
|
||||
gettimeofday( &now, NULL );
|
||||
return now.tv_usec/1000 + now.tv_sec*1000;
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1006,9 +1037,6 @@ void FGAPIENTRY glutMainLoopEvent( void )
|
|||
window->State.MouseX = event.a.x; \
|
||||
window->State.MouseY = event.a.y;
|
||||
|
||||
|
||||
|
||||
|
||||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoopEvent" );
|
||||
|
||||
while( XPending( fgDisplay.Display ) )
|
||||
|
@ -1018,24 +1046,33 @@ void FGAPIENTRY glutMainLoopEvent( void )
|
|||
fghPrintEvent( &event );
|
||||
#endif
|
||||
|
||||
// QB64-PE: custom code begin
|
||||
int qb64_os_event_info = 0;
|
||||
|
||||
qb64_os_event_info = 1;
|
||||
qb64_os_event_linux(&event, fgDisplay.Display, &qb64_os_event_info);
|
||||
if (qb64_os_event_info == 3)
|
||||
return;
|
||||
// QB64-PE: custom code end
|
||||
|
||||
switch (event.type) {
|
||||
switch( event.type )
|
||||
{
|
||||
case ClientMessage:
|
||||
if (fgIsSpaceballXEvent(&event)) {
|
||||
fgSpaceballHandleXEvent(&event);
|
||||
break;
|
||||
}
|
||||
if (fgStructure.CurrentWindow)
|
||||
if(fgIsSpaceballXEvent(&event)) {
|
||||
fgSpaceballHandleXEvent(&event);
|
||||
break;
|
||||
}
|
||||
/* Destroy the window when the WM_DELETE_WINDOW message arrives */
|
||||
if ((Atom)event.xclient.data.l[0] == fgDisplay.DeleteWindow) {
|
||||
GETWINDOW(xclient);
|
||||
if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.DeleteWindow )
|
||||
{
|
||||
GETWINDOW( xclient );
|
||||
|
||||
// QB64-PE: custom code begin
|
||||
qb64_custom_event(QB64_EVENT_CLOSE, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL);
|
||||
/* fgDestroyWindow ( window );
|
||||
|
||||
/*
|
||||
fgDestroyWindow ( window );
|
||||
|
||||
if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
|
||||
{
|
||||
|
@ -1044,8 +1081,10 @@ void FGAPIENTRY glutMainLoopEvent( void )
|
|||
}
|
||||
else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
|
||||
fgState.ExecState = GLUT_EXEC_STATE_STOP;
|
||||
|
||||
return;
|
||||
*/
|
||||
// QB64-PE: custom code end
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1189,6 +1228,13 @@ void FGAPIENTRY glutMainLoopEvent( void )
|
|||
|
||||
case MotionNotify:
|
||||
{
|
||||
/* if GLUT_SKIP_STALE_MOTION_EVENTS is true, then discard all but
|
||||
* the last motion event from the queue
|
||||
*/
|
||||
if(fgState.SkipStaleMotion) {
|
||||
while(XCheckIfEvent(fgDisplay.Display, &event, match_motion, 0));
|
||||
}
|
||||
|
||||
GETWINDOW( xmotion );
|
||||
GETMOUSE( xmotion );
|
||||
|
||||
|
@ -1289,8 +1335,8 @@ void FGAPIENTRY glutMainLoopEvent( void )
|
|||
*
|
||||
* XXX Note that {button} has already been decremented
|
||||
* XXX in mapping from X button numbering to GLUT.
|
||||
*
|
||||
* XXX Should add support for partial wheel turns as Windows does -- 5/27/11
|
||||
*
|
||||
* XXX Should add support for partial wheel turns as Windows does -- 5/27/11
|
||||
*/
|
||||
int wheel_number = (button - glutDeviceGet ( GLUT_NUM_MOUSE_BUTTONS )) / 2;
|
||||
int direction = -1;
|
||||
|
@ -1475,10 +1521,12 @@ void FGAPIENTRY glutMainLoopEvent( void )
|
|||
break;
|
||||
}
|
||||
|
||||
// QB64-PE: custom code begin
|
||||
qb64_os_event_info = 2;
|
||||
qb64_os_event_linux(&event, fgDisplay.Display, &qb64_os_event_info);
|
||||
if (qb64_os_event_info == 3)
|
||||
return; //(although we would return anyway)
|
||||
// QB64-PE: custom code end
|
||||
}
|
||||
|
||||
#elif TARGET_HOST_MS_WINDOWS
|
||||
|
@ -1629,6 +1677,9 @@ static int fghGetWin32Modifiers (void)
|
|||
LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
||||
LPARAM lParam )
|
||||
{
|
||||
// QB64-PE: custom code begin
|
||||
static int raw_setup = 0;
|
||||
static RAWINPUTDEVICE Rid[1];
|
||||
int qb64_os_event_info = 0;
|
||||
LRESULT qb64_os_event_return = 1;
|
||||
|
||||
|
@ -1636,10 +1687,12 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
qb64_os_event_return = qb64_os_event_windows(hWnd, uMsg, wParam, lParam, &qb64_os_event_info);
|
||||
if (qb64_os_event_info == 3)
|
||||
return qb64_os_event_return;
|
||||
// QB64-PE: custom code end
|
||||
|
||||
static unsigned char lControl = 0, rControl = 0, lShift = 0, rShift = 0, lAlt = 0, rAlt = 0;
|
||||
static unsigned char lControl = 0, rControl = 0, lShift = 0,
|
||||
rShift = 0, lAlt = 0, rAlt = 0;
|
||||
|
||||
SFG_Window* window;
|
||||
SFG_Window* window, *child_window = NULL;
|
||||
PAINTSTRUCT ps;
|
||||
LRESULT lRet = 1;
|
||||
|
||||
|
@ -1653,70 +1706,94 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
/* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0,
|
||||
uMsg, wParam, lParam ); */
|
||||
|
||||
/* Some events only sent to main window. Check if the current window that
|
||||
* the mouse is over is a child window. Below when handling some messages,
|
||||
* we make sure that we process callbacks on the child window instead.
|
||||
* This mirrors how GLUT does things.
|
||||
*/
|
||||
if (window && window->Children.First)
|
||||
{
|
||||
POINT mouse_pos;
|
||||
SFG_WindowHandleType hwnd;
|
||||
SFG_Window* temp_window;
|
||||
|
||||
GetCursorPos( &mouse_pos );
|
||||
ScreenToClient( window->Window.Handle, &mouse_pos );
|
||||
hwnd = ChildWindowFromPoint(window->Window.Handle, mouse_pos);
|
||||
if (hwnd) /* can be NULL if mouse outside parent by the time we get here */
|
||||
{
|
||||
temp_window = fgWindowByHandle(hwnd);
|
||||
if (temp_window && temp_window->Parent) /* Verify we got a child window */
|
||||
child_window = temp_window;
|
||||
}
|
||||
}
|
||||
|
||||
if ( window )
|
||||
{
|
||||
SFG_Window* temp_window = child_window?child_window:window;
|
||||
|
||||
fgState.Modifiers = fghGetWin32Modifiers( );
|
||||
|
||||
/* Checking for CTRL, ALT, and SHIFT key positions: Key Down! */
|
||||
if (hWnd == GetForegroundWindow()) {
|
||||
if ( !lControl && GetAsyncKeyState ( VK_LCONTROL ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, Special,
|
||||
( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY )
|
||||
);
|
||||
if ( !lControl && GetAsyncKeyState ( VK_LCONTROL ) )
|
||||
{
|
||||
INVOKE_WCB ( *temp_window, Special,
|
||||
( GLUT_KEY_CTRL_L, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
lControl = 1;
|
||||
}
|
||||
lControl = 1;
|
||||
}
|
||||
|
||||
if ( !rControl && GetAsyncKeyState ( VK_RCONTROL ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, Special,
|
||||
( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY )
|
||||
);
|
||||
if ( !rControl && GetAsyncKeyState ( VK_RCONTROL ) )
|
||||
{
|
||||
INVOKE_WCB ( *temp_window, Special,
|
||||
( GLUT_KEY_CTRL_R, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
rControl = 1;
|
||||
}
|
||||
rControl = 1;
|
||||
}
|
||||
|
||||
if ( !lShift && GetAsyncKeyState ( VK_LSHIFT ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, Special,
|
||||
( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY )
|
||||
);
|
||||
if ( !lShift && GetAsyncKeyState ( VK_LSHIFT ) )
|
||||
{
|
||||
INVOKE_WCB ( *temp_window, Special,
|
||||
( GLUT_KEY_SHIFT_L, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
lShift = 1;
|
||||
}
|
||||
lShift = 1;
|
||||
}
|
||||
|
||||
if ( !rShift && GetAsyncKeyState ( VK_RSHIFT ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, Special,
|
||||
( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY )
|
||||
);
|
||||
if ( !rShift && GetAsyncKeyState ( VK_RSHIFT ) )
|
||||
{
|
||||
INVOKE_WCB ( *temp_window, Special,
|
||||
( GLUT_KEY_SHIFT_R, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
rShift = 1;
|
||||
}
|
||||
rShift = 1;
|
||||
}
|
||||
|
||||
if ( !lAlt && GetAsyncKeyState ( VK_LMENU ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, Special,
|
||||
( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY )
|
||||
);
|
||||
if ( !lAlt && GetAsyncKeyState ( VK_LMENU ) )
|
||||
{
|
||||
INVOKE_WCB ( *temp_window, Special,
|
||||
( GLUT_KEY_ALT_L, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
lAlt = 1;
|
||||
}
|
||||
lAlt = 1;
|
||||
}
|
||||
|
||||
if ( !rAlt && GetAsyncKeyState ( VK_RMENU ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, Special,
|
||||
( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY )
|
||||
);
|
||||
if ( !rAlt && GetAsyncKeyState ( VK_RMENU ) )
|
||||
{
|
||||
INVOKE_WCB ( *temp_window, Special,
|
||||
( GLUT_KEY_ALT_R, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
rAlt = 1;
|
||||
}
|
||||
}
|
||||
rAlt = 1;
|
||||
}
|
||||
|
||||
/* Checking for CTRL, ALT, and SHIFT key positions: Key Up! */
|
||||
if ( lControl && !GetAsyncKeyState ( VK_LCONTROL ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, SpecialUp,
|
||||
( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY )
|
||||
INVOKE_WCB ( *temp_window, SpecialUp,
|
||||
( GLUT_KEY_CTRL_L, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
lControl = 0;
|
||||
|
@ -1724,8 +1801,8 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
|
||||
if ( rControl && !GetAsyncKeyState ( VK_RCONTROL ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, SpecialUp,
|
||||
( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY )
|
||||
INVOKE_WCB ( *temp_window, SpecialUp,
|
||||
( GLUT_KEY_CTRL_R, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
rControl = 0;
|
||||
|
@ -1733,8 +1810,8 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
|
||||
if ( lShift && !GetAsyncKeyState ( VK_LSHIFT ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, SpecialUp,
|
||||
( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY )
|
||||
INVOKE_WCB ( *temp_window, SpecialUp,
|
||||
( GLUT_KEY_SHIFT_L, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
lShift = 0;
|
||||
|
@ -1742,8 +1819,8 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
|
||||
if ( rShift && !GetAsyncKeyState ( VK_RSHIFT ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, SpecialUp,
|
||||
( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY )
|
||||
INVOKE_WCB ( *temp_window, SpecialUp,
|
||||
( GLUT_KEY_SHIFT_R, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
rShift = 0;
|
||||
|
@ -1751,8 +1828,8 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
|
||||
if ( lAlt && !GetAsyncKeyState ( VK_LMENU ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, SpecialUp,
|
||||
( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY )
|
||||
INVOKE_WCB ( *temp_window, SpecialUp,
|
||||
( GLUT_KEY_ALT_L, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
lAlt = 0;
|
||||
|
@ -1760,12 +1837,14 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
|
||||
if ( rAlt && !GetAsyncKeyState ( VK_RMENU ) )
|
||||
{
|
||||
INVOKE_WCB ( *window, SpecialUp,
|
||||
( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY )
|
||||
INVOKE_WCB ( *temp_window, SpecialUp,
|
||||
( GLUT_KEY_ALT_R, temp_window->State.MouseX, temp_window->State.MouseY )
|
||||
);
|
||||
|
||||
rAlt = 0;
|
||||
}
|
||||
|
||||
fgState.Modifiers = INVALID_MODIFIERS;
|
||||
}
|
||||
|
||||
switch( uMsg )
|
||||
|
@ -1882,19 +1961,37 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
|
||||
case WM_SETFOCUS:
|
||||
/* printf("WM_SETFOCUS: %p\n", window ); */
|
||||
|
||||
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||||
INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
|
||||
|
||||
if (child_window)
|
||||
{
|
||||
/* If child should have focus instead, set it here. */
|
||||
SetFocus(child_window->Window.Handle);
|
||||
SetActiveWindow( child_window->Window.Handle );
|
||||
INVOKE_WCB( *child_window, Entry, ( GLUT_ENTERED ) );
|
||||
UpdateWindow ( child_window->Window.Handle );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetActiveWindow( window->Window.Handle );
|
||||
INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
|
||||
}
|
||||
/* Always request update on main window to be safe */
|
||||
UpdateWindow ( hWnd );
|
||||
break;
|
||||
|
||||
case WM_KILLFOCUS:
|
||||
/* printf("WM_KILLFOCUS: %p\n", window ); */
|
||||
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||||
INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
|
||||
|
||||
if( window->IsMenu &&
|
||||
window->ActiveMenu && window->ActiveMenu->IsActive )
|
||||
fgUpdateMenuHighlight( window->ActiveMenu );
|
||||
{
|
||||
SFG_Window* saved_window = fgStructure.CurrentWindow;
|
||||
/* printf("WM_KILLFOCUS: %p\n", window ); */
|
||||
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
|
||||
INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
|
||||
fgSetWindow(saved_window);
|
||||
|
||||
/* Check if there are any open menus that need to be closed */
|
||||
fgPlatformCheckMenuDeactivate();
|
||||
}
|
||||
break;
|
||||
|
||||
#if 0
|
||||
|
@ -1926,25 +2023,28 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
case WM_PAINT:
|
||||
/* Turn on the visibility in case it was turned off somehow */
|
||||
window->State.Visible = GL_TRUE;
|
||||
InvalidateRect( hWnd, NULL, GL_FALSE ); /* Make sure whole window is repainted. Bit of a hack, but a safe one from what google turns up... */
|
||||
BeginPaint( hWnd, &ps );
|
||||
fghRedrawWindow( window );
|
||||
EndPaint( hWnd, &ps );
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
// QB64
|
||||
/*
|
||||
fgDestroyWindow ( window );
|
||||
if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
|
||||
PostQuitMessage(0);
|
||||
*/
|
||||
// QB64-PE: custom code begin
|
||||
qb64_custom_event(QB64_EVENT_CLOSE, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL);
|
||||
|
||||
/*
|
||||
fgDestroyWindow ( window );
|
||||
if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
|
||||
PostQuitMessage(0);
|
||||
*/
|
||||
// QB64-PE: custom code end
|
||||
break;
|
||||
|
||||
// QB64-PE: custom code begin
|
||||
case WM_DROPFILES:
|
||||
qb64_custom_event(QB64_EVENT_FILE_DROP, 0, 0, 0, 0, 0, 0, 0, 0, (void *)wParam, NULL);
|
||||
break;
|
||||
// QB64-PE: custom code end
|
||||
|
||||
case WM_DESTROY:
|
||||
/*
|
||||
|
@ -1952,12 +2052,10 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
*/
|
||||
return 0;
|
||||
|
||||
static int raw_setup = 0;
|
||||
static RAWINPUTDEVICE Rid[1];
|
||||
// QB64-PE: custom code begin
|
||||
case WM_INPUT: {
|
||||
if (raw_setup) {
|
||||
// QB64
|
||||
// adapted from http://msdn.microsoft.com/en-us/library/windows/desktop/ee418864%28v=vs.85%29.aspx#WM_INPUT
|
||||
// Adapted from http://msdn.microsoft.com/en-us/library/windows/desktop/ee418864%28v=vs.85%29.aspx#WM_INPUT
|
||||
UINT dwSize = sizeof(RAWINPUT);
|
||||
static BYTE lpb[sizeof(RAWINPUT)];
|
||||
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
|
||||
|
@ -1971,9 +2069,11 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
}
|
||||
break;
|
||||
}
|
||||
// QB64-PE: custom code end
|
||||
|
||||
case WM_MOUSEMOVE: {
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
// QB64-PE: custom code begin
|
||||
if (!raw_setup) {
|
||||
raw_setup = 1;
|
||||
# ifndef HID_USAGE_PAGE_GENERIC
|
||||
|
@ -1988,8 +2088,9 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
Rid[0].hwndTarget = window->Window.Handle;
|
||||
RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
|
||||
}
|
||||
// QB64-PE: custom code end
|
||||
|
||||
# if defined(_WIN32_WCE)
|
||||
#if defined(_WIN32_WCE)
|
||||
window->State.MouseX = 320-HIWORD( lParam );
|
||||
window->State.MouseY = LOWORD( lParam );
|
||||
#else
|
||||
|
@ -2006,7 +2107,6 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
fgUpdateMenuHighlight( window->ActiveMenu );
|
||||
break;
|
||||
}
|
||||
SetFocus(window->Window.Handle);
|
||||
|
||||
fgState.Modifiers = fghGetWin32Modifiers( );
|
||||
|
||||
|
@ -2020,7 +2120,8 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
window->State.MouseY ) );
|
||||
|
||||
fgState.Modifiers = INVALID_MODIFIERS;
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
|
@ -2132,19 +2233,18 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x020a:
|
||||
/* Should be WM_MOUSEWHEEL but my compiler doesn't recognize it */
|
||||
case WM_MOUSEWHEEL:
|
||||
{
|
||||
int wheel_number = LOWORD( wParam );
|
||||
short ticks = ( short )HIWORD( wParam );
|
||||
fgState.MouseWheelTicks += ticks;
|
||||
fgState.MouseWheelTicks += ticks;
|
||||
|
||||
/*
|
||||
* XXX Should use WHEEL_DELTA instead of 120
|
||||
*/
|
||||
if ( abs ( fgState.MouseWheelTicks ) > 120 )
|
||||
{
|
||||
int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1;
|
||||
if ( abs ( fgState.MouseWheelTicks ) >= 120 )
|
||||
{
|
||||
int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1;
|
||||
|
||||
if( ! FETCH_WCB( *window, MouseWheel ) &&
|
||||
! FETCH_WCB( *window, Mouse ) )
|
||||
|
@ -2156,8 +2256,8 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
/*
|
||||
* XXX Should use WHEEL_DELTA instead of 120
|
||||
*/
|
||||
while( abs ( fgState.MouseWheelTicks ) > 120 )
|
||||
{
|
||||
while( abs ( fgState.MouseWheelTicks ) >= 120 )
|
||||
{
|
||||
if( FETCH_WCB( *window, MouseWheel ) )
|
||||
INVOKE_WCB( *window, MouseWheel,
|
||||
( wheel_number,
|
||||
|
@ -2167,7 +2267,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
)
|
||||
);
|
||||
else /* No mouse wheel, call the mouse button callback twice */
|
||||
{
|
||||
{
|
||||
/*
|
||||
* Map wheel zero to button 3 and 4; +1 to 3, -1 to 4
|
||||
* " " one +1 to 5, -1 to 6, ...
|
||||
|
@ -2186,23 +2286,23 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
( button, GLUT_UP,
|
||||
window->State.MouseX, window->State.MouseY )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX Should use WHEEL_DELTA instead of 120
|
||||
*/
|
||||
fgState.MouseWheelTicks -= 120 * direction;
|
||||
}
|
||||
fgState.MouseWheelTicks -= 120 * direction;
|
||||
}
|
||||
|
||||
fgState.Modifiers = INVALID_MODIFIERS;
|
||||
}
|
||||
}
|
||||
}
|
||||
break ;
|
||||
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_KEYDOWN:
|
||||
{
|
||||
// QB64
|
||||
// QB64-PE: custom code begin
|
||||
if (wParam == VK_PAUSE) {
|
||||
qb64_custom_event(QB64_EVENT_KEY, VK + QBVK_PAUSE, 1, 0, 0, 0, 0, 0, 0, NULL, NULL);
|
||||
break;
|
||||
|
@ -2211,10 +2311,14 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
qb64_custom_event(QB64_EVENT_KEY, VK + QBVK_BREAK, 1, 0, 0, 0, 0, 0, 0, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
// QB64-PE: custom code end
|
||||
|
||||
int keypress = -1;
|
||||
POINT mouse_pos ;
|
||||
|
||||
if (child_window)
|
||||
window = child_window;
|
||||
|
||||
if( ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) )
|
||||
break;
|
||||
|
||||
|
@ -2256,12 +2360,12 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
KEY( VK_RIGHT, GLUT_KEY_RIGHT );
|
||||
KEY( VK_DOWN, GLUT_KEY_DOWN );
|
||||
KEY( VK_INSERT, GLUT_KEY_INSERT );
|
||||
KEY( VK_LCONTROL, GLUT_KEY_CTRL_L );
|
||||
KEY( VK_RCONTROL, GLUT_KEY_CTRL_R );
|
||||
KEY( VK_LSHIFT, GLUT_KEY_SHIFT_L );
|
||||
KEY( VK_RSHIFT, GLUT_KEY_SHIFT_R );
|
||||
KEY( VK_LMENU, GLUT_KEY_ALT_L );
|
||||
KEY( VK_RMENU, GLUT_KEY_ALT_R );
|
||||
|
||||
case VK_LCONTROL: case VK_RCONTROL: case VK_CONTROL:
|
||||
case VK_LSHIFT: case VK_RSHIFT: case VK_SHIFT:
|
||||
case VK_LMENU: case VK_RMENU: case VK_MENU:
|
||||
/* These keypresses and releases are handled earlier in the function */
|
||||
break;
|
||||
|
||||
case VK_DELETE:
|
||||
/* The delete key should be treated as an ASCII keypress: */
|
||||
|
@ -2305,7 +2409,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
case WM_SYSKEYUP:
|
||||
case WM_KEYUP:
|
||||
{
|
||||
// QB64
|
||||
// QB64-PE: custom code begin
|
||||
if (wParam == VK_PAUSE) {
|
||||
qb64_custom_event(QB64_EVENT_KEY, VK + QBVK_PAUSE, -1, 0, 0, 0, 0, 0, 0, NULL, NULL);
|
||||
break;
|
||||
|
@ -2314,10 +2418,14 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
qb64_custom_event(QB64_EVENT_KEY, VK + QBVK_BREAK, -1, 0, 0, 0, 0, 0, 0, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
// QB64-PE: custom code end
|
||||
|
||||
int keypress = -1;
|
||||
POINT mouse_pos;
|
||||
|
||||
if (child_window)
|
||||
window = child_window;
|
||||
|
||||
/*
|
||||
* Remember the current modifiers state. This is done here in order
|
||||
* to make sure the VK_DELETE keyboard callback is executed properly.
|
||||
|
@ -2358,12 +2466,12 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
KEY( VK_RIGHT, GLUT_KEY_RIGHT );
|
||||
KEY( VK_DOWN, GLUT_KEY_DOWN );
|
||||
KEY( VK_INSERT, GLUT_KEY_INSERT );
|
||||
KEY( VK_LCONTROL, GLUT_KEY_CTRL_L );
|
||||
KEY( VK_RCONTROL, GLUT_KEY_CTRL_R );
|
||||
KEY( VK_LSHIFT, GLUT_KEY_SHIFT_L );
|
||||
KEY( VK_RSHIFT, GLUT_KEY_SHIFT_R );
|
||||
KEY( VK_LMENU, GLUT_KEY_ALT_L );
|
||||
KEY( VK_RMENU, GLUT_KEY_ALT_R );
|
||||
|
||||
case VK_LCONTROL: case VK_RCONTROL: case VK_CONTROL:
|
||||
case VK_LSHIFT: case VK_RSHIFT: case VK_SHIFT:
|
||||
case VK_LMENU: case VK_RMENU: case VK_MENU:
|
||||
/* These keypresses and releases are handled earlier in the function */
|
||||
break;
|
||||
|
||||
case VK_DELETE:
|
||||
/* The delete key should be treated as an ASCII keypress: */
|
||||
|
@ -2398,11 +2506,15 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
);
|
||||
|
||||
fgState.Modifiers = INVALID_MODIFIERS;
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSCHAR:
|
||||
case WM_CHAR:
|
||||
{
|
||||
if (child_window)
|
||||
window = child_window;
|
||||
|
||||
if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) )
|
||||
break;
|
||||
|
||||
|
@ -2552,50 +2664,50 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
break;
|
||||
|
||||
#ifdef WM_TOUCH
|
||||
/* handle multi-touch messages */
|
||||
case WM_TOUCH:
|
||||
{
|
||||
unsigned int numInputs = (unsigned int)wParam;
|
||||
unsigned int i = 0;
|
||||
TOUCHINPUT* ti = (TOUCHINPUT*)malloc( sizeof(TOUCHINPUT)*numInputs);
|
||||
/* handle multi-touch messages */
|
||||
case WM_TOUCH:
|
||||
{
|
||||
unsigned int numInputs = (unsigned int)wParam;
|
||||
unsigned int i = 0;
|
||||
TOUCHINPUT* ti = (TOUCHINPUT*)malloc( sizeof(TOUCHINPUT)*numInputs);
|
||||
|
||||
if (fghGetTouchInputInfo == (pGetTouchInputInfo)0xDEADBEEF) {
|
||||
fghGetTouchInputInfo = (pGetTouchInputInfo)GetProcAddress(GetModuleHandle("user32"),"GetTouchInputInfo");
|
||||
fghCloseTouchInputHandle = (pCloseTouchInputHandle)GetProcAddress(GetModuleHandle("user32"),"CloseTouchInputHandle");
|
||||
}
|
||||
if (fghGetTouchInputInfo == (pGetTouchInputInfo)0xDEADBEEF) {
|
||||
fghGetTouchInputInfo = (pGetTouchInputInfo)GetProcAddress(GetModuleHandle("user32"),"GetTouchInputInfo");
|
||||
fghCloseTouchInputHandle = (pCloseTouchInputHandle)GetProcAddress(GetModuleHandle("user32"),"CloseTouchInputHandle");
|
||||
}
|
||||
|
||||
if (!fghGetTouchInputInfo) {
|
||||
free( (void*)ti );
|
||||
break;
|
||||
}
|
||||
if (!fghGetTouchInputInfo) {
|
||||
free( (void*)ti );
|
||||
break;
|
||||
}
|
||||
|
||||
if (fghGetTouchInputInfo( (HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT) )) {
|
||||
/* Handle each contact point */
|
||||
for (i = 0; i < numInputs; ++i ) {
|
||||
if (fghGetTouchInputInfo( (HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT) )) {
|
||||
/* Handle each contact point */
|
||||
for (i = 0; i < numInputs; ++i ) {
|
||||
|
||||
POINT tp;
|
||||
tp.x = TOUCH_COORD_TO_PIXEL(ti[i].x);
|
||||
tp.y = TOUCH_COORD_TO_PIXEL(ti[i].y);
|
||||
ScreenToClient( hWnd, &tp );
|
||||
POINT tp;
|
||||
tp.x = TOUCH_COORD_TO_PIXEL(ti[i].x);
|
||||
tp.y = TOUCH_COORD_TO_PIXEL(ti[i].y);
|
||||
ScreenToClient( hWnd, &tp );
|
||||
|
||||
ti[i].dwID = ti[i].dwID * 2;
|
||||
ti[i].dwID = ti[i].dwID * 2;
|
||||
|
||||
if (ti[i].dwFlags & TOUCHEVENTF_DOWN) {
|
||||
INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_ENTERED ) );
|
||||
INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_DOWN ) );
|
||||
} else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) {
|
||||
INVOKE_WCB( *window, MultiMotion, ( ti[i].dwID, tp.x, tp.y ) );
|
||||
} else if (ti[i].dwFlags & TOUCHEVENTF_UP) {
|
||||
INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_UP ) );
|
||||
INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_LEFT ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
fghCloseTouchInputHandle((HTOUCHINPUT)lParam);
|
||||
free( (void*)ti );
|
||||
lRet = 0; /*DefWindowProc( hWnd, uMsg, wParam, lParam );*/
|
||||
break;
|
||||
}
|
||||
if (ti[i].dwFlags & TOUCHEVENTF_DOWN) {
|
||||
INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_ENTERED ) );
|
||||
INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_DOWN ) );
|
||||
} else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) {
|
||||
INVOKE_WCB( *window, MultiMotion, ( ti[i].dwID, tp.x, tp.y ) );
|
||||
} else if (ti[i].dwFlags & TOUCHEVENTF_UP) {
|
||||
INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_UP ) );
|
||||
INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_LEFT ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
fghCloseTouchInputHandle((HTOUCHINPUT)lParam);
|
||||
free( (void*)ti );
|
||||
lRet = 0; /*DefWindowProc( hWnd, uMsg, wParam, lParam );*/
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
/* Handle unhandled messages */
|
||||
|
@ -2603,10 +2715,12 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
|
|||
break;
|
||||
}
|
||||
|
||||
// QB64-PE: custom code begin
|
||||
qb64_os_event_info = 2;
|
||||
qb64_os_event_return = qb64_os_event_windows(hWnd, uMsg, wParam, lParam, &qb64_os_event_info);
|
||||
if (qb64_os_event_info == 3)
|
||||
return qb64_os_event_return;
|
||||
// QB64-PE: custom code end
|
||||
|
||||
return lRet;
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
#endif
|
||||
|
||||
extern void fghGetCursorPos(SFG_XYUse *mouse_pos);
|
||||
|
||||
|
||||
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||
|
||||
/*
|
||||
|
@ -532,14 +535,15 @@ void fgDisplayMenu( void )
|
|||
static void fghActivateMenu( SFG_Window* window, int button )
|
||||
{
|
||||
int max_x, max_y;
|
||||
SFG_XYUse mouse_pos;
|
||||
|
||||
/* We'll be referencing this menu a lot, so remember its address: */
|
||||
SFG_Menu* menu = window->Menu[ button ];
|
||||
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 )
|
||||
menu->ParentWindow->ActiveMenu = NULL ;
|
||||
fgDeactivateMenu(menu->ParentWindow);
|
||||
|
||||
/* Mark the menu as active, so that it gets displayed: */
|
||||
window->ActiveMenu = menu;
|
||||
|
@ -550,9 +554,17 @@ static void fghActivateMenu( SFG_Window* window, int button )
|
|||
/* Set up the initial menu position now: */
|
||||
fghGetVMaxExtent(menu->ParentWindow, &max_x, &max_y);
|
||||
fgSetWindow( window );
|
||||
menu->X = window->State.MouseX + glutGet( GLUT_WINDOW_X );
|
||||
menu->Y = window->State.MouseY + glutGet( GLUT_WINDOW_Y );
|
||||
/* get mouse position on screen (window->State.MouseX and window->State.MouseY
|
||||
* 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 )
|
||||
menu->X -=menu->Width;
|
||||
|
||||
|
@ -563,10 +575,21 @@ static void fghActivateMenu( SFG_Window* window, int button )
|
|||
menu->Y = 0;
|
||||
}
|
||||
|
||||
menu->Window->State.MouseX =
|
||||
window->State.MouseX + glutGet( GLUT_WINDOW_X ) - menu->X;
|
||||
menu->Window->State.MouseY =
|
||||
window->State.MouseY + glutGet( GLUT_WINDOW_Y ) - menu->Y;
|
||||
/* Set position of mouse relative to top-left menu in menu's window state (could as well set 0 at creation time...) */
|
||||
menu->Window->State.MouseX = mouse_pos.X - menu->X;
|
||||
menu->Window->State.MouseY = mouse_pos.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 );
|
||||
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
|
||||
*
|
||||
* XXX This isn't enough. A downclick outside of
|
||||
* XXX the interior of our freeglut windows should also
|
||||
* XXX deactivate the menu. This is more complicated.
|
||||
* A downclick outside of the interior of our freeglut windows
|
||||
* is dealt with in the WM_KILLFOCUS handler of fgPlatformWindowProc
|
||||
*/
|
||||
fgDeactivateMenu( window->ActiveMenu->ParentWindow );
|
||||
|
||||
|
@ -684,12 +706,13 @@ GLboolean fgCheckActiveMenu ( SFG_Window *window, int button, GLboolean pressed,
|
|||
void fgDeactivateMenu( SFG_Window *window )
|
||||
{
|
||||
SFG_Window *parent_window = NULL;
|
||||
|
||||
/* Check if there is an active menu attached to this window... */
|
||||
SFG_Menu* menu = window->ActiveMenu;
|
||||
SFG_Menu* menu;
|
||||
SFG_MenuEntry *menuEntry;
|
||||
|
||||
/* 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 );
|
||||
|
||||
parent_window = menu->ParentWindow;
|
||||
|
@ -714,12 +737,32 @@ void fgDeactivateMenu( SFG_Window *window )
|
|||
{
|
||||
menuEntry->IsActive = GL_FALSE;
|
||||
|
||||
/* Is that an active submenu by any case? */
|
||||
/* Is that an active submenu by any chance? */
|
||||
if( menuEntry->SubMenu )
|
||||
fghDeactivateSubMenu( menuEntry );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#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 -------------------------------------------------- */
|
||||
|
||||
|
@ -776,6 +866,8 @@ int FGAPIENTRY glutCreateMenu( void(* callback)( int ) )
|
|||
{
|
||||
/* The menu object creation code resides in freeglut_structure.c */
|
||||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" );
|
||||
if (fgGetActiveMenu())
|
||||
fgError("Menu manipulation not allowed while menus in use.");
|
||||
return fgCreateMenu( callback )->ID;
|
||||
}
|
||||
|
||||
|
@ -799,6 +891,9 @@ void FGAPIENTRY glutDestroyMenu( int menuID )
|
|||
|
||||
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 */
|
||||
fgDestroyMenu( menu );
|
||||
}
|
||||
|
@ -839,7 +934,10 @@ void FGAPIENTRY glutAddMenuEntry( const char* label, int value )
|
|||
SFG_MenuEntry* menuEntry;
|
||||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAddMenuEntry" );
|
||||
menuEntry = (SFG_MenuEntry *)calloc( sizeof(SFG_MenuEntry), 1 );
|
||||
|
||||
freeglut_return_if_fail( fgStructure.CurrentMenu );
|
||||
if (fgGetActiveMenu())
|
||||
fgError("Menu manipulation not allowed while menus in use.");
|
||||
|
||||
menuEntry->Text = strdup( label );
|
||||
menuEntry->ID = value;
|
||||
|
@ -863,6 +961,9 @@ void FGAPIENTRY glutAddSubMenu( const char *label, int subMenuID )
|
|||
subMenu = fgMenuByID( subMenuID );
|
||||
|
||||
freeglut_return_if_fail( fgStructure.CurrentMenu );
|
||||
if (fgGetActiveMenu())
|
||||
fgError("Menu manipulation not allowed while menus in use.");
|
||||
|
||||
freeglut_return_if_fail( subMenu );
|
||||
|
||||
menuEntry->Text = strdup( label );
|
||||
|
@ -881,7 +982,10 @@ void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value )
|
|||
SFG_MenuEntry* menuEntry = NULL;
|
||||
|
||||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToMenuEntry" );
|
||||
|
||||
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: */
|
||||
menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item );
|
||||
|
@ -908,10 +1012,15 @@ void FGAPIENTRY glutChangeToSubMenu( int item, const char* label,
|
|||
SFG_MenuEntry* menuEntry;
|
||||
|
||||
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 );
|
||||
menuEntry = NULL;
|
||||
|
||||
freeglut_return_if_fail( fgStructure.CurrentMenu );
|
||||
freeglut_return_if_fail( subMenu );
|
||||
|
||||
/* Get n-th menu entry in the current menu, starting from one: */
|
||||
|
@ -937,7 +1046,10 @@ void FGAPIENTRY glutRemoveMenuItem( int item )
|
|||
SFG_MenuEntry* menuEntry;
|
||||
|
||||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutRemoveMenuItem" );
|
||||
|
||||
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: */
|
||||
menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item );
|
||||
|
@ -960,7 +1072,10 @@ void FGAPIENTRY glutAttachMenu( int button )
|
|||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAttachMenu" );
|
||||
|
||||
freeglut_return_if_fail( fgStructure.CurrentWindow );
|
||||
|
||||
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 < FREEGLUT_MAX_MENUS );
|
||||
|
@ -976,7 +1091,10 @@ void FGAPIENTRY glutDetachMenu( int button )
|
|||
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDetachMenu" );
|
||||
|
||||
freeglut_return_if_fail( fgStructure.CurrentWindow );
|
||||
|
||||
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 < FREEGLUT_MAX_MENUS );
|
||||
|
|
|
@ -124,6 +124,10 @@ void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
|
|||
fgState.SampleNumber = value;
|
||||
break;
|
||||
|
||||
case GLUT_SKIP_STALE_MOTION_EVENTS:
|
||||
fgState.SkipStaleMotion = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
fgWarning( "glutSetOption(): missing enum handle %d", eWhat );
|
||||
break;
|
||||
|
@ -132,7 +136,7 @@ void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
|
|||
|
||||
#if TARGET_HOST_MS_WINDOWS
|
||||
/* 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
|
||||
*/
|
||||
#define WGL_SAMPLES_ARB 0x2042
|
||||
|
@ -434,7 +438,7 @@ int FGAPIENTRY glutGet( GLenum eWhat )
|
|||
* behaviour, both under Windows and under UNIX/X11:
|
||||
* - When you create a window with position (x,y) and size
|
||||
* (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).
|
||||
* - When you query the size and position of the window--as
|
||||
* is happening here for Windows--"freeglut" will return
|
||||
|
@ -451,7 +455,20 @@ int FGAPIENTRY glutGet( GLenum eWhat )
|
|||
#if defined(_WIN32_WCE)
|
||||
GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
|
||||
#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) */
|
||||
|
||||
switch( eWhat )
|
||||
|
@ -465,30 +482,47 @@ int FGAPIENTRY glutGet( GLenum eWhat )
|
|||
break;
|
||||
|
||||
case GLUT_WINDOW_BORDER_WIDTH :
|
||||
case GLUT_WINDOW_HEADER_HEIGHT :
|
||||
case GLUT_WINDOW_BORDER_HEIGHT :
|
||||
#if defined(_WIN32_WCE)
|
||||
return 0;
|
||||
#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)
|
||||
windowStyle = GetWindowLong(fgStructure.CurrentWindow->Window.Handle, GWL_STYLE);
|
||||
fghGetClientArea(&clientRect,fgStructure.CurrentWindow,FALSE);
|
||||
else
|
||||
/* If no window, return sizes for a default window with title bar and border */
|
||||
windowStyle = WS_OVERLAPPEDWINDOW;
|
||||
SetRect(&clientRect,0,0,200,200);
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
case GLUT_WINDOW_BORDER_WIDTH:
|
||||
{
|
||||
int xBorderWidth, yBorderWidth;
|
||||
fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
|
||||
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;
|
||||
return borderWidth;
|
||||
case GLUT_WINDOW_BORDER_HEIGHT:
|
||||
return captionHeight;
|
||||
}
|
||||
}
|
||||
#endif /* defined(_WIN32_WCE) */
|
||||
|
@ -554,6 +588,9 @@ int FGAPIENTRY glutGet( GLenum eWhat )
|
|||
case GLUT_MULTISAMPLE:
|
||||
return fgState.SampleNumber;
|
||||
|
||||
case GLUT_SKIP_STALE_MOTION_EVENTS:
|
||||
return fgState.SkipStaleMotion;
|
||||
|
||||
default:
|
||||
fgWarning( "glutGet(): missing enum handle %d", eWhat );
|
||||
break;
|
||||
|
|
|
@ -380,7 +380,7 @@ void fgDestroyStructure( void )
|
|||
/*
|
||||
* 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;
|
||||
|
||||
|
@ -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
|
||||
* (single level descent)
|
||||
*/
|
||||
void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
|
||||
void fgEnumSubWindows( SFG_Window* window, FGCBWindowEnumerator enumCallback,
|
||||
SFG_Enumerator* enumerator )
|
||||
{
|
||||
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
|
||||
* is defined in freeglut_structure.c file.
|
||||
*/
|
||||
|
@ -495,7 +517,7 @@ SFG_Window* fgWindowByID( int windowID )
|
|||
{
|
||||
SFG_Enumerator enumerator;
|
||||
|
||||
/* Uses a method very similiar for fgWindowByHandle... */
|
||||
/* Uses a method very similar for fgWindowByHandle... */
|
||||
enumerator.found = GL_FALSE;
|
||||
enumerator.data = ( void * )&windowID;
|
||||
fgEnumWindows( fghcbWindowByID, &enumerator );
|
||||
|
@ -506,18 +528,75 @@ SFG_Window* fgWindowByID( int windowID )
|
|||
|
||||
/*
|
||||
* 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...
|
||||
*/
|
||||
SFG_Menu* fgMenuByID( int menuID )
|
||||
{
|
||||
SFG_Menu *menu = NULL;
|
||||
SFG_Enumerator enumerator;
|
||||
|
||||
/* This is easy and makes use of the menus enumeration defined above */
|
||||
enumerator.found = GL_FALSE;
|
||||
enumerator.data = (void *)menuID;
|
||||
fgEnumMenus( fghcbMenuByID, &enumerator );
|
||||
|
||||
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;
|
||||
|
||||
/* It's enough to check all entries in fgStructure.Menus... */
|
||||
for( menu = (SFG_Menu *)fgStructure.Menus.First;
|
||||
menu;
|
||||
menu = (SFG_Menu *)menu->Node.Next )
|
||||
if( menu->ID == menuID )
|
||||
return menu;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
200
internal/c/parts/core/freeglut/freeglut_teapot.c
Normal file
200
internal/c/parts/core/freeglut/freeglut_teapot.c
Normal 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 ***/
|
||||
|
||||
|
||||
|
||||
|
||||
|
2429
internal/c/parts/core/freeglut/freeglut_teapot_data.h
Normal file
2429
internal/c/parts/core/freeglut/freeglut_teapot_data.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -25,16 +25,16 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// QB64
|
||||
void QB64_Window_Handle(void *handle);
|
||||
|
||||
int QB64_Resizable();
|
||||
// QB64-PE: custom code begin
|
||||
/*
|
||||
changed:
|
||||
Changed:
|
||||
WS_OVERLAPPEDWINDOW
|
||||
...to...
|
||||
((WS_OVERLAPPEDWINDOW*QB64_Resizable())|WS_DLGFRAME|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX)
|
||||
((WS_OVERLAPPEDWINDOW * QB64_Resizable()) | WS_DLGFRAME | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
|
||||
*/
|
||||
void QB64_Window_Handle(void *handle);
|
||||
int QB64_Resizable();
|
||||
// QB64-PE: custom code end
|
||||
|
||||
#define FREEGLUT_BUILDING_LIB
|
||||
#include <GL/freeglut.h>
|
||||
|
@ -102,7 +102,7 @@ WS_OVERLAPPEDWINDOW
|
|||
|
||||
#if TARGET_HOST_MS_WINDOWS
|
||||
/* 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.
|
||||
* XXX: should local definitions for extensions be put in a separate include file?
|
||||
*/
|
||||
|
@ -153,7 +153,7 @@ typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShar
|
|||
#endif /* TARGET_HOST_MS_WINDOWS */
|
||||
|
||||
#ifdef WM_TOUCH
|
||||
typedef BOOL (WINAPI *pRegisterTouchWindow)(HWND,ULONG);
|
||||
typedef BOOL (WINAPI *pRegisterTouchWindow)(HWND,ULONG);
|
||||
static pRegisterTouchWindow fghRegisterTouchWindow = (pRegisterTouchWindow)0xDEADBEEF;
|
||||
#endif
|
||||
|
||||
|
@ -186,16 +186,9 @@ typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShar
|
|||
|
||||
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||
|
||||
static int fghIsLegacyContextVersionRequested( void )
|
||||
{
|
||||
return fgState.MajorVersion < 2 || (fgState.MajorVersion == 2 && fgState.MinorVersion <= 1);
|
||||
}
|
||||
|
||||
static int fghIsLegacyContextRequested( void )
|
||||
{
|
||||
return fghIsLegacyContextVersionRequested() &&
|
||||
fgState.ContextFlags == 0 &&
|
||||
fgState.ContextProfile == 0;
|
||||
return fgState.MajorVersion < 2 || (fgState.MajorVersion == 2 && fgState.MinorVersion <= 1);
|
||||
}
|
||||
|
||||
static int fghNumberOfAuxBuffersRequested( void )
|
||||
|
@ -401,8 +394,8 @@ GLXFBConfig* fgChooseFBConfig( int *numcfgs )
|
|||
fbconfig = NULL;
|
||||
}
|
||||
|
||||
if (numcfgs)
|
||||
*numcfgs = fbconfigArraySize;
|
||||
if (numcfgs)
|
||||
*numcfgs = fbconfigArraySize;
|
||||
|
||||
return fbconfig;
|
||||
}
|
||||
|
@ -412,10 +405,8 @@ GLXFBConfig* fgChooseFBConfig( int *numcfgs )
|
|||
static void fghFillContextAttributes( int *attributes ) {
|
||||
int where = 0, contextFlags, contextProfile;
|
||||
|
||||
if ( !fghIsLegacyContextVersionRequested() ) {
|
||||
ATTRIB_VAL( GLX_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
|
||||
ATTRIB_VAL( GLX_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
|
||||
}
|
||||
ATTRIB_VAL( GLX_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
|
||||
ATTRIB_VAL( GLX_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
|
||||
|
||||
contextFlags =
|
||||
fghMapBit( fgState.ContextFlags, GLUT_DEBUG, GLX_CONTEXT_DEBUG_BIT_ARB ) |
|
||||
|
@ -435,8 +426,8 @@ static void fghFillContextAttributes( int *attributes ) {
|
|||
}
|
||||
|
||||
typedef GLXContext (*CreateContextAttribsProc)(Display *dpy, GLXFBConfig config,
|
||||
GLXContext share_list, Bool direct,
|
||||
const int *attrib_list);
|
||||
GLXContext share_list, Bool direct,
|
||||
const int *attrib_list);
|
||||
|
||||
static GLXContext fghCreateNewContext( SFG_Window* window )
|
||||
{
|
||||
|
@ -459,8 +450,8 @@ static GLXContext fghCreateNewContext( SFG_Window* window )
|
|||
/* glXCreateContextAttribsARB not found, yet the user has requested the new context creation */
|
||||
if ( !createContextAttribs && !fghIsLegacyContextRequested() ) {
|
||||
fgWarning( "OpenGL >2.1 context requested but glXCreateContextAttribsARB is not available! Falling back to legacy context creation" );
|
||||
fgState.MajorVersion = 2;
|
||||
fgState.MinorVersion = 1;
|
||||
fgState.MajorVersion = 2;
|
||||
fgState.MinorVersion = 1;
|
||||
}
|
||||
|
||||
/* If nothing fancy has been required, simply use the old context creation GLX API entry */
|
||||
|
@ -535,9 +526,9 @@ static int fghEwmhFullscrToggle(void)
|
|||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE;
|
||||
xev.xclient.data.l[1] = fgDisplay.StateFullScreen;
|
||||
xev.xclient.data.l[2] = 0; /* no second property to toggle */
|
||||
xev.xclient.data.l[3] = 1; /* source indication: application */
|
||||
xev.xclient.data.l[4] = 0; /* unused */
|
||||
xev.xclient.data.l[2] = 0; /* no second property to toggle */
|
||||
xev.xclient.data.l[3] = 1; /* source indication: application */
|
||||
xev.xclient.data.l[4] = 0; /* unused */
|
||||
|
||||
if(!XSendEvent(fgDisplay.Display, fgDisplay.RootWindow, 0, evmask, &xev)) {
|
||||
return -1;
|
||||
|
@ -584,10 +575,8 @@ static wchar_t* fghWstrFromStr(const char* str)
|
|||
static void fghFillContextAttributes( int *attributes ) {
|
||||
int where = 0, contextFlags, contextProfile;
|
||||
|
||||
if ( !fghIsLegacyContextVersionRequested() ) {
|
||||
ATTRIB_VAL( WGL_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
|
||||
ATTRIB_VAL( WGL_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
|
||||
}
|
||||
ATTRIB_VAL( WGL_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
|
||||
ATTRIB_VAL( WGL_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
|
||||
|
||||
contextFlags =
|
||||
fghMapBit( fgState.ContextFlags, GLUT_DEBUG, WGL_CONTEXT_DEBUG_BIT_ARB ) |
|
||||
|
@ -634,6 +623,9 @@ void fgNewWGLCreateContext( SFG_Window* window )
|
|||
|
||||
if ( !fghIsExtensionSupported( window->Window.Device, "WGL_ARB_create_context" ) )
|
||||
{
|
||||
/* wglCreateContextAttribsARB not found, yet the user has requested the new context creation */
|
||||
fgWarning( "OpenGL >2.1 context requested but wglCreateContextAttribsARB is not available! Falling back to legacy context creation" );
|
||||
/* Legacy context already created at this point in WM_CREATE path of fgPlatformWindowProc, just return */
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -643,7 +635,10 @@ void fgNewWGLCreateContext( SFG_Window* window )
|
|||
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress( "wglCreateContextAttribsARB" );
|
||||
if ( wglCreateContextAttribsARB == NULL )
|
||||
{
|
||||
fgError( "wglCreateContextAttribsARB not found" );
|
||||
/* wglCreateContextAttribsARB not found, yet the user has requested the new context creation */
|
||||
fgWarning( "OpenGL >2.1 context requested but wglCreateContextAttribsARB is not available! Falling back to legacy context creation" );
|
||||
/* Legacy context already created at this point in WM_CREATE path of fgPlatformWindowProc, just return */
|
||||
return;
|
||||
}
|
||||
|
||||
context = wglCreateContextAttribsARB( window->Window.Device, 0, attributes );
|
||||
|
@ -760,14 +755,12 @@ GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
|
|||
current_hDC = window->Window.Device;
|
||||
|
||||
fghFillPFD( ppfd, current_hDC, layer_type );
|
||||
|
||||
pixelformat = ChoosePixelFormat( current_hDC, ppfd );
|
||||
|
||||
/* windows hack for multismapling/sRGB */
|
||||
if ( ( fgState.DisplayMode & GLUT_MULTISAMPLE ) ||
|
||||
( fgState.DisplayMode & GLUT_SRGB ) )
|
||||
{
|
||||
|
||||
HGLRC rc, rc_before=wglGetCurrentContext();
|
||||
HWND hWnd;
|
||||
HDC hDC, hDC_before=wglGetCurrentDC();
|
||||
|
@ -781,7 +774,14 @@ GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
|
|||
wndCls.lpszClassName = _T("FREEGLUT_dummy");
|
||||
RegisterClass( &wndCls );
|
||||
|
||||
hWnd=CreateWindow(_T("FREEGLUT_dummy"), _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | ((WS_OVERLAPPEDWINDOW*QB64_Resizable())|WS_DLGFRAME|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX|(WS_MAXIMIZEBOX*QB64_Resizable())) , 0,0,0,0, 0, 0, fgDisplay.Instance, 0 );
|
||||
// QB64-PE: custom code begin
|
||||
hWnd = CreateWindow(
|
||||
_T("FREEGLUT_dummy"), _T(""),
|
||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
|
||||
((WS_OVERLAPPEDWINDOW * QB64_Resizable()) | WS_DLGFRAME | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | (WS_MAXIMIZEBOX * QB64_Resizable())),
|
||||
0, 0, 0, 0, 0, 0, fgDisplay.Instance, 0);
|
||||
// hWnd=CreateWindow(_T("FREEGLUT_dummy"), _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW , 0,0,0,0, 0, 0, fgDisplay.Instance, 0 );
|
||||
// QB64-PE: custom code end
|
||||
hDC=GetDC(hWnd);
|
||||
SetPixelFormat( hDC, pixelformat, ppfd );
|
||||
|
||||
|
@ -865,150 +865,133 @@ void fgSetWindow ( SFG_Window *window )
|
|||
|
||||
#if TARGET_HOST_MS_WINDOWS
|
||||
|
||||
/* Computes position of corners of window Rect (outer position including
|
||||
* decorations) based on the provided client rect and based on the style
|
||||
* of the window in question.
|
||||
* If posIsOutside is set to true, the input client Rect is taken to follow
|
||||
* freeGLUT's window specification convention in which the top-left corner
|
||||
* is at the outside of the window, while the size
|
||||
* (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
|
||||
* area.
|
||||
*/
|
||||
void fghComputeWindowRectFromClientArea_UseStyle( const DWORD windowStyle, RECT *clientRect, BOOL posIsOutside )
|
||||
void fghGetDefaultWindowStyle(DWORD *flags)
|
||||
{
|
||||
RECT windowRect = {0, 0, 0, 0};
|
||||
DWORD windowExStyle = 0;
|
||||
if ( fgState.DisplayMode & GLUT_BORDERLESS )
|
||||
{
|
||||
/* no window decorations needed, no-op */
|
||||
}
|
||||
else if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
|
||||
/* only window decoration is a border, no title bar or buttons */
|
||||
(*flags) |= WS_DLGFRAME;
|
||||
else
|
||||
/* window decoration are a border, title bar and buttons. */
|
||||
// QB64-PE: custom code begin
|
||||
(*flags) |= ((WS_OVERLAPPEDWINDOW * QB64_Resizable()) | WS_DLGFRAME | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | (WS_MAXIMIZEBOX * QB64_Resizable()));
|
||||
//(*flags) |= WS_OVERLAPPEDWINDOW;
|
||||
// QB64-PE: custom code end
|
||||
}
|
||||
|
||||
CopyRect(&windowRect, clientRect);
|
||||
/* Get window style and extended window style of a FreeGLUT window
|
||||
* If the window pointer or the window handle is NULL, a fully
|
||||
* decorated window (caption and border) is assumed.
|
||||
*/
|
||||
void fghGetStyleFromWindow( const SFG_Window *window, DWORD *windowStyle, DWORD *windowExStyle )
|
||||
{
|
||||
if (window && window->Window.Handle)
|
||||
{
|
||||
*windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
|
||||
*windowExStyle = GetWindowLong(window->Window.Handle, GWL_EXSTYLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
*windowStyle = 0;
|
||||
fghGetDefaultWindowStyle(windowStyle);
|
||||
/* WindowExStyle==0 is fine/default, exStyle is currently only used for menu windows */
|
||||
*windowExStyle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Computes position of corners of window Rect (outer position including
|
||||
* decorations) based on the provided client rect and based on the style
|
||||
* of the window in question.
|
||||
* If posIsOutside is set to true, the input client Rect is taken to follow
|
||||
* freeGLUT's window specification convention in which the top-left corner
|
||||
* is at the outside of the window, while the size
|
||||
* (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
|
||||
* area.
|
||||
*/
|
||||
void fghComputeWindowRectFromClientArea_UseStyle( RECT *clientRect, const DWORD windowStyle, const DWORD windowExStyle, BOOL posIsOutside )
|
||||
{
|
||||
RECT windowRect = {0,0,0,0};
|
||||
CopyRect(&windowRect,clientRect);
|
||||
|
||||
/* Get rect including non-client area */
|
||||
AdjustWindowRectEx(&windowRect, windowStyle, FALSE, windowExStyle);
|
||||
AdjustWindowRectEx(&windowRect,windowStyle,FALSE,windowExStyle);
|
||||
|
||||
/* Move window right and down by non-client area extent on left and top, if wanted */
|
||||
if (posIsOutside) {
|
||||
windowRect.right += clientRect->left - windowRect.left;
|
||||
windowRect.bottom += clientRect->top - windowRect.top;
|
||||
windowRect.left = clientRect->left;
|
||||
windowRect.top = clientRect->top;
|
||||
if (posIsOutside)
|
||||
{
|
||||
windowRect.right += clientRect->left-windowRect.left;
|
||||
windowRect.bottom += clientRect->top -windowRect.top;
|
||||
windowRect.left = clientRect->left;
|
||||
windowRect.top = clientRect->top;
|
||||
}
|
||||
|
||||
/* done, copy windowRect to output */
|
||||
CopyRect(clientRect, &windowRect);
|
||||
CopyRect(clientRect,&windowRect);
|
||||
}
|
||||
|
||||
/* Computes position of corners of window Rect (outer position including
|
||||
* decorations) based on the provided client rect and based on the style
|
||||
* of the window in question. If the window pointer or the window handle
|
||||
* is NULL, a fully decorated window (caption and border) is assumed.
|
||||
* Furthermore, if posIsOutside is set to true, the input client Rect is
|
||||
* taken to follow freeGLUT's window specification convention in which the
|
||||
* top-left corner is at the outside of the window, while the size
|
||||
* (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
|
||||
* area.
|
||||
* decorations) based on the provided client rect and based on the style
|
||||
* of the window in question. If the window pointer or the window handle
|
||||
* is NULL, a fully decorated window (caption and border) is assumed.
|
||||
* Furthermore, if posIsOutside is set to true, the input client Rect is
|
||||
* taken to follow freeGLUT's window specification convention in which the
|
||||
* top-left corner is at the outside of the window, while the size
|
||||
* (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
|
||||
* area.
|
||||
*/
|
||||
void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside )
|
||||
void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside )
|
||||
{
|
||||
DWORD windowStyle = 0;
|
||||
DWORD windowStyle = 0, windowExStyle = 0;
|
||||
fghGetStyleFromWindow(window,&windowStyle,&windowExStyle);
|
||||
|
||||
if (window && window->Window.Handle)
|
||||
windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
|
||||
else
|
||||
windowStyle = ((WS_OVERLAPPEDWINDOW*QB64_Resizable())|WS_DLGFRAME|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX|(WS_MAXIMIZEBOX*QB64_Resizable()));
|
||||
|
||||
fghComputeWindowRectFromClientArea_UseStyle(windowStyle, clientRect, posIsOutside);
|
||||
fghComputeWindowRectFromClientArea_UseStyle(clientRect, windowStyle, windowExStyle, posIsOutside);
|
||||
}
|
||||
|
||||
/* Computes position of corners of client area (drawable area) of a window
|
||||
* based on the provided window Rect (outer position including decorations)
|
||||
* and based on the style of the window in question. If the window pointer
|
||||
* or the window handle is NULL, a fully decorated window (caption and
|
||||
* border) is assumed.
|
||||
* Furthermore, if wantPosOutside is set to true, the output client Rect
|
||||
* will follow freeGLUT's window specification convention in which the
|
||||
* top-left corner is at the outside of the window, the size
|
||||
* (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
|
||||
* area.
|
||||
*/
|
||||
void fghComputeClientAreaFromWindowRect( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside )
|
||||
{
|
||||
DWORD windowStyle = 0;
|
||||
int xBorderWidth = 0, yBorderWidth = 0;
|
||||
|
||||
if (window && window->Window.Handle)
|
||||
windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
|
||||
else
|
||||
windowStyle = ((WS_OVERLAPPEDWINDOW*QB64_Resizable())|WS_DLGFRAME|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX|(WS_MAXIMIZEBOX*QB64_Resizable()));
|
||||
|
||||
/* If window has title bar, correct rect for it */
|
||||
if (windowStyle & WS_SYSMENU) /* 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... */
|
||||
if (wantPosOutside)
|
||||
windowRect->bottom -= GetSystemMetrics( SM_CYCAPTION );
|
||||
else
|
||||
windowRect->top += GetSystemMetrics( SM_CYCAPTION );
|
||||
|
||||
/* get width of window's borders (frame), correct rect for it.
|
||||
* Note, borders can be of zero width if style does not specify borders
|
||||
*/
|
||||
fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
|
||||
if (wantPosOutside)
|
||||
{
|
||||
windowRect->right -= xBorderWidth * 2;
|
||||
windowRect->bottom -= yBorderWidth * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
windowRect->left += xBorderWidth;
|
||||
windowRect->right -= xBorderWidth;
|
||||
windowRect->top += yBorderWidth;
|
||||
windowRect->bottom -= yBorderWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/* Gets the rect describing the client area (drawable area) of the
|
||||
* specified window.
|
||||
* Returns an empty rect if window pointer or window handle is NULL.
|
||||
* If wantPosOutside is set to true, the output client Rect
|
||||
* will follow freeGLUT's window specification convention in which the
|
||||
* top-left corner is at the outside of the window, while the size
|
||||
* (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
|
||||
* area.
|
||||
*/
|
||||
RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside )
|
||||
* specified window. Output is position of corners of client area (drawable area) on the screen.
|
||||
* Returns an empty rect if window pointer or window handle is NULL.
|
||||
* If wantPosOutside is set to true, the output client Rect
|
||||
* will follow freeGLUT's window specification convention in which the
|
||||
* top-left corner is at the outside of the window, while the size
|
||||
* (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
|
||||
* area.
|
||||
*/
|
||||
void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL wantPosOutside )
|
||||
{
|
||||
RECT windowRect = {0,0,0,0};
|
||||
POINT topLeftClient = {0,0};
|
||||
POINT topLeftWindow = {0,0};
|
||||
|
||||
freeglut_return_val_if_fail((window && window->Window.Handle),windowRect);
|
||||
freeglut_return_if_fail((window && window->Window.Handle));
|
||||
|
||||
/*
|
||||
* call GetWindowRect()
|
||||
* (this returns the pixel coordinates of the outside of the window)
|
||||
*/
|
||||
GetWindowRect( window->Window.Handle, &windowRect );
|
||||
* call GetWindowRect()
|
||||
* (this returns the pixel coordinates of the outside of the window)
|
||||
* cannot use GetClientRect as it returns a rect relative to
|
||||
* the top-left point of the client area (.top and .left are thus always 0)
|
||||
* and is thus only useful for querying the size of the client area, not
|
||||
* its position.
|
||||
*/
|
||||
GetWindowRect( window->Window.Handle, clientRect );
|
||||
topLeftWindow.x = clientRect->top;
|
||||
topLeftWindow.y = clientRect->left;
|
||||
|
||||
/* Then correct the results */
|
||||
fghComputeClientAreaFromWindowRect(window, &windowRect, wantPosOutside);
|
||||
/* Get size of client rect */
|
||||
GetClientRect(window->Window.Handle, clientRect);
|
||||
/* Get position of top-left of client area on the screen */
|
||||
ClientToScreen(window->Window.Handle,&topLeftClient);
|
||||
/* Add top-left offset */
|
||||
OffsetRect(clientRect,topLeftClient.x,topLeftClient.y);
|
||||
|
||||
return windowRect;
|
||||
}
|
||||
|
||||
/* Returns the width of the window borders based on the window's style.
|
||||
*/
|
||||
void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth)
|
||||
{
|
||||
if (windowStyle & WS_THICKFRAME)
|
||||
/* replace top and left with top and left of window, if wanted */
|
||||
if (wantPosOutside)
|
||||
{
|
||||
*xBorderWidth = GetSystemMetrics(SM_CXSIZEFRAME);
|
||||
*yBorderWidth = GetSystemMetrics(SM_CYSIZEFRAME);
|
||||
}
|
||||
else if (windowStyle & WS_DLGFRAME)
|
||||
{
|
||||
*xBorderWidth = GetSystemMetrics(SM_CXFIXEDFRAME);
|
||||
*yBorderWidth = GetSystemMetrics(SM_CYFIXEDFRAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
*xBorderWidth = 0;
|
||||
*yBorderWidth = 0;
|
||||
clientRect->left = topLeftWindow.x;
|
||||
clientRect->top = topLeftWindow.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1021,9 +1004,9 @@ typedef struct
|
|||
} m_proc_t;
|
||||
|
||||
static BOOL CALLBACK m_proc(HMONITOR mon,
|
||||
HDC hdc,
|
||||
LPRECT rect,
|
||||
LPARAM data)
|
||||
HDC hdc,
|
||||
LPRECT rect,
|
||||
LPARAM data)
|
||||
{
|
||||
m_proc_t *dp=(m_proc_t *)data;
|
||||
MONITORINFOEX info;
|
||||
|
@ -1109,6 +1092,9 @@ void fgOpenWindow( SFG_Window* window, const char* title,
|
|||
unsigned long mask;
|
||||
int num_FBConfigs, i;
|
||||
unsigned int current_DisplayMode = fgState.DisplayMode ;
|
||||
// QB64-PE: custom code begin
|
||||
// XConfigureEvent fakeEvent = {0};
|
||||
// QB64-PE: custom code end
|
||||
|
||||
/* Save the display mode if we are creating a menu window */
|
||||
if( window->IsMenu && ( ! fgStructure.MenuContext ) )
|
||||
|
@ -1146,10 +1132,10 @@ void fgOpenWindow( SFG_Window* window, const char* title,
|
|||
|
||||
/* Get the X visual. */
|
||||
for (i = 0; i < num_FBConfigs; i++) {
|
||||
visualInfo = glXGetVisualFromFBConfig( fgDisplay.Display,
|
||||
window->Window.FBConfig[i] );
|
||||
if (visualInfo)
|
||||
break;
|
||||
visualInfo = glXGetVisualFromFBConfig( fgDisplay.Display,
|
||||
window->Window.FBConfig[i] );
|
||||
if (visualInfo)
|
||||
break;
|
||||
}
|
||||
|
||||
FREEGLUT_INTERNAL_ERROR_EXIT( visualInfo != NULL,
|
||||
|
@ -1202,6 +1188,22 @@ void fgOpenWindow( SFG_Window* window, const char* title,
|
|||
&winAttr
|
||||
);
|
||||
|
||||
// QB64-PE: custom code begin
|
||||
/* Fake configure event to force viewport setup
|
||||
* even with no window manager.
|
||||
*/
|
||||
/*
|
||||
fakeEvent.type = ConfigureNotify;
|
||||
fakeEvent.display = fgDisplay.Display;
|
||||
fakeEvent.window = window->Window.Handle;
|
||||
fakeEvent.x = x;
|
||||
fakeEvent.y = y;
|
||||
fakeEvent.width = w;
|
||||
fakeEvent.height = h;
|
||||
XPutBackEvent(fgDisplay.Display, (XEvent*)&fakeEvent);
|
||||
*/
|
||||
// QB64-PE: custom code begin
|
||||
|
||||
/*
|
||||
* The GLX context creation, possibly trying the direct context rendering
|
||||
* or else use the current context if the user has so specified
|
||||
|
@ -1350,21 +1352,7 @@ void fgOpenWindow( SFG_Window* window, const char* title,
|
|||
#else
|
||||
/* if this is not a subwindow (child), set its style based on the requested display mode */
|
||||
else if( window->Parent == NULL )
|
||||
if ( fgState.DisplayMode & GLUT_BORDERLESS )
|
||||
{
|
||||
/* no window decorations needed */
|
||||
}
|
||||
else if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
|
||||
/* only window decoration is a border, no title bar or buttons */
|
||||
flags |= WS_DLGFRAME;
|
||||
else
|
||||
/* window decoration are a border, title bar and buttons.
|
||||
* NB: we later query whether the window has a title bar or
|
||||
* not by testing for the maximize button, as the test for
|
||||
* WS_CAPTION can be true without the window having a title
|
||||
* bar. This style ((WS_OVERLAPPEDWINDOW*QB64_Resizable())|WS_DLGFRAME|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX) gives you a maximize
|
||||
* button. */
|
||||
flags |= ((WS_OVERLAPPEDWINDOW*QB64_Resizable())|WS_DLGFRAME|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX|(WS_MAXIMIZEBOX*QB64_Resizable()));
|
||||
fghGetDefaultWindowStyle(&flags);
|
||||
#endif
|
||||
else
|
||||
/* subwindows always have no decoration, but are marked as a child window to the OS */
|
||||
|
@ -1421,8 +1409,9 @@ void fgOpenWindow( SFG_Window* window, const char* title,
|
|||
windowRect.right = x+w;
|
||||
windowRect.bottom = y+h;
|
||||
|
||||
fghComputeWindowRectFromClientArea_UseStyle(flags,&windowRect,TRUE);
|
||||
fghComputeWindowRectFromClientArea_UseStyle(&windowRect,flags,exFlags,TRUE);
|
||||
|
||||
/* NB: w and h are now width and height of window including non-client area! */
|
||||
w = windowRect.right - windowRect.left;
|
||||
h = windowRect.bottom- windowRect.top;
|
||||
}
|
||||
|
@ -1469,8 +1458,9 @@ void fgOpenWindow( SFG_Window* window, const char* title,
|
|||
if( !( window->Window.Handle ) )
|
||||
fgError( "Failed to create a window (%s)!", title );
|
||||
|
||||
//QB64
|
||||
QB64_Window_Handle((void*)window->Window.Handle);
|
||||
// QB64-PE: custom code begin
|
||||
QB64_Window_Handle((void *)window->Window.Handle);
|
||||
// QB64-PE: custom code end
|
||||
|
||||
#if !defined(_WIN32_WCE)
|
||||
/* Need to set requested style again, apparently Windows doesn't listen when requesting windows without title bar or borders */
|
||||
|
@ -1490,8 +1480,8 @@ QB64_Window_Handle((void*)window->Window.Handle);
|
|||
/* Enable multitouch: additional flag TWF_FINETOUCH, TWF_WANTPALM */
|
||||
#ifdef WM_TOUCH
|
||||
if (fghRegisterTouchWindow == (pRegisterTouchWindow)0xDEADBEEF)
|
||||
fghRegisterTouchWindow = (pRegisterTouchWindow)GetProcAddress(GetModuleHandle("user32"),"RegisterTouchWindow");
|
||||
if (fghRegisterTouchWindow)
|
||||
fghRegisterTouchWindow = (pRegisterTouchWindow)GetProcAddress(GetModuleHandle("user32"),"RegisterTouchWindow");
|
||||
if (fghRegisterTouchWindow)
|
||||
fghRegisterTouchWindow( window->Window.Handle, TWF_FINETOUCH | TWF_WANTPALM );
|
||||
#endif
|
||||
|
||||
|
@ -2031,14 +2021,17 @@ void FGAPIENTRY glutFullScreen( void )
|
|||
win->State.OldStyle = s = GetWindowLong(win->Window.Handle, GWL_STYLE);
|
||||
|
||||
/* remove decorations from style and add popup style*/
|
||||
s &= ~((WS_OVERLAPPEDWINDOW*QB64_Resizable())|WS_DLGFRAME|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX|(WS_MAXIMIZEBOX*QB64_Resizable()));
|
||||
// QB64-PE: custom code begin
|
||||
s &= ~((WS_OVERLAPPEDWINDOW * QB64_Resizable()) | WS_DLGFRAME | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | (WS_MAXIMIZEBOX * QB64_Resizable()));
|
||||
// s &= ~WS_OVERLAPPEDWINDOW;
|
||||
// QB64-PE: custom code end
|
||||
s |= WS_POPUP;
|
||||
SetWindowLong(win->Window.Handle, GWL_STYLE, s);
|
||||
SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
|
||||
/* For fullscreen mode, find the monitor that is covered the most
|
||||
* by the window and get its rect as the resize target.
|
||||
*/
|
||||
*/
|
||||
hMonitor= MonitorFromRect(&win->State.OldRect, MONITOR_DEFAULTTONEAREST);
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfo(hMonitor, &mi);
|
||||
|
@ -2056,8 +2049,13 @@ void FGAPIENTRY glutFullScreen( void )
|
|||
rect.right = fgDisplay.ScreenWidth;
|
||||
rect.bottom = fgDisplay.ScreenHeight;
|
||||
|
||||
AdjustWindowRect ( &rect, ((WS_OVERLAPPEDWINDOW*QB64_Resizable())|WS_DLGFRAME|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX) | WS_CLIPSIBLINGS |
|
||||
WS_CLIPCHILDREN, FALSE );
|
||||
// QB64-PE: custom code begin
|
||||
AdjustWindowRect(&rect,
|
||||
((WS_OVERLAPPEDWINDOW * QB64_Resizable()) | WS_DLGFRAME | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) | WS_CLIPSIBLINGS |
|
||||
WS_CLIPCHILDREN,
|
||||
FALSE);
|
||||
// AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, FALSE );
|
||||
// QB64-PE: custom code end
|
||||
#endif /* (WINVER >= 0x0500) */
|
||||
|
||||
/*
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include <X11/Xlib.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 */
|
||||
int fghGetXModifiers( int state );
|
||||
|
||||
|
@ -112,9 +115,9 @@ void fgPrintXIDeviceEvent(XIDeviceEvent* event)
|
|||
printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
|
||||
printf(" detail: %d\n", event->detail);
|
||||
printf(" buttons:");
|
||||
for (i = 0; i < event->buttons.mask_len * 8; i++)
|
||||
if (XIMaskIsSet(event->buttons.mask, i))
|
||||
printf(" %d", i);
|
||||
for (i = 0; i < event->buttons.mask_len * 8; i++)
|
||||
if (XIMaskIsSet(event->buttons.mask, i))
|
||||
printf(" %d", i);
|
||||
printf("\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
|
||||
* 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;
|
||||
XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie);
|
||||
/* initialize the generic fields from base_ev */
|
||||
std_ev.xany = base_ev->xany;
|
||||
|
||||
if ( XGetEventData( fgDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) {
|
||||
|
||||
XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data);
|
||||
/*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/
|
||||
XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data);
|
||||
XIEnterEvent *evcross;
|
||||
/*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/
|
||||
|
||||
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:
|
||||
case XI_Leave:
|
||||
fgState.Modifiers = fghGetXModifiers( ((XIEnterEvent*)event)->mods.base );
|
||||
INVOKE_WCB( *window, MultiEntry, (
|
||||
event->deviceid,
|
||||
(event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT)
|
||||
));
|
||||
#if _DEBUG
|
||||
fgPrintXILeaveEvent((XILeaveEvent*)event);
|
||||
#endif
|
||||
break;
|
||||
fgState.Modifiers = fghGetXModifiers( evcross->mods.base );
|
||||
INVOKE_WCB( *window, MultiEntry, (
|
||||
event->deviceid,
|
||||
(event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT)
|
||||
));
|
||||
#if _DEBUG
|
||||
fgPrintXILeaveEvent((XILeaveEvent*)event);
|
||||
#endif
|
||||
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
fgState.Modifiers = fghGetXModifiers( event->mods.base );
|
||||
INVOKE_WCB( *window, MultiButton, (
|
||||
event->deviceid,
|
||||
event->event_x,
|
||||
event->event_y,
|
||||
(event->detail)-1,
|
||||
(event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP)
|
||||
));
|
||||
INVOKE_WCB( *window, Mouse, (
|
||||
(event->detail)-1,
|
||||
(event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP),
|
||||
event->event_x,
|
||||
event->event_y
|
||||
));
|
||||
break;
|
||||
/* Also process the standard crossing event */
|
||||
std_ev.type = evcross->evtype == XI_Enter ? EnterNotify : LeaveNotify;
|
||||
std_ev.xcrossing.window = evcross->event;
|
||||
std_ev.xcrossing.root = evcross->root;
|
||||
std_ev.xcrossing.subwindow = evcross->child;
|
||||
std_ev.xcrossing.x = evcross->event_x;
|
||||
std_ev.xcrossing.y = evcross->event_y;
|
||||
std_ev.xcrossing.x_root = evcross->root_x;
|
||||
std_ev.xcrossing.y_root = evcross->root_y;
|
||||
std_ev.xcrossing.mode = evcross->mode;
|
||||
std_ev.xcrossing.detail = evcross->detail;
|
||||
std_ev.xcrossing.same_screen = evcross->same_screen;
|
||||
std_ev.xcrossing.focus = evcross->focus;
|
||||
std_ev.xcrossing.state = BUTTON_MASK(*(unsigned int*)evcross->buttons.mask);
|
||||
|
||||
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 ) );
|
||||
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;
|
||||
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 );
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
fgState.Modifiers = fghGetXModifiers( event->mods.base );
|
||||
INVOKE_WCB( *window, MultiButton, (
|
||||
event->deviceid,
|
||||
event->event_x,
|
||||
event->event_y,
|
||||
event->detail-1,
|
||||
(event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP)
|
||||
));
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -74,7 +74,8 @@
|
|||
#define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9
|
||||
|
||||
#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
|
||||
|
||||
|
@ -83,6 +84,8 @@
|
|||
|
||||
#define GLUT_FULL_SCREEN 0x01FF
|
||||
|
||||
#define GLUT_SKIP_STALE_MOTION_EVENTS 0x0204
|
||||
|
||||
/*
|
||||
* New tokens for glutInitDisplayMode.
|
||||
* Only one GLUT_AUXn bit may be used at a time.
|
||||
|
|
|
@ -113,14 +113,21 @@
|
|||
*/
|
||||
#define FREEGLUT 1
|
||||
#define GLUT_API_VERSION 4
|
||||
#define FREEGLUT_VERSION_2_0 1
|
||||
#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
|
||||
*/
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#if __APPLE__
|
||||
# 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:
|
||||
|
@ -531,6 +538,13 @@ FGAPI void FGAPIENTRY glutSolidTetrahedron( void );
|
|||
FGAPI void FGAPIENTRY glutWireIcosahedron( 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
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue