Major menu changes (they appear in their own window, have own rendering context) by John Fay and a little by James C. Jones. They work perfectly on Win32, and work... on Linux.

git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@152 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
puggles 2003-08-02 13:31:19 +00:00
parent 9f3c1dcc82
commit fc93453910
10 changed files with 454 additions and 146 deletions

View File

@ -49,6 +49,12 @@
void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) )
{
SET_CALLBACK( Display );
/*
* Force a redisplay with the new callback
*/
fgStructure.Window->State.Redisplay = TRUE;
}
/*

View File

@ -64,9 +64,8 @@ void FGAPIENTRY glutSwapBuffers( void )
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();
/*

View File

@ -61,16 +61,16 @@ struct freeglutBitmapFont
} ;
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

View File

@ -75,6 +75,7 @@ SFG_State fgState = { { -1, -1, FALSE }, /* Position */
#endif
{ NULL, NULL }, /* Timers */
NULL, /* IdleCallback */
FALSE, /* BuildingAMenu */
NULL, /* MenuStateCallback */
NULL, /* MenuStatusCallback */
{ 640, 480, TRUE }, /* GameModeSize */
@ -268,6 +269,15 @@ void fgDeinitialize( void )
return;
}
/*
* If there was a menu created, destroy the rendering context
*/
if ( fgStructure.MenuContext )
{
free ( fgStructure.MenuContext ) ;
fgStructure.MenuContext = NULL ;
}
/*
* Perform the freeglut structure deinitialization
*/

View File

@ -89,9 +89,11 @@
#include <X11/Xatom.h>
#include <X11/keysym.h>
#if HAVE_X11_EXTENSIONS_XF86VMODE_H
#ifndef __sgi
#ifndef SOLARIS
#include <X11/extensions/xf86vmode.h>
#endif
#endif
#endif
/*
@ -235,6 +237,7 @@ struct tagSFG_State
FGCBidle IdleCallback; /* The global idle callback */
GLboolean BuildingAMenu; /* True if we are presently making a menu */
FGCBmenuState MenuStateCallback; /* Menu callbacks are global */
FGCBmenuStatus MenuStatusCallback;
@ -383,9 +386,26 @@ struct tagSFG_WindowCallbacks
FGCBtabletButton TabletButton;
};
/*
* 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
{
@ -399,12 +419,15 @@ 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;
@ -419,7 +442,6 @@ struct tagSFG_MenuEntry
/*
* A window, making part of freeglut windows hierarchy. Should be kept portable.
*/
typedef struct tagSFG_Window SFG_Window;
struct tagSFG_Window
{
SFG_Node Node;
@ -435,6 +457,8 @@ struct tagSFG_Window
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 */
};
/*
@ -460,6 +484,8 @@ struct tagSFG_Structure
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 */
@ -673,6 +699,7 @@ void fgActivateMenu( SFG_Window* window, int button );
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

View File

