Converted the "Callbacks" structure (with named members holding individual

callback pointers) to a "CallBacks" array in fgState.  (This is to allow
us to write a loop to clear all callbacks from windows when the window is
dead/dying.  Using this, we can safely assign NULL to each in a loop.)

Support includes two new macros, FETCH_WCB() and INVOKE_WCB().  See
freeglut_internal.h for more details there.

Some typedefs of function pointer types were altered to make them more
uniform (necessary for the macros).

All references to window-based callbacks in freeglut are updated to
use the new macros.

Old usages will cause compile-time errors.

As a side bonus, the new invocation macro sets the current window and
checks pointers so that these common steps can be uniformly done on
every window-based callback.  This makes it easier to do things right.
At the same time, the array notation (and now required associated casts)
make it harder to bypass the macros and abuse the function pointers,
in general.

After this commit, I will go through the code and clean up dangling issues
about formatting.  This commit is just a "it now works, let's checkpoint it"
type of affair.


git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@303 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
rkrolib 2003-11-06 22:09:35 +00:00
parent b7dd45a935
commit 80a523394c
7 changed files with 424 additions and 219 deletions

View File

@ -41,7 +41,8 @@
#define SET_CALLBACK(a) \ #define SET_CALLBACK(a) \
if( fgStructure.Window == NULL ) \ if( fgStructure.Window == NULL ) \
return; \ return; \
fgStructure.Window->Callbacks.a = callback; FETCH_WCB( ( *( fgStructure.Window ) ), a ) = callback;
/* fgStructure.Window->Callbacks.a = callback; */
/* /*
* Sets the Display callback for the current window * Sets the Display callback for the current window
@ -115,14 +116,25 @@ void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ),
*/ */
static void fghVisibility( int status ) static void fghVisibility( int status )
{ {
FGCBVisibility vis;
int glut_status;
freeglut_assert_ready; freeglut_assert_ready;
freeglut_return_if_fail( fgStructure.Window ); freeglut_return_if_fail( fgStructure.Window );
freeglut_return_if_fail( fgStructure.Window->Callbacks.Visibility ); vis = FETCH_WCB( ( *( fgStructure.Window ) ), Visibility );
freeglut_return_if_fail( vis );
/* Callbacks.Visibility ); */
if( status == GLUT_HIDDEN || status == GLUT_FULLY_COVERED ) if( status == GLUT_HIDDEN || status == GLUT_FULLY_COVERED )
glut_status = GLUT_NOT_VISIBLE;
else
glut_status = GLUT_VISIBLE;
vis( glut_status );
/*
fgStructure.Window->Callbacks.Visibility( GLUT_NOT_VISIBLE ); fgStructure.Window->Callbacks.Visibility( GLUT_NOT_VISIBLE );
else else
fgStructure.Window->Callbacks.Visibility( GLUT_VISIBLE ); fgStructure.Window->Callbacks.Visibility( GLUT_VISIBLE );
*/
} }
void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) ) void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) )

View File

@ -262,8 +262,8 @@ void fgDeinitialize( void )
fgState.Timers.First = fgState.Timers.Last = NULL; fgState.Timers.First = fgState.Timers.Last = NULL;
fgState.IdleCallback = NULL; fgState.IdleCallback = NULL;
fgState.MenuStateCallback = (FGCBmenuState)NULL; fgState.MenuStateCallback = (FGCBMenuState)NULL;
fgState.MenuStatusCallback = (FGCBmenuStatus)NULL; fgState.MenuStatusCallback = (FGCBMenuStatus)NULL;
fgState.SwapCount = 0; fgState.SwapCount = 0;
fgState.SwapTime = 0; fgState.SwapTime = 0;

View File

