1
1
Fork 0
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:
Samuel Gomes 2024-01-30 03:01:26 +05:30
parent b5e896384a
commit 3a260f1002
17 changed files with 8108 additions and 4977 deletions

View file

@ -27,7 +27,7 @@ $(PATH_INTERNAL_C)/parts/core/glew/%.o: $(PATH_INTERNAL_C)/parts/core/glew/%.c
$(CC) -O1 $(CFLAGS) $(FREEGLUT_INCLUDE) -DGLEW_STATIC -Wall $< -c -o $@
$(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)

View file

@ -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

View file

@ -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);

View file

@ -58,7 +58,7 @@ static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)
/* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and
* 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;

View file

@ -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);
}

View file

@ -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 */

View file

@ -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 ***/

View 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;
}

View file

@ -84,6 +84,9 @@ static float menu_pen_hfore [4] = {0.0f, 0.0f, 0.0f, 1.0f};
static float menu_pen_hback [4] = {1.0f, 1.0f, 1.0f, 1.0f};
#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 );

View file

@ -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;

View file

@ -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;
}

View file

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

File diff suppressed because it is too large Load diff

View file

@ -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) */
/*

View file

@ -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

View file

@ -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.

View file

@ -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
*/