@ -652,9 +652,17 @@ void FGAPIENTRY glutMainLoopEvent( void )
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?
@ -669,6 +677,11 @@ void FGAPIENTRY glutMainLoopEvent( void )
*/
if( window->Callbacks.Motion != NULL )
{
/*
* Set the current window
*/
fgStructure.Window = window ;
/*
* Yup. Have it executed immediately
*/
@ -682,6 +695,11 @@ void FGAPIENTRY glutMainLoopEvent( void )
*/
if( window->Callbacks.Passive != NULL )
{
/*
* Set the current window
*/
fgStructure.Window = window ;
/*
* That's right, and there is a passive callback, too.
*/
@ -749,7 +767,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
/* Execute the menu callback */
fgExecuteMenuCallback ( window->ActiveMenu ) ;
fgDeactivateMenu ( window ) ;
fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
/* Restore the current window and menu */
fgSetWindow ( save_window ) ;
@ -757,7 +775,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
}
else /* Outside the menu, deactivate the menu if it's a downclick */
{
if ( pressed == TRUE ) fgDeactivateMenu ( window ) ;
if ( pressed == TRUE ) fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
}
/*
@ -778,6 +796,11 @@ void FGAPIENTRY glutMainLoopEvent( void )
*/
window->State.Redisplay = TRUE ;
/*
* Set the current window
*/
fgSetWindow( window );
/*
* Activate the appropriate menu structure...
*/
@ -789,14 +812,9 @@ void FGAPIENTRY glutMainLoopEvent( void )
/*
* 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
*/
@ -807,12 +825,12 @@ void FGAPIENTRY glutMainLoopEvent( void )
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,
@ -822,7 +840,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
/*
* Trash the modifiers state
*/
window->State.Modifiers = 0xffffffff;
fgStructure.Window->State.Modifiers = 0xffffffff;
}
break;
@ -1169,18 +1187,49 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
*/
window->Window.Device = GetDC( hWnd );
/*
* Create or get the OpenGL rendering context now
*/
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 );
/*
* Create or get the OpenGL rendering context now
*/
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
@ -1465,7 +1514,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
/* Execute the menu callback */
fgExecuteMenuCallback ( window->ActiveMenu ) ;
fgDeactivateMenu ( window ) ;
fgDeactivateMenu ( window->ActiveMenu->ParentWindow ) ;
/* Restore the current window and menu */
fgSetWindow ( save_window ) ;
@ -1473,13 +1522,13 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
}
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 ;
}
@ -1494,6 +1543,11 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
*/
window->State.Redisplay = TRUE ;
/*
* Set the current window
*/
fgSetWindow( window );
/*
* Activate the appropriate menu structure...
*/
@ -1505,18 +1559,13 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
/*
* 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 );
@ -1524,7 +1573,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
/*
* Finally execute the mouse callback
*/
window->Callbacks.Mouse(
fgStructure.Window->Callbacks.Mouse(
button,
pressed == TRUE ? GLUT_DOWN : GLUT_UP,
window->State.MouseX,
@ -1534,7 +1583,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
/*
* Trash the modifiers state
*/
window->State.Modifiers = 0xffffffff;
fgStructure.Window->State.Modifiers = 0xffffffff;
}
break;

View File

@ -96,7 +96,14 @@ static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
* 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 );
}
}
@ -104,8 +111,8 @@ static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
/*
* 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...
@ -116,12 +123,13 @@ static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
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:
@ -140,9 +148,22 @@ static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
menuEntry->IsActive = TRUE;
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;
/*
@ -152,21 +173,31 @@ static GLboolean fghCheckMenuStatus( SFG_Window* window, SFG_Menu* menu )
*/
if( menuEntry->SubMenu != NULL )
{
if ( ! menuEntry->SubMenu->IsActive )
{
SFG_Window *current_window = fgStructure.Window ;
/*
* Set up the initial menu position now...
*/
/*
* 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 ;
/*
* 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 ;
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 ) ;
}
/*
@ -204,20 +235,20 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
* 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();
/*
@ -243,10 +274,10 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
*/
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();
}
}
@ -263,8 +294,8 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
* 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*/
);
/*
@ -292,8 +323,8 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
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();
}
@ -313,11 +344,30 @@ static void fghDisplayMenuBox( SFG_Menu* menu )
/*
* 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
*/
@ -337,9 +387,12 @@ 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:
*/
@ -388,6 +441,13 @@ void fgDisplayMenu( void )
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
glutSwapBuffers () ;
/*
* Restore the current window
*/
fgSetWindow ( window ) ;
}
/*
@ -395,8 +455,6 @@ void fgDisplayMenu( void )
*/
void fgActivateMenu( SFG_Window* window, int button )
{
int x, y;
/*
* We'll be referencing this menu a lot, so remember its address:
*/
@ -408,24 +466,23 @@ void fgActivateMenu( SFG_Window* window, int button )
window->ActiveMenu = menu;
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 ) ;
if( x > ( glutGet( GLUT_WINDOW_WIDTH ) - menu->Width ) )
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 ) )
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; */
}
/*
@ -493,21 +550,81 @@ void fgExecuteMenuCallback( SFG_Menu* menu )
*/
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 ;
}
/*
@ -534,6 +651,13 @@ void fghCalculateMenuBoxSize( void )
*/
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
*/
@ -669,6 +793,11 @@ void FGAPIENTRY glutAddSubMenu( const char* label, int subMenuID )
menuEntry->SubMenu = subMenu;
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
*/
@ -819,6 +948,11 @@ void FGAPIENTRY glutAttachMenu( int button )
* 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 ) ;
}
/*

View File

@ -367,7 +367,8 @@ int FGAPIENTRY glutGet( GLenum eWhat )
/*
* ...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 );
@ -659,7 +660,8 @@ int FGAPIENTRY glutLayerGet( GLenum eWhat )
/*
* 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:
/*

View File

@ -41,7 +41,15 @@
* 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 ---------------------------------------------------- */
@ -102,6 +110,11 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title, int x, int y,
window->State.Cursor = GLUT_CURSOR_INHERIT;
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,6 +132,9 @@ 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
*/
@ -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 */
fgStructure.Window = current_window ;
/*
* Initialize the object properties:
*/
menu->ID = ++fgStructure.MenuID;
menu->Callback = menuCallback;
menu->ActiveEntry = NULL ;
/*
* Initialize the entries list
@ -390,6 +429,11 @@ void fgDestroyMenu( SFG_Menu* menu )
free( entry );
}
/*
* Destroy the window associated with the menu
*/
fgDestroyWindow ( menu->Window, TRUE ) ;
/*
* Remove the menu from the menus list
*/

