Tweaking for menu behavior in Linux regarding mouse whatnot - John Fay
[freeglut] / src / freeglut_structure.c
index 6b54d50..09ad74d 100644 (file)
  * The SFG_Structure container holds information about windows and menus
  * created between glutInit() and glutMainLoop() return.
  */
-SFG_Structure fgStructure;
+
+SFG_Structure fgStructure = { { NULL, NULL },  /* The list of windows       */
+                              { NULL, NULL },  /* The list of menus         */
+                              NULL,            /* The current window        */
+                              NULL,            /* The current menu          */
+                              NULL,            /* The menu OpenGL context   */
+                              NULL,            /* The game mode window      */
+                              0,               /* The current new window ID */
+                              0 };             /* The current new menu ID   */
 
 
 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
@@ -57,7 +65,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, int x, int y,
     /*
      * Have the window object created
      */
-    SFG_Window* window = calloc( sizeof(SFG_Window), 1 );
+    SFG_Window *window = (SFG_Window *)calloc( sizeof(SFG_Window), 1 );
     int fakeArgc = 0;
 
     /*
@@ -103,6 +111,11 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, int x, int y,
     window->State.Modifiers = 0xffffffff;
 
     /*
+     * If this window is a menu, set IsMenu in the structure
+     */
+    window->IsMenu = fgState.BuildingAMenu ;
+
+    /*
      * Open the window now. The fgOpenWindow() function is system
      * dependant, and resides in freeglut_window.c. Uses fgState.
      */
