also add an InvalidateRect call before the BeginPaint in WM_PAINT
[freeglut] / src / fg_menu.c
index 3ad2cb1..6a7d96d 100644 (file)
@@ -29,6 +29,7 @@
 #include <GL/freeglut.h>
 #include "fg_internal.h"
 
+
 /* -- DEFINITIONS ---------------------------------------------------------- */
 
 /*
@@ -75,6 +76,7 @@ static float menu_pen_hback [4] = FREEGLUT_MENU_PEN_HBACK_COLORS;
 
 
 extern GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y );
+extern void fghPlatformGetCursorPos(SFG_XYUse *mouse_pos);
 
 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
 
@@ -403,7 +405,7 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
 
 /*
  * Private static function to set the parent window of a submenu and all
- * of its submenus
+ * of its submenus.
  */
 static void fghSetMenuParentWindow( SFG_Window *window, SFG_Menu *menu )
 {
@@ -543,6 +545,17 @@ static void fghActivateMenu( SFG_Window* window, int button )
     menu->Window->State.MouseY =
         window->State.MouseY + glutGet( GLUT_WINDOW_Y ) - menu->Y;
 
+    /* Menu status callback */
+    if (fgState.MenuStateCallback || fgState.MenuStatusCallback)
+    {
+        fgStructure.CurrentMenu = menu;
+        fgStructure.CurrentWindow = window;
+        if (fgState.MenuStateCallback)
+            fgState.MenuStateCallback(GLUT_MENU_IN_USE);
+        if (fgState.MenuStatusCallback)
+            fgState.MenuStatusCallback(GLUT_MENU_IN_USE, window->State.MouseX, window->State.MouseY);
+    }
+
     fgSetWindow( menu->Window );
     glutPositionWindow( menu->X, menu->Y );
     glutReshapeWindow( menu->Width, menu->Height );
@@ -624,27 +637,7 @@ GLboolean fgCheckActiveMenu ( SFG_Window *window, int button, GLboolean pressed,
              * is dealt with in the WM_KILLFOCUS handler of fgPlatformWindowProc
              */
         {
-            if (window->ActiveMenu->ParentWindow)
-                fgDeactivateMenu( window->ActiveMenu->ParentWindow );
-            else
-            {
-                /* 
-                 * Its a rare occasion that a window has an ActiveMenu but
-                 * that menus does not have a parent window. It happens
-                 * however in the corner case bug when one opens a menu in
-                 * a main window, then opens a different menu in this main
-                 * window's child (you now have two menus open
-                 * simultaneously, thats the bug) and then click somewhere
-                 * else that causes both menus to close. One of them is
-                 * then not properly cleaned up. This finishes the cleaning
-                 * and minimizes the impact on the user, he only needs one
-                 * extra mouse click.
-                 */
-                fghSetMenuParentWindow ( NULL, window->ActiveMenu );
-                window->ActiveMenu->IsActive = GL_FALSE;
-                window->ActiveMenu->ActiveEntry = NULL;
-                window->ActiveMenu = NULL;
-            }
+            fgDeactivateMenu( window->ActiveMenu->ParentWindow );
         }
 
         /*
@@ -683,10 +676,10 @@ void fgDeactivateMenu( SFG_Window *window )
     SFG_Menu* menu;
     SFG_MenuEntry *menuEntry;
 
-    /* Check if there is an active menu attached to this window... */
+    /* Did we find an active window? */
     freeglut_return_if_fail( window );
+    /* Check if there is an active menu attached to this window... */
     menu = window->ActiveMenu;
-    /* Did we find an active window? */
     freeglut_return_if_fail( menu );
 
     parent_window = menu->ParentWindow;
@@ -711,12 +704,32 @@ void fgDeactivateMenu( SFG_Window *window )
     {
         menuEntry->IsActive = GL_FALSE;
 
-        /* Is that an active submenu by any case? */
+        /* Is that an active submenu by any chance? */
         if( menuEntry->SubMenu )
             fghDeactivateSubMenu( menuEntry );
     }
 
     fgSetWindow ( parent_window ) ;
+
+    /* Menu status callback */
+    if (fgState.MenuStateCallback || fgState.MenuStatusCallback)
+    {
+        fgStructure.CurrentMenu = menu;
+        fgStructure.CurrentWindow = parent_window;
+        if (fgState.MenuStateCallback)
+            fgState.MenuStateCallback(GLUT_MENU_NOT_IN_USE);
+        if (fgState.MenuStatusCallback)
+        {
+            /* Get cursor position on screen and convert to relative to parent_window's client area */
+            SFG_XYUse mouse_pos;
+            fghPlatformGetCursorPos(&mouse_pos);
+            
+            mouse_pos.X -= glutGet( GLUT_WINDOW_X );
+            mouse_pos.Y -= glutGet( GLUT_WINDOW_Y );
+
+            fgState.MenuStatusCallback(GLUT_MENU_NOT_IN_USE, mouse_pos.X, mouse_pos.Y);
+        }
+    }
 }
 
 /*
@@ -773,6 +786,9 @@ int FGAPIENTRY glutCreateMenu( void(* callback)( int ) )
 {
     /* The menu object creation code resides in freeglut_structure.c */
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateMenu" );
+    if (fgGetActiveMenu())
+        fgError("Menu manipulation not allowed while menus in use.");
+
     return fgCreateMenu( callback )->ID;
 }
 