View File

@ -363,7 +363,24 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
/*
* Here we are upon the stage. Have the visual selected.
*/
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 )
{
/*
@ -430,7 +447,28 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
* 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();
@ -564,7 +602,7 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
if( gameMode == FALSE )
{
if ( !isSubWindow )
if ( ( !isSubWindow ) && ( ! window->IsMenu ) )
{
/*
* Update the window dimensions, taking account of window decorations.
@ -575,26 +613,27 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
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; }
/*
* 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
{
/*
@ -608,7 +647,6 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
}
/*
* Create the window now, passing the freeglut window structure as the parameter
*/
@ -651,14 +689,12 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
glReadBuffer ( GL_FRONT ) ;
}
/*
* Set the newly created window as the current one
*/
fgSetWindow( window );
}
/*
* Closes a window, destroying the frame and OpenGL context
*/
@ -697,7 +733,6 @@ void fgCloseWindow( SFG_Window* window )
}
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
@ -712,7 +747,6 @@ int FGAPIENTRY glutCreateWindow( const char* title )
fgState.Size.X, fgState.Size.Y, FALSE )->ID );
}
/*
* This function creates a sub window.
*/
@ -744,7 +778,6 @@ int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
return( window->ID );
}
/*
* Destroys a window and all of its subwindows
*/
@ -771,7 +804,6 @@ void FGAPIENTRY glutDestroyWindow( int windowID )
fgState.ExecState = ExecState ;
}
/*
* This function selects the current window
*/
@ -808,11 +840,9 @@ void FGAPIENTRY glutSetWindow( int ID )
return;
}
fgSetWindow ( window ) ;
}
/*
* This function returns the ID number of the current window, 0 if none exists
*/
@ -831,14 +861,12 @@ int FGAPIENTRY glutGetWindow( void )
return( 0 );
}
/*
* Otherwise, return the ID of the current window
*/
return( fgStructure.Window->ID );
}
/*
* This function makes the current window visible
*/
@ -860,8 +888,13 @@ void FGAPIENTRY glutShowWindow( void )
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
@ -882,7 +915,6 @@ void FGAPIENTRY glutHideWindow( void )
*/
XWithdrawWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, fgDisplay.Screen );
}
else
{
/*
@ -891,7 +923,6 @@ void FGAPIENTRY glutHideWindow( void )
XUnmapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
}
/*
* Flush the X state now
*/
@ -904,8 +935,12 @@ void FGAPIENTRY glutHideWindow( void )
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)
@ -928,8 +963,13 @@ void FGAPIENTRY glutIconifyWindow( void )
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
@ -971,7 +1011,6 @@ void FGAPIENTRY glutSetWindowTitle( const char* title )
XFlush( fgDisplay.Display );
}
#elif TARGET_HOST_WIN32
/*
* This seems to be a bit easier under Win32
@ -981,7 +1020,6 @@ void FGAPIENTRY glutSetWindowTitle( const char* title )
#endif
}
/*
* Set the current window's iconified title
*/
@ -1022,7 +1060,6 @@ void FGAPIENTRY glutSetIconTitle( const char* title )
XFlush( fgDisplay.Display );
}
#elif TARGET_HOST_WIN32
/*
* This seems to be a bit easier under Win32
@ -1032,7 +1069,6 @@ void FGAPIENTRY glutSetIconTitle( const char* title )
#endif
}
/*
* Change the current window's size
*/
@ -1062,12 +1098,14 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
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
*/
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 ) ;
@ -1075,7 +1113,6 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
y -= winRect.top + GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ) ;
}
/*
* Resize the window, forcing a redraw to happen
*/
@ -1088,11 +1125,9 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
TRUE
);
}
#endif
}
/*
* Change the current window's position
*/
@ -1129,11 +1164,9 @@ void FGAPIENTRY glutPositionWindow( int x, int y )
);
}
#endif
}
/*
* Lowers the current window (by Z order change)
*/
@ -1161,7 +1194,6 @@ void FGAPIENTRY glutPushWindow( void )
#endif
}
/*
* Raises the current window (by Z order change)
*/
@ -1189,7 +1221,6 @@ void FGAPIENTRY glutPopWindow( void )
#endif
}
/*
* Resize the current window so that it fits the whole screen
*/
@ -1208,7 +1239,6 @@ void FGAPIENTRY glutFullScreen( void )
);
}
/*
* A.Donev: Set and retrieve the window's user data
*/
@ -1217,11 +1247,18 @@ void* FGAPIENTRY glutGetWindowData( void )
return(fgStructure.Window->UserData);
}
void FGAPIENTRY glutSetWindowData(void* data)
{
fgStructure.Window->UserData=data;
}
/*** END OF FILE ***/