4 * The callbacks setting methods.
6 * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
7 * Written by Pawel W. Olszta, <olszta@sourceforge.net>
8 * Creation date: Fri Dec 3 1999
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include <GL/freeglut.h>
29 #include "fg_internal.h"
31 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
37 /* Sets the global idle callback */
38 void FGAPIENTRY glutIdleFuncUcall( FGCBIdleUC callback, FGCBUserData userData )
40 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFuncUcall" );
41 fgState.IdleCallback = callback;
42 fgState.IdleCallbackData = userData;
45 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Idle)
47 /* Creates a timer and sets its callback */
48 void FGAPIENTRY glutTimerFuncUcall( unsigned int timeOut, FGCBTimerUC callback, int timerID, FGCBUserData userData )
50 SFG_Timer *timer, *node;
52 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFuncUcall" );
54 if( (timer = fgState.FreeTimers.Last) )
56 fgListRemove( &fgState.FreeTimers, &timer->Node );
60 if( ! (timer = malloc(sizeof(SFG_Timer))) )
61 fgError( "Fatal error: "
62 "Memory allocation failure in glutTimerFunc()" );
65 timer->Callback = callback;
66 timer->CallbackData = userData;
68 timer->TriggerTime = fgElapsedTime() + timeOut;
70 /* Insert such that timers are sorted by end-time */
71 for( node = fgState.Timers.First; node; node = node->Node.Next )
73 if( node->TriggerTime > timer->TriggerTime )
77 fgListInsert( &fgState.Timers, &node->Node, &timer->Node );
80 IMPLEMENT_CALLBACK_FUNC_CB_ARG1(Timer, Timer)
82 void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID )
84 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" );
87 FGCBTimer* reference = &callback;
88 glutTimerFuncUcall( timeOut, fghTimerFuncCallback, timerID, *((FGCBUserData*)reference) );
91 glutTimerFuncUcall( timeOut, NULL, timerID, NULL );
94 /* Deprecated version of glutMenuStatusFunc callback setting method */
95 void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback )
97 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" );
98 fgState.MenuStateCallback = callback;
101 /* Sets the global menu status callback for the current window */
102 void FGAPIENTRY glutMenuStatusFuncUcall( FGCBMenuStatusUC callback, FGCBUserData userData )
104 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFuncUcall" );
105 fgState.MenuStatusCallback = callback;
106 fgState.MenuStatusCallbackData = userData;
109 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3(MenuStatus)
112 * Menu specific callbacks.
114 /* Callback upon menu destruction */
115 void FGAPIENTRY glutMenuDestroyFuncUcall( FGCBDestroyUC callback, FGCBUserData userData )
117 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFuncUcall" );
118 if( fgStructure.CurrentMenu )
120 fgStructure.CurrentMenu->Destroy = callback;
121 fgStructure.CurrentMenu->DestroyData = userData;
125 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0_2NAME(MenuDestroy, Destroy)
127 /* Implement all these callback setter functions... */
128 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Position)
129 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(Keyboard,unsigned char,int,int)
130 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(KeyboardUp,unsigned char,int,int)
131 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(Special)
132 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(SpecialUp)
133 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(Mouse)
134 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(MouseWheel)
135 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Motion)
136 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2_2NAME(PassiveMotion,Passive)
137 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(Entry)
138 /* glutWMCloseFunc is an alias for glutCloseFunc; both set the window's Destroy callback */
139 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(Close,Destroy)
140 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(WMClose,Destroy)
141 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(OverlayDisplay)
142 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(WindowStatus)
143 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(ButtonBox)
144 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Dials)
145 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(TabletMotion)
146 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(TabletButton)
147 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(MultiEntry)
148 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG5(MultiButton)
149 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiMotion)
150 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiPassive)
151 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(InitContext)
152 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(AppStatus)
155 * Sets the Display callback for the current window
157 void FGAPIENTRY glutDisplayFuncUcall( FGCBDisplayUC callback, FGCBUserData userData )
159 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFuncUcall" );
161 fgError( "Fatal error in program. NULL display callback not "
162 "permitted in GLUT 3.0+ or freeglut 2.0.1+" );
163 SET_CURRENT_WINDOW_CALLBACK( Display );
166 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Display)
168 void fghDefaultReshape( int width, int height, FGCBUserData userData )
170 glViewport( 0, 0, width, height );
173 void FGAPIENTRY glutReshapeFuncUcall( FGCBReshapeUC callback, FGCBUserData userData )
175 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFuncUcall" );
179 callback = fghDefaultReshape;
183 SET_CURRENT_WINDOW_CALLBACK( Reshape );
186 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2(Reshape)
189 * Sets the Visibility callback for the current window.
190 * NB: the Visibility func is deprecated in favor of the WindowStatus func,
191 * which provides more detail. The visibility func callback is implemented
192 * as a translation step from the windowStatus func. When the user sets the
193 * windowStatus func, any visibility func is overwritten.
194 * DEVELOPER NOTE: in the library, only invoke the window status func, this
195 * gets automatically translated to the visibility func if thats what the
197 * window status is kind of anemic on win32 as there are no window messages
198 * to notify us that the window is covered by other windows or not.
199 * Should one want to query this, see
200 * http://stackoverflow.com/questions/5445889/get-which-process-window-is-actually-visible-in-c-sharp
201 * for an implementation outline (but it would be polling based, not push based).
203 static void fghVisibility( int status, FGCBUserData userData )
207 FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Visibility Callback" );
208 freeglut_return_if_fail( fgStructure.CurrentWindow );
210 /* Translate window status func states to visibility states */
211 if( ( status == GLUT_HIDDEN) || ( status == GLUT_FULLY_COVERED) )
212 vis_status = GLUT_NOT_VISIBLE;
213 else /* GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED */
214 vis_status = GLUT_VISIBLE;
216 INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( vis_status ) );
219 void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData userData )
221 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFuncUcall" );
228 SET_CURRENT_WINDOW_CALLBACK( Visibility );
231 glutWindowStatusFuncUcall( fghVisibility, NULL );
233 glutWindowStatusFuncUcall( NULL, NULL );
236 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG1(Visibility)
239 * Sets the joystick callback and polling rate for the current window
241 void FGAPIENTRY glutJoystickFuncUcall( FGCBJoystickUC callback, int pollInterval, FGCBUserData userData )
243 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFuncUcall" );
244 fgInitialiseJoysticks ();
247 fgStructure.CurrentWindow->State.JoystickPollRate <= 0 || /* Joystick callback was disabled */
248 !FETCH_WCB(*fgStructure.CurrentWindow,Joystick)
251 callback && ( pollInterval > 0 ) /* but is now enabled */
253 ++fgState.NumActiveJoysticks;
255 fgStructure.CurrentWindow->State.JoystickPollRate > 0 && /* Joystick callback was enabled */
256 FETCH_WCB(*fgStructure.CurrentWindow,Joystick)
259 !callback || ( pollInterval <= 0 ) /* but is now disabled */
261 --fgState.NumActiveJoysticks;
263 SET_CURRENT_WINDOW_CALLBACK( Joystick );
264 fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval;
266 /* set last poll time such that joystick will be polled asap */
267 fgStructure.CurrentWindow->State.JoystickLastPoll = fgElapsedTime();
268 if (fgStructure.CurrentWindow->State.JoystickLastPoll < pollInterval)
269 fgStructure.CurrentWindow->State.JoystickLastPoll = 0;
271 fgStructure.CurrentWindow->State.JoystickLastPoll -= pollInterval;
274 static void fghJoystickFuncCallback( unsigned int buttons, int axis0, int axis1, int axis2, FGCBUserData userData )
276 FGCBJoystick* callback = (FGCBJoystick*)&userData;
277 (*callback)( buttons, axis0, axis1, axis2 );
280 void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval )
282 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" );
285 FGCBJoystick* reference = &callback;
286 glutJoystickFuncUcall( fghJoystickFuncCallback, pollInterval, *((FGCBUserData*)reference) );
289 glutJoystickFuncUcall( NULL, pollInterval, NULL );
293 * Sets the spaceball motion callback for the current window
295 void FGAPIENTRY glutSpaceballMotionFuncUcall( FGCBSpaceMotionUC callback, FGCBUserData userData )
297 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFuncUcall" );
298 fgInitialiseSpaceball();
300 SET_CURRENT_WINDOW_CALLBACK( SpaceMotion );
303 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballMotion, SpaceMotion)
306 * Sets the spaceball rotate callback for the current window
308 void FGAPIENTRY glutSpaceballRotateFuncUcall( FGCBSpaceRotationUC callback, FGCBUserData userData )
310 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFuncUcall" );
311 fgInitialiseSpaceball();
313 SET_CURRENT_WINDOW_CALLBACK( SpaceRotation );
316 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballRotate, SpaceRotation)
319 * Sets the spaceball button callback for the current window
321 void FGAPIENTRY glutSpaceballButtonFuncUcall( FGCBSpaceButtonUC callback, FGCBUserData userData )
323 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFuncUcall" );
324 fgInitialiseSpaceball();
326 SET_CURRENT_WINDOW_CALLBACK( SpaceButton );
329 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2_2NAME(SpaceballButton, SpaceButton)
331 /*** END OF FILE ***/