3 * Program to invoke all the callbacks that "freeglut" supports
7 #include <GL/freeglut.h>
12 static int sequence_number = 0 ;
14 #define CALLBACKMAKER_N_WINDOWS 4
15 int windows[CALLBACKMAKER_N_WINDOWS] = {0};
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_4V(key,key,x,y,mod);
29 CALLBACK_4V(keyup,key,x,y,mod);
30 CALLBACK_4V(special,key,x,y,mod);
31 CALLBACK_4V(specialup,key,x,y,mod);
32 CALLBACK_4V(joystick,a,b,c,d);
33 CALLBACK_5V(mouse,button,updown,x,y,mod);
34 CALLBACK_5V(mousewheel,number,direction,x,y,mod);
35 CALLBACK_3V(motion,x,y,mod);
36 CALLBACK_3V(passivemotion,x,y,mod);
37 CALLBACK_1V(entry,state);
39 /* menudestroy is registered on each menu, not a window */
40 int menudestroy_called = 0 ;
41 /* menustatus and menustate are global callbacks, set for all menus at the same time */
42 int menustatus_called = 0;
43 int menustate_called = 0;
45 #define STRING_LENGTH 10
48 bitmapPrintf (const char *fmt, ...)
54 #if defined(WIN32) && !defined(__CYGWIN__)
55 (void) _vsnprintf (buf, sizeof(buf), fmt, args);
57 (void) vsnprintf (buf, sizeof(buf), fmt, args);
60 glutBitmapString ( GLUT_BITMAP_HELVETICA_12, (unsigned char*)buf ) ;
64 getWindowAndIdx(int *winIdx)
66 int window = glutGetWindow();
69 (*winIdx) = window==windows[0] ? 0 :
70 window==windows[1] ? 1 :
71 window==windows[2] ? 2 : 3;
77 Mod2Text(int mods, char *text)
79 if (mods&GLUT_ACTIVE_CTRL)
81 if (mods&GLUT_ACTIVE_SHIFT)
83 strcat(text,"+SHIFT");
86 if (mods&GLUT_ACTIVE_ALT)
100 int window = getWindowAndIdx(&winIdx);
101 glClear ( GL_COLOR_BUFFER_BIT );
103 glDisable ( GL_DEPTH_TEST );
104 glMatrixMode ( GL_PROJECTION );
107 glOrtho(0, glutGet ( GLUT_WINDOW_WIDTH ),
108 0, glutGet ( GLUT_WINDOW_HEIGHT ), -1, 1 );
109 glMatrixMode ( GL_MODELVIEW );
112 glColor3ub ( 0, 0, 0 );
113 glRasterPos2i ( 10, glutGet ( GLUT_WINDOW_HEIGHT ) - 20 ); /* 10pt margin above 10pt letters */
115 if ( entry_called[winIdx] )
117 bitmapPrintf ( "Entry %d: %d\n", entry_seq[winIdx], entry_state[winIdx] );
120 if ( visibility_called[winIdx] )
122 bitmapPrintf ( "Visibility %d: %d\n", visibility_seq[winIdx], visibility_vis[winIdx] );
125 if ( reshape_called[winIdx] )
127 bitmapPrintf ( "Reshape %d: %d %d\n", reshape_seq[winIdx], reshape_width[winIdx], reshape_height[winIdx] );
130 if ( position_called[winIdx] )
132 bitmapPrintf ( "Position %d: %d %d\n", position_seq[winIdx], position_left[winIdx], position_top[winIdx] );
135 if ( key_called[winIdx] )
138 Mod2Text(key_mod[winIdx],mods);
139 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 );
142 if ( keyup_called[winIdx] )
145 Mod2Text(keyup_mod[winIdx],mods);
146 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 );
149 if ( special_called[winIdx] )
152 Mod2Text(special_mod[winIdx],mods);
153 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 );
156 if ( specialup_called[winIdx] )
159 Mod2Text(specialup_mod[winIdx],mods);
160 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 );
163 if ( joystick_called[winIdx] )
165 bitmapPrintf ( "Joystick %d: %d %d %d %d\n", joystick_seq[winIdx], joystick_a[winIdx], joystick_b[winIdx], joystick_c[winIdx], joystick_d[winIdx] );
168 if ( mouse_called[winIdx] )
171 Mod2Text(mouse_mod[winIdx],mods);
172 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 );
175 if ( mousewheel_called[winIdx] )
178 Mod2Text(mousewheel_mod[winIdx],mods);
179 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 );
182 if ( motion_called[winIdx] )
185 Mod2Text(motion_mod[winIdx],mods);
186 bitmapPrintf ( "Motion %d: %d %d (mod: %s)\n", motion_seq[winIdx], motion_x[winIdx], motion_y[winIdx], mods );
189 if ( passivemotion_called[winIdx] )
192 Mod2Text(passivemotion_mod[winIdx],mods);
193 bitmapPrintf ( "Passive Motion %d: %d %d (mod: %s)\n", passivemotion_seq[winIdx], passivemotion_x[winIdx], passivemotion_y[winIdx], mods );
196 glMatrixMode ( GL_PROJECTION );
198 glMatrixMode ( GL_MODELVIEW );
200 glEnable ( GL_DEPTH_TEST );
202 printf ( "%6d Window %d Display Callback\n",
203 ++sequence_number, window ) ;
208 Warning(const char *fmt, va_list ap)
210 printf("%6d Warning callback:\n");
212 /* print warning message */
217 Error(const char *fmt, va_list ap)
219 char dummy_string[STRING_LENGTH];
220 printf("%6d Error callback:\n");
222 /* print warning message */
225 /* terminate program, after pause for input so user can see */
226 printf ( "Please enter something to exit: " );
227 fgets ( dummy_string, STRING_LENGTH, stdin );
229 /* Call exit directly as freeglut is messed
230 * up internally when an error is called.
239 int window = getWindowAndIdx(&winIdx);
240 printf ( "%6d Window %d Visibility Callback: %d\n",
241 ++sequence_number, window, vis ) ;
242 visibility_called[winIdx] = 1 ;
243 visibility_vis[winIdx] = vis ;
244 visibility_seq[winIdx] = sequence_number ;
245 glutPostRedisplay () ;
249 Reshape(int width, int height)
252 int window = getWindowAndIdx(&winIdx);
253 printf ( "%6d Window %d Reshape Callback: %d %d\n",
254 ++sequence_number, window, width, height ) ;
255 reshape_called[winIdx] = 1 ;
256 reshape_width[winIdx] = width ;
257 reshape_height[winIdx] = height ;
258 reshape_seq[winIdx] = sequence_number ;
259 glViewport(0,0,width,height);
260 glutPostRedisplay () ;
264 Position(int left, int top)
267 int window = getWindowAndIdx(&winIdx);
268 printf ( "%6d Window %d Position Callback: %d %d\n",
269 ++sequence_number, window, left, top ) ;
270 position_called[winIdx] = 1 ;
271 position_left[winIdx] = left ;
272 position_top[winIdx] = top ;
273 position_seq[winIdx] = sequence_number ;
274 glutPostRedisplay () ;
278 Key(unsigned char key, int x, int y)
281 int window = getWindowAndIdx(&winIdx);
282 printf ( "%6d Window %d Keyboard Callback: %d %d %d\n",
283 ++sequence_number, window, key, x, y ) ;
284 key_called[winIdx] = 1 ;
285 key_key[winIdx] = key ;
288 key_seq[winIdx] = sequence_number ;
289 key_mod[winIdx] = glutGetModifiers() ;
290 glutPostRedisplay () ;
294 KeyUp(unsigned char key, int x, int y)
297 int window = getWindowAndIdx(&winIdx);
298 printf ( "%6d Window %d Key Release Callback: %d %d %d\n",
299 ++sequence_number, window, key, x, y ) ;
300 keyup_called[winIdx] = 1 ;
301 keyup_key[winIdx] = key ;
302 keyup_x[winIdx] = x ;
303 keyup_y[winIdx] = y ;
304 keyup_seq[winIdx] = sequence_number ;
305 keyup_mod[winIdx] = glutGetModifiers() ;
306 glutPostRedisplay () ;
310 Special(int key, int x, int y)
313 int window = getWindowAndIdx(&winIdx);
314 printf ( "%6d Window %d Special Key Callback: %d %d %d\n",
315 ++sequence_number, window, key, x, y ) ;
316 special_called[winIdx] = 1 ;
317 special_key[winIdx] = key ;
318 special_x[winIdx] = x ;
319 special_y[winIdx] = y ;
320 special_seq[winIdx] = sequence_number ;
321 special_mod[winIdx] = glutGetModifiers() ;
322 glutPostRedisplay () ;
326 SpecialUp(int key, int x, int y)
329 int window = getWindowAndIdx(&winIdx);
330 printf ( "%6d Window %d Special Key Release Callback: %d %d %d\n",
331 ++sequence_number, window, key, x, y ) ;
332 specialup_called[winIdx] = 1 ;
333 specialup_key[winIdx] = key ;
334 specialup_x[winIdx] = x ;
335 specialup_y[winIdx] = y ;
336 specialup_seq[winIdx] = sequence_number ;
337 specialup_mod[winIdx] = glutGetModifiers() ;
338 glutPostRedisplay () ;
342 Joystick( unsigned int a, int b, int c, int d) /* Need meaningful names */
345 int window = getWindowAndIdx(&winIdx);
346 printf ( "%6d Window %d Joystick Callback: %d %d %d %d\n",
347 ++sequence_number, window, a, b, c, d ) ;
348 joystick_called[winIdx] = 1 ;
349 joystick_a[winIdx] = a ;
350 joystick_b[winIdx] = b ;
351 joystick_c[winIdx] = c ;
352 joystick_d[winIdx] = d ;
353 joystick_seq[winIdx] = sequence_number ;
354 glutPostRedisplay () ;
358 Mouse(int button, int updown, int x, int y)
361 int window = getWindowAndIdx(&winIdx);
362 printf ( "%6d Window %d Mouse Click Callback: %d %d %d %d\n",
363 ++sequence_number, window, button, updown, x, y ) ;
364 mouse_called[winIdx] = 1 ;
365 mouse_button[winIdx] = button ;
366 mouse_updown[winIdx] = updown ;
367 mouse_x[winIdx] = x ;
368 mouse_y[winIdx] = y ;
369 mouse_seq[winIdx] = sequence_number ;
370 mouse_mod[winIdx] = glutGetModifiers() ;
371 glutPostRedisplay () ;
375 MouseWheel(int wheel_number, int direction, int x, int y)
378 int window = getWindowAndIdx(&winIdx);
379 printf ( "%6d Window %d Mouse Wheel Callback: %d %d %d %d\n",
380 ++sequence_number, window, wheel_number, direction, x, y ) ;
381 mousewheel_called[winIdx] = 1 ;
382 mousewheel_number[winIdx] = wheel_number ;
383 mousewheel_direction[winIdx] = direction ;
384 mousewheel_x[winIdx] = x ;
385 mousewheel_y[winIdx] = y ;
386 mousewheel_seq[winIdx] = sequence_number ;
387 mousewheel_mod[winIdx] = glutGetModifiers() ;
388 glutPostRedisplay () ;
395 int window = getWindowAndIdx(&winIdx);
396 printf ( "%6d Window %d Mouse Motion Callback: %d %d\n",
397 ++sequence_number, window, x, y ) ;
398 motion_called[winIdx] = 1 ;
399 motion_x[winIdx] = x ;
400 motion_y[winIdx] = y ;
401 motion_seq[winIdx] = sequence_number ;
402 motion_mod[winIdx] = glutGetModifiers() ;
403 glutPostRedisplay () ;
407 PassiveMotion(int x, int y)
410 int window = getWindowAndIdx(&winIdx);
411 printf ( "%6d Window %d Mouse Passive Motion Callback: %d %d\n",
412 ++sequence_number, window, x, y ) ;
413 passivemotion_called[winIdx] = 1 ;
414 passivemotion_x[winIdx] = x ;
415 passivemotion_y[winIdx] = y ;
416 passivemotion_seq[winIdx] = sequence_number ;
417 passivemotion_mod[winIdx] = glutGetModifiers() ;
418 glutPostRedisplay () ;
425 int window = getWindowAndIdx(&winIdx);
426 printf ( "%6d Window %d Entry Callback: %d\n",
427 ++sequence_number, window, state ) ;
428 entry_called[winIdx] = 1 ;
429 entry_seq[winIdx] = sequence_number;
430 entry_state[winIdx] = state;
431 glutPostRedisplay () ;
437 int window = getWindowAndIdx(NULL);
438 printf ( "%6d Window %d Close Callback\n",
439 ++sequence_number, window ) ;
445 int window = getWindowAndIdx(NULL);
446 printf ( "%6d Window %d OverlayDisplay Callback\n",
447 ++sequence_number, window ) ;
448 glutPostRedisplay () ;
452 WindowStatus(int state)
454 int window = getWindowAndIdx(NULL);
455 printf ( "%6d Window %d WindowStatus Callback: %d\n",
456 ++sequence_number, window, state ) ;
457 glutPostRedisplay () ;
461 SpaceMotion(int x, int y, int z)
463 int window = getWindowAndIdx(NULL);
464 printf ( "%6d Window %d SpaceMotion Callback: %d %d %d\n",
465 ++sequence_number, window, x, y, z ) ;
466 glutPostRedisplay () ;
470 SpaceRotation(int x, int y, int z)
472 int window = getWindowAndIdx(NULL);
473 printf ( "%6d Window %d SpaceRotation Callback: %d %d %d\n",
474 ++sequence_number, window, x, y, z ) ;
475 glutPostRedisplay () ;
479 SpaceButton(int button, int updown)
481 int window = getWindowAndIdx(NULL);
482 printf ( "%6d Window %d SpaceButton Callback: %d %d\n",
483 ++sequence_number, window, button, updown ) ;
484 glutPostRedisplay () ;
490 int window = getWindowAndIdx(NULL);
491 printf ( "%6d Window %d Dials Callback: %d %d\n",
492 ++sequence_number, window, x, y ) ;
493 glutPostRedisplay () ;
497 ButtonBox(int button, int updown)
499 int window = getWindowAndIdx(NULL);
500 printf ( "%6d Window %d ButtonBox Callback: %d %d\n",
501 ++sequence_number, window, button, updown ) ;
502 glutPostRedisplay () ;
506 TabletMotion(int x, int y)
508 int window = getWindowAndIdx(NULL);
509 printf ( "%6d Window %d TabletMotion Callback: %d %d\n",
510 ++sequence_number, window, x, y ) ;
511 glutPostRedisplay () ;
515 TabletButton(int button, int updown, int x, int y)
517 int window = getWindowAndIdx(NULL);
518 printf ( "%6d Window %d TabletButton Callback: %d %d %d %d\n",
519 ++sequence_number, window, button, updown, x, y ) ;
520 glutPostRedisplay () ;
524 MenuCallback ( int value )
526 int menu = glutGetMenu();
527 int window = getWindowAndIdx(NULL);
528 printf( "%6d Menu %d MenuCallback for menu opened in Window %d - value is %d\n",
529 ++sequence_number, menu, window, value );
535 int menu = glutGetMenu();
536 menudestroy_called = 1 ;
537 printf ( "%6d Menu %d MenuDestroy Callback\n",
538 ++sequence_number, menu ) ;
542 MenuStatus( int status, int x, int y )
544 /* Menu and window for which this event is triggered are current when the callback is called */
545 int menu = glutGetMenu();
546 int window = getWindowAndIdx(NULL);
547 menustatus_called = 1 ;
548 printf ( "%6d Menu %d MenuStatus Callback in Window %d: %d %d %d\n",
549 ++sequence_number, menu, window, status, x, y ) ;
550 glutPostRedisplay () ;
555 MenuState( int status )
557 /* Menu and window for which this event is triggered are current when the callback is called */
558 int menu = glutGetMenu();
559 int window = getWindowAndIdx(NULL);
560 menustate_called = 1 ;
561 printf ( "%6d Menu %d MenuState Callback in Window %d: %d\n",
562 ++sequence_number, menu, window, status) ;
563 glutPostRedisplay () ;
566 static void Idle ( void )
571 static void SetWindowCallbacks( int first )
573 /* All these callbacks are set for only the current window */
574 glutDisplayFunc( Display );
575 glutReshapeFunc( Reshape );
576 glutPositionFunc( Position );
577 glutKeyboardFunc( Key );
578 glutSpecialFunc( Special );
579 glutVisibilityFunc( Visibility );
580 glutKeyboardUpFunc( KeyUp );
581 glutSpecialUpFunc( SpecialUp );
583 glutJoystickFunc( Joystick, 100 );
584 glutMouseFunc ( Mouse ) ;
585 glutMouseWheelFunc ( MouseWheel ) ;
586 glutMotionFunc ( Motion ) ;
587 glutPassiveMotionFunc ( PassiveMotion ) ;
588 glutEntryFunc ( Entry ) ;
589 glutCloseFunc ( Close ) ;
590 glutOverlayDisplayFunc ( OverlayDisplay ) ;
591 glutWindowStatusFunc ( WindowStatus ) ;
592 glutSpaceballMotionFunc ( SpaceMotion ) ;
593 glutSpaceballRotateFunc ( SpaceRotation ) ;
594 glutSpaceballButtonFunc ( SpaceButton ) ;
595 glutButtonBoxFunc ( ButtonBox ) ;
596 glutDialsFunc ( Dials ) ;
597 glutTabletMotionFunc ( TabletMotion ) ;
598 glutTabletButtonFunc ( TabletButton ) ;
602 main(int argc, char *argv[])
604 char dummy_string[STRING_LENGTH];
606 int menuID, subMenuA, subMenuB;
608 glutInitWarningFunc(Warning);
609 glutInitErrorFunc(Error);
610 glutInitWindowSize(500, 250);
611 glutInitWindowPosition ( 140, 140 );
612 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE );
613 glutInit(&argc, argv);
614 /* global setting: mainloop does not return when a window is closed, only returns when all windows are closed */
615 glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_CONTINUE_EXECUTION);
616 /* global setting: repeated keys generating by keeping the key pressed down are passed on to the keyboard callback */
617 /* There are two functions to control this behavior, glutSetKeyRepeat to set it globally, and glutIgnoreKeyRepeat to set it per window.
618 * These two interact however. If key repeat is globally switched off (glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF)), it cannot be overridden
619 * (switched back on) for a specific window with glutIgnoreKeyRepeat. However, if key repeat is globally switched on
620 * (glutSetKeyRepeat(GLUT_KEY_REPEAT_ON)), it can be overridden (switched off) with glutIgnoreKeyRepeat on a per-window basis. That is
621 * what we demonstrate here.
623 glutSetKeyRepeat(GLUT_KEY_REPEAT_ON);
625 /* Set other global callback (global as in not associated with any specific menu or window) */
626 glutIdleFunc ( Idle );
627 glutMenuStatusFunc ( MenuStatus );
628 glutMenuStateFunc ( MenuState ); /* Note that glutMenuStatusFunc is an enhanced version of the deprecated glutMenuStateFunc. */
631 /* Open first window */
632 windows[0] = glutCreateWindow( "Callback Demo" );
633 printf ( "Creating window %d as 'Callback Demo'\n", windows[0] ) ;
635 glClearColor(1.0, 1.0, 1.0, 1.0);
637 /* callbacks, settings and menus for this window */
638 SetWindowCallbacks( 1 );
639 glutIgnoreKeyRepeat(GL_TRUE);
641 subMenuA = glutCreateMenu( MenuCallback );
642 glutAddMenuEntry( "Sub menu A1 (01)", 11 );
643 glutAddMenuEntry( "Sub menu A2 (02)", 12 );
644 glutAddMenuEntry( "Sub menu A3 (03)", 13 );
645 glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */
647 subMenuB = glutCreateMenu( MenuCallback );
648 glutAddMenuEntry( "Sub menu B1 (04)", 14 );
649 glutAddMenuEntry( "Sub menu B2 (05)", 15 );
650 glutAddMenuEntry( "Sub menu B3 (06)", 16 );
651 glutAddSubMenu( "Going to sub menu A", subMenuA );
652 glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */
654 menuID = glutCreateMenu( MenuCallback );
655 glutAddMenuEntry( "Entry one", 21 );
656 glutAddMenuEntry( "Entry two", 22 );
657 glutAddMenuEntry( "Entry three", 23 );
658 glutAddMenuEntry( "Entry four", 24 );
659 glutAddMenuEntry( "Entry five", 25 );
660 glutAddSubMenu( "Enter sub menu A", subMenuA );
661 glutAddSubMenu( "Enter sub menu B", subMenuB );
662 glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */
664 glutAttachMenu( GLUT_LEFT_BUTTON );
667 /* Position second window right next to the first */
668 glutInitWindowPosition ( 140+500+2*glutGet(GLUT_WINDOW_BORDER_WIDTH), 140 );
669 glutInitWindowSize(600, 600);
670 windows[1] = glutCreateWindow( "Second Window" );
671 printf ( "Creating window %d as 'Second Window'\n", windows[1] ) ;
673 glClearColor(1.0, 1.0, 1.0, 1.0);
675 /* callbacks, settings and menus for this window */
676 SetWindowCallbacks( 0 );
677 glutIgnoreKeyRepeat(GL_TRUE);
679 glutSetMenu(subMenuB);
680 glutAttachMenu( GLUT_RIGHT_BUTTON );
683 /* position a third window as a subwindow of the second */
684 windows[2] = glutCreateSubWindow(windows[1],0,300,600,300);
685 printf ( "Creating window %d as subwindow to 'Second Window'\n", windows[2] ) ;
687 glClearColor(0.7f, 0.7f, 0.7f, 1.0);
689 /* callbacks and menus for this window */
690 SetWindowCallbacks( 0 );
692 glutSetMenu(subMenuA);
693 glutAttachMenu( GLUT_RIGHT_BUTTON );
696 /* position a fourth window as a subsubwindow (grandchild) of the second */
697 windows[3] = glutCreateSubWindow(windows[2],300,0,300,300);
698 printf ( "Creating window %d as subsubwindow to 'Second Window'\n", windows[3] ) ;
700 glClearColor(0.4f, 0.4f, 0.4f, 1.0);
702 /* callbacks and menus for this window */
703 SetWindowCallbacks( 0 );
706 printf ( "Please enter something to continue: " );
707 fgets ( dummy_string, STRING_LENGTH, stdin );
711 printf ( "Back from the 'freeglut' main loop\n" ) ;