void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) )
{
SET_CALLBACK( Display );
+
+ /*
+ * Force a redisplay with the new callback
+ */
+ fgStructure.Window->State.Redisplay = TRUE;
+
}
/*
freeglut_assert_ready; freeglut_assert_window;
/*
- * Have the mouse cursor and/or the menus drawn for the current window
+ * Have the mouse cursor drawn for the current window
*/
- fgDisplayMenu();
fgDisplayCursor();
/*
} ;
-struct freeglutStrokeFont glutStrokeRoman ;
-struct freeglutStrokeFont glutStrokeMonoRoman ;
+struct freeglutStrokeFont *glutStrokeRoman ;
+struct freeglutStrokeFont *glutStrokeMonoRoman ;
-struct freeglutBitmapFont glutBitmap9By15 ;
-struct freeglutBitmapFont glutBitmap8By13 ;
-struct freeglutBitmapFont glutBitmapTimesRoman10 ;
-struct freeglutBitmapFont glutBitmapTimesRoman24 ;
-struct freeglutBitmapFont glutBitmapHelvetica10 ;
-struct freeglutBitmapFont glutBitmapHelvetica12 ;
-struct freeglutBitmapFont glutBitmapHelvetica18 ;
+struct freeglutBitmapFont *glutBitmap9By15 ;
+struct freeglutBitmapFont *glutBitmap8By13 ;
+struct freeglutBitmapFont *glutBitmapTimesRoman10 ;
+struct freeglutBitmapFont *glutBitmapTimesRoman24 ;
+struct freeglutBitmapFont *glutBitmapHelvetica10 ;
+struct freeglutBitmapFont *glutBitmapHelvetica12 ;
+struct freeglutBitmapFont *glutBitmapHelvetica18 ;
#endif
#endif
{ NULL, NULL }, /* Timers */
NULL, /* IdleCallback */
+ FALSE, /* BuildingAMenu */
NULL, /* MenuStateCallback */
NULL, /* MenuStatusCallback */
{ 640, 480, TRUE }, /* GameModeSize */
}
/*
+ * If there was a menu created, destroy the rendering context
+ */
+ if ( fgStructure.MenuContext )
+ {
+ free ( fgStructure.MenuContext ) ;
+ fgStructure.MenuContext = NULL ;
+ }
+
+ /*
* Perform the freeglut structure deinitialization
*/
fgDestroyStructure();
#include <X11/Xatom.h>
#include <X11/keysym.h>
- #if HAVE_X11_EXTENSIONS_XF86VMODE_H
- #include <X11/extensions/xf86vmode.h>
+ #ifndef __sgi
+ #ifndef SOLARIS
+ #include <X11/extensions/xf86vmode.h>
+ #endif
#endif
#endif
FGCBidle IdleCallback; /* The global idle callback */
+ GLboolean BuildingAMenu; /* True if we are presently making a menu */
FGCBmenuState MenuStateCallback; /* Menu callbacks are global */
FGCBmenuStatus MenuStatusCallback;
};
/*
+ * This structure holds the OpenGL rendering context for all the menu windows
+ */
+typedef struct tagSFG_MenuContext SFG_MenuContext;
+struct tagSFG_MenuContext
+{
+#if TARGET_HOST_UNIX_X11
+ GLXContext Context; /* The menu OpenGL context */
+ XVisualInfo* VisualInfo; /* The window's visual information */
+#elif TARGET_HOST_WIN32
+ HGLRC Context; /* The menu window's WGL context */
+#endif
+
+};
+
+/*
* This structure describes a menu
*/
+typedef struct tagSFG_Window SFG_Window;
+typedef struct tagSFG_MenuEntry SFG_MenuEntry;
typedef struct tagSFG_Menu SFG_Menu;
struct tagSFG_Menu
{
int Width; /* Menu box width in pixels */
int Height; /* Menu box height in pixels */
int X, Y; /* Menu box raster position */
+
+ SFG_MenuEntry *ActiveEntry ; /* Currently active entry in the menu */
+ SFG_Window *Window ; /* OpenGL window for menu */
+ SFG_Window *ParentWindow ; /* OpenGL window in which the menu is defined */
};
/*
* This is a menu entry
*/
-typedef struct tagSFG_MenuEntry SFG_MenuEntry;
struct tagSFG_MenuEntry
{
SFG_Node Node;
/*
* A window, making part of freeglut windows hierarchy. Should be kept portable.
*/
-typedef struct tagSFG_Window SFG_Window;
struct tagSFG_Window
{
SFG_Node Node;
SFG_Window* Parent; /* The parent to this window */
SFG_List Children; /* The subwindows d.l. list */
+
+ GLboolean IsMenu; /* Set to 1 if we are a menu */
};
/*
SFG_Window* Window; /* The currently active win. */
SFG_Menu* Menu; /* Same, but menu... */
+ SFG_MenuContext* MenuContext; /* OpenGL rendering context for menus */
+
SFG_Window* GameMode; /* The game mode window */
int WindowID; /* The new current window ID */
void fgExecuteMenuCallback( SFG_Menu* menu ) ;
GLboolean fgCheckActiveMenu ( SFG_Window *window, SFG_Menu *menu ) ;
void fgDeactivateMenu( SFG_Window *window );
+void fgDeactivateSubMenu( SFG_MenuEntry *menuEntry );
/*
* This function gets called just before the buffers swap, so that
GETWINDOW( xmotion ); GETMOUSE( xmotion );
/*
- * Set the current window
+ * Fallback if there's an active menu hooked to this window
*/
- fgStructure.Window = window ;
+ if( window->ActiveMenu != NULL )
+ {
+ /*
+ * Let's make the window redraw as a result of the mouse motion.
+ */
+ window->State.Redisplay = TRUE ;
+
+ break;
+ }
/*
* What kind of a movement was it?
if( window->Callbacks.Motion != NULL )
{
/*
+ * Set the current window
+ */
+ fgStructure.Window = window ;
+
+ /*
* Yup. Have it executed immediately
*/
window->Callbacks.Motion( event.xmotion.x, event.xmotion.y );
if( window->Callbacks.Passive != NULL )
{
/*
+ * Set the current window
+ */
+ fgStructure.Window = window ;
+
+ /*
* That's right, and there is a passive callback, too.
*/
window->Callbacks.Passive( event.xmotion.x, event.xmotion.y );
/* Execute the menu callback */
fgExecuteMenuCallback ( window->ActiveMenu ) ;
- fgDeactivateMenu ( window ) ;
+ fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
/* Restore the current window and menu */
fgSetWindow ( save_window ) ;
}
else /* Outside the menu, deactivate the menu if it's a downclick */
{
- if ( pressed == TRUE ) fgDeactivateMenu ( window ) ;
+ if ( pressed == TRUE ) fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
}
/*
window->State.Redisplay = TRUE ;
/*
+ * Set the current window
+ */
+ fgSetWindow( window );
+
+ /*
* Activate the appropriate menu structure...
*/
fgActivateMenu( window, button );
/*
* Check if there is a mouse callback hooked to the window
*/
- if( window->Callbacks.Mouse == NULL )
+ if( fgStructure.Window->Callbacks.Mouse == NULL )
break;
/*
- * Set the current window
- */
- fgSetWindow( window );
-
- /*
* Remember the current modifiers state
*/
modifiers = 0;
modifiers |= GLUT_ACTIVE_CTRL;
if (event.xbutton.state & Mod1Mask)
modifiers |= GLUT_ACTIVE_ALT;
- window->State.Modifiers = modifiers;
+ fgStructure.Window->State.Modifiers = modifiers;
/*
* Finally execute the mouse callback
*/
- window->Callbacks.Mouse(
+ fgStructure.Window->Callbacks.Mouse(
button,
event.type == ButtonPress ? GLUT_DOWN : GLUT_UP,
event.xbutton.x,
/*
* Trash the modifiers state
*/
- window->State.Modifiers = 0xffffffff;
+ fgStructure.Window->State.Modifiers = 0xffffffff;
}
break;
window->Window.Device = GetDC( hWnd );
/*
- * Setup the pixel format of our window
- */
- fgSetupPixelFormat( window, FALSE, PFD_MAIN_PLANE );
-
- /*
* Create or get the OpenGL rendering context now
*/
- if ( fgState.UseCurrentContext == TRUE )
- window->Window.Context = wglGetCurrentContext();
- else
+ if ( fgState.BuildingAMenu )
+ {
+ /*
+ * Setup the pixel format of our window
+ */
+ unsigned int current_DisplayMode = fgState.DisplayMode ;
+ fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ;
+ fgSetupPixelFormat( window, FALSE, PFD_MAIN_PLANE );
+ fgState.DisplayMode = current_DisplayMode ;
+
+ /*
+ * If there isn't already an OpenGL rendering context for menu windows, make one
+ */
+ if ( !fgStructure.MenuContext )
+ {
+ fgStructure.MenuContext = (SFG_MenuContext *)malloc ( sizeof(SFG_MenuContext) ) ;
+ fgStructure.MenuContext->Context = wglCreateContext( window->Window.Device );
+ }
+ else
+ wglMakeCurrent ( window->Window.Device, fgStructure.MenuContext->Context ) ;
+
+/* window->Window.Context = wglGetCurrentContext () ; */
window->Window.Context = wglCreateContext( window->Window.Device );
+ }
+ else
+ {
+ /*
+ * Setup the pixel format of our window
+ */
+ fgSetupPixelFormat( window, FALSE, PFD_MAIN_PLANE );
+
+ if ( fgState.UseCurrentContext == TRUE )
+ {
+ window->Window.Context = wglGetCurrentContext();
+ if ( ! window->Window.Context )
+ window->Window.Context = wglCreateContext( window->Window.Device );
+ }
+ else
+ window->Window.Context = wglCreateContext( window->Window.Device );
+ }
/*
* Still, we'll be needing to explicitly resize the window
/* Execute the menu callback */
fgExecuteMenuCallback ( window->ActiveMenu ) ;
- fgDeactivateMenu ( window ) ;
+ fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
/* Restore the current window and menu */
fgSetWindow ( save_window ) ;
}
else /* Outside the menu, deactivate the menu if it's a downclick */
{
- if ( pressed == TRUE ) fgDeactivateMenu ( window ) ;
+ if ( pressed == TRUE ) fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
}
/*
* Let's make the window redraw as a result of the mouse click and menu activity.
*/
- window->State.Redisplay = TRUE ;
+ if ( ! window->IsMenu ) window->State.Redisplay = TRUE ;
break ;
}
window->State.Redisplay = TRUE ;
/*
+ * Set the current window
+ */
+ fgSetWindow( window );
+
+ /*
* Activate the appropriate menu structure...
*/
fgActivateMenu( window, button );
/*
* Check if there is a mouse callback hooked to the window
*/
- if( window->Callbacks.Mouse == NULL )
+ if( fgStructure.Window->Callbacks.Mouse == NULL )
break;
/*
- * Set the current window
- */
- fgSetWindow( window );
-
- /*
* Remember the current modifiers state.
*/
- window->State.Modifiers =
+ fgStructure.Window->State.Modifiers =
( ( (GetKeyState( VK_LSHIFT ) < 0 ) || ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
( ( (GetKeyState( VK_LCONTROL ) < 0 ) || ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
( ( (GetKeyState( VK_LMENU ) < 0 ) || ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
/*
* Finally execute the mouse callback
*/
- window->Callbacks.Mouse(
+ fgStructure.Window->Callbacks.Mouse(
button,
pressed == TRUE ? GLUT_DOWN : GLUT_UP,
window->State.MouseX,
/*
* Trash the modifiers state
*/
- window->State.Modifiers = 0xffffffff;
+ fgStructure.Window->State.Modifiers = 0xffffffff;
}
break;
* that it caught the mouse cursor and we do not need to regenerate
* the activity list, and so our parents do...
*/
- if( fghCheckMenuStatus( window, menuEntry->SubMenu ) == TRUE )
+ GLboolean return_status = fghCheckMenuStatus( window, menuEntry->SubMenu ) ;
+
+ /*
+ * Reactivate the submenu as the checkMenuStatus may have turned it off if the mouse
+ * is in its parent menu entry.
+ */
+ menuEntry->SubMenu->IsActive = TRUE ;
+ if ( return_status == TRUE )
return( TRUE );
}
}
/*
* That much about our sub menus, let's get to checking the current menu:
*/
- x = window->State.MouseX - menu->X;
- y = window->State.MouseY - menu->Y;
+ x = window->State.MouseX;
+ y = window->State.MouseY;
/*
* Mark all menu entries inactive...
menuEntry->IsActive = FALSE;
}
+
menu->IsActive = FALSE;
/*
* Check if the mouse cursor is contained within the current menu box
*/
- if( x >= 0 && x < menu->Width && y >= 0 && y < menu->Height )
+ if ( ( x >= 0 ) && ( x < menu->Width ) && ( y >= 0 ) && ( y < menu->Height ) && ( window == menu->Window ) )
{
/*
* Calculation of the highlighted menu item is easy enough now:
menuEntry->Ordinal = menuID;
/*
+ * If this is not the same as the last active menu entry, deactivate the previous entry.
+ * Specifically, if the previous active entry was a submenu then deactivate it.
+ */
+ if ( menu->ActiveEntry && ( menuEntry != menu->ActiveEntry ) )
+ {
+ if ( menu->ActiveEntry->SubMenu != NULL )
+ fgDeactivateSubMenu ( menu->ActiveEntry ) ;
+ }
+
+ menu->ActiveEntry = menuEntry ;
+
+ /*
* Don't forget about marking the current menu as active, too:
*/
+
menu->IsActive = TRUE;
/*
*/
if( menuEntry->SubMenu != NULL )
{
- /*
- * Set up the initial menu position now...
- */
+ if ( ! menuEntry->SubMenu->IsActive )
+ {
+ SFG_Window *current_window = fgStructure.Window ;
- menuEntry->SubMenu->X = menu->X + menu->Width ;
- menuEntry->SubMenu->Y = menu->Y + menuEntry->Ordinal * FREEGLUT_MENU_HEIGHT ;
+ /*
+ * Set up the initial menu position now...
+ */
- /*
- * Make sure the submenu stays within the window
- */
- if ( menuEntry->SubMenu->X + menuEntry->SubMenu->Width > glutGet ( GLUT_WINDOW_WIDTH ) )
- {
- menuEntry->SubMenu->X = menu->X - menuEntry->SubMenu->Width ;
- if ( menuEntry->SubMenu->X < 0 )
- menuEntry->SubMenu->X = glutGet ( GLUT_WINDOW_WIDTH ) - menuEntry->SubMenu->Width ;
+ /*
+ * Mark the menu as active, so that it gets displayed:
+ */
+ menuEntry->SubMenu->IsActive = TRUE ;
+
+ /*
+ * Set up the initial submenu position now:
+ */
+ menuEntry->SubMenu->X = menu->X + menu->Width ;
+ menuEntry->SubMenu->Y = menu->Y + menuEntry->Ordinal * FREEGLUT_MENU_HEIGHT ;
+
+ fgSetWindow ( menuEntry->SubMenu->Window ) ;
+ glutShowWindow () ;
+ glutPositionWindow ( menuEntry->SubMenu->X, menuEntry->SubMenu->Y ) ;
+ glutReshapeWindow ( menuEntry->SubMenu->Width, menuEntry->SubMenu->Height ) ;
+ menuEntry->SubMenu->Window->ActiveMenu = menuEntry->SubMenu ;
+ fgSetWindow ( current_window ) ;
}
/*
* Have the menu box drawn first. The +- values are
* here just to make it more nice-looking...
*/
- glColor4f( 0.0f, 0.0f, 0.0f, 1.0f );
+ glColor4f( 0.1289f, 0.2257f, 0.28516f, 1.0f ); /* a non-black dark version of the below. */
glBegin( GL_QUADS );
- glVertex2i( menu->X , menu->Y - 1 );
- glVertex2i( menu->X + menu->Width, menu->Y - 1 );
- glVertex2i( menu->X + menu->Width, menu->Y + 4 + menu->Height );
- glVertex2i( menu->X , menu->Y + 4 + menu->Height );
+ glVertex2i( 0 , 0 );
+ glVertex2i( menu->Width, 0 );
+ glVertex2i( menu->Width, menu->Height );
+ glVertex2i( 0 , menu->Height );
glEnd();
glColor4f( 0.3f, 0.4f, 0.5f, 1.0f );
glBegin( GL_QUADS );
- glVertex2i( menu->X - 2 , menu->Y + 1 );
- glVertex2i( menu->X - 2 + menu->Width, menu->Y + 1 );
- glVertex2i( menu->X - 2 + menu->Width, menu->Y + 2 + menu->Height );
- glVertex2i( menu->X - 2 , menu->Y + 2 + menu->Height );
+ glVertex2i( 1, 1 );
+ glVertex2i( menu->Width-1, 1 );
+ glVertex2i( menu->Width-1, menu->Height-1);
+ glVertex2i( 1, menu->Height-1);
glEnd();
/*
*/
glColor4f( 0.2f, 0.3f, 0.4f, 1.0f );
glBegin( GL_QUADS );
- glVertex2i( menu->X - 2 , menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
- glVertex2i( menu->X - 2 + menu->Width, menu->Y + (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
- glVertex2i( menu->X - 2 + menu->Width, menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
- glVertex2i( menu->X - 2 , menu->Y + (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
+ glVertex2i( 2 , (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
+ glVertex2i( menu->Width-2, (menuID + 0)*FREEGLUT_MENU_HEIGHT + 1 );
+ glVertex2i( menu->Width-2, (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
+ glVertex2i( 2 , (menuID + 1)*FREEGLUT_MENU_HEIGHT + 2 );
glEnd();
}
}
* Move the raster into position...
*/
glRasterPos2i(
- menu->X + FREEGLUT_MENU_BORDER,
- menu->Y + (i + 1)*FREEGLUT_MENU_HEIGHT
+ FREEGLUT_MENU_BORDER,
+ (i + 1)*FREEGLUT_MENU_HEIGHT-(int)(FREEGLUT_MENU_HEIGHT*0.3) /* Try to center the text - JCJ 31 July 2003*/
);
/*
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
- glRasterPos2i ( menu->X + menu->Width - 2 - width,
- menu->Y + (i + 1)*FREEGLUT_MENU_HEIGHT ) ;
+ glRasterPos2i ( menu->Width - 2 - width,
+ (i + 1)*FREEGLUT_MENU_HEIGHT ) ;
glBitmap ( width, FREEGLUT_MENU_HEIGHT, 0, 0, 0.0, 0.0, arrow_char ) ;
glPopClientAttrib();
}
/*
* Yeah, indeed. Have it redrawn now:
*/
+ fgSetWindow ( menuEntry->SubMenu->Window ) ;
fghDisplayMenuBox( menuEntry->SubMenu );
+ fgSetWindow ( menu->Window ) ;
}
}
}
/*
+ * Private static function to set the parent window of a submenu and all of its submenus
+ */
+static void fghSetSubmenuParentWindow ( SFG_Window *window, SFG_Menu *menu )
+{
+ SFG_MenuEntry *menuEntry ;
+
+ menu->ParentWindow = window ;
+
+ for ( menuEntry = menu->Entries.First; menuEntry; menuEntry = menuEntry->Node.Next )
+ {
+ if ( menuEntry->SubMenu != NULL )
+ fghSetSubmenuParentWindow ( window, menuEntry->SubMenu ) ;
+ }
+}
+
+
+/*
* Displays the currently active menu for the current window
*/
void fgDisplayMenu( void )
menu = window->ActiveMenu;
/*
- * Did we find an active window?
+ * Did we find an active menu?
*/
freeglut_return_if_fail( menu != NULL );
+
+ fgSetWindow ( menu->Window ) ;
+
/*
* Prepare the OpenGL state to do the rendering first:
*/
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
+
+ glutSwapBuffers () ;
+
+ /*
+ * Restore the current window
+ */
+ fgSetWindow ( window ) ;
}
/*
*/
void fgActivateMenu( SFG_Window* window, int button )
{
- int x, y;
-
/*
* We'll be referencing this menu a lot, so remember its address:
*/
menu->IsActive = TRUE ;
/*
- * Grab the mouse cursor position respective to the current window
- */
- x = window->State.MouseX;
- y = window->State.MouseY;
-
- /*
* Set up the initial menu position now:
*/
- menu->X = x ;
- menu->Y = y ;
- fgSetWindow ( window ) ;
+ menu->X = window->State.MouseX + glutGet ( GLUT_WINDOW_X ) ;
+ menu->Y = window->State.MouseY + glutGet ( GLUT_WINDOW_Y ) ;
+
+ fgSetWindow ( menu->Window ) ;
+ glutShowWindow () ;
+ glutPositionWindow ( menu->X, menu->Y ) ;
+ glutReshapeWindow ( menu->Width, menu->Height ) ;
+ menu->Window->ActiveMenu = menu ;
- if( x > ( glutGet( GLUT_WINDOW_WIDTH ) - menu->Width ) )
+/* if( x > ( glutGet( GLUT_WINDOW_WIDTH ) - menu->Width ) )
menu->X = glutGet( GLUT_WINDOW_WIDTH ) - menu->Width;
if( y > ( glutGet( GLUT_WINDOW_HEIGHT ) - menu->Height) )
- menu->Y = glutGet( GLUT_WINDOW_HEIGHT ) - menu->Height;
+ menu->Y = glutGet( GLUT_WINDOW_HEIGHT ) - menu->Height; */
}
/*
*/
void fgDeactivateMenu( SFG_Window *window )
{
+ SFG_Window *current_window = fgStructure.Window ;
+
/*
* Check if there is an active menu attached to this window...
*/
SFG_Menu* menu = window->ActiveMenu;
+ SFG_MenuEntry *menuEntry ;
/*
* Did we find an active window?
freeglut_return_if_fail( menu != NULL );
/*
+ * Hide the present menu's window
+ */
+ fgSetWindow ( menu->Window ) ;
+ glutHideWindow () ;
+
+ /*
* Forget about having that menu active anymore, now:
*/
- window->ActiveMenu = NULL;
+ menu->Window->ActiveMenu = NULL ;
+ menu->ParentWindow->ActiveMenu = NULL ;
menu->IsActive = FALSE ;
+
+ /*
+ * Hide all submenu windows, and the root menu's window.
+ */
+ for ( menuEntry = menu->Entries.First; menuEntry;
+ menuEntry = menuEntry->Node.Next )
+ {
+ /*
+ * Is that an active submenu by any case?
+ */
+ if ( ( menuEntry->SubMenu != NULL ) && menuEntry->SubMenu->IsActive )
+ fgDeactivateSubMenu ( menuEntry ) ;
+ }
+
+ fgStructure.Window = current_window ;
+}
+
+/*
+ * Deactivates a menu pointed by the function argument.
+ */
+void fgDeactivateSubMenu( SFG_MenuEntry *menuEntry )
+{
+ SFG_Window *current_window = fgStructure.Window ;
+ SFG_MenuEntry *subMenuIter ;
+ /*
+ * Hide the present menu's window
+ */
+ fgSetWindow ( menuEntry->SubMenu->Window ) ;
+ glutHideWindow () ;
+
+ /*
+ * Forget about having that menu active anymore, now:
+ */
+ menuEntry->SubMenu->Window->ActiveMenu = NULL ;
+ menuEntry->SubMenu->IsActive = FALSE ;
+
+ /*
+ * Hide all submenu windows, and the root menu's window.
+ */
+ for ( subMenuIter = menuEntry->SubMenu->Entries.First; subMenuIter;
+ subMenuIter = subMenuIter->Node.Next )
+ {
+ /*
+ * Is that an active submenu by any case?
+ */
+ if ( ( subMenuIter->SubMenu != NULL ) && subMenuIter->SubMenu->IsActive )
+ fgDeactivateSubMenu ( subMenuIter ) ;
+ }
+
+ fgStructure.Window = current_window ;
}
/*
menuEntry->Width = glutBitmapLength( FREEGLUT_MENU_FONT, menuEntry->Text );
/*
+ * If the entry is a submenu, then it needs to be wider to accomodate the arrow. JCJ 31 July 2003
+ */
+
+ if (menuEntry->SubMenu != NULL)
+ menuEntry->Width += glutBitmapLength( FREEGLUT_MENU_FONT, " " );
+
+ /*
* Check if it's the biggest we've found
*/
if( menuEntry->Width > width )
menuEntry->ID = -1;
/*
+ * Make the submenu's parent window be the menu's parent window
+ */
+ fghSetSubmenuParentWindow ( fgStructure.Menu->ParentWindow, subMenu ) ;
+
+ /*
* Have the new menu entry attached to the current menu
*/
fgListAppend( &fgStructure.Menu->Entries, &menuEntry->Node );
* It is safe now to attach the menu
*/
fgStructure.Window->Menu[ button ] = fgStructure.Menu;
+
+ /*
+ * Make the parent window of the menu (and all submenus) the current window
+ */
+ fghSetSubmenuParentWindow ( fgStructure.Window, fgStructure.Menu ) ;
}
/*
/*
* ...then we've got to correct the results we've just received...
*/
- if ( ( fgStructure.GameMode != fgStructure.Window ) && ( fgStructure.Window->Parent == NULL ) )
+ if ( ( fgStructure.GameMode != fgStructure.Window ) && ( fgStructure.Window->Parent == NULL ) &&
+ ( ! fgStructure.Window->IsMenu ) )
{
winRect.left += GetSystemMetrics( SM_CXSIZEFRAME );
winRect.right -= GetSystemMetrics( SM_CXSIZEFRAME );
/*
* Check if an overlay display mode is possible
*/
- return FALSE;
+/* return( fgSetupPixelFormat( fgStructure.Window, TRUE, PFD_OVERLAY_PLANE ) ); */
+ return FALSE ;
case GLUT_LAYER_IN_USE:
/*
* 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 ---------------------------------------------------- */
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.
*/
*/
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
*/
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 */
+ fgStructure.Window = current_window ;
+
/*
* Initialize the object properties:
*/
menu->ID = ++fgStructure.MenuID;
menu->Callback = menuCallback;
+ menu->ActiveEntry = NULL ;
/*
* Initialize the entries list
}
/*
+ * Destroy the window associated with the menu
+ */
+ fgDestroyWindow ( menu->Window, TRUE ) ;
+
+ /*
* Remove the menu from the menus list
*/
fgListRemove( &fgStructure.Menus, &menu->Node );
* It might be the case for us to use double buffering
*/
if( fgState.DisplayMode & GLUT_DOUBLE )
- flags |= PFD_DOUBLEBUFFER;
+ flags |= PFD_DOUBLEBUFFER;
/*
* Specify which pixel format do we opt for...
/*
* Here we are upon the stage. Have the visual selected.
*/
- window->Window.VisualInfo = fgChooseVisual();
+ if ( fgState.BuildingAMenu )
+ {
+ /*
+ * If there isn't already an OpenGL rendering context for menu windows, make one
+ */
+ if ( !fgStructure.MenuContext )
+ {
+ unsigned int current_DisplayMode = fgState.DisplayMode ;
+ fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ;
+ window->Window.VisualInfo = fgChooseVisual();
+ fgState.DisplayMode = current_DisplayMode ;
+ }
+ else
+ window->Window.VisualInfo = fgChooseVisual();
+ }
+ else
+ window->Window.VisualInfo = fgChooseVisual();
+
if ( ! window->Window.VisualInfo )
{
/*
* The GLX context creation, possibly trying the direct context rendering
* or else use the current context if the user has so specified
*/
- if ( fgState.UseCurrentContext == TRUE )
+ if ( fgState.BuildingAMenu )
+ {
+ /*
+ * If there isn't already an OpenGL rendering context for menu windows, make one
+ */
+ if ( !fgStructure.MenuContext )
+ {
+ fgStructure.MenuContext = (SFG_MenuContext *)malloc ( sizeof(SFG_MenuContext) ) ;
+ fgStructure.MenuContext->VisualInfo = window->Window.VisualInfo ;
+ fgStructure.MenuContext->Context = glXCreateContext(
+ fgDisplay.Display, fgStructure.MenuContext->VisualInfo,
+ NULL, fgState.ForceDirectContext | fgState.TryDirectContext
+ );
+ }
+
+/* window->Window.Context = fgStructure.MenuContext->Context ; */
+ window->Window.Context = glXCreateContext(
+ fgDisplay.Display, window->Window.VisualInfo,
+ NULL, fgState.ForceDirectContext | fgState.TryDirectContext
+ );
+ }
+ else if ( fgState.UseCurrentContext == TRUE )
{
window->Window.Context = glXGetCurrentContext();
if( gameMode == FALSE )
{
- if ( !isSubWindow )
+ if ( ( !isSubWindow ) && ( ! window->IsMenu ) )
{
/*
* Update the window dimensions, taking account of window decorations.
h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 + GetSystemMetrics( SM_CYCAPTION );
}
-
/*
* Check if the user wants us to use the default position/size
*/
if( fgState.Position.Use == FALSE ) { x = CW_USEDEFAULT; y = CW_USEDEFAULT; }
-
- if( fgState.Size .Use == FALSE ) { w = CW_USEDEFAULT; h = CW_USEDEFAULT; }
+ if( fgState.Size .Use == FALSE ) { w = CW_USEDEFAULT; h = CW_USEDEFAULT; }
-
- /*
+ /*
* There's a small difference between creating the top, child and game mode windows
*/
flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
- if( window->Parent == NULL )
+ /*
+ * If we're a menu, set our flags to include WS_POPUP to remove decorations
+ */
+ if ( window->IsMenu )
+ flags |= WS_POPUP ;
+ else if( window->Parent == NULL )
flags |= WS_OVERLAPPEDWINDOW;
else
flags |= WS_CHILD;
}
-
else
{
/*
flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
}
-
/*
* Create the window now, passing the freeglut window structure as the parameter
*/
glReadBuffer ( GL_FRONT ) ;
}
-
/*
* Set the newly created window as the current one
*/
fgSetWindow( window );
}
-
/*
* Closes a window, destroying the frame and OpenGL context
*/
}
-
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
fgState.Size.X, fgState.Size.Y, FALSE )->ID );
}
-
/*
* This function creates a sub window.
*/
return( window->ID );
}
-
/*
* Destroys a window and all of its subwindows
*/
fgState.ExecState = ExecState ;
}
-
/*
* This function selects the current window
*/
return;
}
-
fgSetWindow ( window ) ;
}
-
/*
* This function returns the ID number of the current window, 0 if none exists
*/
return( 0 );
}
-
/*
* Otherwise, return the ID of the current window
*/
return( fgStructure.Window->ID );
}
-
/*
* This function makes the current window visible
*/
ShowWindow( fgStructure.Window->Window.Handle, SW_SHOW );
#endif
-}
+ /*
+ * Since the window is visible, we need to redisplay it ...
+ */
+ fgStructure.Window->State.Redisplay = TRUE;
+
+}
/*
* This function hides the current window
*/
XWithdrawWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, fgDisplay.Screen );
}
-
else
{
/*
XUnmapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
}
-
/*
* Flush the X state now
*/
ShowWindow( fgStructure.Window->Window.Handle, SW_HIDE );
#endif
-}
+ /*
+ * Since the window is hidden, we don't need to redisplay it ...
+ */
+ fgStructure.Window->State.Redisplay = FALSE;
+}
/*
* Iconify the current window (top-level windows only)
ShowWindow( fgStructure.Window->Window.Handle, SW_MINIMIZE );
#endif
-}
+ /*
+ * Since the window is just an icon, we don't need to redisplay it ...
+ */
+ fgStructure.Window->State.Redisplay = FALSE;
+
+}
/*
* Set the current window's title
XFlush( fgDisplay.Display );
}
-
#elif TARGET_HOST_WIN32
/*
* This seems to be a bit easier under Win32
#endif
}
-
/*
* Set the current window's iconified title
*/
XFlush( fgDisplay.Display );
}
-
#elif TARGET_HOST_WIN32
/*
* This seems to be a bit easier under Win32
#endif
}
-
/*
* Change the current window's size
*/
if ( fgStructure.Window->Parent == NULL ) /* If this is not a subwindow ... */
{
/*
- * Adjust the size of the window to allow for the size of the frame
+ * Adjust the size of the window to allow for the size of the frame, if we are not a menu
*/
- width += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
- height += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + GetSystemMetrics( SM_CYCAPTION );
+ if ( ! fgStructure.Window->IsMenu )
+ {
+ width += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
+ height += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + GetSystemMetrics( SM_CYCAPTION );
+ }
}
-
else /* This is a subwindow, get the parent window's position and subtract it off */
{
GetWindowRect ( fgStructure.Window->Parent->Window.Handle, &winRect ) ;
y -= winRect.top + GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ) ;
}
-
/*
* Resize the window, forcing a redraw to happen
*/
TRUE
);
}
-
#endif
}
-
/*
* Change the current window's position
*/
);
}
-
#endif
}
-
/*
* Lowers the current window (by Z order change)
*/
#endif
}
-
/*
* Raises the current window (by Z order change)
*/
#endif
}
-
/*
* Resize the current window so that it fits the whole screen
*/
);
}
-
/*
* A.Donev: Set and retrieve the window's user data
*/
return(fgStructure.Window->UserData);
}
-
void FGAPIENTRY glutSetWindowData(void* data)
{
fgStructure.Window->UserData=data;
}
-
/*** END OF FILE ***/
+
+
+
+
+
+
+
+
+