X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_structure.c;h=cc1e9a383d86a93ed374b0eabcc26ec81dcd00aa;hb=7fad69335a7488fd62a47281d7a5a22acf20db16;hp=353bb038f9e5aae701e35f4274f0fd4cf7a7ab4c;hpb=453e9bfabcaa1885f602129d9f775e23b6ef9cd3;p=freeglut diff --git a/src/freeglut_structure.c b/src/freeglut_structure.c index 353bb03..cc1e9a3 100644 --- a/src/freeglut_structure.c +++ b/src/freeglut_structure.c @@ -29,8 +29,6 @@ #include "config.h" #endif -#define G_LOG_DOMAIN "freeglut-structure" - #include "../include/GL/freeglut.h" #include "freeglut_internal.h" @@ -54,6 +52,13 @@ SFG_Structure fgStructure = { { NULL, NULL }, /* The list of windows */ /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ +void fgClearCallBacks( SFG_Window *window ) +{ + int i; + for( i = 0; i < TOTAL_CALLBACKS; ++i ) + window->CallBacks[ i ] = NULL; +} + /* * This private function creates, opens and adds to the hierarchy * a freeglut window complete with OpenGL context and stuff... @@ -69,6 +74,8 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, SFG_Window *window = (SFG_Window *)calloc( sizeof(SFG_Window), 1 ); int fakeArgc = 0; + fgClearCallBacks( window ); + /* * If the freeglut internals haven't been initialized yet, * do it now. Hack's idea courtesy of Chris Purnell... @@ -111,7 +118,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, /* * This private function creates a menu and adds it to the menus list */ -SFG_Menu* fgCreateMenu( FGCBmenu menuCallback ) +SFG_Menu* fgCreateMenu( FGCBMenu menuCallback ) { int x = 100, y = 100, w = 100, h = 100 ; SFG_Window *current_window = fgStructure.Window ; @@ -184,72 +191,85 @@ static SFG_WindowList* WindowsToDestroy = (SFG_WindowList*)NULL ; */ void fgAddToWindowDestroyList ( SFG_Window* window, GLboolean needToClose ) { - SFG_WindowList *new_list_entry = - (SFG_WindowList*)malloc ( sizeof(SFG_WindowList) ) ; - new_list_entry->window = window ; - new_list_entry->needToClose = needToClose ; - new_list_entry->next = WindowsToDestroy ; - WindowsToDestroy = new_list_entry ; + SFG_WindowList *new_list_entry = + ( SFG_WindowList* )malloc( sizeof(SFG_WindowList ) ); + new_list_entry->window = window; + new_list_entry->needToClose = needToClose; + new_list_entry->next = WindowsToDestroy; + WindowsToDestroy = new_list_entry; - /* - * Check if the window is the current one... - */ - if ( fgStructure.Window == window ) - fgStructure.Window = NULL; + /* + * Check if the window is the current one... + */ + if( fgStructure.Window == window ) + fgStructure.Window = NULL; - /* - * If the destroyed window has the highest window ID number, decrement - * the window ID number. - * - * XXX Do we REALLY want to *ever* recycle window IDs? Integers are - * XXX plentiful, and clients may rely upon the implied promise in - * XXX the GLUT docs to not recycle these. (I can't remember if it - * XXX is explicit.) - * - * XXX If we *do* want to do this, we should actually recompute the - * XXX highest window-ID; the new highest may not in fact be one less - * XXX than what we have just deleted. - */ - if ( window->ID == fgStructure.WindowID ) - fgStructure.WindowID-- ; + /* + * Clear all window callbacks except Destroy, which will + * be invoked later. Right now, we are potentially carrying + * out a freeglut operation at the behest of a client callback, + * so we are reluctant to re-enter the client with the Destroy + * callback, right now. The others are all wiped out, however, + * to ensure that they are no longer called after this point. + */ + { + void *destroy = FETCH_WCB( *window, Destroy ); + fgClearCallBacks( window ); + FETCH_WCB( *window, Destroy ) = destroy; + } + - /* - * Check the execution state. If this has been called from - * "glutDestroyWindow", a statement in that function will reset the - * "ExecState" after this function returns. - */ - if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION ) - { /* - * Set the execution state flag to drop out of the main loop. + * If the destroyed window has the highest window ID number, decrement + * the window ID number. + * + * XXX Do we REALLY want to *ever* recycle window IDs? Integers are + * XXX plentiful, and clients may rely upon the implied promise in + * XXX the GLUT docs to not recycle these. (I can't remember if it + * XXX is explicit.) + * + * XXX If we *do* want to do this, we should actually recompute the + * XXX highest window-ID; the new highest may not in fact be one less + * XXX than what we have just deleted. */ - if ( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT ) - fgState.ExecState = GLUT_EXEC_STATE_STOP ; - } + if ( window->ID == fgStructure.WindowID ) + fgStructure.WindowID--; + + /* + * Check the execution state. If this has been called from + * "glutDestroyWindow", a statement in that function will reset the + * "ExecState" after this function returns. + */ + if( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION ) + /* + * Set the execution state flag to drop out of the main loop. + */ + if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT ) + fgState.ExecState = GLUT_EXEC_STATE_STOP; } /* * Function to close down all the windows in the "WindowsToDestroy" list */ -void fgCloseWindows () +void fgCloseWindows( ) { - SFG_WindowList *window_ptr = WindowsToDestroy ; - WindowsToDestroy = (SFG_WindowList*)NULL ; - /* In case the destroy callbacks cause more windows to be closed */ - - while ( window_ptr ) - { - SFG_WindowList *next = window_ptr->next ; - fgDestroyWindow ( window_ptr->window, window_ptr->needToClose ) ; - free ( window_ptr ) ; - window_ptr = next ; + SFG_WindowList *window_ptr = WindowsToDestroy; + WindowsToDestroy = ( SFG_WindowList* )NULL; + /* In case the destroy callbacks cause more windows to be closed */ - if ( !window_ptr ) + while( window_ptr ) { - window_ptr = WindowsToDestroy ; - WindowsToDestroy = (SFG_WindowList*)NULL ; + SFG_WindowList *next = window_ptr->next; + fgDestroyWindow( window_ptr->window, window_ptr->needToClose ); + free( window_ptr ); + window_ptr = next; + + if( !window_ptr ) + { + window_ptr = WindowsToDestroy; + WindowsToDestroy = ( SFG_WindowList* )NULL; + } } - } } /* @@ -268,11 +288,15 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose ) while ( (subWindow = (SFG_Window *)window->Children.First) != NULL ) fgDestroyWindow( subWindow, needToClose ); - if ( window->Callbacks.Destroy != NULL ) + /* + * XXX Since INVOKE_WCB() tests the function pointer, why not make + * XXX this unconditional? Overhead is close to nil, and it would + * XXX clarify the code by omitting a conditional test. + */ + if ( FETCH_WCB( *window, Destroy ) ) { SFG_Window *activeWindow = fgStructure.Window ; - fgSetWindow ( window ) ; - window->Callbacks.Destroy () ; + INVOKE_WCB( *window, Destroy, ( ) ); fgSetWindow ( activeWindow ) ; } @@ -295,6 +319,7 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose ) free( window ); if ( fgStructure.Window == window ) fgStructure.Window = NULL ; + fgClearCallBacks( window ); } /* @@ -561,7 +586,7 @@ static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator ) /* * Check the window's handle. Hope this works. Looks ugly. That's for sure. */ - if( window->ID == (int) (enumerator->data) ) + if( window->ID == (int) (enumerator->data) ) /* XXX int/ptr conversion! */ { enumerator->found = TRUE; enumerator->data = window; @@ -588,7 +613,7 @@ SFG_Window* fgWindowByID( int windowID ) * Uses a method very similiar for fgWindowByHandle... */ enumerator.found = FALSE; - enumerator.data = (void *) windowID; + enumerator.data = (void *) windowID; /* XXX int/pointer conversion! */ fgEnumWindows( fghcbWindowByID, &enumerator ); if( enumerator.found == TRUE ) return( SFG_Window *) enumerator.data; @@ -608,19 +633,12 @@ SFG_Menu* fgMenuByID( int menuID ) /* * It's enough to check all entries in fgStructure.Menus... */ - for( menu = (SFG_Menu *)fgStructure.Menus.First; menu; menu = (SFG_Menu *)menu->Node.Next ) - { - /* - * Does the ID number match? - */ + for( menu = (SFG_Menu *)fgStructure.Menus.First; + menu; + menu = (SFG_Menu *)menu->Node.Next ) if( menu->ID == menuID ) - return( menu ); - } - - /* - * We have not found the requested menu ID - */ - return( NULL ); + return menu; + return NULL; } /* @@ -673,7 +691,7 @@ int fgListLength(SFG_List *list) for( node = (SFG_Node *)list->First; node; node = (SFG_Node *)node->Next ) ++length; - return( length ); + return length; } /*** END OF FILE ***/