added glutPositionFunc callback, now just need to implement so it does
[freeglut] / src / fg_callbacks.c
1 /*
2  * freeglut_callbacks.c
3  *
4  * The callbacks setting methods.
5  *
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
9  *
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:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
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.
26  */
27
28 #include <GL/freeglut.h>
29 #include "fg_internal.h"
30
31 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
32
33
34 /*
35  * Global callbacks.
36  */
37 /* Sets the global idle callback */
38 void FGAPIENTRY glutIdleFunc( FGCBIdle callback )
39 {
40     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" );
41     fgState.IdleCallback = callback;
42 }
43
44 /* Creates a timer and sets its callback */
45 void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, int timerID )
46 {
47     SFG_Timer *timer, *node;
48
49     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" );
50
51     if( (timer = fgState.FreeTimers.Last) )
52     {
53         fgListRemove( &fgState.FreeTimers, &timer->Node );
54     }
55     else
56     {
57         if( ! (timer = malloc(sizeof(SFG_Timer))) )
58             fgError( "Fatal error: "
59                      "Memory allocation failure in glutTimerFunc()" );
60     }
61
62     timer->Callback  = callback;
63     timer->ID        = timerID;
64     timer->TriggerTime = fgElapsedTime() + timeOut;
65
66     for( node = fgState.Timers.First; node; node = node->Node.Next )
67     {
68         if( node->TriggerTime > timer->TriggerTime )
69             break;
70     }
71
72     fgListInsert( &fgState.Timers, &node->Node, &timer->Node );
73 }
74
75 /* Deprecated version of glutMenuStatusFunc callback setting method */
76 void FGAPIENTRY glutMenuStateFunc( FGCBMenuState callback )
77 {
78     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" );
79     fgState.MenuStateCallback = callback;
80 }
81
82 /* Sets the global menu status callback for the current window */
83 void FGAPIENTRY glutMenuStatusFunc( FGCBMenuStatus callback )
84 {
85     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" );
86     fgState.MenuStatusCallback = callback;
87 }
88
89
90 /*
91  * Menu specific callbacks.
92  */
93 /* Callback upon menu destruction */
94 void FGAPIENTRY glutMenuDestroyFunc( FGCBDestroy callback )
95 {
96     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" );
97     if( fgStructure.CurrentMenu )
98         fgStructure.CurrentMenu->Destroy = callback;
99 }
100
101
102 /*
103  * All of the window-specific callbacks setting methods can be generalized to this:
104  */
105 #define SET_CALLBACK(a)                                         \
106 do                                                              \
107 {                                                               \
108     if( fgStructure.CurrentWindow == NULL )                     \
109         return;                                                 \
110     SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback ); \
111 } while( 0 )
112
113 /*
114  * Sets the Display callback for the current window
115  */
116 void FGAPIENTRY glutDisplayFunc( FGCBDisplay callback )
117 {
118     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" );
119     if( !callback )
120         fgError( "Fatal error in program.  NULL display callback not "
121                  "permitted in GLUT 3.0+ or freeglut 2.0.1+" );
122     SET_CALLBACK( Display );
123 }
124
125 /*
126  * Sets the Reshape callback for the current window
127  */
128 void FGAPIENTRY glutReshapeFunc( FGCBReshape callback )
129 {
130     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" );
131     SET_CALLBACK( Reshape );
132 }
133
134 /*
135  * Sets the Keyboard callback for the current window
136  */
137 void FGAPIENTRY glutKeyboardFunc( FGCBKeyboard callback )
138 {
139     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardFunc" );
140     SET_CALLBACK( Keyboard );
141 }
142
143 /*
144  * Sets the keyboard key release callback for the current window
145  */
146 void FGAPIENTRY glutKeyboardUpFunc( FGCBKeyboardUp callback )
147 {
148     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardUpFunc" );
149     SET_CALLBACK( KeyboardUp );
150 }
151
152 /*
153  * Sets the Special callback for the current window
154  */
155 void FGAPIENTRY glutSpecialFunc( FGCBSpecial callback )
156 {
157     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialFunc" );
158     SET_CALLBACK( Special );
159 }
160
161 /*
162  * Sets the special key release callback for the current window
163  */
164 void FGAPIENTRY glutSpecialUpFunc( FGCBSpecialUp callback )
165 {
166     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialUpFunc" );
167     SET_CALLBACK( SpecialUp );
168 }
169
170 /*
171  * Sets the Visibility callback for the current window.
172  */
173 static void fghVisibility( int status )
174 {
175     int glut_status = GLUT_VISIBLE;
176
177     FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Visibility Callback" );
178     freeglut_return_if_fail( fgStructure.CurrentWindow );
179
180     if( ( GLUT_HIDDEN == status )  || ( GLUT_FULLY_COVERED == status ) )
181         glut_status = GLUT_NOT_VISIBLE;
182     INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( glut_status ) );
183 }
184
185 void FGAPIENTRY glutVisibilityFunc( FGCBVisibility callback )
186 {
187     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" );
188     SET_CALLBACK( Visibility );
189
190     if( callback )
191         glutWindowStatusFunc( fghVisibility );
192     else
193         glutWindowStatusFunc( NULL );
194 }
195
196 /*
197  * Sets the joystick callback and polling rate for the current window
198  */
199 void FGAPIENTRY glutJoystickFunc( FGCBJoystick callback, int pollInterval )
200 {
201     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" );
202     fgInitialiseJoysticks ();
203
204     if ( ( ( fgStructure.CurrentWindow->State.JoystickPollRate < 0 ) ||
205            !FETCH_WCB(*fgStructure.CurrentWindow,Joystick) ) &&  /* Joystick callback was disabled */
206          ( callback && ( pollInterval >= 0 ) ) )               /* but is now enabled */
207         ++fgState.NumActiveJoysticks;
208     else if ( ( ( fgStructure.CurrentWindow->State.JoystickPollRate >= 0 ) &&
209                 FETCH_WCB(*fgStructure.CurrentWindow,Joystick) ) &&  /* Joystick callback was enabled */
210               ( !callback || ( pollInterval < 0 ) ) )              /* but is now disabled */
211         --fgState.NumActiveJoysticks;
212
213     SET_CALLBACK( Joystick );
214     fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval;
215
216     fgStructure.CurrentWindow->State.JoystickLastPoll =
217         fgElapsedTime() - fgStructure.CurrentWindow->State.JoystickPollRate;
218
219     if( fgStructure.CurrentWindow->State.JoystickLastPoll < 0 )
220         fgStructure.CurrentWindow->State.JoystickLastPoll = 0;
221 }
222
223 /*
224  * Sets the mouse callback for the current window
225  */
226 void FGAPIENTRY glutMouseFunc( FGCBMouse callback )
227 {
228     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseFunc" );
229     SET_CALLBACK( Mouse );
230 }
231
232 /*
233  * Sets the mouse wheel callback for the current window
234  */
235 void FGAPIENTRY glutMouseWheelFunc( FGCBMouseWheel callback )
236 {
237     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseWheelFunc" );
238     SET_CALLBACK( MouseWheel );
239 }
240
241 /*
242  * Sets the mouse motion callback for the current window (one or more buttons
243  * are pressed)
244  */
245 void FGAPIENTRY glutMotionFunc( FGCBMotion callback )
246 {
247     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMotionFunc" );
248     SET_CALLBACK( Motion );
249 }
250
251 /*
252  * Sets the passive mouse motion callback for the current window (no mouse
253  * buttons are pressed)
254  */
255 void FGAPIENTRY glutPassiveMotionFunc( FGCBPassive callback )
256 {
257     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPassiveMotionFunc" );
258     SET_CALLBACK( Passive );
259 }
260
261 /*
262  * Window mouse entry/leave callback
263  */
264 void FGAPIENTRY glutEntryFunc( FGCBEntry callback )
265 {
266     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEntryFunc" );
267     SET_CALLBACK( Entry );
268 }
269
270 /*
271  * Window destruction callbacks
272  */
273 void FGAPIENTRY glutCloseFunc( FGCBDestroy callback )
274 {
275     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCloseFunc" );
276     SET_CALLBACK( Destroy );
277 }
278
279 void FGAPIENTRY glutWMCloseFunc( FGCBDestroy callback )
280 {
281     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWMCloseFunc" );
282     glutCloseFunc( callback );
283 }
284
285 /*
286  * Sets the overlay display callback for the current window
287  */
288 void FGAPIENTRY glutOverlayDisplayFunc( FGCBOverlayDisplay callback )
289 {
290     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutOverlayDisplayFunc" );
291     SET_CALLBACK( OverlayDisplay );
292 }
293
294 /*
295  * Sets the window status callback for the current window
296  */
297 void FGAPIENTRY glutWindowStatusFunc( FGCBWindowStatus callback )
298 {
299     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWindowStatusFunc" );
300     SET_CALLBACK( WindowStatus );
301 }
302
303 /*
304  * Sets the spaceball motion callback for the current window
305  */
306 void FGAPIENTRY glutSpaceballMotionFunc( FGCBSpaceMotion callback )
307 {
308     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" );
309     fgInitialiseSpaceball();
310
311     SET_CALLBACK( SpaceMotion );
312 }
313
314 /*
315  * Sets the spaceball rotate callback for the current window
316  */
317 void FGAPIENTRY glutSpaceballRotateFunc( FGCBSpaceRotation callback )
318 {
319     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" );
320     fgInitialiseSpaceball();
321
322     SET_CALLBACK( SpaceRotation );
323 }
324
325 /*
326  * Sets the spaceball button callback for the current window
327  */
328 void FGAPIENTRY glutSpaceballButtonFunc( FGCBSpaceButton callback )
329 {
330     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" );
331     fgInitialiseSpaceball();
332
333     SET_CALLBACK( SpaceButton );
334 }
335
336 /*
337  * Sets the button box callback for the current window
338  */
339 void FGAPIENTRY glutButtonBoxFunc( FGCBButtonBox callback )
340 {
341     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutButtonBoxFunc" );
342     SET_CALLBACK( ButtonBox );
343 }
344
345 /*
346  * Sets the dials box callback for the current window
347  */
348 void FGAPIENTRY glutDialsFunc( FGCBDials callback )
349 {
350     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDialsFunc" );
351     SET_CALLBACK( Dials );
352 }
353
354 /*
355  * Sets the tablet motion callback for the current window
356  */
357 void FGAPIENTRY glutTabletMotionFunc( FGCBTabletMotion callback )
358 {
359     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletMotionFunc" );
360     SET_CALLBACK( TabletMotion );
361 }
362
363 /*
364  * Sets the tablet buttons callback for the current window
365  */
366 void FGAPIENTRY glutTabletButtonFunc( FGCBTabletButton callback )
367 {
368     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletButtonFunc" );
369     SET_CALLBACK( TabletButton );
370 }
371
372 /*
373  * Sets the multi-pointer entry callback for the current window
374  */
375 void FGAPIENTRY glutMultiEntryFunc( FGCBMultiEntry callback )
376 {
377     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiEntryFunc" );
378     SET_CALLBACK( MultiEntry );
379 }
380
381 /*
382  * Sets the multi-pointer button callback for the current window
383  */
384 void FGAPIENTRY glutMultiButtonFunc( FGCBMultiButton callback )
385 {
386     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiButtonFunc" );
387     SET_CALLBACK( MultiButton );
388 }
389
390 /*
391  * Sets the multi-pointer motion callback for the current window
392  */
393 void FGAPIENTRY glutMultiMotionFunc( FGCBMultiMotion callback )
394 {
395     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiMotionFunc" );
396     SET_CALLBACK( MultiMotion );
397 }
398
399 /*
400  * Sets the multi-pointer passive motion callback for the current window
401  */
402 void FGAPIENTRY glutMultiPassiveFunc( FGCBMultiPassive callback )
403 {
404     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiPassiveFunc" );
405     SET_CALLBACK( MultiPassive );
406 }
407
408 /*
409  * Sets the context reload callback for the current window
410  */
411 void FGAPIENTRY glutInitContextFunc( FGCBInitContext callback )
412 {
413     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutInitContextFunc" );
414     SET_CALLBACK( InitContext );
415 }
416
417 /*
418  * Sets the pause callback for the current window
419  */
420 void FGAPIENTRY glutPauseFunc( FGCBPause callback )
421 {
422     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPauseFunc" );
423     SET_CALLBACK( Pause );
424 }
425
426 /*
427  * Sets the resume callback for the current window
428  */
429 void FGAPIENTRY glutResumeFunc( FGCBResume callback )
430 {
431     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutResumeFunc" );
432     SET_CALLBACK( Resume );
433 }
434
435 /*** END OF FILE ***/