@@ -119,10 +132,13 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, int x, int y,
  */
 SFG_Menu* fgCreateMenu( FGCBmenu menuCallback )
 {
+  int x = 100, y = 100, w = 100, h = 100 ;
+  SFG_Window *current_window = fgStructure.Window ;
+
     /*
      * Have the menu object created
      */
-    SFG_Menu* menu = calloc( sizeof(SFG_Menu), 1 );
+    SFG_Menu* menu = (SFG_Menu *)calloc( sizeof(SFG_Menu), 1 );
     int fakeArgc = 0;
 
     /*
@@ -132,11 +148,34 @@ SFG_Menu* fgCreateMenu( FGCBmenu menuCallback )
     if( !fgState.Time.Set )
         glutInit( &fakeArgc, NULL );
 
+    menu->ParentWindow = fgStructure.Window ;
+
+    /*
+     * Create a window for the menu to reside in.  Set the
+     * global variable BuildingAMenu to true so we can ensure
+     * it is created without decorations.
+     */
+    fgState.BuildingAMenu = TRUE ;
+
+    fgCreateWindow ( NULL, NULL, x, y, w, h, FALSE ) ;
+    menu->Window = fgStructure.Window ;
+    glutDisplayFunc ( fgDisplayMenu ) ;
+
+    /*
+     * While BuildingAMenu is true, all windows built have no decorations.  That's
+     * not a good default behavior, so let's set it false again.
+     */
+    fgState.BuildingAMenu = FALSE ;
+
+    glutHideWindow () ;  /* Hide the window for now */
+    fgSetWindow ( current_window ) ;
+
     /*
      * Initialize the object properties:
      */
     menu->ID       = ++fgStructure.MenuID;
     menu->Callback = menuCallback;
+    menu->ActiveEntry = NULL ;
 
     /*
      * Initialize the entries list
@@ -234,6 +273,7 @@ void fgCloseWindows ()
 void fgDestroyWindow( SFG_Window* window, GLboolean needToClose )
 {
     SFG_Window* subWindow;
+    int menu_index ;
 
     assert( window != NULL );
     freeglut_assert_ready;
@@ -241,7 +281,7 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose )
     /*
      * Does this window have any subwindows?
      */
-    while ( (subWindow = window->Children.First) != NULL )
+    while ( (subWindow = (SFG_Window *)window->Children.First) != NULL )
     {
         /*
          * Destroy the first window in the list (possibly destroying
@@ -257,9 +297,9 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose )
     if ( window->Callbacks.Destroy != NULL )
     {
       SFG_Window *activeWindow = fgStructure.Window ;
-      fgStructure.Window = window ;
+      fgSetWindow ( window ) ;
       window->Callbacks.Destroy () ;
-      fgStructure.Window = activeWindow ;
+      fgSetWindow ( activeWindow ) ;
     }
 
     /*
@@ -270,6 +310,15 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose )
     else
         fgListRemove( &fgStructure.Windows, &window->Node );
 
+    if ( window->ActiveMenu != NULL )
+      fgDeactivateMenu ( window ) ;
+
+    for ( menu_index = 0; menu_index < 3; menu_index ++ )
+    {
+      if ( window->Menu[menu_index] != NULL )
+        window->Menu[menu_index]->ParentWindow = NULL ;
+    }
+
     /*
      * OK, this window seems disconnected from the structure enough
      * in order to be closed without any bigger risks...
@@ -282,6 +331,7 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose )
      * have everything inside it freed and we do not have to care...
      */
     free( window );
+    if ( fgStructure.Window == window ) fgStructure.Window = NULL ;
 }
 
 /*
@@ -306,8 +356,8 @@ static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu )
     /*
      * Call this function for all of the window's children recursively:
      */
-    for( subWindow = window->Children.First; subWindow;
-         subWindow = subWindow->Node.Next)
+    for( subWindow = (SFG_Window *)window->Children.First; subWindow;
+         subWindow = (SFG_Window *)subWindow->Node.Next)
     {
         fghRemoveMenuFromWindow( subWindow, menu );
     }
@@ -321,7 +371,7 @@ static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu )
 {
   SFG_MenuEntry *entry;
 
-  for( entry = from->Entries.First; entry; entry = entry->Node.Next )
+  for( entry = (SFG_MenuEntry *)from->Entries.First; entry; entry = (SFG_MenuEntry *)entry->Node.Next )
   {
     if (entry->SubMenu == menu)
     {
@@ -346,7 +396,7 @@ void fgDestroyMenu( SFG_Menu* menu )
   /*
    * First of all, have all references to this menu removed from all windows:
    */
-  for( window = fgStructure.Windows.First; window; window = window->Node.Next )
+  for( window = (SFG_Window *)fgStructure.Windows.First; window; window = (SFG_Window *)window->Node.Next )
   {
     fghRemoveMenuFromWindow( window, menu );
   }
@@ -354,7 +404,7 @@ void fgDestroyMenu( SFG_Menu* menu )
   /*
    * Now proceed with removing menu entries that lead to this menu
    */
-  for( from = fgStructure.Menus.First; from; from = from->Node.Next )
+  for( from = (SFG_Menu *)fgStructure.Menus.First; from; from = (SFG_Menu *)from->Node.Next )
   {
     fghRemoveMenuFromMenu( from, menu );
   }
@@ -375,7 +425,7 @@ void fgDestroyMenu( SFG_Menu* menu )
    * Now we are pretty sure the menu is not used anywhere
    * and that we can remove all of its entries
    */
-  while( (entry = menu->Entries.First) != NULL )
+  while( (entry = (SFG_MenuEntry *)menu->Entries.First) != NULL )
   {
     fgListRemove(&menu->Entries, &entry->Node);
 
@@ -391,6 +441,14 @@ void fgDestroyMenu( SFG_Menu* menu )
   }
 
   /*
+   * Destroy the window associated with the menu
+   */
+  if ( fgStructure.Window == menu->Window )
+    fgSetWindow ( menu->ParentWindow ) ;
+
+  fgDestroyWindow ( menu->Window, TRUE ) ;
+
+  /*
    * Remove the menu from the menus list
    */
   fgListRemove( &fgStructure.Menus, &menu->Node );
@@ -442,11 +500,11 @@ void fgDestroyStructure( void )
   /*
    * Make sure all windows and menus have been deallocated
    */
-  while( (window = fgStructure.Windows.First) != NULL )
-    fgDestroyWindow( window, TRUE );
-
-  while( (menu = fgStructure.Menus.First) != NULL )
+  while( (menu = (SFG_Menu *)fgStructure.Menus.First) != NULL )
     fgDestroyMenu( menu );
+
+  while( (window = (SFG_Window *)fgStructure.Windows.First) != NULL )
+    fgDestroyWindow( window, TRUE );
 }
 
 /*
@@ -462,8 +520,8 @@ void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
   /*
    * Check every of the top-level windows
    */
-  for( window = fgStructure.Windows.First; window;
-       window = window->Node.Next )
+  for( window = (SFG_Window *)fgStructure.Windows.First; window;
+       window = (SFG_Window *)window->Node.Next )
   {
     /*
      * Execute the callback...
@@ -491,7 +549,7 @@ void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, SFG_Enum
   /*
    * Check every of the window's children:
    */
-  for( child = window->Children.First; child; child = child->Node.Next )
+  for( child = (SFG_Window *)window->Children.First; child; child = (SFG_Window *)child->Node.Next )
   {
     /*
      * Execute the callback...
@@ -650,7 +708,7 @@ SFG_Menu* fgMenuByID( int menuID )
     /*
      * It's enough to check all entries in fgStructure.Menus...
      */
-    for( menu = fgStructure.Menus.First; menu; menu = menu->Node.Next )
+    for( menu = (SFG_Menu *)fgStructure.Menus.First; menu; menu = (SFG_Menu *)menu->Node.Next )
     {
         /*
          * Does the ID number match?
@@ -678,7 +736,7 @@ void fgListAppend(SFG_List *list, SFG_Node *node)
 {
     SFG_Node *ln;
 
-    if ( (ln = list->Last) != NULL )
+    if ( (ln = (SFG_Node *)list->Last) != NULL )
     {
         ln->Next = node;
         node->Prev = ln;
@@ -697,13 +755,13 @@ void fgListRemove(SFG_List *list, SFG_Node *node)
 {
     SFG_Node *ln;
 
-    if ( (ln = node->Next) != NULL )
+    if ( (ln = (SFG_Node *)node->Next) != NULL )
         ln->Prev = node->Prev;
-    if ( (ln = node->Prev) != NULL )
+    if ( (ln = (SFG_Node *)node->Prev) != NULL )
         ln->Next = node->Next;
-    if ( (ln = list->First) == node )
+    if ( (ln = (SFG_Node *)list->First) == node )
         list->First = node->Next;
-    if ( (ln = list->Last) == node )
+    if ( (ln = (SFG_Node *)list->Last) == node )
         list->Last = node->Prev;
 }
 
@@ -712,7 +770,7 @@ int fgListLength(SFG_List *list)
     SFG_Node *node;
     int length = 0;
 
-    for( node = list->First; node; node = node->Next )
+    for( node = (SFG_Node *)list->First; node; node = (SFG_Node *)node->Next )
         ++length;
 
     return( length );