b6bb7dcc2a717153e14b03d88f0da226d872dc6a
[freeglut] / progs / demos / CallbackMaker / CallbackMaker.c
1 /* CallbackMaker.c */
2 /*
3  * Program to invoke all the callbacks that "freeglut" supports
4  */
5
6
7 #include <GL/freeglut.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11
12 static int sequence_number = 0 ;
13
14 #define CALLBACKMAKER_N_WINDOWS 4
15 int windows[CALLBACKMAKER_N_WINDOWS] = {0};
16
17 /* define status vars showing whether given callback has been called for given window */
18 #define CALLBACK_CALLED_VAR(name)                            int name##_called[CALLBACKMAKER_N_WINDOWS]   = {0};
19 #define CALLBACK_0V(name)                                    int name##_seq[CALLBACKMAKER_N_WINDOWS]      = {-1}; CALLBACK_CALLED_VAR(name); 
20 #define CALLBACK_1V(name,field)                              int name##_##field[CALLBACKMAKER_N_WINDOWS]  = {-1}; CALLBACK_0V(name);
21 #define CALLBACK_2V(name,field1,field2)                      int name##_##field2[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_1V(name,field1);
22 #define CALLBACK_3V(name,field1,field2,field3)               int name##_##field3[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_2V(name,field1,field2);
23 #define CALLBACK_4V(name,field1,field2,field3,field4)        int name##_##field4[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_3V(name,field1,field2,field3);
24 #define CALLBACK_5V(name,field1,field2,field3,field4,field5) int name##_##field5[CALLBACKMAKER_N_WINDOWS] = {-1}; CALLBACK_4V(name,field1,field2,field3,field4);
25 CALLBACK_2V(reshape,width,height);
26 CALLBACK_2V(position,top,left);
27 CALLBACK_1V(visibility,vis);
28 CALLBACK_1V(windowStatus,state);
29 CALLBACK_4V(key,key,x,y,mod);
30 CALLBACK_4V(keyup,key,x,y,mod);
31 CALLBACK_4V(special,key,x,y,mod);
32 CALLBACK_4V(specialup,key,x,y,mod);
33 CALLBACK_4V(joystick,a,b,c,d);
34 CALLBACK_5V(mouse,button,updown,x,y,mod);
35 CALLBACK_5V(mousewheel,number,direction,x,y,mod);
36 CALLBACK_3V(motion,x,y,mod);
37 CALLBACK_3V(passivemotion,x,y,mod);
38 CALLBACK_1V(entry,state);
39 CALLBACK_0V(close);
40 /* menudestroy is registered on each menu, not a window */
41 int menudestroy_called = 0 ;
42 /* menustatus and menustate are global callbacks, set for all menus at the same time */
43 int menustatus_called = 0;
44 int menustate_called = 0;
45
46 #define STRING_LENGTH   10
47
48 static void
49 bitmapPrintf (const char *fmt, ...)
50 {
51     static char buf[256];
52     va_list args;
53
54     va_start(args, fmt);
55 #if defined(WIN32) && !defined(__CYGWIN__)
56     (void) _vsnprintf (buf, sizeof(buf), fmt, args);
57 #else
58     (void) vsnprintf (buf, sizeof(buf), fmt, args);
59 #endif
60     va_end(args);
61     glutBitmapString ( GLUT_BITMAP_HELVETICA_12, (unsigned char*)buf ) ;
62 }
63
64 static int
65 getWindowAndIdx(int *winIdx)
66 {
67     int window = glutGetWindow();
68
69     if (winIdx)
70         (*winIdx) = window==windows[0] ? 0 :
71                     window==windows[1] ? 1 :
72                     window==windows[2] ? 2 : 3;
73
74     return window;
75 }
76
77 static void
78 Mod2Text(int mods, char *text)
79 {
80     if (mods&GLUT_ACTIVE_CTRL)
81         strcat(text,"CTRL");
82     if (mods&GLUT_ACTIVE_SHIFT)
83         if (text[0])
84             strcat(text,"+SHIFT");
85         else
86             strcat(text,"SHIFT");
87     if (mods&GLUT_ACTIVE_ALT)
88         if (text[0])
89             strcat(text,"+ALT");
90         else
91             strcat(text,"ALT");
92
93     if (!text[0])
94         strcat(text,"none");
95 }
96
97 static void 
98 Display(void)
99 {
100   int winIdx;
101   int window = getWindowAndIdx(&winIdx);
102   glClear ( GL_COLOR_BUFFER_BIT );
103
104   glDisable ( GL_DEPTH_TEST );
105   glMatrixMode ( GL_PROJECTION );
106   glPushMatrix();
107   glLoadIdentity();
108   glOrtho(0, glutGet ( GLUT_WINDOW_WIDTH ), 
109           0, glutGet ( GLUT_WINDOW_HEIGHT ), -1, 1 );
110   glMatrixMode ( GL_MODELVIEW );
111   glPushMatrix ();
112   glLoadIdentity ();
113   glColor3ub ( 0, 0, 0 );
114   glRasterPos2i ( 10, glutGet ( GLUT_WINDOW_HEIGHT ) - 20 );    /* 10pt margin above 10pt letters */
115
116   if ( entry_called[winIdx] )
117   {
118     bitmapPrintf ( "Entry %d:  %d\n", entry_seq[winIdx], entry_state[winIdx] );
119   }
120   
121   if ( visibility_called[winIdx] )
122   {
123     bitmapPrintf ( "Visibility %d:  %d\n", visibility_seq[winIdx], visibility_vis[winIdx] );
124   }
125
126   if ( windowStatus_called[winIdx] )
127   {
128     bitmapPrintf ( "WindowStatus %d:  %d\n", windowStatus_seq[winIdx], windowStatus_state[winIdx] );
129   }
130
131   if ( reshape_called[winIdx] )
132   {
133     bitmapPrintf ( "Reshape %d:  %d %d\n", reshape_seq[winIdx], reshape_width[winIdx], reshape_height[winIdx] );
134   }
135
136   if ( position_called[winIdx] )
137   {
138     bitmapPrintf ( "Position %d:  %d %d\n", position_seq[winIdx], position_left[winIdx], position_top[winIdx] );
139   }
140
141   if ( key_called[winIdx] )
142   {
143     char mods[50] = {0};
144     Mod2Text(key_mod[winIdx],mods);
145     bitmapPrintf ( "Key %d:  %d(%c) %d %d (mod: %s)\n", key_seq[winIdx], key_key[winIdx], key_key[winIdx], key_x[winIdx], key_y[winIdx], mods );
146   }
147
148   if ( keyup_called[winIdx] )
149   {
150     char mods[50] = {0};
151     Mod2Text(keyup_mod[winIdx],mods);
152     bitmapPrintf ( "Key Up %d:  %d(%c) %d %d (mod: %s)\n", keyup_seq[winIdx], keyup_key[winIdx], keyup_key[winIdx], keyup_x[winIdx], keyup_y[winIdx], mods );
153   }
154
155   if ( special_called[winIdx] )
156   {
157     char mods[50] = {0};
158     Mod2Text(special_mod[winIdx],mods);
159     bitmapPrintf ( "Special %d:  %d(%c) %d %d (mod: %s)\n", special_seq[winIdx], special_key[winIdx], special_key[winIdx], special_x[winIdx], special_y[winIdx], mods );
160   }
161
162   if ( specialup_called[winIdx] )
163   {
164     char mods[50] = {0};
165     Mod2Text(specialup_mod[winIdx],mods);
166     bitmapPrintf ( "Special Up %d:  %d(%c) %d %d (mod: %s)\n", specialup_seq[winIdx], specialup_key[winIdx], specialup_key[winIdx], specialup_x[winIdx], specialup_y[winIdx], mods );
167   }
168
169   if ( joystick_called[winIdx] )
170   {
171     bitmapPrintf ( "Joystick %d:  %d %d %d %d\n", joystick_seq[winIdx], joystick_a[winIdx], joystick_b[winIdx], joystick_c[winIdx], joystick_d[winIdx] );
172   }
173
174   if ( mouse_called[winIdx] )
175   {
176     char mods[50] = {0};
177     Mod2Text(mouse_mod[winIdx],mods);
178     bitmapPrintf ( "Mouse %d:  %d %d %d %d (mod: %s)\n", mouse_seq[winIdx], mouse_button[winIdx], mouse_updown[winIdx], mouse_x[winIdx], mouse_y[winIdx], mods );
179   }
180
181   if ( mousewheel_called[winIdx] )
182   {
183     char mods[50] = {0};
184     Mod2Text(mousewheel_mod[winIdx],mods);
185     bitmapPrintf ( "Mouse Wheel %d:  %d %d %d %d (mod: %s)\n", mousewheel_seq[winIdx], mousewheel_number[winIdx], mousewheel_direction[winIdx], mousewheel_x[winIdx], mousewheel_y[winIdx], mods );
186   }
187
188   if ( motion_called[winIdx] )
189   {
190     char mods[50] = {0};
191     Mod2Text(motion_mod[winIdx],mods);
192     bitmapPrintf ( "Motion %d:  %d %d (mod: %s)\n", motion_seq[winIdx], motion_x[winIdx], motion_y[winIdx], mods );
193   }
194
195   if ( passivemotion_called[winIdx] )
196   {
197     char mods[50] = {0};
198     Mod2Text(passivemotion_mod[winIdx],mods);
199     bitmapPrintf ( "Passive Motion %d:  %d %d (mod: %s)\n", passivemotion_seq[winIdx], passivemotion_x[winIdx], passivemotion_y[winIdx], mods );
200   }
201
202   glMatrixMode ( GL_PROJECTION );
203   glPopMatrix ();
204   glMatrixMode ( GL_MODELVIEW );
205   glPopMatrix ();
206   glEnable ( GL_DEPTH_TEST );
207
208   printf ( "%6d Window %d Display Callback\n",
209             ++sequence_number, window ) ;
210   glutSwapBuffers();
211 }
212
213 static void
214 Warning(const char *fmt, va_list ap)
215 {
216     printf("%6d Warning callback:\n");
217
218     /* print warning message */
219     vprintf(fmt, ap);
220 }
221
222 static void
223 Error(const char *fmt, va_list ap)
224 {
225     char dummy_string[STRING_LENGTH];
226     printf("%6d Error callback:\n");
227
228     /* print warning message */
229     vprintf(fmt, ap);
230
231     /* terminate program, after pause for input so user can see */
232     printf ( "Please enter something to exit: " );
233     fgets ( dummy_string, STRING_LENGTH, stdin );
234
235     /* Call exit directly as freeglut is messed
236      * up internally when an error is called. 
237      */
238     exit(1);
239 }
240
241 static void 
242 Reshape(int width, int height)
243 {
244   int winIdx;
245   int window = getWindowAndIdx(&winIdx);
246   printf ( "%6d Window %d Reshape Callback:  %d %d\n",
247             ++sequence_number, window, width, height ) ;
248   reshape_called[winIdx] = 1 ;
249   reshape_width[winIdx] = width ;
250   reshape_height[winIdx] = height ;
251   reshape_seq[winIdx] = sequence_number ;
252   glViewport(0,0,width,height);
253   glutPostRedisplay () ;
254 }
255
256 static void 
257 Position(int left, int top)
258 {
259   int winIdx;
260   int window = getWindowAndIdx(&winIdx);
261   printf ( "%6d Window %d Position Callback:  %d %d\n",
262             ++sequence_number, window, left, top ) ;
263   position_called[winIdx] = 1 ;
264   position_left[winIdx] = left ;
265   position_top[winIdx] = top ;
266   position_seq[winIdx] = sequence_number ;
267   glutPostRedisplay () ;
268 }
269
270 static void 
271 Key(unsigned char key, int x, int y)
272 {
273   int winIdx;
274   int window = getWindowAndIdx(&winIdx);
275   printf ( "%6d Window %d Keyboard Callback:  %d %d %d\n",
276             ++sequence_number, window, key, x, y ) ;
277   key_called[winIdx] = 1 ;
278   key_key[winIdx] = key ;
279   key_x[winIdx] = x ;
280   key_y[winIdx] = y ;
281   key_seq[winIdx] = sequence_number ;
282   key_mod[winIdx] = glutGetModifiers() ;
283   glutPostRedisplay () ;
284 }
285
286 static void 
287 KeyUp(unsigned char key, int x, int y)
288 {
289   int winIdx;
290   int window = getWindowAndIdx(&winIdx);
291   printf ( "%6d Window %d Key Release Callback:  %d %d %d\n",
292             ++sequence_number, window, key, x, y ) ;
293   keyup_called[winIdx] = 1 ;
294   keyup_key[winIdx] = key ;
295   keyup_x[winIdx] = x ;
296   keyup_y[winIdx] = y ;
297   keyup_seq[winIdx] = sequence_number ;
298   keyup_mod[winIdx] = glutGetModifiers() ;
299   glutPostRedisplay () ;
300 }
301
302 static void 
303 Special(int key, int x, int y)
304 {
305   int winIdx;
306   int window = getWindowAndIdx(&winIdx);
307   printf ( "%6d Window %d Special Key Callback:  %d %d %d\n",
308             ++sequence_number, window, key, x, y ) ;
309   special_called[winIdx] = 1 ;
310   special_key[winIdx] = key ;
311   special_x[winIdx] = x ;
312   special_y[winIdx] = y ;
313   special_seq[winIdx] = sequence_number ;
314   special_mod[winIdx] = glutGetModifiers() ;
315   glutPostRedisplay () ;
316 }
317
318 static void 
319 SpecialUp(int key, int x, int y)
320 {
321   int winIdx;
322   int window = getWindowAndIdx(&winIdx);
323   printf ( "%6d Window %d Special Key Release Callback:  %d %d %d\n",
324             ++sequence_number, window, key, x, y ) ;
325   specialup_called[winIdx] = 1 ;
326   specialup_key[winIdx] = key ;
327   specialup_x[winIdx] = x ;
328   specialup_y[winIdx] = y ;
329   specialup_seq[winIdx] = sequence_number ;
330   specialup_mod[winIdx] = glutGetModifiers() ;
331   glutPostRedisplay () ;
332 }
333
334 static void 
335 Joystick( unsigned int a, int b, int c, int d)  /* Need meaningful names */
336 {
337   int winIdx;
338   int window = getWindowAndIdx(&winIdx);
339   printf ( "%6d Window %d Joystick Callback:  %d %d %d %d\n",
340             ++sequence_number, window, a, b, c, d ) ;
341   joystick_called[winIdx] = 1 ;
342   joystick_a[winIdx] = a ;
343   joystick_b[winIdx] = b ;
344   joystick_c[winIdx] = c ;
345   joystick_d[winIdx] = d ;
346   joystick_seq[winIdx] = sequence_number ;
347   glutPostRedisplay () ;
348 }
349
350 static void 
351 Mouse(int button, int updown, int x, int y)
352 {
353   int winIdx;
354   int window = getWindowAndIdx(&winIdx);
355   printf ( "%6d Window %d Mouse Click Callback:  %d %d %d %d\n",
356             ++sequence_number, window, button, updown, x, y ) ;
357   mouse_called[winIdx] = 1 ;
358   mouse_button[winIdx] = button ;
359   mouse_updown[winIdx] = updown ;
360   mouse_x[winIdx] = x ;
361   mouse_y[winIdx] = y ;
362   mouse_seq[winIdx] = sequence_number ;
363   mouse_mod[winIdx] = glutGetModifiers() ;
364   glutPostRedisplay () ;
365 }
366
367 static void 
368 MouseWheel(int wheel_number, int direction, int x, int y)
369 {
370   int winIdx;
371   int window = getWindowAndIdx(&winIdx);
372   printf ( "%6d Window %d Mouse Wheel Callback:  %d %d %d %d\n",
373             ++sequence_number, window, wheel_number, direction, x, y ) ;
374   mousewheel_called[winIdx] = 1 ;
375   mousewheel_number[winIdx] = wheel_number ;
376   mousewheel_direction[winIdx] = direction ;
377   mousewheel_x[winIdx] = x ;
378   mousewheel_y[winIdx] = y ;
379   mousewheel_seq[winIdx] = sequence_number ;
380   mousewheel_mod[winIdx] = glutGetModifiers() ;
381   glutPostRedisplay () ;
382 }
383
384 static void 
385 Motion(int x, int y)
386 {
387   int winIdx;
388   int window = getWindowAndIdx(&winIdx);
389   printf ( "%6d Window %d Mouse Motion Callback:  %d %d\n",
390             ++sequence_number, window, x, y ) ;
391   motion_called[winIdx] = 1 ;
392   motion_x[winIdx] = x ;
393   motion_y[winIdx] = y ;
394   motion_seq[winIdx] = sequence_number ;
395   motion_mod[winIdx] = glutGetModifiers() ;
396   glutPostRedisplay () ;
397 }
398
399 static void 
400 PassiveMotion(int x, int y)
401 {
402   int winIdx;
403   int window = getWindowAndIdx(&winIdx);
404   printf ( "%6d Window %d Mouse Passive Motion Callback:  %d %d\n",
405             ++sequence_number, window, x, y ) ;
406   passivemotion_called[winIdx] = 1 ;
407   passivemotion_x[winIdx] = x ;
408   passivemotion_y[winIdx] = y ;
409   passivemotion_seq[winIdx] = sequence_number ;
410   passivemotion_mod[winIdx] = glutGetModifiers() ;
411   glutPostRedisplay () ;
412 }
413
414 static void 
415 Entry(int state)
416 {
417   int winIdx;
418   int window = getWindowAndIdx(&winIdx);
419   printf ( "%6d Window %d Entry Callback:  %d\n",
420             ++sequence_number, window, state ) ;
421   entry_called[winIdx] = 1 ;
422   entry_seq[winIdx] = sequence_number;
423   entry_state[winIdx] = state;
424   glutPostRedisplay () ;
425 }
426
427 static void 
428 Close(void)
429 {
430   int window = getWindowAndIdx(NULL);
431   printf ( "%6d Window %d Close Callback\n",
432             ++sequence_number, window ) ;
433 }
434
435 static void 
436 OverlayDisplay(void)
437 {
438   int window = getWindowAndIdx(NULL);
439   printf ( "%6d Window %d OverlayDisplay Callback\n",
440             ++sequence_number, window ) ;
441   glutPostRedisplay () ;
442 }
443
444 static void 
445 Visibility(int vis)
446 {
447   int winIdx;
448   int window = getWindowAndIdx(&winIdx);
449   printf ( "%6d Window %d Visibility Callback:  %d\n",
450             ++sequence_number, window, vis ) ;
451   visibility_called[winIdx] = 1 ;
452   visibility_vis[winIdx] = vis ;
453   visibility_seq[winIdx] = sequence_number ;
454   glutPostRedisplay () ;
455 }
456
457 static void 
458 WindowStatus(int state)
459 {
460   int winIdx;
461   int window = getWindowAndIdx(&winIdx);
462   printf ( "%6d Window %d WindowStatus Callback:  %d\n",
463             ++sequence_number, window, state ) ;
464   windowStatus_called[winIdx] = 1 ;
465   windowStatus_state[winIdx] = state ;
466   windowStatus_seq[winIdx] = sequence_number ;
467   glutPostRedisplay () ;
468 }
469
470 static void 
471 SpaceMotion(int x, int y, int z)
472 {
473   int window = getWindowAndIdx(NULL);
474   printf ( "%6d Window %d SpaceMotion Callback:  %d %d %d\n",
475             ++sequence_number, window, x, y, z ) ;
476   glutPostRedisplay () ;
477 }
478
479 static void 
480 SpaceRotation(int x, int y, int z)
481 {
482   int window = getWindowAndIdx(NULL);
483   printf ( "%6d Window %d SpaceRotation Callback:  %d %d %d\n",
484             ++sequence_number, window, x, y, z ) ;
485   glutPostRedisplay () ;
486 }
487
488 static void 
489 SpaceButton(int button, int updown)
490 {
491   int window = getWindowAndIdx(NULL);
492   printf ( "%6d Window %d SpaceButton Callback:  %d %d\n",
493             ++sequence_number, window, button, updown ) ;
494   glutPostRedisplay () ;
495 }
496
497 static void 
498 Dials(int x, int y)
499 {
500   int window = getWindowAndIdx(NULL);
501   printf ( "%6d Window %d Dials Callback:  %d %d\n",
502             ++sequence_number, window, x, y ) ;
503   glutPostRedisplay () ;
504 }
505
506 static void 
507 ButtonBox(int button, int updown)
508 {
509   int window = getWindowAndIdx(NULL);
510   printf ( "%6d Window %d ButtonBox Callback:  %d %d\n",
511             ++sequence_number, window, button, updown ) ;
512   glutPostRedisplay () ;
513 }
514
515 static void 
516 TabletMotion(int x, int y)
517 {
518   int window = getWindowAndIdx(NULL);
519   printf ( "%6d Window %d TabletMotion Callback:  %d %d\n",
520             ++sequence_number, window, x, y ) ;
521   glutPostRedisplay () ;
522 }
523
524 static void 
525 TabletButton(int button, int updown, int x, int y)
526 {
527   int window = getWindowAndIdx(NULL);
528   printf ( "%6d Window %d TabletButton Callback:  %d %d %d %d\n",
529             ++sequence_number, window, button, updown, x, y ) ;
530   glutPostRedisplay () ;
531 }
532
533 static void
534 MenuCallback ( int value )
535 {
536   int menu = glutGetMenu();
537   int window = getWindowAndIdx(NULL);
538   printf( "%6d Menu %d MenuCallback for menu opened in Window %d - value is %d\n",
539           ++sequence_number, menu, window, value );
540 }
541
542 static void 
543 MenuDestroy( void )
544 {
545   int menu = glutGetMenu();
546   menudestroy_called = 1 ;
547   printf ( "%6d Menu %d MenuDestroy Callback\n",
548             ++sequence_number, menu ) ;
549 }
550
551 static void 
552 MenuStatus( int status, int x, int y )
553 {
554   /* Menu and window for which this event is triggered are current when the callback is called */
555   int menu = glutGetMenu();
556   int window = getWindowAndIdx(NULL);
557   menustatus_called = 1 ;
558   printf ( "%6d Menu %d MenuStatus Callback in Window %d:  %d %d %d\n",
559             ++sequence_number, menu, window, status, x, y ) ;
560   glutPostRedisplay () ;
561 }
562
563
564 static void 
565 MenuState( int status )
566 {
567   /* Menu and window for which this event is triggered are current when the callback is called */
568   int menu = glutGetMenu();
569   int window = getWindowAndIdx(NULL);
570   menustate_called = 1 ;
571   printf ( "%6d Menu %d MenuState Callback in Window %d:  %d\n",
572             ++sequence_number, menu, window, status) ;
573   glutPostRedisplay () ;
574 }
575
576 static void Idle ( void )
577 {
578   ++sequence_number ;
579 }
580
581 static void SetWindowCallbacks( int first )
582 {
583     /* All these callbacks are set for only the current window */
584     glutDisplayFunc( Display );
585     glutReshapeFunc( Reshape );
586     glutPositionFunc( Position );
587     glutKeyboardFunc( Key );
588     glutSpecialFunc( Special );
589     glutKeyboardUpFunc( KeyUp );
590     glutSpecialUpFunc( SpecialUp );
591     if (first)
592         glutJoystickFunc( Joystick, 100 );
593     glutMouseFunc ( Mouse ) ;
594     glutMouseWheelFunc ( MouseWheel ) ;
595     glutMotionFunc ( Motion ) ;
596     glutPassiveMotionFunc ( PassiveMotion ) ;
597     glutEntryFunc ( Entry ) ;
598     glutCloseFunc ( Close ) ;
599     glutOverlayDisplayFunc ( OverlayDisplay ) ;
600     glutSpaceballMotionFunc ( SpaceMotion ) ;
601     glutSpaceballRotateFunc ( SpaceRotation ) ;
602     glutSpaceballButtonFunc ( SpaceButton ) ;
603     glutButtonBoxFunc ( ButtonBox ) ;
604     glutDialsFunc ( Dials ) ;
605     glutTabletMotionFunc ( TabletMotion ) ;
606     glutTabletButtonFunc ( TabletButton ) ;
607     /* glutVisibilityFunc is deprecated in favor of glutWindowStatusFunc, which provides more detail.
608      * Setting one of these overwrites the other (see docs).
609      */
610     glutVisibilityFunc ( Visibility );  /* This will thus never be called, as glutWindowStatusFunc is set afterwards */
611     glutWindowStatusFunc ( WindowStatus ) ;
612 }
613
614 int 
615 main(int argc, char *argv[])
616 {
617   char dummy_string[STRING_LENGTH];
618
619   int menuID, subMenuA, subMenuB;
620
621   glutInitWarningFunc(Warning);
622   glutInitErrorFunc(Error);
623   glutInitWindowSize(500, 250);
624   glutInitWindowPosition ( 140, 140 );
625   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE );
626   glutInit(&argc, argv);
627   /* global setting: mainloop does not return when a window is closed, only returns when all windows are closed */
628   glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_CONTINUE_EXECUTION);
629   /* global setting: repeated keys generating by keeping the key pressed down are passed on to the keyboard callback */
630   /* There are two functions to control this behavior, glutSetKeyRepeat to set it globally, and glutIgnoreKeyRepeat to set it per window.
631    * These two interact however. If key repeat is globally switched off (glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF)), it cannot be overridden
632    * (switched back on) for a specific window with glutIgnoreKeyRepeat. However, if key repeat is globally switched on
633    * (glutSetKeyRepeat(GLUT_KEY_REPEAT_ON)), it can be overridden (switched off) with glutIgnoreKeyRepeat on a per-window basis. That is
634    * what we demonstrate here.
635    */
636   glutSetKeyRepeat(GLUT_KEY_REPEAT_ON);
637
638   /* Set other global callback (global as in not associated with any specific menu or window) */
639   glutIdleFunc ( Idle );
640   glutMenuStatusFunc ( MenuStatus );
641   glutMenuStateFunc  ( MenuState ); /* Note that glutMenuStatusFunc is an enhanced version of the deprecated glutMenuStateFunc. */
642
643
644   /* Open first window */
645   windows[0] = glutCreateWindow( "Callback Demo" );
646   printf ( "Creating window %d as 'Callback Demo'\n", windows[0] ) ;
647
648   glClearColor(1.0, 1.0, 1.0, 1.0);
649
650   /* callbacks, settings and menus for this window */
651   SetWindowCallbacks( 1 );
652   glutIgnoreKeyRepeat(GL_TRUE);
653   glutSetIconTitle("Icon Test - Callback Demo");
654
655   subMenuA = glutCreateMenu( MenuCallback );
656   glutAddMenuEntry( "Sub menu A1 (01)", 11 );
657   glutAddMenuEntry( "Sub menu A2 (02)", 12 );
658   glutAddMenuEntry( "Sub menu A3 (03)", 13 );
659   glutMenuDestroyFunc ( MenuDestroy );  /* callback specific to this menu */
660
661   subMenuB = glutCreateMenu( MenuCallback );
662   glutAddMenuEntry( "Sub menu B1 (04)", 14 );
663   glutAddMenuEntry( "Sub menu B2 (05)", 15 );
664   glutAddMenuEntry( "Sub menu B3 (06)", 16 );
665   glutAddSubMenu( "Going to sub menu A", subMenuA );
666   glutMenuDestroyFunc ( MenuDestroy );  /* callback specific to this menu */
667
668   menuID = glutCreateMenu( MenuCallback );
669   glutAddMenuEntry( "Entry one",   21 );
670   glutAddMenuEntry( "Entry two",   22 );
671   glutAddMenuEntry( "Entry three", 23 );
672   glutAddMenuEntry( "Entry four",  24 );
673   glutAddMenuEntry( "Entry five",  25 );
674   glutAddSubMenu( "Enter sub menu A", subMenuA );
675   glutAddSubMenu( "Enter sub menu B", subMenuB );
676   glutMenuDestroyFunc ( MenuDestroy );  /* callback specific to this menu */
677
678   glutAttachMenu( GLUT_LEFT_BUTTON );
679
680
681   /* Position second window right next to the first */
682   glutInitWindowPosition ( 140+500+2*glutGet(GLUT_WINDOW_BORDER_WIDTH), 140 );
683   glutInitWindowSize(600, 600);
684   windows[1] = glutCreateWindow( "Second Window" );
685   printf ( "Creating window %d as 'Second Window'\n", windows[1] ) ;
686
687   glClearColor(1.0, 1.0, 1.0, 1.0);
688
689   /* callbacks, settings and menus for this window */
690   SetWindowCallbacks( 0 );
691   glutIgnoreKeyRepeat(GL_TRUE);
692
693   glutSetMenu(subMenuB);
694   glutAttachMenu( GLUT_RIGHT_BUTTON );
695
696
697   /* position a third window as a subwindow of the second */
698   windows[2] = glutCreateSubWindow(windows[1],0,300,600,300);
699   printf ( "Creating window %d as subwindow to 'Second Window'\n", windows[2] ) ;
700
701   glClearColor(0.7f, 0.7f, 0.7f, 1.0);
702
703   /* callbacks, settings and menus for this window */
704   SetWindowCallbacks( 0 );
705   glutSetCursor(GLUT_CURSOR_CROSSHAIR); /* Cursors are per window */
706
707   glutSetMenu(subMenuA);
708   glutAttachMenu( GLUT_RIGHT_BUTTON );
709
710
711   /* position a fourth window as a subsubwindow (grandchild) of the second */
712   windows[3] = glutCreateSubWindow(windows[2],300,0,300,300);
713   printf ( "Creating window %d as subsubwindow to 'Second Window'\n", windows[3] ) ;
714
715   glClearColor(0.4f, 0.4f, 0.4f, 1.0);
716
717   /* callbacks and menus for this window */
718   SetWindowCallbacks( 0 );
719   glutSetCursor(GLUT_CURSOR_INHERIT);   /* Inherit cursor look from parent (this is default on window creation) - comment the below to see in action */
720   glutSetCursor(GLUT_CURSOR_CYCLE);
721
722
723   printf ( "Please enter something to continue: " );
724   fgets ( dummy_string, STRING_LENGTH, stdin );
725
726   glutMainLoop();
727
728   printf ( "Back from the 'freeglut' main loop\n" ) ;
729
730   return EXIT_SUCCESS;
731 }