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" );
86 glutTimerFuncUcall( timeOut, fghTimerFuncCallback, timerID, (FGCBUserData)callback );
88 glutTimerFuncUcall( timeOut, NULL, timerID, NULL );
91 /* Deprecated version of glutMenuStatusFunc callback setting method */
92 void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback )
94 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" );
95 fgState.MenuStateCallback = callback;
98 /* Sets the global menu status callback for the current window */
99 void FGAPIENTRY glutMenuStatusFuncUcall( FGCBMenuStatusUC callback, FGCBUserData userData )
101 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFuncUcall" );
102 fgState.MenuStatusCallback = callback;
103 fgState.MenuStatusCallbackData = userData;
106 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3(MenuStatus)
109 * Menu specific callbacks.
111 /* Callback upon menu destruction */
112 void FGAPIENTRY glutMenuDestroyFuncUcall( FGCBDestroyUC callback, FGCBUserData userData )
114 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFuncUcall" );
115 if( fgStructure.CurrentMenu )
117 fgStructure.CurrentMenu->Destroy = callback;
118 fgStructure.CurrentMenu->DestroyData = userData;
122 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0_2NAME(MenuDestroy, Destroy)
124 /* Implement all these callback setter functions... */
125 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Position)
126 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(Keyboard,unsigned char,int,int)
127 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3_USER(KeyboardUp,unsigned char,int,int)
128 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(Special)
129 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(SpecialUp)
130 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(Mouse)
131 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(MouseWheel)
132 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Motion)
133 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2_2NAME(PassiveMotion,Passive)
134 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(Entry)
135 /* glutWMCloseFunc is an alias for glutCloseFunc; both set the window's Destroy callback */
136 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(Close,Destroy)
137 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0_2NAME(WMClose,Destroy)
138 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(OverlayDisplay)
139 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(WindowStatus)
140 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(ButtonBox)
141 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(Dials)
142 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(TabletMotion)
143 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG4(TabletButton)
144 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG2(MultiEntry)
145 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG5(MultiButton)
146 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiMotion)
147 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG3(MultiPassive)
148 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG0(InitContext)
149 IMPLEMENT_CURRENT_WINDOW_CALLBACK_FUNC_ARG1(AppStatus)
152 * Sets the Display callback for the current window
154 void FGAPIENTRY glutDisplayFuncUcall( FGCBDisplayUC callback, FGCBUserData userData )
156 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFuncUcall" );
158 fgError( "Fatal error in program. NULL display callback not "
159 "permitted in GLUT 3.0+ or freeglut 2.0.1+" );
160 SET_CURRENT_WINDOW_CALLBACK( Display );
163 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG0(Display)
165 void fghDefaultReshape( int width, int height, FGCBUserData userData )
167 glViewport( 0, 0, width, height );
170 void FGAPIENTRY glutReshapeFuncUcall( FGCBReshapeUC callback, FGCBUserData userData )
172 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFuncUcall" );
176 callback = fghDefaultReshape;
180 SET_CURRENT_WINDOW_CALLBACK( Reshape );
183 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2(Reshape)
186 * Sets the Visibility callback for the current window.
187 * NB: the Visibility func is deprecated in favor of the WindowStatus func,
188 * which provides more detail. The visibility func callback is implemented
189 * as a translation step from the windowStatus func. When the user sets the
190 * windowStatus func, any visibility func is overwritten.
191 * DEVELOPER NOTE: in the library, only invoke the window status func, this
192 * gets automatically translated to the visibility func if thats what the
194 * window status is kind of anemic on win32 as there are no window messages
195 * to notify us that the window is covered by other windows or not.
196 * Should one want to query this, see
197 * http://stackoverflow.com/questions/5445889/get-which-process-window-is-actually-visible-in-c-sharp
198 * for an implementation outline (but it would be polling based, not push based).
200 static void fghVisibility( int status, FGCBUserData userData )
204 FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Visibility Callback" );
205 freeglut_return_if_fail( fgStructure.CurrentWindow );
207 /* Translate window status func states to visibility states */
208 if( ( status == GLUT_HIDDEN) || ( status == GLUT_FULLY_COVERED) )
209 vis_status = GLUT_NOT_VISIBLE;
210 else /* GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED */
211 vis_status = GLUT_VISIBLE;
213 INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( vis_status ) );
216 void FGAPIENTRY glutVisibilityFuncUcall( FGCBVisibilityUC callback, FGCBUserData userData )
218 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFuncUcall" );
225 SET_CURRENT_WINDOW_CALLBACK( Visibility );
228 glutWindowStatusFuncUcall( fghVisibility, NULL );
230 glutWindowStatusFuncUcall( NULL, NULL );
233 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG1(Visibility)
236 * Sets the joystick callback and polling rate for the current window
238 void FGAPIENTRY glutJoystickFuncUcall( FGCBJoystickUC callback, int pollInterval, FGCBUserData userData )
240 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFuncUcall" );
241 fgInitialiseJoysticks ();
244 fgStructure.CurrentWindow->State.JoystickPollRate <= 0 || /* Joystick callback was disabled */
245 !FETCH_WCB(*fgStructure.CurrentWindow,Joystick)
248 callback && ( pollInterval > 0 ) /* but is now enabled */
250 ++fgState.NumActiveJoysticks;
252 fgStructure.CurrentWindow->State.JoystickPollRate > 0 && /* Joystick callback was enabled */
253 FETCH_WCB(*fgStructure.CurrentWindow,Joystick)
256 !callback || ( pollInterval <= 0 ) /* but is now disabled */
258 --fgState.NumActiveJoysticks;
260 SET_CURRENT_WINDOW_CALLBACK( Joystick );
261 fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval;
263 /* set last poll time such that joystick will be polled asap */
264 fgStructure.CurrentWindow->State.JoystickLastPoll = fgElapsedTime();
265 if (fgStructure.CurrentWindow->State.JoystickLastPoll < pollInterval)
266 fgStructure.CurrentWindow->State.JoystickLastPoll = 0;
268 fgStructure.CurrentWindow->State.JoystickLastPoll -= pollInterval;
271 static void fghJoystickFuncCallback( unsigned int buttons, int axis0, int axis1, int axis2, FGCBUserData userData )
273 FGCBJoystick callback = (FGCBJoystick)userData;
274 callback( buttons, axis0, axis1, axis2 );
277 void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval )
279 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" );
281 glutJoystickFuncUcall( fghJoystickFuncCallback, pollInterval, (FGCBUserData)callback );
283 glutJoystickFuncUcall( NULL, pollInterval, NULL );
287 * Sets the spaceball motion callback for the current window
289 void FGAPIENTRY glutSpaceballMotionFuncUcall( FGCBSpaceMotionUC callback, FGCBUserData userData )
291 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFuncUcall" );
292 fgInitialiseSpaceball();
294 SET_CURRENT_WINDOW_CALLBACK( SpaceMotion );
297 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballMotion, SpaceMotion)
300 * Sets the spaceball rotate callback for the current window
302 void FGAPIENTRY glutSpaceballRotateFuncUcall( FGCBSpaceRotationUC callback, FGCBUserData userData )
304 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFuncUcall" );
305 fgInitialiseSpaceball();
307 SET_CURRENT_WINDOW_CALLBACK( SpaceRotation );
310 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG3_2NAME(SpaceballRotate, SpaceRotation)
313 * Sets the spaceball button callback for the current window
315 void FGAPIENTRY glutSpaceballButtonFuncUcall( FGCBSpaceButtonUC callback, FGCBUserData userData )
317 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFuncUcall" );
318 fgInitialiseSpaceball();
320 SET_CURRENT_WINDOW_CALLBACK( SpaceButton );
323 IMPLEMENT_GLUT_CALLBACK_FUNC_ARG2_2NAME(SpaceballButton, SpaceButton)
325 /*** END OF FILE ***/