/* * freeglut_callbacks.c * * The callbacks setting methods. * * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. * Written by Pawel W. Olszta, * Creation date: Fri Dec 3 1999 * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include "freeglut_internal.h" /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ /* * All of the callbacks setting methods can be generalized to this: */ #define SET_CALLBACK(a) \ do \ { \ if( fgStructure.CurrentWindow == NULL ) \ return; \ SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback ); \ } while( 0 ) /* * Sets the Display callback for the current window */ void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" ); if( !callback ) fgError( "Fatal error in program. NULL display callback not " "permitted in GLUT 3.0+ or freeglut 2.0.1+" ); SET_CALLBACK( Display ); } /* * Sets the Reshape callback for the current window */ void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" ); SET_CALLBACK( Reshape ); } /* * Sets the Keyboard callback for the current window */ void FGAPIENTRY glutKeyboardFunc( void (* callback) ( unsigned char, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardFunc" ); SET_CALLBACK( Keyboard ); } /* * Sets the Special callback for the current window */ void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialFunc" ); SET_CALLBACK( Special ); } /* * Sets the global idle callback */ void FGAPIENTRY glutIdleFunc( void (* callback)( void ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" ); fgState.IdleCallback = callback; } /* * Sets the Timer callback for the current window */ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ), int timerID ) { SFG_Timer *timer, *node; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" ); if( (timer = fgState.FreeTimers.Last) ) { fgListRemove( &fgState.FreeTimers, &timer->Node ); } else { if( ! (timer = malloc(sizeof(SFG_Timer))) ) fgError( "Fatal error: " "Memory allocation failure in glutTimerFunc()" ); } timer->Callback = callback; timer->ID = timerID; timer->TriggerTime = fgElapsedTime() + timeOut; for( node = fgState.Timers.First; node; node = node->Node.Next ) { if( node->TriggerTime > timer->TriggerTime ) break; } fgListInsert( &fgState.Timers, &node->Node, &timer->Node ); } /* * Sets the Visibility callback for the current window. */ static void fghVisibility( int status ) { int glut_status = GLUT_VISIBLE; FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Visibility Callback" ); freeglut_return_if_fail( fgStructure.CurrentWindow ); if( ( GLUT_HIDDEN == status ) || ( GLUT_FULLY_COVERED == status ) ) glut_status = GLUT_NOT_VISIBLE; INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( glut_status ) ); } void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" ); SET_CALLBACK( Visibility ); if( callback ) glutWindowStatusFunc( fghVisibility ); else glutWindowStatusFunc( NULL ); } /* * Sets the keyboard key release callback for the current window */ void FGAPIENTRY glutKeyboardUpFunc( void (* callback) ( unsigned char, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardUpFunc" ); SET_CALLBACK( KeyboardUp ); } /* * Sets the special key release callback for the current window */ void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialUpFunc" ); SET_CALLBACK( SpecialUp ); } /* * Sets the joystick callback and polling rate for the current window */ void FGAPIENTRY glutJoystickFunc( void (* callback) ( unsigned int, int, int, int ), int pollInterval ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" ); fgInitialiseJoysticks (); if ( ( ( fgStructure.CurrentWindow->State.JoystickPollRate < 0 ) || !FETCH_WCB(*fgStructure.CurrentWindow,Joystick) ) && /* Joystick callback was disabled */ ( callback && ( pollInterval >= 0 ) ) ) /* but is now enabled */ ++fgState.NumActiveJoysticks; else if ( ( ( fgStructure.CurrentWindow->State.JoystickPollRate >= 0 ) && FETCH_WCB(*fgStructure.CurrentWindow,Joystick) ) && /* Joystick callback was enabled */ ( !callback || ( pollInterval < 0 ) ) ) /* but is now disabled */ --fgState.NumActiveJoysticks; SET_CALLBACK( Joystick ); fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval; fgStructure.CurrentWindow->State.JoystickLastPoll = fgElapsedTime() - fgStructure.CurrentWindow->State.JoystickPollRate; if( fgStructure.CurrentWindow->State.JoystickLastPoll < 0 ) fgStructure.CurrentWindow->State.JoystickLastPoll = 0; } /* * Sets the mouse callback for the current window */ void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseFunc" ); SET_CALLBACK( Mouse ); } /* * Sets the mouse wheel callback for the current window */ void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseWheelFunc" ); SET_CALLBACK( MouseWheel ); } /* * Sets the mouse motion callback for the current window (one or more buttons * are pressed) */ void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMotionFunc" ); SET_CALLBACK( Motion ); } /* * Sets the passive mouse motion callback for the current window (no mouse * buttons are pressed) */ void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPassiveMotionFunc" ); SET_CALLBACK( Passive ); } /* * Window mouse entry/leave callback */ void FGAPIENTRY glutEntryFunc( void (* callback)( int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEntryFunc" ); SET_CALLBACK( Entry ); } /* * Window destruction callbacks */ void FGAPIENTRY glutCloseFunc( void (* callback)( void ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCloseFunc" ); SET_CALLBACK( Destroy ); } void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWMCloseFunc" ); glutCloseFunc( callback ); } /* A. Donev: Destruction callback for menus */ void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" ); if( fgStructure.CurrentMenu ) fgStructure.CurrentMenu->Destroy = callback; } /* * Deprecated version of glutMenuStatusFunc callback setting method */ void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" ); fgState.MenuStateCallback = callback; } /* * Sets the global menu status callback for the current window */ void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" ); fgState.MenuStatusCallback = callback; } /* * Sets the overlay display callback for the current window */ void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutOverlayDisplayFunc" ); SET_CALLBACK( OverlayDisplay ); } /* * Sets the window status callback for the current window */ void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWindowStatusFunc" ); SET_CALLBACK( WindowStatus ); } /* * Sets the spaceball motion callback for the current window */ void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" ); fgInitialiseSpaceball(); SET_CALLBACK( SpaceMotion ); } /* * Sets the spaceball rotate callback for the current window */ void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" ); fgInitialiseSpaceball(); SET_CALLBACK( SpaceRotation ); } /* * Sets the spaceball button callback for the current window */ void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" ); fgInitialiseSpaceball(); SET_CALLBACK( SpaceButton ); } /* * Sets the button box callback for the current window */ void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutButtonBoxFunc" ); SET_CALLBACK( ButtonBox ); } /* * Sets the dials box callback for the current window */ void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDialsFunc" ); SET_CALLBACK( Dials ); } /* * Sets the tablet motion callback for the current window */ void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletMotionFunc" ); SET_CALLBACK( TabletMotion ); } /* * Sets the tablet buttons callback for the current window */ void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletButtonFunc" ); SET_CALLBACK( TabletButton ); } /* * Sets the multi-pointer entry callback for the current window */ void FGAPIENTRY glutMultiEntryFunc( void (* callback)(int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiEntryFunc" ); SET_CALLBACK( MultiEntry ); } /* * Sets the multi-pointer button callback for the current window */ void FGAPIENTRY glutMultiButtonFunc( void (* callback)(int, int, int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiButtonFunc" ); SET_CALLBACK( MultiButton ); } /* * Sets the multi-pointer motion callback for the current window */ void FGAPIENTRY glutMultiMotionFunc( void (* callback)(int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiMotionFunc" ); SET_CALLBACK( MultiMotion ); } /* * Sets the multi-pointer passive motion callback for the current window */ void FGAPIENTRY glutMultiPassiveFunc( void (* callback)(int, int, int ) ) { FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiPassiveFunc" ); SET_CALLBACK( MultiPassive ); } /*** END OF FILE ***/