Adding "glutFullScreenToggle" for X11 -- still needs implementation in Windows (e...
[freeglut] / src / freeglut_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 "freeglut_internal.h"
30
31 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
32
33 /*
34  * All of the callbacks setting methods can be generalized to this:
35  */
36 #define SET_CALLBACK(a)                                         \
37 do                                                              \
38 {                                                               \
39     if( fgStructure.CurrentWindow == NULL )                     \
40         return;                                                 \
41     SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback ); \
42 } while( 0 )
43
44 /*
45  * Sets the Display callback for the current window
46  */
47 void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) )
48 {
49     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" );
50     if( !callback )
51         fgError( "Fatal error in program.  NULL display callback not "
52                  "permitted in GLUT 3.0+ or freeglut 2.0.1+" );
53     SET_CALLBACK( Display );
54 }
55
56 /*
57  * Sets the Reshape callback for the current window
58  */
59 void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) )
60 {
61     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" );
62     SET_CALLBACK( Reshape );
63 }
64
65 /*
66  * Sets the Keyboard callback for the current window
67  */
68 void FGAPIENTRY glutKeyboardFunc( void (* callback)
69                                   ( unsigned char, int, int ) )
70 {
71     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardFunc" );
72     SET_CALLBACK( Keyboard );
73 }
74
75 /*
76  * Sets the Special callback for the current window
77  */
78 void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) )
79 {
80     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialFunc" );
81     SET_CALLBACK( Special );
82 }
83
84 /*
85  * Sets the global idle callback
86  */
87 void FGAPIENTRY glutIdleFunc( void (* callback)( void ) )
88 {
89     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" );
90     fgState.IdleCallback = callback;
91 }
92
93 /*
94  * Sets the Timer callback for the current window
95  */
96 void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ),
97                                int timerID )
98 {
99     SFG_Timer *timer, *node;
100
101     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" );
102
103     if( (timer = fgState.FreeTimers.Last) )
104     {
105         fgListRemove( &fgState.FreeTimers, &timer->Node );
106     }
107     else
108     {
109         if( ! (timer = malloc(sizeof(SFG_Timer))) )
110             fgError( "Fatal error: "
111                      "Memory allocation failure in glutTimerFunc()" );
112     }
113
114     timer->Callback  = callback;
115     timer->ID        = timerID;
116     timer->TriggerTime = fgElapsedTime() + timeOut;
117
118     for( node = fgState.Timers.First; node; node = node->Node.Next )
119     {
120         if( node->TriggerTime > timer->TriggerTime )
121             break;
122     }
123
124     fgListInsert( &fgState.Timers, &node->Node, &timer->Node );
125 }
126
127 /*
128  * Sets the Visibility callback for the current window.
129  */
130 static void fghVisibility( int status )
131 {
132     int glut_status = GLUT_VISIBLE;
133
134     FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Visibility Callback" );
135     freeglut_return_if_fail( fgStructure.CurrentWindow );
136
137     if( ( GLUT_HIDDEN == status )  || ( GLUT_FULLY_COVERED == status ) )
138         glut_status = GLUT_NOT_VISIBLE;
139     INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( glut_status ) );
140 }
141
142 void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) )
143 {
144     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" );
145     SET_CALLBACK( Visibility );
146
147     if( callback )
148         glutWindowStatusFunc( fghVisibility );
149     else
150         glutWindowStatusFunc( NULL );
151 }
152
153 /*
154  * Sets the keyboard key release callback for the current window
155  */
156 void FGAPIENTRY glutKeyboardUpFunc( void (* callback)
157                                     ( unsigned char, int, int ) )
158 {
159     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardUpFunc" );
160     SET_CALLBACK( KeyboardUp );
161 }
162
163 /*
164  * Sets the special key release callback for the current window
165  */
166 void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) )
167 {
168     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialUpFunc" );
169     SET_CALLBACK( SpecialUp );
170 }
171
172 /*
173  * Sets the joystick callback and polling rate for the current window
174  */
175 void FGAPIENTRY glutJoystickFunc( void (* callback)
176                                   ( unsigned int, int, int, int ),
177                                   int pollInterval )
178 {
179     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" );
180     fgInitialiseJoysticks ();
181
182     SET_CALLBACK( Joystick );
183     fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval;
184
185     fgStructure.CurrentWindow->State.JoystickLastPoll =
186         fgElapsedTime() - fgStructure.CurrentWindow->State.JoystickPollRate;
187
188     if( fgStructure.CurrentWindow->State.JoystickLastPoll < 0 )
189         fgStructure.CurrentWindow->State.JoystickLastPoll = 0;
190 }
191
192 /*
193  * Sets the mouse callback for the current window
194  */
195 void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) )
196 {
197     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseFunc" );
198     SET_CALLBACK( Mouse );
199 }
200
201 /*
202  * Sets the mouse wheel callback for the current window
203  */
204 void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) )
205 {
206     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseWheelFunc" );
207     SET_CALLBACK( MouseWheel );
208 }
209
210 /*
211  * Sets the mouse motion callback for the current window (one or more buttons
212  * are pressed)
213  */
214 void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) )
215 {
216     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMotionFunc" );
217     SET_CALLBACK( Motion );
218 }
219
220 /*
221  * Sets the passive mouse motion callback for the current window (no mouse
222  * buttons are pressed)
223  */
224 void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) )
225 {
226     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPassiveMotionFunc" );
227     SET_CALLBACK( Passive );
228 }
229
230 /*
231  * Window mouse entry/leave callback
232  */
233 void FGAPIENTRY glutEntryFunc( void (* callback)( int ) )
234 {
235     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEntryFunc" );
236     SET_CALLBACK( Entry );
237 }
238
239 /*
240  * Window destruction callbacks
241  */
242 void FGAPIENTRY glutCloseFunc( void (* callback)( void ) )
243 {
244     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCloseFunc" );
245     SET_CALLBACK( Destroy );
246 }
247
248 void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) )
249 {
250     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWMCloseFunc" );
251     glutCloseFunc( callback );
252 }
253
254 /* A. Donev: Destruction callback for menus */
255 void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) )
256 {
257     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" );
258     if( fgStructure.CurrentMenu )
259         fgStructure.CurrentMenu->Destroy = callback;
260 }
261
262 /*
263  * Deprecated version of glutMenuStatusFunc callback setting method
264  */
265 void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) )
266 {
267     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" );
268     fgState.MenuStateCallback = callback;
269 }
270
271 /*
272  * Sets the global menu status callback for the current window
273  */
274 void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) )
275 {
276     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" );
277     fgState.MenuStatusCallback = callback;
278 }
279
280 /*
281  * Sets the overlay display callback for the current window
282  */
283 void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) )
284 {
285     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutOverlayDisplayFunc" );
286     SET_CALLBACK( OverlayDisplay );
287 }
288
289 /*
290  * Sets the window status callback for the current window
291  */
292 void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) )
293 {
294     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWindowStatusFunc" );
295     SET_CALLBACK( WindowStatus );
296 }
297
298 /*
299  * Sets the spaceball motion callback for the current window
300  */
301 void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) )
302 {
303     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" );
304     SET_CALLBACK( SpaceMotion );
305 }
306
307 /*
308  * Sets the spaceball rotate callback for the current window
309  */
310 void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) )
311 {
312     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" );
313     SET_CALLBACK( SpaceRotation );
314 }
315
316 /*
317  * Sets the spaceball button callback for the current window
318  */
319 void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) )
320 {
321     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" );
322     SET_CALLBACK( SpaceButton );
323 }
324
325 /*
326  * Sets the button box callback for the current window
327  */
328 void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) )
329 {
330     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutButtonBoxFunc" );
331     SET_CALLBACK( ButtonBox );
332 }
333
334 /*
335  * Sets the dials box callback for the current window
336  */
337 void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) )
338 {
339     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDialsFunc" );
340     SET_CALLBACK( Dials );
341 }
342
343 /*
344  * Sets the tablet motion callback for the current window
345  */
346 void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) )
347 {
348     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletMotionFunc" );
349     SET_CALLBACK( TabletMotion );
350 }
351
352 /*
353  * Sets the tablet buttons callback for the current window
354  */
355 void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) )
356 {
357     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletButtonFunc" );
358     SET_CALLBACK( TabletButton );
359 }
360
361 /*** END OF FILE ***/