GLboolean found; /* Used to terminate search */
void* data; /* Custom data pointer */
};
-typedef void (* FGCBenumerator )( SFG_Window *, SFG_Enumerator * );
+typedef void (* FGCBWindowEnumerator )( SFG_Window *, SFG_Enumerator * );
+typedef void (* FGCBMenuEnumerator )( SFG_Menu *, SFG_Enumerator * );
/* The bitmap font structure */
typedef struct tagSFG_Font SFG_Font;
* and userData is the a custom user-supplied pointer. Functions
* are defined and exported from freeglut_structure.c file.
*/
-void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator );
-void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
+void fgEnumWindows( FGCBWindowEnumerator enumCallback, SFG_Enumerator* enumerator );
+void fgEnumSubWindows( SFG_Window* window, FGCBWindowEnumerator enumCallback,
SFG_Enumerator* enumerator );
/*
SFG_Menu* fgMenuByID( int menuID );
/*
+ * Returns active menu, if any. Assumption: only one menu active throughout application at any one time.
+ * This is easier than fgWindowByXXX as all menus are placed in one doubly linked list...
+ */
+SFG_Menu* fgGetActiveMenu( );
+
+/*
* The menu activation and deactivation the code. This is the meat
* of the menu user interface handling code...
*/
SFG_Menu* menu = window->Menu[ button ];
SFG_Window* current_window = fgStructure.CurrentWindow;
- /* If the menu is already active in another window, deactivate it (and any submenu's) there */
+ /* If the menu is already active in another window, deactivate it (and any submenus) there */
if ( menu->ParentWindow )
fgDeactivateMenu(menu->ParentWindow);
/*
* Helper function to enumerate through all registered top-level windows
*/
-void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
+void fgEnumWindows( FGCBWindowEnumerator enumCallback, SFG_Enumerator* enumerator )
{
SFG_Window *window;
}
/*
+* Helper function to enumerate through all registered top-level windows
+*/
+void fgEnumMenus( FGCBMenuEnumerator enumCallback, SFG_Enumerator* enumerator )
+{
+ SFG_Menu *menu;
+
+ FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator,
+ "Enumerator or callback missing from window enumerator call",
+ "fgEnumWindows" );
+
+ /* It's enough to check all entries in fgStructure.Menus... */
+ for( menu = (SFG_Menu *)fgStructure.Menus.First;
+ menu;
+ menu = (SFG_Menu *)menu->Node.Next )
+ {
+ enumCallback( menu, enumerator );
+ if( enumerator->found )
+ return;
+ }
+}
+
+/*
* Helper function to enumerate through all a window's subwindows
* (single level descent)
*/
-void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
+void fgEnumSubWindows( SFG_Window* window, FGCBWindowEnumerator enumCallback,
SFG_Enumerator* enumerator )
{
SFG_Window *child;
}
/*
- * This function is similiar to the previous one, except it is
+ * This function is similar to the previous one, except it is
* looking for a specified (sub)window identifier. The function
* is defined in freeglut_structure.c file.
*/
{
SFG_Enumerator enumerator;
- /* Uses a method very similiar for fgWindowByHandle... */
+ /* Uses a method very similar for fgWindowByHandle... */
enumerator.found = GL_FALSE;
enumerator.data = ( void * )&windowID;
fgEnumWindows( fghcbWindowByID, &enumerator );
}
/*
- * Looks up a menu given its ID. This is easier that fgWindowByXXX
+ * A static helper function to look for a menu given its ID
+ */
+static void fghcbMenuByID( SFG_Menu *menu,
+ SFG_Enumerator *enumerator )
+{
+ if ( enumerator->found )
+ return;
+
+ /* Check the menu's ID. */
+ if( menu->ID == (int)(enumerator->data) )
+ {
+ enumerator->found = GL_TRUE;
+ enumerator->data = menu;
+
+ return;
+ }
+}
+
+/*
+ * Looks up a menu given its ID. This is easier than fgWindowByXXX
* as all menus are placed in one doubly linked list...
*/
SFG_Menu* fgMenuByID( int menuID )
{
- SFG_Menu *menu = NULL;
+ SFG_Enumerator enumerator;
+
+ /* This is easy and makes use of the menus enumeration defined above */
+ enumerator.found = GL_FALSE;
+ enumerator.data = (void *)menuID;
+ fgEnumMenus( fghcbMenuByID, &enumerator );
+
+ if( enumerator.found )
+ return( SFG_Menu *) enumerator.data;
+
+ return NULL;
+}
+
+/*
+ * A static helper function to look for an active menu
+ */
+static void fghcbGetActiveMenu( SFG_Menu *menu,
+ SFG_Enumerator *enumerator )
+{
+ if ( enumerator->found )
+ return;
+
+ /* Check the menu's ID. */
+ if( menu->IsActive )
+ {
+ enumerator->found = GL_TRUE;
+ enumerator->data = menu;
+
+ return;
+ }
+}
+
+/*
+ * Returns active menu, if any. Assumption: only one menu active throughout application at any one time.
+ * This is easier than fgWindowByXXX as all menus are placed in one doubly linked list...
+ */
+SFG_Menu* fgGetActiveMenu( )
+{
+ SFG_Enumerator enumerator;
+
+ /* This is easy and makes use of the menus enumeration defined above */
+ enumerator.found = GL_FALSE;
+ fgEnumMenus( fghcbGetActiveMenu, &enumerator );
+
+ if( enumerator.found )
+ return( SFG_Menu *) enumerator.data;
- /* It's enough to check all entries in fgStructure.Menus... */
- for( menu = (SFG_Menu *)fgStructure.Menus.First;
- menu;
- menu = (SFG_Menu *)menu->Node.Next )
- if( menu->ID == menuID )
- return menu;
return NULL;
}
break;
case WM_KILLFOCUS:
-/* printf("WM_KILLFOCUS (ismenu: %i): %p\n", window->IsMenu, window ); */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
-
- /* If this is a menu that lost focus, see if user either switched
- application or FreeGLUT window (if one is running multiple
- windows). If so, close menu that lost focus.
- */
- if( window->IsMenu &&
- window->ActiveMenu && window->ActiveMenu->IsActive )
{
- SFG_Window* wnd = NULL;
- HWND hwnd = GetForegroundWindow(); /* Get window with current focus */
- if (hwnd)
- /* See if its one of our windows */
- wnd = fgWindowByHandle(hwnd);
-
- if (!hwnd || !wnd)
- /* User switched to another application*/
- fgDeactivateMenu(window->ActiveMenu->ParentWindow);
- else if (
- ( wnd->IsMenu && wnd->ActiveMenu->ParentWindow!=window->ActiveMenu->ParentWindow) || /* Make sure we don't kill the menu when trying to enter a submenu */
- (!wnd->IsMenu && wnd!=window->ActiveMenu->ParentWindow)
- )
- /* User switched to another FreeGLUT window */
- fgDeactivateMenu(window->ActiveMenu->ParentWindow);
- }
+ SFG_Menu* menu = NULL;
+/* printf("WM_KILLFOCUS (ismenu: %i): %p\n", window->IsMenu, window ); */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
+ /* If we have an open menu, see if the open menu should be closed
+ when focus was lost because user either switched
+ application or FreeGLUT window (if one is running multiple
+ windows). If so, close menu the active menu.
+ */
+ if ( fgStructure.CurrentMenu )
+ menu = fgGetActiveMenu();
+
+ if ( menu )
+ {
+ SFG_Window* wnd = NULL;
+ HWND hwnd = GetForegroundWindow(); /* Get window with current focus */
+ if (hwnd)
+ /* See if its one of our windows */
+ wnd = fgWindowByHandle(hwnd);
+
+ if (!hwnd || !wnd)
+ /* User switched to another application*/
+ fgDeactivateMenu(menu->ParentWindow);
+ else if (
+ ( wnd->IsMenu && wnd->ActiveMenu && wnd->ActiveMenu->ParentWindow!=menu->ParentWindow) || /* Make sure we don't kill the menu when trying to enter a submenu */
+ (!wnd->IsMenu && wnd!=menu->ParentWindow)
+ )
+ /* User switched to another FreeGLUT window */
+ fgDeactivateMenu(menu->ParentWindow);
+ }
+ }
break;
#if 0