@ -114,43 +114,43 @@
/* /*
* Freeglut callbacks type definitions * Freeglut callbacks type definitions
*/ */
typedef void (* FGCBdisplay )( void ); typedef void (* FGCBDisplay )( void );
typedef void (* FGCBreshape )( int, int ); typedef void (* FGCBReshape )( int, int );
typedef void (* FGCBvisibility )( int ); typedef void (* FGCBVisibility )( int );
typedef void (* FGCBkeyboard )( unsigned char, int, int ); typedef void (* FGCBKeyboard )( unsigned char, int, int );
typedef void (* FGCBspecial )( int, int, int ); typedef void (* FGCBSpecial )( int, int, int );
typedef void (* FGCBmouse )( int, int, int, int ); typedef void (* FGCBMouse )( int, int, int, int );
typedef void (* FGCBmousewheel )( int, int, int, int ); typedef void (* FGCBMouseWheel )( int, int, int, int );
typedef void (* FGCBmotion )( int, int ); typedef void (* FGCBMotion )( int, int );
typedef void (* FGCBpassive )( int, int ); typedef void (* FGCBPassive )( int, int );
typedef void (* FGCBentry )( int ); typedef void (* FGCBEntry )( int );
typedef void (* FGCBwindowStatus )( int ); typedef void (* FGCBWindowStatus )( int );
typedef void (* FGCBselect )( int, int, int ); typedef void (* FGCBSelect )( int, int, int );
typedef void (* FGCBjoystick )( unsigned int, int, int, int ); typedef void (* FGCBJoystick )( unsigned int, int, int, int );
typedef void (* FGCBkeyboardUp )( unsigned char, int, int ); typedef void (* FGCBKeyboardUp )( unsigned char, int, int );
typedef void (* FGCBspecialUp )( int, int, int ); typedef void (* FGCBSpecialUp )( int, int, int );
typedef void (* FGCBoverlayDisplay)( void ); typedef void (* FGCBOverlayDisplay)( void );
typedef void (* FGCBspaceMotion )( int, int, int ); typedef void (* FGCBSpaceMotion )( int, int, int );
typedef void (* FGCBspaceRotate )( int, int, int ); typedef void (* FGCBSpaceRotation )( int, int, int );
typedef void (* FGCBspaceButton )( int, int ); typedef void (* FGCBSpaceButton )( int, int );
typedef void (* FGCBdials )( int, int ); typedef void (* FGCBDials )( int, int );
typedef void (* FGCBbuttonBox )( int, int ); typedef void (* FGCBButtonBox )( int, int );
typedef void (* FGCBtabletMotion )( int, int ); typedef void (* FGCBTabletMotion )( int, int );
typedef void (* FGCBtabletButton )( int, int, int, int ); typedef void (* FGCBTabletButton )( int, int, int, int );
typedef void (* FGCBdestroy )( void ); typedef void (* FGCBDestroy )( void );
/* /*
* The global callbacks type definitions * The global callbacks type definitions
*/ */
typedef void (* FGCBidle )( void ); typedef void (* FGCBIdle )( void );
typedef void (* FGCBtimer )( int ); typedef void (* FGCBTimer )( int );
typedef void (* FGCBmenuState )( int ); typedef void (* FGCBMenuState )( int );
typedef void (* FGCBmenuStatus )( int, int, int ); typedef void (* FGCBMenuStatus )( int, int, int );
/* /*
* The callback used when creating/using menus * The callback used when creating/using menus
*/ */
typedef void (* FGCBmenu )( int ); typedef void (* FGCBMenu )( int );
/* /*
@ -234,12 +234,12 @@ struct tagSFG_State
SFG_Time Time; /* The time that glutInit was called */ SFG_Time Time; /* The time that glutInit was called */
SFG_List Timers; /* The freeglut timer hooks */ SFG_List Timers; /* The freeglut timer hooks */
FGCBidle IdleCallback; /* The global idle callback */ FGCBIdle IdleCallback; /* The global idle callback */
GLboolean BuildingAMenu; /* True if we are presently making a menu */ GLboolean BuildingAMenu; /* True if we are presently making a menu */
int ActiveMenus; /* Number of currently active menus */ int ActiveMenus; /* Number of currently active menus */
FGCBmenuState MenuStateCallback; /* Menu callbacks are global */ FGCBMenuState MenuStateCallback; /* Menu callbacks are global */
FGCBmenuStatus MenuStatusCallback; FGCBMenuStatus MenuStatusCallback;
SFG_XYUse GameModeSize; /* The game mode screen's dimensions */ SFG_XYUse GameModeSize; /* The game mode screen's dimensions */
int GameModeDepth; /* The pixel depth for game mode */ int GameModeDepth; /* The pixel depth for game mode */
@ -300,7 +300,7 @@ struct tagSFG_Timer
{ {
SFG_Node Node; SFG_Node Node;
int ID; /* The timer ID integer */ int ID; /* The timer ID integer */
FGCBtimer Callback; /* The timer callback */ FGCBTimer Callback; /* The timer callback */
long TriggerTime; /* The timer trigger time */ long TriggerTime; /* The timer trigger time */
}; };
@ -363,35 +363,98 @@ struct tagSFG_WindowCallbacks
* Following callbacks are fully supported right now * Following callbacks are fully supported right now
* and are ready to be tested for GLUT conformance: * and are ready to be tested for GLUT conformance:
*/ */
FGCBdisplay Display; FGCBDisplay Display;
FGCBreshape Reshape; FGCBReshape Reshape;
FGCBkeyboard Keyboard; FGCBKeyboard Keyboard;
FGCBkeyboardUp KeyboardUp; FGCBKeyboardUp KeyboardUp;
FGCBspecial Special; FGCBSpecial Special;
FGCBspecialUp SpecialUp; FGCBSpecialUp SpecialUp;
FGCBmouse Mouse; FGCBMouse Mouse;
FGCBmousewheel MouseWheel; FGCBMouseWheel MouseWheel;
FGCBmotion Motion; FGCBMotion Motion;
FGCBpassive Passive; FGCBPassive Passive;
FGCBentry Entry; FGCBEntry Entry;
FGCBvisibility Visibility; FGCBVisibility Visibility;
FGCBwindowStatus WindowStatus; FGCBWindowStatus WindowStatus;
FGCBjoystick Joystick; FGCBJoystick Joystick;
FGCBdestroy Destroy; FGCBDestroy Destroy;
/* /*
* Those callbacks are being ignored for the moment * Those callbacks are being ignored for the moment
*/ */
FGCBselect Select; FGCBSelect Select;
FGCBoverlayDisplay OverlayDisplay; FGCBOverlayDisplay OverlayDisplay;
FGCBspaceMotion SpaceMotion; FGCBSpaceMotion SpaceMotion;
FGCBspaceRotate SpaceRotation; FGCBSpaceRotation SpaceRotation;
FGCBspaceButton SpaceButton; FGCBSpaceButton SpaceButton;
FGCBdials Dials; FGCBDials Dials;
FGCBbuttonBox ButtonBox; FGCBButtonBox ButtonBox;
FGCBtabletMotion TabletMotion; FGCBTabletMotion TabletMotion;
FGCBtabletButton TabletButton; FGCBTabletButton TabletButton;
}; };
#define FETCH_WCB(window,cbname) \
((FGCB ## cbname)((window).CallBacks[CB_ ## cbname]))
/*
* INVOKE_WCB() is used as:
*
* INVOKE_WCB( window, Visibility, ( status ) );
*
* ...where {window} is the freeglut window,
* {Visibility} is the window-specific callback,
* {(status)} is the parameter list.
*
* The callback is invoked as:
*
* callback( status );
*
* ...so the parentheses are REQUIRED in the {arg_list}.
*
* NOTE that it does a sanity-check and also sets the
* current window.
*
*/
#define INVOKE_WCB(window,cbname,arg_list) \
{ \
if( FETCH_WCB( window, cbname ) ) \
{ \
fgSetWindow( &window ); \
FETCH_WCB( window, cbname ) arg_list; \
} \
}
enum
{
CB_Display,
CB_Reshape,
CB_Keyboard,
CB_KeyboardUp,
CB_Special,
CB_SpecialUp,
CB_Mouse,
CB_MouseWheel,
CB_Motion,
CB_Passive,
CB_Entry,
CB_Visibility,
CB_WindowStatus,
CB_Joystick,
CB_Destroy,
/* Presently ignored */
CB_Select,
CB_OverlayDisplay,
CB_SpaceMotion,
CB_SpaceRotation,
CB_SpaceButton,
CB_Dials,
CB_ButtonBox,
CB_TabletMotion,
CB_TabletButton,
/* Always make this the LAST one */
TOTAL_CALLBACKS
};
/* /*
* This structure holds the OpenGL rendering context for all the menu windows * This structure holds the OpenGL rendering context for all the menu windows
@ -420,8 +483,8 @@ struct tagSFG_Menu
void *UserData ; /* A. Donev: User data passed back at callback */ void *UserData ; /* A. Donev: User data passed back at callback */
int ID; /* The global menu ID */ int ID; /* The global menu ID */
SFG_List Entries; /* The menu entries list */ SFG_List Entries; /* The menu entries list */
FGCBmenu Callback; /* The menu callback */ FGCBMenu Callback; /* The menu callback */
FGCBdestroy Destroy; /* A. Donev: Destruction callback */ FGCBDestroy Destroy; /* A. Donev: Destruction callback */
GLboolean IsActive; /* Is the menu selected? */ GLboolean IsActive; /* Is the menu selected? */
int Width; /* Menu box width in pixels */ int Width; /* Menu box width in pixels */
int Height; /* Menu box height in pixels */ int Height; /* Menu box height in pixels */
@ -456,7 +519,8 @@ struct tagSFG_Window
SFG_Context Window; /* Window and OpenGL context */ SFG_Context Window; /* Window and OpenGL context */
SFG_WindowState State; /* The window state */ SFG_WindowState State; /* The window state */
SFG_WindowCallbacks Callbacks; /* The window callbacks */ /* SFG_WindowCallbacks Callbacks; /* The window callbacks */
void *CallBacks[ TOTAL_CALLBACKS ]; /* Array of window callbacks */
void *UserData ; /* A. Donev: A pointer to user data used in rendering */ void *UserData ; /* A. Donev: A pointer to user data used in rendering */
SFG_Menu* Menu[ FREEGLUT_MAX_MENUS ]; /* Menus appended to window */ SFG_Menu* Menu[ FREEGLUT_MAX_MENUS ]; /* Menus appended to window */
@ -468,6 +532,7 @@ struct tagSFG_Window
GLboolean IsMenu; /* Set to 1 if we are a menu */ GLboolean IsMenu; /* Set to 1 if we are a menu */
}; };
/* /*
* A linked list structure of windows * A linked list structure of windows
*/ */
@ -648,7 +713,7 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose );
/* /*
* Menu creation and destruction. Defined in freeglut_structure.c * Menu creation and destruction. Defined in freeglut_structure.c
*/ */
SFG_Menu* fgCreateMenu( FGCBmenu menuCallback ); SFG_Menu* fgCreateMenu( FGCBMenu menuCallback );
void fgDestroyMenu( SFG_Menu* menu ); void fgDestroyMenu( SFG_Menu* menu );
/* /*

View File

@ -597,17 +597,26 @@ void fgJoystickPollWindow( SFG_Window* window )
int buttons; int buttons;
freeglut_return_if_fail( fgJoystick != NULL && window != NULL ); freeglut_return_if_fail( fgJoystick != NULL && window != NULL );
freeglut_return_if_fail( window->Callbacks.Joystick != NULL ); freeglut_return_if_fail( FETCH_WCB( *window, Joystick ) );
fghJoystickRead( fgJoystick, &buttons, axes ); fghJoystickRead( fgJoystick, &buttons, axes );
fgSetWindow (window); INVOKE_WCB( *window, Joystick,
window->Callbacks.Joystick( ( buttons,
buttons, (int) (axes[ 0 ] * 1000.0f ),
(int) (axes[ 0 ] * 1000.0f), (int) (axes[ 1 ] * 1000.0f ),
(int) (axes[ 1 ] * 1000.0f), (int) (axes[ 2 ] * 1000.0f ) )
(int) (axes[ 2 ] * 1000.0f)
); );
/*
* fgSetWindow (window);
* window->Callbacks.Joystick(
* buttons,
* (int) (axes[ 0 ] * 1000.0f),
* (int) (axes[ 1 ] * 1000.0f),
* (int) (axes[ 2 ] * 1000.0f)
* );
*/
} }
/* /*

View File

@ -83,12 +83,13 @@ static void fghRedrawWindowByHandle
{ {
SFG_Window* window = fgWindowByHandle( handle ); SFG_Window* window = fgWindowByHandle( handle );
freeglut_return_if_fail( window != NULL ); freeglut_return_if_fail( window != NULL );
freeglut_return_if_fail( window->Callbacks.Display != NULL ); freeglut_return_if_fail( FETCH_WCB( *window, Display ) );
freeglut_return_if_fail( window->State.Visible == TRUE ); freeglut_return_if_fail( window->State.Visible == TRUE );
fgSetWindow( window ); /* fgSetWindow( window ); */
window->State.Redisplay = FALSE; window->State.Redisplay = FALSE;
window->Callbacks.Display( ); /* window->Callbacks.Display( ); */
INVOKE_WCB( *window, Display, ( ) );
} }
/* /*
@ -108,11 +109,20 @@ static void fghReshapeWindowByHandle
SFG_Window* window = fgWindowByHandle( handle ); SFG_Window* window = fgWindowByHandle( handle );
freeglut_return_if_fail( window != NULL ); freeglut_return_if_fail( window != NULL );
/*
* fgSetWindow( window );
* if( window->Callbacks.Reshape != NULL )
* window->Callbacks.Reshape( width, height );
* else
* glViewport( 0, 0, width, height );
*/
if( !( FETCH_WCB( *window, Reshape ) ) )
{
fgSetWindow( window ); fgSetWindow( window );
if( window->Callbacks.Reshape != NULL )
window->Callbacks.Reshape( width, height );
else
glViewport( 0, 0, width, height ); glViewport( 0, 0, width, height );
}
else
INVOKE_WCB( *window, Reshape, ( width, height ) );
/* /*
* Force a window redraw. In Windows at least this is only a partial * Force a window redraw. In Windows at least this is only a partial
@ -133,15 +143,16 @@ static void fghReshapeWindowByHandle
static void fghcbDisplayWindow( SFG_Window *window, SFG_Enumerator *enumerator ) static void fghcbDisplayWindow( SFG_Window *window, SFG_Enumerator *enumerator )
{ {
#if TARGET_HOST_UNIX_X11 #if TARGET_HOST_UNIX_X11
if( (window->Callbacks.Display != NULL) && if( ( FETCH_WCB( *window, Display ) ) &&
(window->State.Redisplay == TRUE) && ( window->State.Redisplay == TRUE ) &&
(window->State.Visible == TRUE) ) ( window->State.Visible == TRUE ) )
{ {
SFG_Window *current_window = fgStructure.Window ; SFG_Window *current_window = fgStructure.Window ;
fgSetWindow( window ); /* fgSetWindow( window ); */
window->State.Redisplay = FALSE; window->State.Redisplay = FALSE;
window->Callbacks.Display( ); /* window->Callbacks.Display( ); */
INVOKE_WCB( *window, Display, ( ) );
fgSetWindow( current_window ); fgSetWindow( current_window );
} }
@ -163,9 +174,9 @@ static void fghcbDisplayWindow( SFG_Window *window, SFG_Enumerator *enumerator )
fgSetWindow ( current_window ); fgSetWindow ( current_window );
} }
if( (window->Callbacks.Display != NULL) && if( ( FETCH_WCB( *window, Display ) ) &&
(window->State.Redisplay == TRUE) && ( window->State.Redisplay == TRUE ) &&
(window->State.Visible == TRUE) ) ( window->State.Visible == TRUE ) )
{ {
window->State.Redisplay = FALSE; window->State.Redisplay = FALSE;
@ -339,7 +350,7 @@ void fgWarning( const char *fmt, ... )
*/ */
static void fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e) static void fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e)
{ {
if( w->Callbacks.Joystick ) if( FETCH_WCB( *w, Joystick ) )
{ {
e->found = TRUE; e->found = TRUE;
e->data = w; e->data = w;
@ -553,7 +564,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
case VisibilityNotify: case VisibilityNotify:
{ {
GETWINDOW( xvisibility ); GETWINDOW( xvisibility );
if( window->Callbacks.WindowStatus == NULL ) if( ! FETCH_WCB( *window, WindowStatus ) )
break; break;
fgSetWindow( window ); fgSetWindow( window );
@ -566,17 +577,18 @@ void FGAPIENTRY glutMainLoopEvent( void )
switch( event.xvisibility.state ) switch( event.xvisibility.state )
{ {
case VisibilityUnobscured: case VisibilityUnobscured:
window->Callbacks.WindowStatus( GLUT_FULLY_RETAINED ); INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) );
window->State.Visible = TRUE; window->State.Visible = TRUE;
break; break;
case VisibilityPartiallyObscured: case VisibilityPartiallyObscured:
window->Callbacks.WindowStatus( GLUT_PARTIALLY_RETAINED ); INVOKE_WCB( *window, WindowStatus,
( GLUT_PARTIALLY_RETAINED ) );
window->State.Visible = TRUE; window->State.Visible = TRUE;
break; break;
case VisibilityFullyObscured: case VisibilityFullyObscured:
window->Callbacks.WindowStatus( GLUT_FULLY_COVERED ); INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_COVERED ) );
window->State.Visible = FALSE; window->State.Visible = FALSE;
break; break;
@ -592,23 +604,29 @@ void FGAPIENTRY glutMainLoopEvent( void )
{ {
GETWINDOW( xcrossing ); GETWINDOW( xcrossing );
GETMOUSE( xcrossing ); GETMOUSE( xcrossing );
if( window->Callbacks.Entry ) /*
{ * if( window->Callbacks.Entry )
fgSetWindow( window ) ; * {
window->Callbacks.Entry( GLUT_ENTERED ); * fgSetWindow( window ) ;
} * window->Callbacks.Entry( GLUT_ENTERED );
* }
*/
INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
} }
break; break;
/* XXX Combine EnterNotify and LeaveNotify */
case LeaveNotify: case LeaveNotify:
{ {
GETWINDOW( xcrossing ); GETWINDOW( xcrossing );
GETMOUSE( xcrossing ); GETMOUSE( xcrossing );
if( window->Callbacks.Entry ) /*
{ * if( window->Callbacks.Entry )
fgSetWindow( window ) ; * {
window->Callbacks.Entry( GLUT_LEFT ); * fgSetWindow( window ) ;
} * window->Callbacks.Entry( GLUT_LEFT );
* }
*/
INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
} }
break; break;
@ -646,21 +664,29 @@ void FGAPIENTRY glutMainLoopEvent( void )
* A mouse button was pressed during the movement... * A mouse button was pressed during the movement...
* Is there a motion callback hooked to the window? * Is there a motion callback hooked to the window?
*/ */
if( window->Callbacks.Motion ) /*
{ * if( window->Callbacks.Motion )
fgSetWindow ( window ) ; * {
window->Callbacks.Motion( event.xmotion.x, * fgSetWindow ( window ) ;
event.xmotion.y ); * window->Callbacks.Motion( event.xmotion.x,
} * event.xmotion.y );
* }
*/
INVOKE_WCB( *window, Motion, ( event.xmotion.x,
event.xmotion.y ) );
} }
else else
{ {
if( window->Callbacks.Passive ) /*
{ * if( window->Callbacks.Passive )
fgSetWindow( window ); * {
window->Callbacks.Passive( event.xmotion.x, * fgSetWindow( window );
event.xmotion.y ); * window->Callbacks.Passive( event.xmotion.x,
} * event.xmotion.y );
* }
*/
INVOKE_WCB( *window, Passive, ( event.xmotion.x,
event.xmotion.y ) );
} }
} }
break; break;
@ -773,11 +799,11 @@ void FGAPIENTRY glutMainLoopEvent( void )
* Check if there is a mouse or mouse wheel callback hooked to the * Check if there is a mouse or mouse wheel callback hooked to the
* window * window
*/ */
if( ( window->Callbacks.Mouse == NULL ) && if( ! FETCH_WCB( *window, Mouse ) &&
( window->Callbacks.MouseWheel == NULL ) ) ! FETCH_WCB( *window, MouseWheel ) )
break; break;
fgSetWindow( window ); /* fgSetWindow( window ); */
/* /*
* XXX Why don't we use {window}? Other code here does... * XXX Why don't we use {window}? Other code here does...
@ -789,14 +815,21 @@ void FGAPIENTRY glutMainLoopEvent( void )
* *
* XXX Use a symbolic constant, *not* "4"! * XXX Use a symbolic constant, *not* "4"!
*/ */
if( ( button < 4 ) || ( !( window->Callbacks.MouseWheel ) ) ) if( ( button < 4 ) || ( ! FETCH_WCB( *window, MouseWheel ) ) )
{ {
if( window->Callbacks.Mouse ) /*
fgStructure.Window->Callbacks.Mouse( * if( window->Callbacks.Mouse )
button, * fgStructure.Window->Callbacks.Mouse(
* button,
* pressed ? GLUT_DOWN : GLUT_UP,
* event.xbutton.x,
* event.xbutton.y
* );
*/
INVOKE_WCB( *window, Mouse, ( button,
pressed ? GLUT_DOWN : GLUT_UP, pressed ? GLUT_DOWN : GLUT_UP,
event.xbutton.x, event.xbutton.x,
event.xbutton.y event.xbutton.y )
); );
} }
else else
@ -813,12 +846,20 @@ void FGAPIENTRY glutMainLoopEvent( void )
int wheel_number = (button - 4) / 2; int wheel_number = (button - 4) / 2;
int direction = (button & 1)*2 - 1; int direction = (button & 1)*2 - 1;
/*
* if( pressed )
* fgStructure.Window->Callbacks.MouseWheel(
* wheel_number,
* direction,
* event.xbutton.x,
* event.xbutton.y
* );
*/
if( pressed ) if( pressed )
fgStructure.Window->Callbacks.MouseWheel( INVOKE_WCB( *window, MouseWheel, ( wheel_number,
wheel_number,
direction, direction,
event.xbutton.x, event.xbutton.x,
event.xbutton.y event.xbutton.y )
); );
} }
@ -832,21 +873,21 @@ void FGAPIENTRY glutMainLoopEvent( void )
case KeyRelease: case KeyRelease:
case KeyPress: case KeyPress:
{ {
FGCBkeyboard keyboard_cb; FGCBKeyboard keyboard_cb;
FGCBspecial special_cb; FGCBSpecial special_cb;
GETWINDOW( xkey ); GETWINDOW( xkey );
GETMOUSE( xkey ); GETMOUSE( xkey );
if( event.type == KeyPress ) if( event.type == KeyPress )
{ {
keyboard_cb = window->Callbacks.Keyboard; keyboard_cb = FETCH_WCB( *window, Keyboard );
special_cb = window->Callbacks.Special; special_cb = FETCH_WCB( *window, Special );
} }
else else
{ {
keyboard_cb = window->Callbacks.KeyboardUp; keyboard_cb = FETCH_WCB( *window, KeyboardUp );
special_cb = window->Callbacks.SpecialUp; special_cb = FETCH_WCB( *window, SpecialUp );
} }
/* /*
@ -989,12 +1030,15 @@ void FGAPIENTRY glutMainLoop( void )
*/ */
while( window ) while( window )
{ {
if ( window->Callbacks.Visibility ) if ( FETCH_WCB( *window, Visibility ) )
{ {
SFG_Window *current_window = fgStructure.Window ; SFG_Window *current_window = fgStructure.Window ;
fgSetWindow( window ); /*
window->Callbacks.Visibility ( window->State.Visible ) ; * fgSetWindow( window );
* window->Callbacks.Visibility ( window->State.Visible ) ;
*/
INVOKE_WCB( *window, Visibility, ( window->State.Visible ) );
fgSetWindow( current_window ); fgSetWindow( current_window );
} }
@ -1264,21 +1308,29 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
( wParam & MK_MBUTTON ) || ( wParam & MK_MBUTTON ) ||
( wParam & MK_RBUTTON ) ) ( wParam & MK_RBUTTON ) )
{ {
if( window->Callbacks.Motion ) /*
{ * if( window->Callbacks.Motion )
fgSetWindow( window ); * {
window->Callbacks.Motion( window->State.MouseX, * fgSetWindow( window );
window->State.MouseY ); * window->Callbacks.Motion( window->State.MouseX,
} * window->State.MouseY );
* }
*/
INVOKE_WCB( *window, Motion, ( window->State.MouseX,
window->State.MouseY ) );
} }
else else
{ {
if( window->Callbacks.Passive ) /*
{ * if( window->Callbacks.Passive )
fgSetWindow( window ); * {
window->Callbacks.Passive( window->State.MouseX, * fgSetWindow( window );
window->State.MouseY ); * window->Callbacks.Passive( window->State.MouseX,
} * window->State.MouseY );
* }
*/
INVOKE_WCB( *window, Passive, ( window->State.MouseX,
window->State.MouseY ) );
} }
window->State.Modifiers = 0xffffffff; window->State.Modifiers = 0xffffffff;
@ -1391,18 +1443,28 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
break; break;
} }
if( window->Callbacks.Mouse == NULL ) if( ! FETCH_WCB( *window, Mouse ) )
break; break;
fgSetWindow( window ); fgSetWindow( window );
fgStructure.Window->State.Modifiers = fgGetWin32Modifiers( ); fgStructure.Window->State.Modifiers = fgGetWin32Modifiers( );
window->Callbacks.Mouse( INVOKE_WCB(
button, *window, Mouse,
( button,
pressed == TRUE ? GLUT_DOWN : GLUT_UP, pressed == TRUE ? GLUT_DOWN : GLUT_UP,
window->State.MouseX, window->State.MouseX,
window->State.MouseY window->State.MouseY
)
); );
/*
* window->Callbacks.Mouse(
* button,
* pressed == TRUE ? GLUT_DOWN : GLUT_UP,
* window->State.MouseX,
* window->State.MouseY
* );
*/
fgStructure.Window->State.Modifiers = 0xffffffff; fgStructure.Window->State.Modifiers = 0xffffffff;
} }
@ -1431,21 +1493,33 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
/* window->State.MouseY = HIWORD( lParam ); */ /* window->State.MouseY = HIWORD( lParam ); */
/* change "lParam" to other parameter */ /* change "lParam" to other parameter */
if( ( window->Callbacks.MouseWheel == NULL ) && if( ! FETCH_WCB( *window, MouseWheel ) &&
( window->Callbacks.Mouse == NULL ) ) ! FETCH_WCB( *window, Mouse ) )
break; break;
fgSetWindow( window ); fgSetWindow( window );
fgStructure.Window->State.Modifiers = fgGetWin32Modifiers( ); fgStructure.Window->State.Modifiers = fgGetWin32Modifiers( );
while( ticks-- ) while( ticks-- )
if( window->Callbacks.MouseWheel ) if( FETCH_WCB( *window, MouseWheel ) )
window->Callbacks.MouseWheel( {
wheel_number, INVOKE_WCB( *window, MouseWheel,
( wheel_number,
direction, direction,
window->State.MouseX, window->State.MouseX,
window->State.MouseY window->State.MouseY
)
); );
}
/*
* if( window->Callbacks.MouseWheel )
* window->Callbacks.MouseWheel(
* wheel_number,
* direction,
* window->State.MouseX,
* window->State.MouseY
* );
*/
else /* No mouse wheel, call the mouse button callback twice */ else /* No mouse wheel, call the mouse button callback twice */
{ {
/* /*
@ -1455,14 +1529,25 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
int button = wheel_number*2 + 4; int button = wheel_number*2 + 4;
if( direction > 0 ) if( direction > 0 )
++button; ++button;
window->Callbacks.Mouse( button, GLUT_DOWN, INVOKE_WCB( *window, Mouse,
window->State.MouseX, ( button, GLUT_DOWN,
window->State.MouseY window->State.MouseX, window->State.MouseY )
); );
window->Callbacks.Mouse( button, GLUT_UP, INVOKE_WCB( *window, Mouse,
window->State.MouseX, ( button, GLUT_UP,
window->State.MouseY window->State.MouseX, window->State.MouseX )
); );
/*
* window->Callbacks.Mouse( button, GLUT_DOWN,
* window->State.MouseX,
* window->State.MouseY
* );
* window->Callbacks.Mouse( button, GLUT_UP,
* window->State.MouseX,
* window->State.MouseY
* );
*/
} }
fgStructure.Window->State.Modifiers = 0xffffffff; fgStructure.Window->State.Modifiers = 0xffffffff;
@ -1523,20 +1608,30 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
/* /*
* The delete key should be treated as an ASCII keypress: * The delete key should be treated as an ASCII keypress:
*/ */
if( window->Callbacks.Keyboard ) /*
{ * if( window->Callbacks.Keyboard )
fgSetWindow( window ); * {
window->Callbacks.Keyboard( 127, window->State.MouseX, * fgSetWindow( window );
window->State.MouseY ); * window->Callbacks.Keyboard( 127, window->State.MouseX,
} * window->State.MouseY );
* }
*/
INVOKE_WCB( *window, Keyboard,
( 127, window->State.MouseX, window->State.MouseY )
);
} }
if( ( keypress != -1 ) && window->Callbacks.Special ) /* if( ( keypress != -1 ) && window->Callbacks.Special )
{ * {
fgSetWindow( window ); * fgSetWindow( window );
window->Callbacks.Special( keypress, window->State.MouseX, * window->Callbacks.Special( keypress, window->State.MouseX,
window->State.MouseY ); * window->State.MouseY );
} * }
*/
if( keypress != -1 )
INVOKE_WCB( *window, Special,
( keypress, window->State.MouseX, window->State.MouseY )
);
window->State.Modifiers = 0xffffffff; window->State.Modifiers = 0xffffffff;
} }
@ -1593,13 +1688,16 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
/* /*
* The delete key should be treated as an ASCII keypress: * The delete key should be treated as an ASCII keypress:
*/ */
if( window->Callbacks.KeyboardUp ) /* if( window->Callbacks.KeyboardUp )
{ * {
fgSetWindow( window ); * fgSetWindow( window );
window->Callbacks.KeyboardUp( 127, window->State.MouseX, * window->Callbacks.KeyboardUp( 127, window->State.MouseX,
window->State.MouseY ); * window->State.MouseY );
} * }
*/
INVOKE_WCB( *window, KeyboardUp,
( 127, window->State.MouseX, window->State.MouseY )
);
break; break;
default: default:
@ -1612,22 +1710,35 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
if( ToAscii( wParam, 0, state, code, 0 ) == 1 ) if( ToAscii( wParam, 0, state, code, 0 ) == 1 )
wParam=code[ 0 ]; wParam=code[ 0 ];
if( window->Callbacks.KeyboardUp ) /*
{ * if( window->Callbacks.KeyboardUp )
fgSetWindow( window ); * {
window->Callbacks.KeyboardUp( (char)wParam, * fgSetWindow( window );
window->State.MouseX, * window->Callbacks.KeyboardUp( (char)wParam,
window->State.MouseY ); * window->State.MouseX,
} * window->State.MouseY );
* }
*/
INVOKE_WCB( *window, KeyboardUp,
( (char)wParam,
window->State.MouseX, window->State.MouseY )
);
} }
} }
if( (keypress != -1) && window->Callbacks.SpecialUp ) /*
{ * if( (keypress != -1) && window->Callbacks.SpecialUp )
fgSetWindow( window ); * {
window->Callbacks.SpecialUp( keypress, window->State.MouseX, * fgSetWindow( window );
window->State.MouseY ); * window->Callbacks.SpecialUp( keypress, window->State.MouseX,
} * window->State.MouseY );
* }
*/
if( keypress != -1 )
INVOKE_WCB( *window, SpecialUp,
( keypress,
window->State.MouseX, window->State.MouseY )
);
window->State.Modifiers = 0xffffffff; window->State.Modifiers = 0xffffffff;
} }
@ -1639,12 +1750,16 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
if( fgState.IgnoreKeyRepeat && (lParam & KF_REPEAT) ) if( fgState.IgnoreKeyRepeat && (lParam & KF_REPEAT) )
break; break;
if( window->Callbacks.Keyboard ) if( FETCH_WCB( *window, Keyboard ) )
{ {
fgSetWindow( window ); /* fgSetWindow( window ); */
window->State.Modifiers = fgGetWin32Modifiers( ); window->State.Modifiers = fgGetWin32Modifiers( );
window->Callbacks.Keyboard( (char)wParam, window->State.MouseX, /* window->Callbacks.Keyboard( (char)wParam, window->State.MouseX,
window->State.MouseY ); window->State.MouseY ); */
INVOKE_WCB( *window, Keyboard,
( (char)wParam,
window->State.MouseX, window->State.MouseY )
);
window->State.Modifiers = 0xffffffff; window->State.Modifiers = 0xffffffff;
} }
} }
@ -1652,11 +1767,14 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
case WM_CAPTURECHANGED: case WM_CAPTURECHANGED:
/* User has finished resizing the window, force a redraw */ /* User has finished resizing the window, force a redraw */
if( window->Callbacks.Display ) /*
{ * if( window->Callbacks.Display )
fgSetWindow( window ); * {
window->Callbacks.Display( ); * fgSetWindow( window );
} * window->Callbacks.Display( );
* }
*/
INVOKE_WCB( *window, Display, ( ) );
/*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ) ; */ /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ) ; */
break; break;

