+ int window = getWindowAndIdx(NULL);
+ printf ( "%6d Window %d OverlayDisplay Callback\n",
+ ++sequence_number, window ) ;
+ glutPostRedisplay () ;
+}
+
+static void
+Visibility(int vis)
+{
+ int winIdx;
+ int window = getWindowAndIdx(&winIdx);
+ printf ( "%6d Window %d Visibility Callback: %d\n",
+ ++sequence_number, window, vis ) ;
+ visibility_called[winIdx] = 1 ;
+ visibility_vis[winIdx] = vis ;
+ visibility_seq[winIdx] = sequence_number ;
+ glutPostRedisplay () ;
+}
+
+static void
+WindowStatus(int state)
+{
+ int winIdx;
+ int window = getWindowAndIdx(&winIdx);
+ printf ( "%6d Window %d WindowStatus Callback: %d\n",
+ ++sequence_number, window, state ) ;
+ windowStatus_called[winIdx] = 1 ;
+ windowStatus_state[winIdx] = state ;
+ windowStatus_seq[winIdx] = sequence_number ;
+ glutPostRedisplay () ;
+}
+
+static void
+SpaceMotion(int x, int y, int z)
+{
+ int window = getWindowAndIdx(NULL);
+ printf ( "%6d Window %d SpaceMotion Callback: %d %d %d\n",
+ ++sequence_number, window, x, y, z ) ;
+ glutPostRedisplay () ;
+}
+
+static void
+SpaceRotation(int x, int y, int z)
+{
+ int window = getWindowAndIdx(NULL);
+ printf ( "%6d Window %d SpaceRotation Callback: %d %d %d\n",
+ ++sequence_number, window, x, y, z ) ;
+ glutPostRedisplay () ;
+}
+
+static void
+SpaceButton(int button, int updown)
+{
+ int window = getWindowAndIdx(NULL);
+ printf ( "%6d Window %d SpaceButton Callback: %d %d\n",
+ ++sequence_number, window, button, updown ) ;
+ glutPostRedisplay () ;
+}
+
+static void
+Dials(int x, int y)
+{
+ int window = getWindowAndIdx(NULL);
+ printf ( "%6d Window %d Dials Callback: %d %d\n",
+ ++sequence_number, window, x, y ) ;
+ glutPostRedisplay () ;
+}
+
+static void
+ButtonBox(int button, int updown)
+{
+ int window = getWindowAndIdx(NULL);
+ printf ( "%6d Window %d ButtonBox Callback: %d %d\n",
+ ++sequence_number, window, button, updown ) ;
+ glutPostRedisplay () ;
+}
+
+static void
+TabletMotion(int x, int y)
+{
+ int window = getWindowAndIdx(NULL);
+ printf ( "%6d Window %d TabletMotion Callback: %d %d\n",
+ ++sequence_number, window, x, y ) ;
+ glutPostRedisplay () ;
+}
+
+static void
+TabletButton(int button, int updown, int x, int y)
+{
+ int window = getWindowAndIdx(NULL);
+ printf ( "%6d Window %d TabletButton Callback: %d %d %d %d\n",
+ ++sequence_number, window, button, updown, x, y ) ;
+ glutPostRedisplay () ;
+}
+
+static void
+MenuCallback ( int value )
+{
+ int menu = glutGetMenu();
+ int window = getWindowAndIdx(NULL);
+ printf( "%6d Menu %d MenuCallback for menu opened in Window %d - value is %d\n",
+ ++sequence_number, menu, window, value );
+}
+
+static void
+MenuDestroy( void )
+{
+ int menu = glutGetMenu();
+ menudestroy_called = 1 ;
+ printf ( "%6d Menu %d MenuDestroy Callback\n",
+ ++sequence_number, menu ) ;
+}
+
+static void
+MenuStatus( int status, int x, int y )
+{
+ /* Menu and window for which this event is triggered are current when the callback is called */
+ int menu = glutGetMenu();
+ int window = getWindowAndIdx(NULL);
+ menustatus_called = 1 ;
+ printf ( "%6d Menu %d MenuStatus Callback in Window %d: %d %d %d\n",
+ ++sequence_number, menu, window, status, x, y ) ;
+ glutPostRedisplay () ;
+}
+
+
+static void
+MenuState( int status )
+{
+ /* Menu and window for which this event is triggered are current when the callback is called */
+ int menu = glutGetMenu();
+ int window = getWindowAndIdx(NULL);
+ menustate_called = 1 ;
+ printf ( "%6d Menu %d MenuState Callback in Window %d: %d\n",
+ ++sequence_number, menu, window, status) ;
+ glutPostRedisplay () ;
+}
+
+static void Idle ( void )
+{
+ ++sequence_number ;
+}
+
+static void SetWindowCallbacks( int first )
+{
+ /* All these callbacks are set for only the current window */
+ glutDisplayFunc( Display );
+ glutReshapeFunc( Reshape );
+ glutPositionFunc( Position );
+ glutKeyboardFunc( Key );
+ glutSpecialFunc( Special );
+ glutKeyboardUpFunc( KeyUp );
+ glutSpecialUpFunc( SpecialUp );
+ if (first)
+ glutJoystickFunc( Joystick, 100 );
+ glutMouseFunc ( Mouse ) ;
+ glutMouseWheelFunc ( MouseWheel ) ;
+ glutMotionFunc ( Motion ) ;
+ glutPassiveMotionFunc ( PassiveMotion ) ;
+ glutEntryFunc ( Entry ) ;
+ glutCloseFunc ( Close ) ;
+ glutOverlayDisplayFunc ( OverlayDisplay ) ;
+ glutSpaceballMotionFunc ( SpaceMotion ) ;
+ glutSpaceballRotateFunc ( SpaceRotation ) ;
+ glutSpaceballButtonFunc ( SpaceButton ) ;
+ glutButtonBoxFunc ( ButtonBox ) ;
+ glutDialsFunc ( Dials ) ;
+ glutTabletMotionFunc ( TabletMotion ) ;
+ glutTabletButtonFunc ( TabletButton ) ;
+ /* glutVisibilityFunc is deprecated in favor of glutWindowStatusFunc, which provides more detail.
+ * Setting one of these overwrites the other (see docs).
+ */
+ glutVisibilityFunc ( Visibility ); /* This will thus never be called, as glutWindowStatusFunc is set afterwards */
+ glutWindowStatusFunc ( WindowStatus ) ;
+}
+
+int
+main(int argc, char *argv[])
+{
+ char dummy_string[STRING_LENGTH];
+
+ int menuID, subMenuA, subMenuB;
+
+ glutInitWarningFunc(Warning);
+ glutInitErrorFunc(Error);
+ glutInitWindowSize(500, 250);
+ glutInitWindowPosition ( 140, 140 );
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE );
+ glutInit(&argc, argv);
+ /* global setting: mainloop does not return when a window is closed, only returns when all windows are closed */
+ glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_CONTINUE_EXECUTION);
+ /* global setting: repeated keys generating by keeping the key pressed down are passed on to the keyboard callback */
+ /* There are two functions to control this behavior, glutSetKeyRepeat to set it globally, and glutIgnoreKeyRepeat to set it per window.
+ * These two interact however. If key repeat is globally switched off (glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF)), it cannot be overridden
+ * (switched back on) for a specific window with glutIgnoreKeyRepeat. However, if key repeat is globally switched on
+ * (glutSetKeyRepeat(GLUT_KEY_REPEAT_ON)), it can be overridden (switched off) with glutIgnoreKeyRepeat on a per-window basis. That is
+ * what we demonstrate here.
+ */
+ glutSetKeyRepeat(GLUT_KEY_REPEAT_ON);
+
+ /* Set other global callback (global as in not associated with any specific menu or window) */
+ glutIdleFunc ( Idle );
+ glutMenuStatusFunc ( MenuStatus );
+ glutMenuStateFunc ( MenuState ); /* Note that glutMenuStatusFunc is an enhanced version of the deprecated glutMenuStateFunc. */
+
+
+ /* Open first window */
+ windows[0] = glutCreateWindow( "Callback Demo" );
+ printf ( "Creating window %d as 'Callback Demo'\n", windows[0] ) ;
+
+ glClearColor(1.0, 1.0, 1.0, 1.0);
+
+ /* callbacks, settings and menus for this window */
+ SetWindowCallbacks( 1 );
+ glutIgnoreKeyRepeat(GL_TRUE);
+ glutSetIconTitle("Icon Test - Callback Demo");
+
+ subMenuA = glutCreateMenu( MenuCallback );
+ glutAddMenuEntry( "Sub menu A1 (01)", 11 );
+ glutAddMenuEntry( "Sub menu A2 (02)", 12 );
+ glutAddMenuEntry( "Sub menu A3 (03)", 13 );
+ glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */
+ /* Change font for this menu */
+ glutSetMenuFont(subMenuA, GLUT_BITMAP_HELVETICA_12);
+
+ subMenuB = glutCreateMenu( MenuCallback );
+ glutAddMenuEntry( "Sub menu B1 (04)", 14 );
+ glutAddMenuEntry( "Sub menu B2 (05)", 15 );
+ glutAddMenuEntry( "Sub menu B3 (06)", 16 );
+ glutAddSubMenu( "Going to sub menu A", subMenuA );
+ glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */
+ glutSetMenuFont(subMenuB, GLUT_BITMAP_9_BY_15);
+
+ menuID = glutCreateMenu( MenuCallback );
+ glutAddMenuEntry( "Entry one", 21 );
+ glutAddMenuEntry( "Entry two", 22 );
+ glutAddMenuEntry( "Entry three", 23 );
+ glutAddMenuEntry( "Entry four", 24 );
+ glutAddMenuEntry( "Entry five", 25 );
+ glutAddSubMenu( "Enter sub menu A", subMenuA );
+ glutAddSubMenu( "Enter sub menu B", subMenuB );
+ glutMenuDestroyFunc ( MenuDestroy ); /* callback specific to this menu */
+
+ glutAttachMenu( GLUT_LEFT_BUTTON );
+
+
+ /* Position second window right next to the first */
+ glutInitWindowPosition ( 140+500+2*glutGet(GLUT_WINDOW_BORDER_WIDTH), 140 );
+ glutInitWindowSize(600, 600);
+ windows[1] = glutCreateWindow( "Second Window" );
+ printf ( "Creating window %d as 'Second Window'\n", windows[1] ) ;
+
+ glClearColor(1.0, 1.0, 1.0, 1.0);
+
+ /* callbacks, settings and menus for this window */
+ SetWindowCallbacks( 0 );
+ glutIgnoreKeyRepeat(GL_TRUE);
+
+ glutSetMenu(subMenuB);
+ glutAttachMenu( GLUT_RIGHT_BUTTON );
+
+
+ /* position a third window as a subwindow of the second */
+ windows[2] = glutCreateSubWindow(windows[1],0,300,600,300);
+ printf ( "Creating window %d as subwindow to 'Second Window'\n", windows[2] ) ;
+
+ glClearColor(0.7f, 0.7f, 0.7f, 1.0);
+
+ /* callbacks, settings and menus for this window */
+ SetWindowCallbacks( 0 );
+ glutSetCursor(GLUT_CURSOR_CROSSHAIR); /* Cursors are per window */
+
+ glutSetMenu(subMenuA);
+ glutAttachMenu( GLUT_RIGHT_BUTTON );
+
+
+ /* position a fourth window as a subsubwindow (grandchild) of the second */
+ windows[3] = glutCreateSubWindow(windows[2],300,0,300,300);
+ printf ( "Creating window %d as subsubwindow to 'Second Window'\n", windows[3] ) ;
+
+ glClearColor(0.4f, 0.4f, 0.4f, 1.0);
+
+ /* callbacks and menus for this window */
+ SetWindowCallbacks( 0 );
+ glutSetCursor(GLUT_CURSOR_INHERIT); /* Inherit cursor look from parent (this is default on window creation) - comment the below to see in action */
+ glutSetCursor(GLUT_CURSOR_CYCLE);
+
+
+ printf ( "Please enter something to continue: " );
+ fgets ( dummy_string, STRING_LENGTH, stdin );
+
+ glutMainLoop();
+
+ printf ( "Back from the 'freeglut' main loop\n" ) ;
+
+ return EXIT_SUCCESS;