/* * This function destroys a window and all of its subwindows. Actually, * another function, defined in freeglut_window.c is called, but this is * a whole different story... */ void fgDestroyWindow( SFG_Window* window ) { FREEGLUT_INTERNAL_ERROR_EXIT ( window, "Window destroy function called with null window", "fgDestroyWindow" ); while( window->Children.First ) fgDestroyWindow( ( SFG_Window * )window->Children.First ); { SFG_Window *activeWindow = fgStructure.CurrentWindow; INVOKE_WCB( *window, Destroy, ( ) ); fgSetWindow( activeWindow ); } if( window->Parent ) fgListRemove( &window->Parent->Children, &window->Node ); else fgListRemove( &fgStructure.Windows, &window->Node ); if( window->ActiveMenu ) fgDeactivateMenu( window ); fghClearCallBacks( window ); fgCloseWindow( window ); free( window ); if( fgStructure.CurrentWindow == window ) fgStructure.CurrentWindow = NULL; }
/* * This function destroys a menu specified by the parameter. All menus * and windows are updated to make sure no ill pointers hang around. */ void fgDestroyMenu( SFG_Menu* menu ) { SFG_Window *window; SFG_Menu *from; FREEGLUT_INTERNAL_ERROR_EXIT ( menu, "Menu destroy function called with null menu", "fgDestroyMenu" ); /* First of all, have all references to this menu removed from all windows: */ for( window = (SFG_Window *)fgStructure.Windows.First; window; window = (SFG_Window *)window->Node.Next ) fghRemoveMenuFromWindow( window, menu ); /* Now proceed with removing menu entries that lead to this menu */ for( from = ( SFG_Menu * )fgStructure.Menus.First; from; from = ( SFG_Menu * )from->Node.Next ) fghRemoveMenuFromMenu( from, menu ); /* * If the programmer defined a destroy callback, call it * A. Donev: But first make this the active menu */ if( menu->Destroy ) { SFG_Menu *activeMenu=fgStructure.CurrentMenu; fgStructure.CurrentMenu = menu; menu->Destroy( ); fgStructure.CurrentMenu = activeMenu; } /* * Now we are pretty sure the menu is not used anywhere * and that we can remove all of its entries */ while( menu->Entries.First ) { SFG_MenuEntry *entry = ( SFG_MenuEntry * ) menu->Entries.First; fgListRemove( &menu->Entries, &entry->Node ); if( entry->Text ) free( entry->Text ); entry->Text = NULL; free( entry ); } if( fgStructure.CurrentWindow == menu->Window ) fgSetWindow( NULL ); fgDestroyWindow( menu->Window ); fgListRemove( &fgStructure.Menus, &menu->Node ); if( fgStructure.CurrentMenu == menu ) fgStructure.CurrentMenu = NULL; free( menu ); }
/* Creates a timer and sets its callback */ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, FGCBTimer callback, 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; /* Insert such that timers are sorted by end-time */ 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 Timer callback for the current window */ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ), int timerID ) { SFG_Timer *timer, *node; glutes_assert_ready; 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()\n" ); } 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 ); }
/* * Function to close down all the windows in the "WindowsToDestroy" list */ void fgCloseWindows( ) { while( fgStructure.WindowsToDestroy.First ) { SFG_WindowList *window_ptr = fgStructure.WindowsToDestroy.First; fgDestroyWindow( window_ptr->window ); fgListRemove( &fgStructure.WindowsToDestroy, &window_ptr->node ); free( window_ptr ); } }
/* * Check the global timers */ static void fghCheckTimers( void ) { fg_time_t checkTime = fgElapsedTime( ); while( fgState.Timers.First ) { SFG_Timer *timer = fgState.Timers.First; if( timer->TriggerTime > checkTime ) /* Timers are sorted by triggerTime */ break; fgListRemove( &fgState.Timers, &timer->Node ); fgListAppend( &fgState.FreeTimers, &timer->Node ); timer->Callback( timer->ID ); } }
/* * Removes the specified menu item from the current menu */ void FGAPIENTRY glutRemoveMenuItem( int item ) { SFG_MenuEntry* menuEntry; FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutRemoveMenuItem" ); freeglut_return_if_fail( fgStructure.CurrentMenu ); /* Get n-th menu entry in the current menu, starting from one: */ menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item ); freeglut_return_if_fail( menuEntry ); fgListRemove( &fgStructure.CurrentMenu->Entries, &menuEntry->Node ); if ( menuEntry->Text ) free( menuEntry->Text ); free( menuEntry ); fghCalculateMenuBoxSize( ); }
/* * Removes the specified menu item from the current menu */ void FGAPIENTRY glutRemoveMenuItem( int item ) { SFG_MenuEntry* menuEntry; freeglut_assert_ready; freeglut_return_if_fail( fgStructure.Menu ); /* * Get n-th menu entry in the current menu, starting from one: */ menuEntry = fghFindMenuEntry( fgStructure.Menu, item ); freeglut_return_if_fail( menuEntry ); fgListRemove( &fgStructure.Menu->Entries, &menuEntry->Node ); if ( menuEntry->Text ) free( menuEntry->Text ); free( menuEntry ); fghCalculateMenuBoxSize( ); }
/* * Perform the freeglut deinitialization... */ void fgDeinitialize( void ) { SFG_Timer *timer; if( !fgState.Initialised ) { return; } /* If we're in game mode, we want to leave game mode */ if( fgStructure.GameModeWindow ) { glutLeaveGameMode(); } /* If there was a menu created, destroy the rendering context */ if( fgStructure.MenuContext ) { fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext ); free( fgStructure.MenuContext ); fgStructure.MenuContext = NULL; } fgDestroyStructure( ); while( ( timer = fgState.Timers.First) ) { fgListRemove( &fgState.Timers, &timer->Node ); free( timer ); } while( ( timer = fgState.FreeTimers.First) ) { fgListRemove( &fgState.FreeTimers, &timer->Node ); free( timer ); } fgPlatformDeinitialiseInputDevices (); fgState.MouseWheelTicks = 0; fgState.MajorVersion = 1; fgState.MinorVersion = 0; fgState.ContextFlags = 0; fgState.ContextProfile = 0; fgState.Initialised = GL_FALSE; fgState.Position.X = -1; fgState.Position.Y = -1; fgState.Position.Use = GL_FALSE; fgState.Size.X = 300; fgState.Size.Y = 300; fgState.Size.Use = GL_TRUE; fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH; fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT; fgState.ForceIconic = GL_FALSE; fgState.UseCurrentContext = GL_FALSE; fgState.GLDebugSwitch = GL_FALSE; fgState.XSyncSwitch = GL_FALSE; fgState.ActionOnWindowClose = GLUT_ACTION_EXIT; fgState.ExecState = GLUT_EXEC_STATE_INIT; fgState.KeyRepeat = GLUT_KEY_REPEAT_ON; fgState.Modifiers = INVALID_MODIFIERS; fgState.GameModeSize.X = -1; fgState.GameModeSize.Y = -1; fgState.GameModeDepth = -1; fgState.GameModeRefresh = -1; fgListInit( &fgState.Timers ); fgListInit( &fgState.FreeTimers ); fgState.IdleCallback = NULL; fgState.MenuStateCallback = ( FGCBMenuState )NULL; fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL; fgState.SwapCount = 0; fgState.SwapTime = 0; fgState.FPSInterval = 0; if( fgState.ProgramName ) { free( fgState.ProgramName ); fgState.ProgramName = NULL; } fgPlatformCloseDisplay (); fgState.Initialised = GL_FALSE; }
/* * Perform the freeglut deinitialization... */ void fgDeinitialize( void ) { SFG_Timer *timer; if( !fgState.Initialised ) { fgWarning( "fgDeinitialize(): " "no valid initialization has been performed" ); return; } /* fgState.Initialised = GL_FALSE; */ /* * If there was a menu created, destroy the rendering context */ if( fgStructure.MenuContext ) { free( fgStructure.MenuContext ); fgStructure.MenuContext = NULL; } fgDestroyStructure( ); while( (timer = fgState.Timers.First) ) { fgListRemove( &fgState.Timers, &timer->Node ); free( timer ); } while( (timer = fgState.FreeTimers.First) ) { fgListRemove( &fgState.FreeTimers, &timer->Node ); free( timer ); } #ifndef _WIN32_WCE fgJoystickClose( ); #endif fgState.Initialised = GL_FALSE; fgState.Position.X = -1; fgState.Position.Y = -1; fgState.Position.Use = GL_FALSE; fgState.Size.X = 240; fgState.Size.Y = 320; fgState.Size.Use = GL_TRUE; fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH; fgState.ForceDirectContext = GL_FALSE; fgState.TryDirectContext = GL_TRUE; fgState.ForceIconic = GL_FALSE; fgState.UseCurrentContext = GL_FALSE; fgState.GLDebugSwitch = GL_FALSE; fgState.XSyncSwitch = GL_FALSE; fgState.ActionOnWindowClose = GLUT_ACTION_EXIT; fgState.ExecState = GLUT_EXEC_STATE_INIT; fgState.IgnoreKeyRepeat = GL_TRUE; fgState.Modifiers = 0xffffffff; fgState.GameModeSize.X = 240; fgState.GameModeSize.Y = 320; fgState.GameModeDepth = 16; fgState.GameModeRefresh = 72; fgState.Time.Set = GL_FALSE; fgListInit( &fgState.Timers ); fgListInit( &fgState.FreeTimers ); fgState.IdleCallback = NULL; fgState.MenuStateCallback = ( FGCBMenuState )NULL; fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL; fgState.SwapCount = 0; fgState.SwapTime = 0; fgState.FPSInterval = 0; if( fgState.ProgramName ) { free( fgState.ProgramName ); fgState.ProgramName = NULL; } __glDestroy(); #if TARGET_HOST_UNIX_X11 /* * Make sure all X-client data we have created will be destroyed on * display closing */ XSetCloseDownMode( fgDisplay.Display, DestroyAll ); /* * Close the display connection, destroying all windows we have * created so far */ XCloseDisplay( fgDisplay.Display ); #endif }
/* * Perform the freeglut deinitialization... */ void fgDeinitialize( void ) { SFG_Timer *timer; if( !fgState.Initialised ) { return; } /* If we're in game mode, we want to leave game mode */ if( fgStructure.GameModeWindow ) { glutLeaveGameMode(); } /* If there was a menu created, destroy the rendering context */ if( fgStructure.MenuContext ) { #if TARGET_HOST_POSIX_X11 /* Note that the MVisualInfo is not owned by the MenuContext! */ glXDestroyContext( fgDisplay.Display, fgStructure.MenuContext->MContext ); #endif free( fgStructure.MenuContext ); fgStructure.MenuContext = NULL; } fgDestroyStructure( ); while( ( timer = fgState.Timers.First) ) { fgListRemove( &fgState.Timers, &timer->Node ); free( timer ); } while( ( timer = fgState.FreeTimers.First) ) { fgListRemove( &fgState.FreeTimers, &timer->Node ); free( timer ); } #if !defined(_WIN32_WCE) if ( fgState.JoysticksInitialised ) fgJoystickClose( ); if ( fgState.InputDevsInitialised ) fgInputDeviceClose( ); #endif /* !defined(_WIN32_WCE) */ fgState.JoysticksInitialised = GL_FALSE; fgState.InputDevsInitialised = GL_FALSE; fgState.MouseWheelTicks = 0; fgState.MajorVersion = 1; fgState.MinorVersion = 0; fgState.ContextFlags = 0; fgState.ContextProfile = 0; fgState.Initialised = GL_FALSE; fgState.Position.X = -1; fgState.Position.Y = -1; fgState.Position.Use = GL_FALSE; fgState.Size.X = 300; fgState.Size.Y = 300; fgState.Size.Use = GL_TRUE; fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH; fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT; fgState.ForceIconic = GL_FALSE; fgState.UseCurrentContext = GL_FALSE; fgState.GLDebugSwitch = GL_FALSE; fgState.XSyncSwitch = GL_FALSE; fgState.ActionOnWindowClose = GLUT_ACTION_EXIT; fgState.ExecState = GLUT_EXEC_STATE_INIT; fgState.KeyRepeat = GLUT_KEY_REPEAT_ON; fgState.Modifiers = INVALID_MODIFIERS; fgState.GameModeSize.X = -1; fgState.GameModeSize.Y = -1; fgState.GameModeDepth = -1; fgState.GameModeRefresh = -1; fgListInit( &fgState.Timers ); fgListInit( &fgState.FreeTimers ); fgState.IdleCallback = NULL; fgState.MenuStateCallback = ( FGCBMenuState )NULL; fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL; fgState.SwapCount = 0; fgState.SwapTime = 0; fgState.FPSInterval = 0; if( fgState.ProgramName ) { free( fgState.ProgramName ); fgState.ProgramName = NULL; } #if TARGET_HOST_POSIX_X11 /* * Make sure all X-client data we have created will be destroyed on * display closing */ XSetCloseDownMode( fgDisplay.Display, DestroyAll ); /* * Close the display connection, destroying all windows we have * created so far */ XCloseDisplay( fgDisplay.Display ); #elif TARGET_HOST_MS_WINDOWS if( fgDisplay.DisplayName ) { free( fgDisplay.DisplayName ); fgDisplay.DisplayName = NULL; } /* Reset the timer granularity */ timeEndPeriod ( 1 ); #endif fgState.Initialised = GL_FALSE; }