diff --git a/freeglut/freeglut/CMakeLists.txt b/freeglut/freeglut/CMakeLists.txt index c6713ab..c86d4ce 100644 --- a/freeglut/freeglut/CMakeLists.txt +++ b/freeglut/freeglut/CMakeLists.txt @@ -68,6 +68,7 @@ ENDIF() SET(FREEGLUT_HEADERS include/GL/freeglut.h + include/GL/freeglut_ucall.h include/GL/freeglut_ext.h include/GL/freeglut_std.h ) @@ -90,6 +91,7 @@ SET(FREEGLUT_SRCS src/fg_init.c src/fg_init.h src/fg_internal.h + src/fg_callback_macros.h src/fg_input_devices.c src/fg_joystick.c src/fg_main.c @@ -551,6 +553,7 @@ IF(UNIX) ENDIF() ADD_DEMO(subwin progs/demos/subwin/subwin.c) ADD_DEMO(timer progs/demos/timer/timer.c) +ADD_DEMO(timer_callback progs/demos/timer_callback/timer.c) diff --git a/freeglut/freeglut/include/GL/freeglut_ext.h b/freeglut/freeglut/include/GL/freeglut_ext.h index 2ef96c2..9b0ac50 100644 --- a/freeglut/freeglut/include/GL/freeglut_ext.h +++ b/freeglut/freeglut/include/GL/freeglut_ext.h @@ -256,13 +256,13 @@ FGAPI void FGAPIENTRY glutInitErrorFunc( void (* callback)( const char *fmt, FGAPI void FGAPIENTRY glutInitWarningFunc( void (* callback)( const char *fmt, va_list ap ) ); /* OpenGL >= 2.0 support */ -FGAPI void FGAPIENTRY glutSetVertexAttribCoord3(GLint attrib); -FGAPI void FGAPIENTRY glutSetVertexAttribNormal(GLint attrib); -FGAPI void FGAPIENTRY glutSetVertexAttribTexCoord2(GLint attrib); +FGAPI void FGAPIENTRY glutSetVertexAttribCoord3( GLint attrib ); +FGAPI void FGAPIENTRY glutSetVertexAttribNormal( GLint attrib ); +FGAPI void FGAPIENTRY glutSetVertexAttribTexCoord2( GLint attrib ); /* Mobile platforms lifecycle */ -FGAPI void FGAPIENTRY glutInitContextFunc(void (* callback)()); -FGAPI void FGAPIENTRY glutAppStatusFunc(void (* callback)(int)); +FGAPI void FGAPIENTRY glutInitContextFunc( void (* callback)( void ) ); +FGAPI void FGAPIENTRY glutAppStatusFunc( void (* callback)( int ) ); /* state flags that can be passed to callback set by glutAppStatusFunc */ #define GLUT_APPSTATUS_PAUSE 0x0001 #define GLUT_APPSTATUS_RESUME 0x0002 @@ -274,6 +274,9 @@ FGAPI void FGAPIENTRY glutAppStatusFunc(void (* callback)(int)); #define GLUT_BORDERLESS 0x0800 #define GLUT_SRGB 0x1000 +/* User-argument callbacks and implementation */ +#include "freeglut_ucall.h" + #ifdef __cplusplus } #endif diff --git a/freeglut/freeglut/include/GL/freeglut_ucall.h b/freeglut/freeglut/include/GL/freeglut_ucall.h new file mode 100644 index 0000000..f6fc99a --- /dev/null +++ b/freeglut/freeglut/include/GL/freeglut_ucall.h @@ -0,0 +1,113 @@ +#ifndef __FREEGLUT_UCALL_H__ +#define __FREEGLUT_UCALL_H__ + +/* + * freeglut_ucall.h + * + * Callbacks with user data arguments. + * + * 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. + */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* + * Menu stuff, see fg_menu.c + */ +FGAPI int FGAPIENTRY glutCreateMenuUcall( void (* callback)( int menu, void* user_data ), void* user_data ); + +/* + * Global callback functions, see fg_callbacks.c + */ +FGAPI void FGAPIENTRY glutTimerFuncUcall( unsigned int time, void (* callback)( int, void* ), int value, void* user_data ); +FGAPI void FGAPIENTRY glutIdleFuncUcall( void (* callback)( void* ), void* user_data ); + +/* + * Window-specific callback functions, see fg_callbacks.c + */ +FGAPI void FGAPIENTRY glutKeyboardFuncUcall( void (* callback)( unsigned char, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpecialFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutReshapeFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutVisibilityFuncUcall( void (* callback)( int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutDisplayFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMouseFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutPassiveMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutEntryFuncUcall( void (* callback)( int, void* ), void* user_data ); + +FGAPI void FGAPIENTRY glutKeyboardUpFuncUcall( void (* callback)( unsigned char, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpecialUpFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutJoystickFuncUcall( void (* callback)( unsigned int, int, int, int, void* ), int pollInterval, void* user_data ); +FGAPI void FGAPIENTRY glutMenuStatusFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutOverlayDisplayFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutWindowStatusFuncUcall( void (* callback)( int, void* ), void* user_data ); + +FGAPI void FGAPIENTRY glutSpaceballMotionFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpaceballRotateFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutSpaceballButtonFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutButtonBoxFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutDialsFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutTabletMotionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutTabletButtonFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data ); + +FGAPI void FGAPIENTRY glutMouseWheelFuncUcall( void (* callback)( int, int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutPositionFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutCloseFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutWMCloseFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMenuDestroyFuncUcall( void (* callback)( void* ), void* user_data ); + +/* + * Multi-touch/multi-pointer extensions + */ +FGAPI void FGAPIENTRY glutMultiEntryFuncUcall( void (* callback)( int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMultiButtonFuncUcall( void (* callback)( int, int, int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMultiMotionFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); +FGAPI void FGAPIENTRY glutMultiPassiveFuncUcall( void (* callback)( int, int, int, void* ), void* user_data ); + +/* + * Initialization functions, see fg_init.c + */ +#include +FGAPI void FGAPIENTRY glutInitErrorFuncUcall( void (* callback)( const char *fmt, va_list ap, void* user_data ), void* user_data ); +FGAPI void FGAPIENTRY glutInitWarningFuncUcall( void (* callback)( const char *fmt, va_list ap, void* user_data ), void* user_data ); + +/* Mobile platforms lifecycle */ +FGAPI void FGAPIENTRY glutInitContextFuncUcall( void (* callback)( void* ), void* user_data ); +FGAPI void FGAPIENTRY glutAppStatusFuncUcall( void (* callback)( int, void* ), void* user_data ); + +/* + * Continued "hack" from GLUT applied to Ucall functions. + * For more info, see bottom of freeglut_std.h + */ + +/* to get the prototype for exit() */ +#include + +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__) +FGAPI int FGAPIENTRY __glutCreateMenuUcallWithExit(void(*func)(int, void*), void(__cdecl *exitfunc)(int), void* user_data); +#ifndef FREEGLUT_BUILDING_LIB +#if defined(__GNUC__) +#define FGUNUSED __attribute__((unused)) +#else +#define FGUNUSED +#endif +static int FGAPIENTRY FGUNUSED glutCreateMenuUcall_ATEXIT_HACK(void(*func)(int, void*), void* user_data) { return __glutCreateMenuUcallWithExit(func, exit, user_data); } +#define glutCreateMenuUcall glutCreateMenuUcall_ATEXIT_HACK +#endif +#endif + +#ifdef __cplusplus + } +#endif + +/*** END OF FILE ***/ + +#endif /* __FREEGLUT_UCALL_H__ */ + diff --git a/freeglut/freeglut/progs/demos/timer_callback/timer.c b/freeglut/freeglut/progs/demos/timer_callback/timer.c new file mode 100644 index 0000000..03acd40 --- /dev/null +++ b/freeglut/freeglut/progs/demos/timer_callback/timer.c @@ -0,0 +1,174 @@ +/* Timer (callback) demo + * + * Written by John Tsiombikas + * Modified by Vincent Simonetti + * + * A modification of the timer sample, but with this + * offering a use of the user-data callback. + */ +#include +#include + +struct display_index_s +{ + /* color index will be advanced every time the timer expires */ + int surround_color_index; + int center_color_index; +}; +typedef struct display_index_s display_index_t; + +struct timer_state_s +{ + int* color_index_ptr; + int* timer_time_ptr; +}; +typedef struct timer_state_s timer_state_t; + +struct menu_state_s +{ + int* timer_time_ptr; + int menu_id; +}; +typedef struct menu_state_s menu_state_t; + +void disp(void* uptr); +void timer_func(int which, void* uptr); + +const float color[][3] = { + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + {1, 1, 0}, + {0, 1, 1}, + {1, 0, 1} +}; +const int timerInts[] = { + 250, + 500, + 1000 +}; + +void createMenuEntries(menu_state_t* menuState) +{ + int i; + for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++) + { + char temp[10] = {'\0'}; + /* flag current value */ + if ((*menuState->timer_time_ptr) == timerInts[i]) + temp[0] = '+'; + else + temp[0] = '-'; + + sprintf(temp + 1, " %4d ms", timerInts[i]); + + glutAddMenuEntry(temp, timerInts[i]); + } +} + +void updateMenuEntries(menu_state_t* menuState) +{ + int i; + for (i = 0; i < sizeof(timerInts) / sizeof(*timerInts); i++) + { + char temp[10] = { '\0' }; + /* flag current value */ + if ((*menuState->timer_time_ptr) == timerInts[i]) + temp[0] = '+'; + else + temp[0] = '-'; + + sprintf(temp + 1, " %4d ms", timerInts[i]); + + glutChangeToMenuEntry(i+1, temp, timerInts[i]); + } +} + +void MenuHandler(int timerInt, void* user_ptr) +{ + menu_state_t* menuState; + + if (!user_ptr) + { + /* In case main menu is selected somehow */ + return; + } + + menuState = (menu_state_t*)user_ptr; + + *menuState->timer_time_ptr = timerInt; + glutSetMenu(menuState->menu_id); + updateMenuEntries(menuState); +} + +int main(int argc, char **argv) +{ + int timerSurroundInt = 1000, timerCenterInt = 500; + display_index_t displayIndex = { 0, 2 }; + timer_state_t surroundTimerState = { &displayIndex.surround_color_index, &timerSurroundInt }; + timer_state_t centerTimerState = { &displayIndex.center_color_index, &timerCenterInt }; + menu_state_t surroundMenuState = { &timerSurroundInt, 0 }; + menu_state_t centerMenuState = { &timerCenterInt, 0 }; + + glutInit(&argc, argv); + glutInitWindowSize(128, 128); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("timer test"); + + glutDisplayFuncUcall(disp, &displayIndex); + + /* get timer started, its reset in the timer function itself */ + glutTimerFuncUcall(timerSurroundInt, timer_func, 1, &surroundTimerState); + glutTimerFuncUcall(timerCenterInt, timer_func, 2, ¢erTimerState); + + /* menus for setting timing */ + surroundMenuState.menu_id = glutCreateMenuUcall(MenuHandler, &surroundMenuState); + createMenuEntries(&surroundMenuState); + + centerMenuState.menu_id = glutCreateMenuUcall(MenuHandler, ¢erMenuState); + createMenuEntries(¢erMenuState); + + glutCreateMenuUcall(MenuHandler, NULL); /* doesn't matter, no clickable entries in this menu */ + glutAddSubMenu("Center", centerMenuState.menu_id); + glutAddSubMenu("Surround", surroundMenuState.menu_id); + glutAttachMenu(GLUT_RIGHT_BUTTON); + + glutMainLoop(); + return 0; +} + +void disp(void* user_ptr) +{ + const display_index_t* displayIndex; + int cidx, pcidx; + + displayIndex = (display_index_t*)user_ptr; + + cidx = displayIndex->surround_color_index; + glClearColor(color[cidx][0], color[cidx][1], color[cidx][2], 1); + glClear(GL_COLOR_BUFFER_BIT); + + pcidx = displayIndex->center_color_index; + glPointSize(10.f); + glColor3f(color[pcidx][0], color[pcidx][1], color[pcidx][2]); + glBegin(GL_POINTS); + glVertex2i(0,0); + glEnd(); + + glutSwapBuffers(); +} + +void timer_func(int which, void* user_ptr) +{ + const timer_state_t* timerState; + + timerState = (timer_state_t*)user_ptr; + + /* advance the color index and trigger a redisplay */ + *timerState->color_index_ptr = (*timerState->color_index_ptr + 1) % (sizeof color / sizeof *color); + + glutPostRedisplay(); + + /* (re)set the timer callback and ask glut to call it in x ms */ + glutTimerFuncUcall(*timerState->timer_time_ptr, timer_func, which, user_ptr); +} diff --git a/freeglut/freeglut/src/fg_callback_macros.h b/freeglut/freeglut/src/fg_callback_macros.h new file mode 100644 index 0000000..76d76b1 --- /dev/null +++ b/freeglut/freeglut/src/fg_callback_macros.h @@ -0,0 +1,333 @@ +/* + * fg_callback_macros.h + * + * The freeglut library callback macro file. + * + * Copyright (C) 2016 Vincent Simonetti + * Creation date: Sat Jan 16 2016 + * + * 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. + */ + +#ifndef FREEGLUT_CALLBACK_MACROS_H +#define FREEGLUT_CALLBACK_MACROS_H + +/* + * ---------------------------------------------------------------------------------------------------------------------- + * There are two sets of macros here. One is for executing window callbacks, the others are for setting window callbacks. + * ---------------------------------------------------------------------------------------------------------------------- + */ + +/* + * Compiler define: FG_COMPILER_SUPPORTS_VA_ARGS: if the compiler supports variadic macros + */ + +/* What supports variadic macros based off Wikipedia article on it (GCC-like must support C99 or higher to use variadic macros) */ +#if (((defined(__GNUC__) && (__GNUC__ >= 3)) || \ + (defined(__clang__))) && \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1400)) || \ + (defined(__BORLANDC__) && (__BORLANDC__ >= 0x570)) || \ + (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x530)) +#define FG_COMPILER_SUPPORTS_VA_ARGS 1 +#else +#define FG_COMPILER_SUPPORTS_VA_ARGS 0 +#endif + +/* + * -------------------------- + * Executing window callbacks + * -------------------------- + * + * Info: + * + * This took a while to figure out, so be sure try to understand what is happening so that you can ensure that whatever you + * change won't break other areas. + * + * If you are just adding a new callback/changing it's argument count, just go to the bottom of the file. + * + * This whole file exists purely for the sake of preventing the need to implement additional parsing logic for each callback + * to pass user arguments. Of course, the necessity to support older compilers means that, as seen in the line above, there + * is still a requirement to add/modify code to handle callbacks. If freeglut ever requires newer compilers (at minimum, ones + * that support C99 or higher), code can very slowly be removed from this file. Even better would be if the C standard eventually + * supports something similar to what GCC has implemented or offers an alternative. Another option is if C++ would be "allowed" by + * project maintaners, as then templates can be used and function overloading. Ironically, the template would probably look worse + * then the GCC macro, so maybe it's good to stay as is. + * + * Onto the different "versions" of macros: + * + * The first is for any compiler that supports C99 by default. It requires each callback to have a specific argument count + * passthrough macro. The only reason there are specific count macros is so that (see paraghraph below) don't need have their own + * set of callback macros. Ideally, there would only be ZERO and ONE_OR_MORE. This works by having callback-specific macros call a + * specific handler macro to return user data (ZERO) or return one or more arguments along with userData (ONE_OR_MORE) where, with + * variadic macros, it just reuses the arguments. + * + * The last macro set is for the poor individual who has to use a compiler that doesn't support C99 by default, or may not support + * it at all. Stuff like MSVC6... It works by having a specific-count macro that "extracts" each argument to have them reused without + * the parathesis. + * + * There is a 3rd macro set that only worked on GCC/Clang, and thus was removed (last seen in revision e9676fc of the GIT mirror. + * Not sure at this time what the SVN number is.) as it's a non-standard functionality. + */ + +/* + * EXPAND_WCB() is used as: + * + * EXPAND_WCB( cbname )(( arg_list, userData )) + * + * ... where {(arg_list)} is the parameter list and userData is user + * provided data. + * + * This will take the arg_list and extend it by one argument, adding + * the argument "userData" to the end of the list. + * + * In order for this to work, each callback must have a define that + * properly handles the arguments as needed by the callback. + * This callback is in the format of EXPAND_WCB_SUB_. + * Helper functions exist for zero to five parameters: EXPAND_WCB_ZERO, + * EXPAND_WCB_ONE, EXPAND_WCB_TWO, EXPAND_WCB_THREE< EXPAND_WCB_FOUR, + * and EXPAND_WCB_FIVE. Each handle the callback argument counts. + * + * An example for the "Entry" callback, where "Entry" is the cbname: + * typedef void (* FGCBEntry )( int ); + * typedef void (* FGCBEntryUC)( int, FGCBUserData ); + * #define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args + */ + +#if FG_COMPILER_SUPPORTS_VA_ARGS + +#define EXPAND_WCB_UNPARAN(...) __VA_ARGS__ +#define EXPAND_WCB_ONE_OR_MORE(args, userData) ( EXPAND_WCB_UNPARAN args, userData ) + +#define EXPAND_WCB_ONE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_TWO(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_THREE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_FOUR(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) +#define EXPAND_WCB_FIVE(args, userData) EXPAND_WCB_ONE_OR_MORE( args, userData ) + +#else + +#define EXPAND_WCB_EXTRACT_ONE_ARGS(arg1) arg1 +#define EXPAND_WCB_EXTRACT_TWO_ARGS(arg1, arg2) arg1, arg2 +#define EXPAND_WCB_EXTRACT_THREE_ARGS(arg1, arg2, arg3) arg1, arg2, arg3 +#define EXPAND_WCB_EXTRACT_FOUR_ARGS(arg1, arg2, arg3, arg4) arg1, arg2, arg3, arg4 +#define EXPAND_WCB_EXTRACT_FIVE_ARGS(arg1, arg2, arg3, arg4, arg5) arg1, arg2, arg3, arg4, arg5 + +#define EXPAND_WCB_ONE(args, userData) (EXPAND_WCB_EXTRACT_ONE_ARGS args, userData) +#define EXPAND_WCB_TWO(args, userData) (EXPAND_WCB_EXTRACT_TWO_ARGS args, userData) +#define EXPAND_WCB_THREE(args, userData) (EXPAND_WCB_EXTRACT_THREE_ARGS args, userData) +#define EXPAND_WCB_FOUR(args, userData) (EXPAND_WCB_EXTRACT_FOUR_ARGS args, userData) +#define EXPAND_WCB_FIVE(args, userData) (EXPAND_WCB_EXTRACT_FIVE_ARGS args, userData) + +#endif + +#define EXPAND_WCB_ZERO(args, userData) ( userData ) + +#define EXPAND_WCB(cbname) EXPAND_WCB_SUB_ ## cbname + +/* + * Freeglut callbacks type definitions macros + * + * Every time a callback is updated in fg_internal.h is updated, this needs updated + * if argument counts change, new callbacks are added, or callbacks are removed. + */ + +#define EXPAND_WCB_SUB_Display(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_Reshape(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Position(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Visibility(args) EXPAND_WCB_ONE args +#define EXPAND_WCB_SUB_Keyboard(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_KeyboardUp(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_Special(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_SpecialUp(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_Mouse(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_MouseWheel(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_Motion(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Passive(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Entry(args) EXPAND_WCB_ONE args +#define EXPAND_WCB_SUB_WindowStatus(args) EXPAND_WCB_ONE args +#define EXPAND_WCB_SUB_Joystick(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_OverlayDisplay(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_SpaceMotion(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_SpaceRotation(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_SpaceButton(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_Dials(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_ButtonBox(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_TabletMotion(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_TabletButton(args) EXPAND_WCB_FOUR args +#define EXPAND_WCB_SUB_Destroy(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_MultiEntry(args) EXPAND_WCB_TWO args +#define EXPAND_WCB_SUB_MultiButton(args) EXPAND_WCB_FIVE args +#define EXPAND_WCB_SUB_MultiMotion(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_MultiPassive(args) EXPAND_WCB_THREE args +#define EXPAND_WCB_SUB_InitContext(args) EXPAND_WCB_ZERO args +#define EXPAND_WCB_SUB_AppStatus(args) EXPAND_WCB_ONE args + +/* + * ------------------------ + * Setting window callbacks + * ------------------------ + * + * These originally existed in fg_callbacks.c + */ + +/* + * All of the window-specific callbacks setting methods can be generalized to this: + */ +#define SET_CURRENT_WINDOW_CALLBACK(a) \ +do \ +{ \ + if( fgStructure.CurrentWindow == NULL ) \ + return; \ + SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback, userData ); \ +} while( 0 ) + +/* + * Types need to be defined for callbacks. It's not ideal, but it works for this. + */ +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ +static void fgh##a##FuncCallback( FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback(); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,b) \ +static void fgh##a##FuncCallback( int arg1val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,arg1,arg2,arg3) \ +static void fgh##a##FuncCallback( arg1 arg1val, arg2 arg2val, arg3 arg3val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val, arg3val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b) IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,b,int,int,int) +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,b) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val, arg3val, arg4val ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,b) \ +static void fgh##a##FuncCallback( int arg1val, int arg2val, int arg3val, int arg4val, int arg5val, FGCBUserData userData ) \ +{ \ + FGCB##b callback = (FGCB##b)userData; \ + callback( arg1val, arg2val, arg3val, arg4val, arg5val ); \ +} + +/* + * And almost every time the callback setter function can be implemented with these: + */ +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT_UCALL(a,b) \ +void FGAPIENTRY glut##a##FuncUcall( FGCB##b##UC callback, FGCBUserData userData ) \ +{ \ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"FuncUcall" ); \ + SET_CURRENT_WINDOW_CALLBACK( b ); \ +} +#define IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) \ +void FGAPIENTRY glut##a##Func( FGCB##b callback ) \ +{ \ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"Func" ); \ + if( callback ) \ + glut##a##FuncUcall( fgh##a##FuncCallback, (FGCBUserData)callback ); \ + else \ + glut##a##FuncUcall( NULL, NULL ); \ +} + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT_UCALL(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +/* + * Combine _glut and _cb macros: + */ +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG0(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG1(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG1(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,b) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG2(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(a,arg1,arg2,arg3) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3_USER(a,a,arg1,arg2,arg3) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,a) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,a) + +#define IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(a,b) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG3(a,b) \ + IMPLEMENT_CALLBACK_FUNC_2NAME_GLUT_BASE(a,b) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG4(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#define IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG5(a) \ + IMPLEMENT_CALLBACK_FUNC_CB_ARG5(a,a) \ + IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_2NAME_GLUT(a,a) + +#endif /* FREEGLUT_CALLBACK_MACROS_H */ + +/*** END OF FILE ***/ diff --git a/freeglut/freeglut/src/fg_callbacks.c b/freeglut/freeglut/src/fg_callbacks.c index 11924b3..0e656a8 100644 --- a/freeglut/freeglut/src/fg_callbacks.c +++ b/freeglut/freeglut/src/fg_callbacks.c @@ -30,23 +30,26 @@ /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ - /* * Global callbacks. */ + /* Sets the global idle callback */ -void FGAPIENTRY glutIdleFunc( FGCBIdle callback ) +void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFuncUcall" ); fgState.IdleCallback = callback; + fgState.IdleCallbackData = userData; } +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Idle) + /* Creates a timer and sets its callback */ -void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID ) +void FGAPIENTRY glutTimerFuncUcall( unsigned int timeOut, FGCBTimerUC callback, int timerID, FGCBUserData userData ) { SFG_Timer *timer, *node; - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFuncUcall" ); if( (timer = fgState.FreeTimers.Last) ) { @@ -59,9 +62,10 @@ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int tim "Memory allocation failure in glutTimerFunc()" ); } - timer->Callback = callback; - timer->ID = timerID; - timer->TriggerTime = fgElapsedTime() + timeOut; + timer->Callback = callback; + timer->CallbackData = userData; + timer->ID = timerID; + timer->TriggerTime = fgElapsedTime() + timeOut; /* Insert such that timers are sorted by end-time */ for( node = fgState.Timers.First; node; node = node->Node.Next ) @@ -73,6 +77,17 @@ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int tim fgListInsert( &fgState.Timers, &node->Node, &timer->Node ); } +IMPLEMENT_CALLBACK_FUNC_CB_ARG1(Timer, Timer) + +void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" ); + if( callback ) + glutTimerFuncUcall( timeOut, fghTimerFuncCallback, timerID, (FGCBUserData)callback ); + else + glutTimerFuncUcall( timeOut, NULL, timerID, NULL ); +} + /* Deprecated version of glutMenuStatusFunc callback setting method */ void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback ) { @@ -81,102 +96,92 @@ void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback ) } /* Sets the global menu status callback for the current window */ -void FGAPIENTRY glutMenuStatusFunc( FGCBMenuStatus callback ) +void FGAPIENTRY glutMenuStatusFuncUcall( FGCBMenuStatusUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFuncUcall" ); fgState.MenuStatusCallback = callback; + fgState.MenuStatusCallbackData = userData; } +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3(MenuStatus) /* * Menu specific callbacks. */ /* Callback upon menu destruction */ -void FGAPIENTRY glutMenuDestroyFunc( FGCBDestroy callback ) +void FGAPIENTRY glutMenuDestroyFuncUcall( FGCBDestroyUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFuncUcall" ); if( fgStructure.CurrentMenu ) + { fgStructure.CurrentMenu->Destroy = callback; + fgStructure.CurrentMenu->DestroyData = userData; + } } - -/* - * All of the window-specific callbacks setting methods can be generalized to this: - */ -#define SET_CALLBACK(a) \ -do \ -{ \ - if( fgStructure.CurrentWindow == NULL ) \ - return; \ - SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback ); \ -} while( 0 ) -/* - * And almost every time the callback setter function can be implemented like this: - */ -#define IMPLEMENT_CALLBACK_FUNC_2NAME(a,b) \ -void FGAPIENTRY glut##a##Func( FGCB##b callback ) \ -{ \ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glut"#a"Func" ); \ - SET_CALLBACK( b ); \ -} -#define IMPLEMENT_CALLBACK_FUNC(a) IMPLEMENT_CALLBACK_FUNC_2NAME(a,a) +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0_2NAME(MenuDestroy, Destroy) /* Implement all these callback setter functions... */ -IMPLEMENT_CALLBACK_FUNC(Position) -IMPLEMENT_CALLBACK_FUNC(Keyboard) -IMPLEMENT_CALLBACK_FUNC(KeyboardUp) -IMPLEMENT_CALLBACK_FUNC(Special) -IMPLEMENT_CALLBACK_FUNC(SpecialUp) -IMPLEMENT_CALLBACK_FUNC(Mouse) -IMPLEMENT_CALLBACK_FUNC(MouseWheel) -IMPLEMENT_CALLBACK_FUNC(Motion) -IMPLEMENT_CALLBACK_FUNC_2NAME(PassiveMotion,Passive) -IMPLEMENT_CALLBACK_FUNC(Entry) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Position) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(Keyboard,unsigned char,int,int) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(KeyboardUp,unsigned char,int,int) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(Special) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(SpecialUp) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(Mouse) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(MouseWheel) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Motion) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2_2NAME(PassiveMotion,Passive) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(Entry) /* glutWMCloseFunc is an alias for glutCloseFunc; both set the window's Destroy callback */ -IMPLEMENT_CALLBACK_FUNC_2NAME(Close,Destroy) -IMPLEMENT_CALLBACK_FUNC_2NAME(WMClose,Destroy) -IMPLEMENT_CALLBACK_FUNC(OverlayDisplay) -IMPLEMENT_CALLBACK_FUNC(WindowStatus) -IMPLEMENT_CALLBACK_FUNC(ButtonBox) -IMPLEMENT_CALLBACK_FUNC(Dials) -IMPLEMENT_CALLBACK_FUNC(TabletMotion) -IMPLEMENT_CALLBACK_FUNC(TabletButton) -IMPLEMENT_CALLBACK_FUNC(MultiEntry) -IMPLEMENT_CALLBACK_FUNC(MultiButton) -IMPLEMENT_CALLBACK_FUNC(MultiMotion) -IMPLEMENT_CALLBACK_FUNC(MultiPassive) -IMPLEMENT_CALLBACK_FUNC(InitContext) -IMPLEMENT_CALLBACK_FUNC(AppStatus) - - +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(Close,Destroy) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(WMClose,Destroy) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(OverlayDisplay) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(WindowStatus) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(ButtonBox) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Dials) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(TabletMotion) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(TabletButton) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(MultiEntry) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG5(MultiButton) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiMotion) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiPassive) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(InitContext) +IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(AppStatus) /* * Sets the Display callback for the current window */ -void FGAPIENTRY glutDisplayFunc( FGCBDisplay callback ) +void FGAPIENTRY glutDisplayFuncUcall( FGCBDisplayUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFuncUcall" ); if( !callback ) fgError( "Fatal error in program. NULL display callback not " "permitted in GLUT 3.0+ or freeglut 2.0.1+" ); - SET_CALLBACK( Display ); + SET_CURRENT_WINDOW_CALLBACK( Display ); } -void fghDefaultReshape(int width, int height) +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Display) + +void fghDefaultReshape( int width, int height, FGCBUserData userData ) { glViewport( 0, 0, width, height ); } -void FGAPIENTRY glutReshapeFunc( FGCBReshape callback ) +void FGAPIENTRY glutReshapeFuncUcall( FGCBReshapeUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFuncUcall" ); if( !callback ) + { callback = fghDefaultReshape; + userData = NULL; + } - SET_CALLBACK( Reshape ); + SET_CURRENT_WINDOW_CALLBACK( Reshape ); } +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2(Reshape) + /* * Sets the Visibility callback for the current window. * NB: the Visibility func is deprecated in favor of the WindowStatus func, @@ -192,7 +197,7 @@ void FGAPIENTRY glutReshapeFunc( FGCBReshape callback ) * http://stackoverflow.com/questions/5445889/get-which-process-window-is-actually-visible-in-c-sharp * for an implementation outline (but it would be polling based, not push based). */ -static void fghVisibility( int status ) +static void fghVisibility( int status, FGCBUserData userData ) { int vis_status; @@ -200,7 +205,7 @@ static void fghVisibility( int status ) freeglut_return_if_fail( fgStructure.CurrentWindow ); /* Translate window status func states to visibility states */ - if( ( GLUT_HIDDEN == status ) || ( GLUT_FULLY_COVERED == status ) ) + if( ( status == GLUT_HIDDEN) || ( status == GLUT_FULLY_COVERED) ) vis_status = GLUT_NOT_VISIBLE; else /* GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED */ vis_status = GLUT_VISIBLE; @@ -208,23 +213,31 @@ static void fghVisibility( int status ) INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( vis_status ) ); } -void FGAPIENTRY glutVisibilityFunc( FGCBVisibility callback ) +void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" ); - SET_CALLBACK( Visibility ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFuncUcall" ); + + if ( !callback ) + { + userData = NULL; + } + + SET_CURRENT_WINDOW_CALLBACK( Visibility ); if( callback ) - glutWindowStatusFunc( fghVisibility ); + glutWindowStatusFuncUcall( fghVisibility, NULL ); else - glutWindowStatusFunc( NULL ); + glutWindowStatusFuncUcall( NULL, NULL ); } +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG1(Visibility) + /* * Sets the joystick callback and polling rate for the current window */ -void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval ) +void FGAPIENTRY glutJoystickFuncUcall( FGCBJoystickUC callback, int pollInterval, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFuncUcall" ); fgInitialiseJoysticks (); if ( ( @@ -244,7 +257,7 @@ void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval ) ) ) --fgState.NumActiveJoysticks; - SET_CALLBACK( Joystick ); + SET_CURRENT_WINDOW_CALLBACK( Joystick ); fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval; /* set last poll time such that joystick will be polled asap */ @@ -255,39 +268,58 @@ void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval ) fgStructure.CurrentWindow->State.JoystickLastPoll -= pollInterval; } +static void fghJoystickFuncCallback( unsigned int buttons, int axis0, int axis1, int axis2, FGCBUserData userData ) +{ + FGCBJoystick callback = (FGCBJoystick)userData; + callback( buttons, axis0, axis1, axis2 ); +} +void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" ); + if( callback ) + glutJoystickFuncUcall( fghJoystickFuncCallback, pollInterval, (FGCBUserData)callback ); + else + glutJoystickFuncUcall( NULL, pollInterval, NULL ); +} /* * Sets the spaceball motion callback for the current window */ -void FGAPIENTRY glutSpaceballMotionFunc( FGCBSpaceMotion callback ) +void FGAPIENTRY glutSpaceballMotionFuncUcall( FGCBSpaceMotionUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFuncUcall" ); fgInitialiseSpaceball(); - SET_CALLBACK( SpaceMotion ); + SET_CURRENT_WINDOW_CALLBACK( SpaceMotion ); } +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballMotion, SpaceMotion) + /* * Sets the spaceball rotate callback for the current window */ -void FGAPIENTRY glutSpaceballRotateFunc( FGCBSpaceRotation callback ) +void FGAPIENTRY glutSpaceballRotateFuncUcall( FGCBSpaceRotationUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFuncUcall" ); fgInitialiseSpaceball(); - SET_CALLBACK( SpaceRotation ); + SET_CURRENT_WINDOW_CALLBACK( SpaceRotation ); } +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballRotate, SpaceRotation) + /* * Sets the spaceball button callback for the current window */ -void FGAPIENTRY glutSpaceballButtonFunc( FGCBSpaceButton callback ) +void FGAPIENTRY glutSpaceballButtonFuncUcall( FGCBSpaceButtonUC callback, FGCBUserData userData ) { - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" ); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFuncUcall" ); fgInitialiseSpaceball(); - SET_CALLBACK( SpaceButton ); + SET_CURRENT_WINDOW_CALLBACK( SpaceButton ); } +IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2_2NAME(SpaceballButton, SpaceButton) + /*** END OF FILE ***/ diff --git a/freeglut/freeglut/src/fg_ext.c b/freeglut/freeglut/src/fg_ext.c index d96849a..0ddb560 100644 --- a/freeglut/freeglut/src/fg_ext.c +++ b/freeglut/freeglut/src/fg_ext.c @@ -210,6 +210,46 @@ static GLUTproc fghGetGLUTProcAddress( const char* procName ) CHECK_NAME(glutSetVertexAttribCoord3); CHECK_NAME(glutSetVertexAttribNormal); CHECK_NAME(glutSetVertexAttribTexCoord2); + + /* freeglut user callback functions */ + CHECK_NAME(glutCreateMenuUcall); + CHECK_NAME(glutTimerFuncUcall); + CHECK_NAME(glutIdleFuncUcall); + CHECK_NAME(glutKeyboardFuncUcall); + CHECK_NAME(glutSpecialFuncUcall); + CHECK_NAME(glutReshapeFuncUcall); + CHECK_NAME(glutVisibilityFuncUcall); + CHECK_NAME(glutDisplayFuncUcall); + CHECK_NAME(glutMouseFuncUcall); + CHECK_NAME(glutMotionFuncUcall); + CHECK_NAME(glutPassiveMotionFuncUcall); + CHECK_NAME(glutEntryFuncUcall); + CHECK_NAME(glutKeyboardUpFuncUcall); + CHECK_NAME(glutSpecialUpFuncUcall); + CHECK_NAME(glutJoystickFuncUcall); + CHECK_NAME(glutMenuStatusFuncUcall); + CHECK_NAME(glutOverlayDisplayFuncUcall); + CHECK_NAME(glutWindowStatusFuncUcall); + CHECK_NAME(glutSpaceballMotionFuncUcall); + CHECK_NAME(glutSpaceballRotateFuncUcall); + CHECK_NAME(glutSpaceballButtonFuncUcall); + CHECK_NAME(glutButtonBoxFuncUcall); + CHECK_NAME(glutDialsFuncUcall); + CHECK_NAME(glutTabletMotionFuncUcall); + CHECK_NAME(glutTabletButtonFuncUcall); + CHECK_NAME(glutMouseWheelFuncUcall); + CHECK_NAME(glutPositionFuncUcall); + CHECK_NAME(glutCloseFuncUcall); + CHECK_NAME(glutWMCloseFuncUcall); + CHECK_NAME(glutMenuDestroyFuncUcall); + CHECK_NAME(glutMultiEntryFuncUcall); + CHECK_NAME(glutMultiButtonFuncUcall); + CHECK_NAME(glutMultiMotionFuncUcall); + CHECK_NAME(glutMultiPassiveFuncUcall); + CHECK_NAME(glutInitErrorFuncUcall); + CHECK_NAME(glutInitWarningFuncUcall); + CHECK_NAME(glutInitContextFuncUcall); + CHECK_NAME(glutAppStatusFuncUcall); #undef CHECK_NAME return NULL; diff --git a/freeglut/freeglut/src/fg_init.c b/freeglut/freeglut/src/fg_init.c index ae87212..c3c00e5 100644 --- a/freeglut/freeglut/src/fg_init.c +++ b/freeglut/freeglut/src/fg_init.c @@ -70,9 +70,11 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */ { NULL, NULL }, /* Timers */ { NULL, NULL }, /* FreeTimers */ NULL, /* IdleCallback */ + NULL, /* IdleCallbackData */ 0, /* ActiveMenus */ NULL, /* MenuStateCallback */ NULL, /* MenuStatusCallback */ + NULL, /* MenuStatusCallbackData */ FREEGLUT_MENU_FONT, { -1, -1, GL_TRUE }, /* GameModeSize */ -1, /* GameModeDepth */ @@ -95,7 +97,9 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */ 0, /* OpenGL ContextProfile */ 0, /* HasOpenGL20 */ NULL, /* ErrorFunc */ - NULL /* WarningFunc */ + NULL, /* ErrorFuncData */ + NULL, /* WarningFunc */ + NULL /* WarningFuncData */ }; @@ -298,9 +302,11 @@ void fgDeinitialize( void ) fgListInit( &fgState.Timers ); fgListInit( &fgState.FreeTimers ); - fgState.IdleCallback = NULL; - fgState.MenuStateCallback = ( FGCBMenuState )NULL; - fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL; + fgState.IdleCallback = ( FGCBIdleUC )NULL; + fgState.IdleCallbackData = NULL; + fgState.MenuStateCallback = ( FGCBMenuState )NULL; + fgState.MenuStatusCallback = ( FGCBMenuStatusUC )NULL; + fgState.MenuStatusCallbackData = NULL; fgState.SwapCount = 0; fgState.SwapTime = 0; @@ -668,19 +674,57 @@ void FGAPIENTRY glutInitContextProfile( int profile ) /* * Sets the user error handler (note the use of va_list for the args to the fmt) */ -void FGAPIENTRY glutInitErrorFunc( FGError callback ) +void FGAPIENTRY glutInitErrorFuncUcall( FGErrorUC callback, FGCBUserData userData ) { /* This allows user programs to handle freeglut errors */ fgState.ErrorFunc = callback; + fgState.ErrorFuncData = userData; +} + +static void fghInitErrorFuncCallback( const char *fmt, va_list ap, FGCBUserData userData ) +{ + FGError callback = (FGError)userData; + callback( fmt, ap ); +} + +void FGAPIENTRY glutInitErrorFunc( FGError callback ) +{ + if (callback) + { + glutInitErrorFuncUcall( fghInitErrorFuncCallback, (FGCBUserData)callback ); + } + else + { + glutInitErrorFuncUcall( NULL, NULL ); + } } /* * Sets the user warning handler (note the use of va_list for the args to the fmt) */ -void FGAPIENTRY glutInitWarningFunc( FGWarning callback ) +void FGAPIENTRY glutInitWarningFuncUcall( FGWarningUC callback, FGCBUserData userData ) { /* This allows user programs to handle freeglut warnings */ fgState.WarningFunc = callback; + fgState.WarningFuncData = userData; +} + +static void fghInitWarningFuncCallback( const char *fmt, va_list ap, FGCBUserData userData ) +{ + FGWarning callback = (FGWarning)userData; + callback( fmt, ap ); +} + +void FGAPIENTRY glutInitWarningFunc( FGWarning callback ) +{ + if (callback) + { + glutInitWarningFuncUcall( fghInitWarningFuncCallback, (FGCBUserData)callback ); + } + else + { + glutInitWarningFuncUcall( NULL, NULL ); + } } /*** END OF FILE ***/ diff --git a/freeglut/freeglut/src/fg_internal.h b/freeglut/freeglut/src/fg_internal.h index 2cecf71..a95027b 100644 --- a/freeglut/freeglut/src/fg_internal.h +++ b/freeglut/freeglut/src/fg_internal.h @@ -33,12 +33,14 @@ #endif #include "fg_version.h" +#include "fg_callback_macros.h" /* Freeglut is intended to function under all Unix/X11 and Win32 platforms. */ /* XXX: Don't all MS-Windows compilers (except Cygwin) have _WIN32 defined? * XXX: If so, remove the first set of defined()'s below. */ -#if !defined(TARGET_HOST_POSIX_X11) && !defined(TARGET_HOST_MS_WINDOWS) && !defined(TARGET_HOST_MAC_OSX) && !defined(TARGET_HOST_SOLARIS) +#if !defined(TARGET_HOST_POSIX_X11) && !defined(TARGET_HOST_MS_WINDOWS) && !defined(TARGET_HOST_MAC_OSX) && !defined(TARGET_HOST_SOLARIS) && \ + !defined(TARGET_HOST_ANDROID) && !defined(TARGET_HOST_BLACKBERRY) && !defined(TARGET_HOST_POSIX_WAYLAND) #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__) \ || defined(_WIN32) || defined(_WIN32_WCE) \ || ( defined(__CYGWIN__) && defined(X_DISPLAY_MISSING) ) @@ -215,52 +217,97 @@ /* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ -/* Freeglut callbacks type definitions */ -typedef void (* FGCBDisplay )( void ); -typedef void (* FGCBReshape )( int, int ); -typedef void (* FGCBPosition )( int, int ); -typedef void (* FGCBVisibility )( int ); -typedef void (* FGCBKeyboard )( unsigned char, int, int ); -typedef void (* FGCBKeyboardUp )( unsigned char, int, int ); -typedef void (* FGCBSpecial )( int, int, int ); -typedef void (* FGCBSpecialUp )( int, int, int ); -typedef void (* FGCBMouse )( int, int, int, int ); -typedef void (* FGCBMouseWheel )( int, int, int, int ); -typedef void (* FGCBMotion )( int, int ); -typedef void (* FGCBPassive )( int, int ); -typedef void (* FGCBEntry )( int ); -typedef void (* FGCBWindowStatus )( int ); -typedef void (* FGCBJoystick )( unsigned int, int, int, int ); -typedef void (* FGCBOverlayDisplay)( void ); -typedef void (* FGCBSpaceMotion )( int, int, int ); -typedef void (* FGCBSpaceRotation )( int, int, int ); -typedef void (* FGCBSpaceButton )( int, int ); -typedef void (* FGCBDials )( int, int ); -typedef void (* FGCBButtonBox )( int, int ); -typedef void (* FGCBTabletMotion )( int, int ); -typedef void (* FGCBTabletButton )( int, int, int, int ); -typedef void (* FGCBDestroy )( void ); /* Used for both window and menu destroy callbacks */ +/* + * Freeglut callbacks type definitions + * + * If anything here is modified or added, update fg_callback_macros.h functions. + * + * This is not ideal, but freeglut needs to either define minimal compiler specs, + * or update header every time this is changed or updated. + */ +typedef void* FGCBUserData; -typedef void (* FGCBMultiEntry )( int, int ); -typedef void (* FGCBMultiButton )( int, int, int, int, int ); -typedef void (* FGCBMultiMotion )( int, int, int ); -typedef void (* FGCBMultiPassive )( int, int, int ); +typedef void (* FGCBDisplay )( void ); +typedef void (* FGCBDisplayUC )( FGCBUserData ); +typedef void (* FGCBReshape )( int, int ); +typedef void (* FGCBReshapeUC )( int, int, FGCBUserData ); +typedef void (* FGCBPosition )( int, int ); +typedef void (* FGCBPositionUC )( int, int, FGCBUserData ); +typedef void (* FGCBVisibility )( int ); +typedef void (* FGCBVisibilityUC )( int, FGCBUserData ); +typedef void (* FGCBKeyboard )( unsigned char, int, int ); +typedef void (* FGCBKeyboardUC )( unsigned char, int, int, FGCBUserData ); +typedef void (* FGCBKeyboardUp )( unsigned char, int, int ); +typedef void (* FGCBKeyboardUpUC )( unsigned char, int, int, FGCBUserData ); +typedef void (* FGCBSpecial )( int, int, int ); +typedef void (* FGCBSpecialUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBSpecialUp )( int, int, int ); +typedef void (* FGCBSpecialUpUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBMouse )( int, int, int, int ); +typedef void (* FGCBMouseUC )( int, int, int, int, FGCBUserData ); +typedef void (* FGCBMouseWheel )( int, int, int, int ); +typedef void (* FGCBMouseWheelUC )( int, int, int, int, FGCBUserData ); +typedef void (* FGCBMotion )( int, int ); +typedef void (* FGCBMotionUC )( int, int, FGCBUserData ); +typedef void (* FGCBPassive )( int, int ); +typedef void (* FGCBPassiveUC )( int, int, FGCBUserData ); +typedef void (* FGCBEntry )( int ); +typedef void (* FGCBEntryUC )( int, FGCBUserData ); +typedef void (* FGCBWindowStatus )( int ); +typedef void (* FGCBWindowStatusUC )( int, FGCBUserData ); +typedef void (* FGCBJoystick )( unsigned int, int, int, int ); +typedef void (* FGCBJoystickUC )( unsigned int, int, int, int, FGCBUserData ); +typedef void (* FGCBOverlayDisplay )( void ); +typedef void (* FGCBOverlayDisplayUC)( FGCBUserData ); +typedef void (* FGCBSpaceMotion )( int, int, int ); +typedef void (* FGCBSpaceMotionUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBSpaceRotation )( int, int, int ); +typedef void (* FGCBSpaceRotationUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBSpaceButton )( int, int ); +typedef void (* FGCBSpaceButtonUC )( int, int, FGCBUserData ); +typedef void (* FGCBDials )( int, int ); +typedef void (* FGCBDialsUC )( int, int, FGCBUserData ); +typedef void (* FGCBButtonBox )( int, int ); +typedef void (* FGCBButtonBoxUC )( int, int, FGCBUserData ); +typedef void (* FGCBTabletMotion )( int, int ); +typedef void (* FGCBTabletMotionUC )( int, int, FGCBUserData ); +typedef void (* FGCBTabletButton )( int, int, int, int ); +typedef void (* FGCBTabletButtonUC )( int, int, int, int, FGCBUserData ); +typedef void (* FGCBDestroy )( void ); /* Used for both window and menu destroy callbacks */ +typedef void (* FGCBDestroyUC )( FGCBUserData ); -typedef void (* FGCBInitContext)(); -typedef void (* FGCBAppStatus)(int); +typedef void (* FGCBMultiEntry )( int, int ); +typedef void (* FGCBMultiEntryUC )( int, int, FGCBUserData ); +typedef void (* FGCBMultiButton )( int, int, int, int, int ); +typedef void (* FGCBMultiButtonUC )( int, int, int, int, int, FGCBUserData ); +typedef void (* FGCBMultiMotion )( int, int, int ); +typedef void (* FGCBMultiMotionUC )( int, int, int, FGCBUserData ); +typedef void (* FGCBMultiPassive )( int, int, int ); +typedef void (* FGCBMultiPassiveUC )( int, int, int, FGCBUserData ); + +typedef void (* FGCBInitContext )( void ); +typedef void (* FGCBInitContextUC )( FGCBUserData ); +typedef void (* FGCBAppStatus )( int ); +typedef void (* FGCBAppStatusUC )( int, FGCBUserData ); /* The global callbacks type definitions */ -typedef void (* FGCBIdle )( void ); -typedef void (* FGCBTimer )( int ); -typedef void (* FGCBMenuState )( int ); -typedef void (* FGCBMenuStatus )( int, int, int ); +typedef void (* FGCBIdle )( void ); +typedef void (* FGCBIdleUC )( FGCBUserData ); +typedef void (* FGCBTimer )( int ); +typedef void (* FGCBTimerUC )( int, FGCBUserData ); +typedef void (* FGCBMenuState )( int ); +typedef void (* FGCBMenuStatus )( int, int, int ); +typedef void (* FGCBMenuStatusUC )( int, int, int, FGCBUserData ); /* The callback used when creating/using menus */ -typedef void (* FGCBMenu )( int ); +typedef void (* FGCBMenu )( int ); +typedef void (* FGCBMenuUC )( int, FGCBUserData ); /* The FreeGLUT error/warning handler type definition */ -typedef void (* FGError ) ( const char *fmt, va_list ap); -typedef void (* FGWarning ) ( const char *fmt, va_list ap); +typedef void (* FGError )( const char *fmt, va_list ap ); +typedef void (* FGErrorUC )( const char *fmt, va_list ap, FGCBUserData userData ); +typedef void (* FGWarning )( const char *fmt, va_list ap ); +typedef void (* FGWarningUC )( const char *fmt, va_list ap, FGCBUserData userData ); /* A list structure */ @@ -327,28 +374,30 @@ struct tagSFG_State SFG_List Timers; /* The freeglut timer hooks */ SFG_List FreeTimers; /* The unused timer hooks */ - FGCBIdle IdleCallback; /* The global idle callback */ + FGCBIdleUC IdleCallback; /* The global idle callback */ + FGCBUserData IdleCallbackData; /* The global idle callback data */ int ActiveMenus; /* Num. of currently active menus */ FGCBMenuState MenuStateCallback; /* Menu callbacks are global */ - FGCBMenuStatus MenuStatusCallback; + FGCBMenuStatusUC MenuStatusCallback; + FGCBUserData MenuStatusCallbackData; void* MenuFont; /* Font to be used for newly created menus */ SFG_XYUse GameModeSize; /* Game mode screen's dimensions */ int GameModeDepth; /* The pixel depth for game mode */ int GameModeRefresh; /* The refresh rate for game mode */ - int ActionOnWindowClose; /* Action when user closes window */ + int ActionOnWindowClose; /* Action when user closes window */ - fgExecutionState ExecState; /* Used for GLUT termination */ - char *ProgramName; /* Name of the invoking program */ - GLboolean JoysticksInitialised; /* Only initialize if application calls for them */ - int NumActiveJoysticks; /* Number of active joysticks (callback defined and positive pollrate) -- if zero, don't poll joysticks */ - GLboolean InputDevsInitialised; /* Only initialize if application calls for them */ + fgExecutionState ExecState; /* Used for GLUT termination */ + char *ProgramName; /* Name of the invoking program */ + GLboolean JoysticksInitialised; /* Only initialize if application calls for them */ + int NumActiveJoysticks; /* Number of active joysticks (callback defined and positive pollrate) -- if zero, don't poll joysticks */ + GLboolean InputDevsInitialised; /* Only initialize if application calls for them */ int MouseWheelTicks; /* Number of ticks the mouse wheel has turned */ - int AuxiliaryBufferNumber; /* Number of auxiliary buffers */ + int AuxiliaryBufferNumber;/* Number of auxiliary buffers */ int SampleNumber; /* Number of samples per pixel */ GLboolean SkipStaleMotion; /* skip stale motion events */ @@ -361,8 +410,10 @@ struct tagSFG_State int ContextFlags; /* OpenGL context flags */ int ContextProfile; /* OpenGL context profile */ int HasOpenGL20; /* fgInitGL2 could find all OpenGL 2.0 functions */ - FGError ErrorFunc; /* User defined error handler */ - FGWarning WarningFunc; /* User defined warning handler */ + FGErrorUC ErrorFunc; /* User defined error handler */ + FGCBUserData ErrorFuncData; /* User defined error handler user data */ + FGWarningUC WarningFunc; /* User defined warning handler */ + FGCBUserData WarningFuncData; /* User defined warning handler user data */ }; /* The structure used by display initialization in fg_init.c */ @@ -384,7 +435,8 @@ struct tagSFG_Timer { SFG_Node Node; int ID; /* The timer ID integer */ - FGCBTimer Callback; /* The timer callback */ + FGCBTimerUC Callback; /* The timer callback */ + FGCBUserData CallbackData; /* The timer callback user data */ fg_time_t TriggerTime; /* The timer trigger time */ }; @@ -511,11 +563,12 @@ typedef void (*SFG_Proc)(); /* * SET_WCB() is used as: * - * SET_WCB( window, cbname, func ); + * SET_WCB( window, cbname, func, udata ); * * ...where {window} is the freeglut window to set the callback, * {cbname} is the window-specific callback to set, - * {func} is a function-pointer. + * {func} is a function-pointer, + * {udata} is a void* pointer for user data. * * Originally, {FETCH_WCB( ... ) = func} was rather sloppily used, * but this can cause warnings because the FETCH_WCB() macro type- @@ -524,12 +577,25 @@ typedef void (*SFG_Proc)(); * The {if( FETCH_WCB( ... ) != func )} test is to do type-checking * and for no other reason. Since it's hidden in the macro, the * ugliness is felt to be rather benign. + * + * If the function-pointer is the same, the data will be the only + * value updated. If the function-pointer changes, the data will + * be changed as well, preventing stail data from being passed in. + * Just updating the data does nothing unless a function-pointer + * exists, as the data is otherwise already allocated. */ -#define SET_WCB(window,cbname,func) \ +#define SET_WCB(window,cbname,func,udata) \ do \ { \ if( FETCH_WCB( window, cbname ) != (SFG_Proc)(func) ) \ + { \ (((window).CallBacks[WCB_ ## cbname]) = (SFG_Proc)(func)); \ + (((window).CallbackDatas[WCB_ ## cbname]) = (udata)); \ + } \ + else if( FETCH_USER_DATA_WCB( window, cbname ) != udata ) \ + { \ + (((window).CallbackDatas[WCB_ ## cbname]) = (udata)); \ + } \ } while( 0 ) /* @@ -546,6 +612,39 @@ do \ #define FETCH_WCB(window,cbname) \ ((window).CallBacks[WCB_ ## cbname]) +/* + * FETCH_USER_DATA_WCB() is used as: + * + * FETCH_USER_DATA_WCB( window, cbname ); + * + * ...where {window} is the freeglut window, + * {cbname} is the window-specific callback to be invoked, + * + * This expects a variable named "window" of type tagSFG_Window to exist. + * + * The result is the callback data pointer. + */ +#define FETCH_USER_DATA_WCB(window,cbname) \ + ((window).CallbackDatas[WCB_ ## cbname]) + +/* + * EXPAND_WCB() is used as: + * + * EXPAND_WCB( cbname )(( arg_list, userData )) + * + * ... where {(arg_list)} is the parameter list and userData is user + * provided data. + * + * This will take the arg_list and extend it by one argument, adding + * the argument "userData" to the end of the list. + * + * All of this is defined in fg_callback_macros.h + * + * See that header for more info. + * + * ------------------------------------------------------------------ + */ + /* * INVOKE_WCB() is used as: * @@ -557,36 +656,26 @@ do \ * * The callback is invoked as: * - * callback( arg_list ); + * callback( arg_list, userData ); * - * ...so the parentheses are REQUIRED in the {arg_list}. + * ...where userData is added to the arg_list, but the parentheses + * are REQUIRED in the {arg_list}. * * NOTE that it does a sanity-check and also sets the * current window. * */ -#if TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: also WinCE? */ #define INVOKE_WCB(window,cbname,arg_list) \ do \ { \ if( FETCH_WCB( window, cbname ) ) \ { \ - FGCB ## cbname func = (FGCB ## cbname)(FETCH_WCB( window, cbname )); \ + FGCB ## cbname ## UC func = (FGCB ## cbname ## UC)(FETCH_WCB( window, cbname )); \ + FGCBUserData userData = FETCH_USER_DATA_WCB( window, cbname ); \ fgSetWindow( &window ); \ - func arg_list; \ + func EXPAND_WCB( cbname )(( arg_list, userData )); \ } \ } while( 0 ) -#else -#define INVOKE_WCB(window,cbname,arg_list) \ -do \ -{ \ - if( FETCH_WCB( window, cbname ) ) \ - { \ - fgSetWindow( &window ); \ - ((FGCB ## cbname)FETCH_WCB( window, cbname )) arg_list; \ - } \ -} while( 0 ) -#endif /* * The window callbacks the user can supply us with. Should be kept portable. @@ -662,8 +751,10 @@ struct tagSFG_Menu void *UserData; /* User data passed back at callback */ int ID; /* The global menu ID */ SFG_List Entries; /* The menu entries list */ - FGCBMenu Callback; /* The menu callback */ - FGCBDestroy Destroy; /* Destruction callback */ + FGCBMenuUC Callback; /* The menu callback */ + FGCBUserData CallbackData; /* The menu callback user data */ + FGCBDestroyUC Destroy; /* Destruction callback */ + FGCBUserData DestroyData; /* Destruction callback user data */ GLboolean IsActive; /* Is the menu selected? */ void* Font; /* Font to be used for displaying this menu */ int Width; /* Menu box width in pixels */ @@ -701,10 +792,11 @@ struct tagSFG_Window SFG_Context Window; /* Window and OpenGL context */ SFG_WindowState State; /* The window state */ SFG_Proc CallBacks[ TOTAL_CALLBACKS ]; /* Array of window callbacks */ + FGCBUserData CallbackDatas[ TOTAL_CALLBACKS ]; /* Array of window callback datas */ void *UserData ; /* For use by user */ - SFG_Menu* Menu[ FREEGLUT_MAX_MENUS ]; /* Menus appended to window */ - SFG_Menu* ActiveMenu; /* The window's active menu */ + SFG_Menu* Menu[ FREEGLUT_MAX_MENUS ]; /* Menus appended to window */ + SFG_Menu* ActiveMenu; /* The window's active menu */ SFG_Window* Parent; /* The parent to this window */ SFG_List Children; /* The subwindows d.l. list */ @@ -970,7 +1062,7 @@ void fgCloseWindows (); void fgDestroyWindow( SFG_Window* window ); /* Menu creation and destruction. Defined in fg_structure.c */ -SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ); +SFG_Menu* fgCreateMenu( FGCBMenuUC menuCallback, FGCBUserData userData ); void fgDestroyMenu( SFG_Menu* menu ); /* Joystick device management functions, defined in fg_joystick.c */ diff --git a/freeglut/freeglut/src/fg_main.c b/freeglut/freeglut/src/fg_main.c index 0f47c8d..97c7a32 100644 --- a/freeglut/freeglut/src/fg_main.c +++ b/freeglut/freeglut/src/fg_main.c @@ -233,7 +233,7 @@ static void fghCheckTimers( void ) fgListRemove( &fgState.Timers, &timer->Node ); fgListAppend( &fgState.FreeTimers, &timer->Node ); - timer->Callback( timer->ID ); + timer->Callback( timer->ID, timer->CallbackData ); } } @@ -269,7 +269,7 @@ void fgError( const char *fmt, ... ) va_start( ap, fmt ); /* call user set error handler here */ - fgState.ErrorFunc(fmt, ap); + fgState.ErrorFunc(fmt, ap, fgState.ErrorFuncData); va_end( ap ); @@ -302,7 +302,7 @@ void fgWarning( const char *fmt, ... ) va_start( ap, fmt ); /* call user set warning handler here */ - fgState.WarningFunc(fmt, ap); + fgState.WarningFunc(fmt, ap, fgState.WarningFuncData); va_end( ap ); @@ -400,7 +400,7 @@ void fgProcessWork(SFG_Window *window) fgPlatformInitWork(window); /* Call init context callback */ - INVOKE_WCB( *window, InitContext, ()); + INVOKE_WCB( *window, InitContext, ( ) ); /* Lastly, check if we have a display callback, error out if not * This is the right place to do it, as the redisplay will be @@ -509,7 +509,7 @@ void FGAPIENTRY glutMainLoop( void ) fgStructure.CurrentWindow->IsMenu ) /* fail safe */ fgSetWindow( window ); - fgState.IdleCallback( ); + fgState.IdleCallback( fgState.IdleCallbackData ); } else fghSleepForEvents( ); diff --git a/freeglut/freeglut/src/fg_menu.c b/freeglut/freeglut/src/fg_menu.c index 36b24ce..ae7405c 100644 --- a/freeglut/freeglut/src/fg_menu.c +++ b/freeglut/freeglut/src/fg_menu.c @@ -531,7 +531,7 @@ static void fghActivateMenu( SFG_Window* window, int button ) 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); + fgState.MenuStatusCallback(GLUT_MENU_IN_USE, window->State.MouseX, window->State.MouseY, fgState.MenuStatusCallbackData); } fgSetWindow( menu->Window ); @@ -609,7 +609,7 @@ GLboolean fgCheckActiveMenu ( SFG_Window *window, int button, GLboolean pressed, /* Deactivate menu and then call callback (we don't want menu to stay in view while callback is executing, and user should be able to change menus in callback) */ fgDeactivateMenu( parent_window ); - active_menu->Callback( active_entry->ID ); + active_menu->Callback( active_entry->ID, active_menu->CallbackData ); /* Restore the current window and menu */ fgSetWindow( save_window ); @@ -725,7 +725,7 @@ void fgDeactivateMenu( SFG_Window *window ) SFG_XYUse mouse_pos; fghPlatformGetCursorPos(parent_window, GL_TRUE, &mouse_pos); - fgState.MenuStatusCallback(GLUT_MENU_NOT_IN_USE, mouse_pos.X, mouse_pos.Y); + fgState.MenuStatusCallback(GLUT_MENU_NOT_IN_USE, mouse_pos.X, mouse_pos.Y, fgState.MenuStatusCallbackData); } } } @@ -780,14 +780,33 @@ void fghCalculateMenuBoxSize( void ) /* * Creates a new menu object, adding it to the freeglut structure */ -int FGAPIENTRY glutCreateMenu( FGCBMenu callback ) +int FGAPIENTRY glutCreateMenuUcall( FGCBMenuUC callback, FGCBUserData userData ) { /* The menu object creation code resides in fg_structure.c */ - FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" ); - if (fgState.ActiveMenus) - fgError("Menu manipulation not allowed while menus in use."); + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenuUcall" ); + if (fgState.ActiveMenus) + { + fgError( "Menu manipulation not allowed while menus in use." ); + } - return fgCreateMenu( callback )->ID; + return fgCreateMenu( callback, userData )->ID; +} + +/* Standard glutCreateMenu */ +static void fghCreateMenuCallback( int menu, FGCBUserData userData ) +{ + FGCBMenu callback = (FGCBMenu)userData; + callback( menu ); +} + +int FGAPIENTRY glutCreateMenu( FGCBMenu callback ) +{ + FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" ); + if (!callback) + { + return glutCreateMenuUcall( NULL, NULL ); + } + return glutCreateMenuUcall( fghCreateMenuCallback, (FGCBUserData)callback ); } /* diff --git a/freeglut/freeglut/src/fg_structure.c b/freeglut/freeglut/src/fg_structure.c index f0bc9a2..4274667 100644 --- a/freeglut/freeglut/src/fg_structure.c +++ b/freeglut/freeglut/src/fg_structure.c @@ -49,7 +49,7 @@ SFG_Structure fgStructure = { { NULL, NULL }, /* The list of windows */ /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ extern void fgPlatformCreateWindow ( SFG_Window *window ); -extern void fghDefaultReshape(int width, int height); +extern void fghDefaultReshape(int width, int height, FGCBUserData userData); static void fghClearCallBacks( SFG_Window *window ) { @@ -57,7 +57,10 @@ static void fghClearCallBacks( SFG_Window *window ) { int i; for( i = 0; i < TOTAL_CALLBACKS; ++i ) + { window->CallBacks[ i ] = NULL; + window->CallbackDatas[ i ] = NULL; + } } } @@ -83,7 +86,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, fgPlatformCreateWindow ( window ); fghClearCallBacks( window ); - SET_WCB( *window, Reshape, fghDefaultReshape); + SET_WCB( *window, Reshape, fghDefaultReshape, NULL); /* Initialize the object properties */ window->ID = ++fgStructure.WindowID; @@ -116,7 +119,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, /* * This private function creates a menu and adds it to the menus list */ -SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ) +SFG_Menu* fgCreateMenu( FGCBMenuUC menuCallback, FGCBUserData userData ) { SFG_Window *current_window = fgStructure.CurrentWindow; @@ -134,10 +137,11 @@ SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ) fgSetWindow( current_window ); /* Initialize the object properties: */ - menu->ID = ++fgStructure.MenuID; - menu->Callback = menuCallback; - menu->ActiveEntry = NULL; - menu->Font = fgState.MenuFont; + menu->ID = ++fgStructure.MenuID; + menu->Callback = menuCallback; + menu->CallbackData = userData; + menu->ActiveEntry = NULL; + menu->Font = fgState.MenuFont; fgListInit( &menu->Entries ); fgListAppend( &fgStructure.Menus, &menu->Node ); @@ -173,9 +177,10 @@ void fgAddToWindowDestroyList( SFG_Window* window ) * to ensure that they are no longer called after this point. */ { - FGCBDestroy destroy = (FGCBDestroy)FETCH_WCB( *window, Destroy ); + FGCBDestroyUC destroy = (FGCBDestroyUC)FETCH_WCB( *window, Destroy ); + FGCBUserData destroyData = FETCH_USER_DATA_WCB( *window, Destroy ); fghClearCallBacks( window ); - SET_WCB( *window, Destroy, destroy ); + SET_WCB( *window, Destroy, destroy, destroyData ); } } @@ -302,7 +307,7 @@ void fgDestroyMenu( SFG_Menu* menu ) { SFG_Menu *activeMenu=fgStructure.CurrentMenu; fgStructure.CurrentMenu = menu; - menu->Destroy( ); + menu->Destroy( menu->DestroyData ); fgStructure.CurrentMenu = activeMenu; } diff --git a/freeglut/freeglut/src/mswin/fg_menu_mswin.c b/freeglut/freeglut/src/mswin/fg_menu_mswin.c index 27bc356..42d056b 100644 --- a/freeglut/freeglut/src/mswin/fg_menu_mswin.c +++ b/freeglut/freeglut/src/mswin/fg_menu_mswin.c @@ -106,3 +106,8 @@ int FGAPIENTRY __glutCreateMenuWithExit( void(* callback)( int ), void (__cdecl return glutCreateMenu( callback ); } +int FGAPIENTRY __glutCreateMenuUcallWithExit(void(*callback)(int, void*), void(__cdecl *exit_function)(int), void* user_data) +{ + __glutExitFunc = exit_function; + return glutCreateMenuUcall(callback, user_data); +} diff --git a/freeglut/freeglut/src/wayland/fg_input_devices_wl.c b/freeglut/freeglut/src/wayland/fg_input_devices_wl.c index 0aaa91e..bb32f98 100644 --- a/freeglut/freeglut/src/wayland/fg_input_devices_wl.c +++ b/freeglut/freeglut/src/wayland/fg_input_devices_wl.c @@ -71,8 +71,10 @@ void fghKeyboardInterpretKeysym( SFG_Window* window, xkb_keysym_t sym, uint32_t state ) { - FGCBKeyboard keyboard_cb; - FGCBSpecial special_cb; + FGCBKeyboardUC keyboard_cb; + FGCBSpecialUC special_cb; + FGCBUserData keyboard_ud; + FGCBUserData special_ud; char string[16]; int special = -1; @@ -81,13 +83,17 @@ void fghKeyboardInterpretKeysym( SFG_Window* window, * others, which need to be translated to GLUT_KEY_Xs... */ if( state ) { - keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, Keyboard )); - special_cb = (FGCBSpecial) ( FETCH_WCB( *window, Special )); + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, Keyboard )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, Special )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, Keyboard ); + special_ud = FETCH_USER_DATA_WCB( *window, Special ); } else { - keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, KeyboardUp )); - special_cb = (FGCBSpecial) ( FETCH_WCB( *window, SpecialUp )); + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, KeyboardUp )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, SpecialUp )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, KeyboardUp ); + special_ud = FETCH_USER_DATA_WCB( *window, SpecialUp ); } switch( sym ) @@ -127,13 +133,13 @@ void fghKeyboardInterpretKeysym( SFG_Window* window, if( special_cb && (special != -1) ) { fgSetWindow( window ); - special_cb( special, window->State.MouseX, window->State.MouseY ); + special_cb( special, window->State.MouseX, window->State.MouseY, special_ud ); } else if( keyboard_cb && (special == -1) ) { fgSetWindow( window ); xkb_keysym_to_utf8( sym, string, sizeof( string ) ); - keyboard_cb( string[0], window->State.MouseX, window->State.MouseY ); + keyboard_cb( string[0], window->State.MouseX, window->State.MouseY, keyboard_ud ); } } diff --git a/freeglut/freeglut/src/x11/fg_main_x11.c b/freeglut/freeglut/src/x11/fg_main_x11.c index 0e54253..80fd2c8 100644 --- a/freeglut/freeglut/src/x11/fg_main_x11.c +++ b/freeglut/freeglut/src/x11/fg_main_x11.c @@ -890,8 +890,10 @@ void fgPlatformProcessSingleEvent ( void ) case KeyRelease: case KeyPress: { - FGCBKeyboard keyboard_cb; - FGCBSpecial special_cb; + FGCBKeyboardUC keyboard_cb; + FGCBSpecialUC special_cb; + FGCBUserData keyboard_ud; + FGCBUserData special_ud; GETWINDOW( xkey ); GETMOUSE( xkey ); @@ -932,13 +934,17 @@ void fgPlatformProcessSingleEvent ( void ) if( event.type == KeyPress ) { - keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, Keyboard )); - special_cb = (FGCBSpecial) ( FETCH_WCB( *window, Special )); + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, Keyboard )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, Special )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, Keyboard ); + special_ud = FETCH_USER_DATA_WCB( *window, Special ); } else { - keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, KeyboardUp )); - special_cb = (FGCBSpecial) ( FETCH_WCB( *window, SpecialUp )); + keyboard_cb = (FGCBKeyboardUC)( FETCH_WCB( *window, KeyboardUp )); + special_cb = (FGCBSpecialUC) ( FETCH_WCB( *window, SpecialUp )); + keyboard_ud = FETCH_USER_DATA_WCB( *window, KeyboardUp ); + special_ud = FETCH_USER_DATA_WCB( *window, SpecialUp ); } /* Is there a keyboard/special callback hooked for this window? */ @@ -963,7 +969,8 @@ void fgPlatformProcessSingleEvent ( void ) fgSetWindow( window ); fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state ); keyboard_cb( asciiCode[ 0 ], - event.xkey.x, event.xkey.y + event.xkey.x, event.xkey.y, + keyboard_ud ); fgState.Modifiers = INVALID_MODIFIERS; } @@ -1031,7 +1038,7 @@ void fgPlatformProcessSingleEvent ( void ) { fgSetWindow( window ); fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state ); - special_cb( special, event.xkey.x, event.xkey.y ); + special_cb( special, event.xkey.x, event.xkey.y, special_ud ); fgState.Modifiers = INVALID_MODIFIERS; } } diff --git a/freeglut/web-src/docs/api.php b/freeglut/web-src/docs/api.php index faeb433..8603eb2 100644 --- a/freeglut/web-src/docs/api.php +++ b/freeglut/web-src/docs/api.php @@ -301,7 +301,7 @@ and their compatibility with GLUT, are made explicit.

There is considerable confusion about the "right thing to do" concerning -window size and position. GLUT itself is not consistent between +window size and position. GLUT itself is not consistent between Windows and UNIX/X11; since platform independence is a virtue for freeglut, we decided to break with GLUT's behaviour.
Under UNIX/X11, it is apparently not possible to get the window border @@ -327,6 +327,40 @@ area--which is NOT the (x,y) position of the window you specified when you created it.

+

3.2.2 User-data callbacks

+ +

+GLUT was created as a tool to help teach OpenGL programming. To simplify +development, callbacks were used for handling display, input, and other +events. But at the time it was developed, the purpose, or for some other +unknown reason, the callbacks lacked any user-provided data argument. +This has caused considerable difficulties for any significantly advanced +usage of GLUT, and now freeglut. This has prevented any attempt to +wrap freeglut in a C++ wrapper, make per-window, per-callback data +structure, and potentially made it undesirable to modern C developers who +tend to be well versed in "don't use globals". To combat these +complaints and issues, many callbacks (with some deprecated +callbacks excluded) support user-data callbacks provided through additional +functions provided in freeglut. All callbacks that support user-data +callbacks are marked as such. +

+ +

+The general rule to follow is to take the freeglut callback function +and append "Ucall" to the end of the function, add an additional void* +argument to the end of the argument list of both the freeglut function +and the callback function. This will pass the user-data to the callback when it's +invoked. +

+ +

Examples

+ +

void glutPositionFunc ( void (* func)( int x, int y ) );
+void glutPositionFuncUcall ( void (* func)( int x, int y, void* user_data ), void* user_data );

+ +

void glutKeyboardUpFunc ( void (* func)( unsigned char key, int x, int y ) );
+void glutKeyboardUpFuncUcall ( void (* func)( unsigned char key, int x, int y, void* user_data ), void* user_data );

+

3.3 Terminology

3.4 Differences from GLUT 3.7

@@ -524,6 +558,8 @@ from the library can be handled by the user.

void glutInitErrorFunc   ( void (* callback)( const char *fmt, va_list ap) );
void glutInitWarningFunc ( void (* callback)( const char *fmt, va_list ap) );

+

These functions have user-data callback functions.

+

Description

The users callback is passed a format string and a variable argument @@ -943,6 +979,8 @@ The glutShowOverlay and glutHideOverlay functions are not impl

10.1 glutCreateMenu

+

Has user-data callback function.

+

10.2 glutDestroyMenu

10.3 glutGetMenu, glutSetMenu

@@ -985,10 +1023,14 @@ stroke font, or an unknown font.

10.11 glutMenuDestroyFunc

+

Has user-data callback function.

+

11. Global Callback Registration Functions

11.1 glutTimerFunc

+

Has user-data callback function.

+

11.2 glutIdleFunc

@@ -998,11 +1040,11 @@ freeglut calls the idle callback when there are no inputs from the user.

Usage

-

void glutIdleFunc ( void (*func) -( void ) );

+

void glutIdleFunc ( void (*func ) ( void ) );

-

funcThe new -global idle callback function

+

func The new global idle callback function

+ +

Has user-data callback function.

Description

@@ -1042,16 +1084,24 @@ the idle callback.

11.3 glutMenuStatusFunc

+

Has user-data callback function.

+

11.4 glutMenuStateFunc

12. Window-Specific Callback Registration Functions

12.1 glutDisplayFunc

+

Has user-data callback function.

+

12.2 glutOverlayDisplayFunc

+

Has user-data callback function.

+

12.3 glutReshapeFunc

+

Has user-data callback function.

+

12.4 glutPositionFunc

@@ -1065,6 +1115,8 @@ repositioned/moved programatically or by the user.

void glutPositionFunc ( void (* func)( int x, int y) );

+

Has user-data callback function.

+

Description

When freeglut calls this callback, it provides the new @@ -1094,6 +1146,8 @@ about to be destroyed.

func The window's new closure callback function

+

Has user-data callback function.

+

Description

@@ -1121,6 +1175,8 @@ alias to glutCloseFunc.

12.6 glutKeyboardFunc

+

Has user-data callback function.

+

12.7 glutSpecialFunc

@@ -1145,6 +1201,8 @@ to the window at the time the key is pressed
The y-coordinate of the mouse relative to the window at the time the key is pressed

+

Has user-data callback function.

+

Description

@@ -1200,6 +1258,8 @@ to the window at the time the key is released
The y-coordinate of the mouse relative to the window at the time the key is released

+

Has user-data callback function.

+

Description

@@ -1252,6 +1312,8 @@ to the window at the time the key is released
The y-coordinate of the mouse relative to the window at the time the key is released

+

Has user-data callback function.

+

Description

@@ -1289,8 +1351,12 @@ have them fixed.

12.10 glutMotionFunc, glutPassiveMotionFunc

+

Both functions have user-data callback functions.

+

12.11 glutMouseFunc

+

Has user-data callback function.

+

12.12 glutMouseWheelFunc

@@ -1304,6 +1370,8 @@ spins the mouse wheel.

void glutMouseWheelFunc ( void( *callback )( int wheel, int direction, int x, int y ));

+

Has user-data callback function.

+

Description

If the mouse wheel is spun over your (sub)window, freeglut @@ -1320,8 +1388,12 @@ as mouse buttons.

12.13 glutEntryFunc

+

Has user-data callback function.

+

12.14 glutJoystickFunc

+

Has user-data callback function.

+

12.15 glutSpaceballMotionFunc

@@ -1337,6 +1409,8 @@ provided so that GLUT-based programs can compile and link against

void glutSpaceballMotionFunc ( void (* callback)( int x, int y, int z ) );

+

Has user-data callback function.

+

Description

The x, y, and z arguments indicate the amount of translation in integer along x, y, and z axis respectively.

@@ -1357,6 +1431,8 @@ provided so that GLUT-based programs can compile and link against

void glutSpaceballRotateFunc ( void (* callback)( int rx, int ry, int rz ) );

+

Has user-data callback function.

+

Description

The rx, ry, and rz arguments indicate the amount of rotation in integer with respect to x, y, and z axis respectively.

@@ -1379,6 +1455,8 @@ The glutSpaceballButtonFunc function sets the window's Spaceball button

void glutSpaceballButtonFunc ( void (* callback)( int button, int updown ) );

+

Has user-data callback function.

+

Description

The button argument may take one of the following defined @@ -1418,6 +1496,8 @@ The glutDialsFunc function sets the global dials&buttons box callback. void glutButtonBoxFunc ( void (* callback)( int button, int updown ) );

+

Has user-data callback function.

+

Description

@@ -1442,6 +1522,8 @@ The glutDialsFunc function sets the global dials&buttons box callback.

void glutDialsFunc ( void (* callback)( int dial, int value ) );

+

Has user-data callback function.

+

Description

@@ -1469,6 +1551,8 @@ that a call to the function will not produce an error.. void glutTabletMotionFunc ( void (* callback)( int x, int y ) );

+

Has user-data callback function.

+

Description

The glutTabletMotionFunc function @@ -1491,6 +1575,8 @@ that a call to the function will not produce an error..

void glutTabletButtonFunc ( void (* callback)( int button, int updown, int x, int y ) );

+

Has user-data callback function.

+

Description

@@ -1517,6 +1603,8 @@ these callbacks when the visibility status of a window changes.
void glutWindowStatusFunc ( void( *callback )( int state ));

+

Both functions have user-data callback functions.

+

Description

@@ -2701,6 +2789,8 @@ Currently, under windows, the first (oldest) touch point also controls the mouse cursor, which triggers the non-multi callbacks as usual.
+All these functions have user-data callback functions. +
Limitation: currently on the cursor id is provided. It may be @@ -2729,9 +2819,11 @@ whether/how to implement it.

  • glutInitContextFunc ← void : called when the context -is initialized or re-initialized (e.g. after a pause)
  • +is initialized or re-initialized (e.g. after a pause). Has user-data callback +function.
  • glutAppStatusFunc ← event : called when the -application's status changes, with event identifying the state entered. +application's status changes, with event identifying the state entered. Has +user-data callback function. Possible states:
    • application goes on a pause (or a stop) → GLUT_APPSTATUS_PAUSE