View File

@ -145,7 +145,7 @@ void FGAPIENTRY glutForceJoystickFunc( void )
{ {
freeglut_assert_ready; freeglut_assert_ready;
freeglut_return_if_fail( fgStructure.Window != NULL ); freeglut_return_if_fail( fgStructure.Window != NULL );
freeglut_return_if_fail( fgStructure.Window->Callbacks.Joystick != NULL ); freeglut_return_if_fail( FETCH_WCB( *( fgStructure.Window ), Joystick ) );
fgJoystickPollWindow( fgStructure.Window ); fgJoystickPollWindow( fgStructure.Window );
} }

View File

@ -109,7 +109,7 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title,
/* /*
* This private function creates a menu and adds it to the menus list * This private function creates a menu and adds it to the menus list
*/ */
SFG_Menu* fgCreateMenu( FGCBmenu menuCallback ) SFG_Menu* fgCreateMenu( FGCBMenu menuCallback )
{ {
int x = 100, y = 100, w = 100, h = 100 ; int x = 100, y = 100, w = 100, h = 100 ;
SFG_Window *current_window = fgStructure.Window ; SFG_Window *current_window = fgStructure.Window ;
@ -266,11 +266,12 @@ void fgDestroyWindow( SFG_Window* window, GLboolean needToClose )
while ( (subWindow = (SFG_Window *)window->Children.First) != NULL ) while ( (subWindow = (SFG_Window *)window->Children.First) != NULL )
fgDestroyWindow( subWindow, needToClose ); fgDestroyWindow( subWindow, needToClose );
if ( window->Callbacks.Destroy != NULL ) if ( FETCH_WCB( *window, Destroy ) )
{ {
SFG_Window *activeWindow = fgStructure.Window ; SFG_Window *activeWindow = fgStructure.Window ;
fgSetWindow ( window ) ; /* fgSetWindow ( window ) ; */
window->Callbacks.Destroy () ; /* window->Callbacks.Destroy () ; */
INVOKE_WCB( *window, Destroy, ( ) );
fgSetWindow ( activeWindow ) ; fgSetWindow ( activeWindow ) ;
} }