@@ -787,6 +803,8 @@ void FGAPIENTRY glutDestroyMenu( int menuID )
     menu = fgMenuByID( menuID );
 
     freeglut_return_if_fail( menu );
+    if (fgGetActiveMenu())
+        fgError("Menu manipulation not allowed while menus in use.");
 
     /* The menu object destruction code resides in freeglut_structure.c */
     fgDestroyMenu( menu );
@@ -828,7 +846,10 @@ void FGAPIENTRY glutAddMenuEntry( const char* label, int value )
     SFG_MenuEntry* menuEntry;
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAddMenuEntry" );
     menuEntry = (SFG_MenuEntry *)calloc( sizeof(SFG_MenuEntry), 1 );
+
     freeglut_return_if_fail( fgStructure.CurrentMenu );
+    if (fgGetActiveMenu())
+        fgError("Menu manipulation not allowed while menus in use.");
 
     menuEntry->Text = strdup( label );
     menuEntry->ID   = value;
@@ -852,6 +873,9 @@ void FGAPIENTRY glutAddSubMenu( const char *label, int subMenuID )
     subMenu = fgMenuByID( subMenuID );
 
     freeglut_return_if_fail( fgStructure.CurrentMenu );
+    if (fgGetActiveMenu())
+        fgError("Menu manipulation not allowed while menus in use.");
+
     freeglut_return_if_fail( subMenu );
 
     menuEntry->Text    = strdup( label );
@@ -870,7 +894,10 @@ void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value )
     SFG_MenuEntry* menuEntry = NULL;
 
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToMenuEntry" );
+
     freeglut_return_if_fail( fgStructure.CurrentMenu );
+    if (fgGetActiveMenu())
+        fgError("Menu manipulation not allowed while menus in use.");
 
     /* Get n-th menu entry in the current menu, starting from one: */
     menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item );
@@ -897,10 +924,14 @@ void FGAPIENTRY glutChangeToSubMenu( int item, const char* label,
     SFG_MenuEntry* menuEntry;
 
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutChangeToSubMenu" );
-    subMenu = fgMenuByID( subMenuID );
-    menuEntry = NULL;
 
     freeglut_return_if_fail( fgStructure.CurrentMenu );
+    if (fgGetActiveMenu())
+        fgError("Menu manipulation not allowed while menus in use.");
+
+    /* Get handle to sub menu */
+    subMenu = fgMenuByID( subMenuID );
+    menuEntry = NULL;
     freeglut_return_if_fail( subMenu );
 
     /* Get n-th menu entry in the current menu, starting from one: */
@@ -926,7 +957,10 @@ void FGAPIENTRY glutRemoveMenuItem( int item )
     SFG_MenuEntry* menuEntry;
 
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutRemoveMenuItem" );
+
     freeglut_return_if_fail( fgStructure.CurrentMenu );
+    if (fgGetActiveMenu())
+        fgError("Menu manipulation not allowed while menus in use.");
 
     /* Get n-th menu entry in the current menu, starting from one: */
     menuEntry = fghFindMenuEntry( fgStructure.CurrentMenu, item );
@@ -949,7 +983,10 @@ void FGAPIENTRY glutAttachMenu( int button )
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutAttachMenu" );
 
     freeglut_return_if_fail( fgStructure.CurrentWindow );
+
     freeglut_return_if_fail( fgStructure.CurrentMenu );
+    if (fgGetActiveMenu())
+        fgError("Menu manipulation not allowed while menus in use.");
 
     freeglut_return_if_fail( button >= 0 );
     freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS );
@@ -965,7 +1002,10 @@ void FGAPIENTRY glutDetachMenu( int button )
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDetachMenu" );
 
     freeglut_return_if_fail( fgStructure.CurrentWindow );
+
     freeglut_return_if_fail( fgStructure.CurrentMenu );
+    if (fgGetActiveMenu())
+        fgError("Menu manipulation not allowed while menus in use.");
 
     freeglut_return_if_fail( button >= 0 );
     freeglut_return_if_fail( button < FREEGLUT_MAX_MENUS );