X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_main.c;h=823087b0129be3537273cbf2075a770c2d1bc2ce;hb=164f40e04e857b4edd4f58427cae44ceb85dbce0;hp=6a1b2c7c186eaa7e67985299a57f78e5840b5413;hpb=87474a5362f15affd6dbc3ce37cd9986b873562d;p=freeglut diff --git a/src/freeglut_main.c b/src/freeglut_main.c index 6a1b2c7..823087b 100644 --- a/src/freeglut_main.c +++ b/src/freeglut_main.c @@ -29,8 +29,6 @@ #include "config.h" #endif -#define G_LOG_DOMAIN "freeglut-main" - #include "../include/GL/freeglut.h" #include "freeglut_internal.h" @@ -85,12 +83,28 @@ static void fghRedrawWindowByHandle { SFG_Window* window = fgWindowByHandle( handle ); freeglut_return_if_fail( window != NULL ); - freeglut_return_if_fail( window->Callbacks.Display != NULL ); + + /* + * XXX Other than clearing the Redisplay flag or not, + * XXX we may as well rely on the INVOK_WCB() doing this + * XXX pointer-check. + * XXX + * XXX If we do not invoke the display because the pointer + * XXX is not defined (should never happen, really), then + * XXX we may enter an infinite busy-loop trying to update + * XXX the window. Similarly, if we skip because the window + * XXX is not visible. However, if the window becomes visible + * XXX at a later time, the window should get its callback + * XXX invoked. I would recommend removing the first check, + * XXX and making the second check only affect whether the + * XXX callback is invoked---but always clear the flag, if + * XXX the {window} pointer is defined. + */ + freeglut_return_if_fail( FETCH_WCB( *window, Display ) ); freeglut_return_if_fail( window->State.Visible == TRUE ); - fgSetWindow( window ); window->State.Redisplay = FALSE; - window->Callbacks.Display(); + INVOKE_WCB( *window, Display, ( ) ); } /* @@ -105,16 +119,18 @@ static void fghReshapeWindowByHandle ( HWND handle, int width, int height ) #endif { - SFG_Window *current_window = fgStructure.Window ; + SFG_Window *current_window = fgStructure.Window; SFG_Window* window = fgWindowByHandle( handle ); freeglut_return_if_fail( window != NULL ); - fgSetWindow( window ); - if( window->Callbacks.Reshape != NULL ) - window->Callbacks.Reshape( width, height ); - else + if( !( FETCH_WCB( *window, Reshape ) ) ) + { + fgSetWindow( window ); 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 @@ -123,10 +139,10 @@ static void fghReshapeWindowByHandle * But without this we get this bad behaviour whenever we resize the * window. */ - window->State.Redisplay = TRUE ; + window->State.Redisplay = TRUE; if( window->IsMenu ) - fgSetWindow( current_window ) ; + fgSetWindow( current_window ); } /* @@ -135,23 +151,31 @@ static void fghReshapeWindowByHandle static void fghcbDisplayWindow( SFG_Window *window, SFG_Enumerator *enumerator ) { #if TARGET_HOST_UNIX_X11 - if( (window->Callbacks.Display != NULL) && - (window->State.Redisplay == TRUE) && - (window->State.Visible == TRUE) ) + /* + * XXX Do we need/want to check the callback pointer here? + * XXX INVOKE_WCB() will check for us. Arguably, the + * XXX Redisplay status flag should be cleared regardless + * XXX of any concern but that {window} is a valid pointer + * XXX (which this function is assuming anyway). + * XXX Especially since old GLUT wouldn't even enter its main + * XXX loop if you didn't have a display callback defined... + */ + if( ( FETCH_WCB( *window, Display ) ) && + ( window->State.Redisplay == TRUE ) && + ( window->State.Visible == TRUE ) ) { SFG_Window *current_window = fgStructure.Window ; - fgSetWindow( window ); window->State.Redisplay = FALSE; - window->Callbacks.Display(); - fgSetWindow( current_window ) ; + INVOKE_WCB( *window, Display, ( ) ); + fgSetWindow( current_window ); } #elif TARGET_HOST_WIN32 if( window->State.NeedToResize ) { - SFG_Window *current_window = fgStructure.Window ; + SFG_Window *current_window = fgStructure.Window; fgSetWindow( window ); @@ -162,16 +186,19 @@ static void fghcbDisplayWindow( SFG_Window *window, SFG_Enumerator *enumerator ) ); window->State.NeedToResize = FALSE; - fgSetWindow ( current_window ) ; + fgSetWindow ( current_window ); } - if( (window->Callbacks.Display != NULL) && - (window->State.Redisplay == TRUE) && - (window->State.Visible == TRUE) ) + /* + * XXX See above comment about the Redisplay flag... + */ + if( ( FETCH_WCB( *window, Display ) ) && + ( window->State.Redisplay == TRUE ) && + ( window->State.Visible == TRUE ) ) { window->State.Redisplay = FALSE; - RedrawWindow( + RedrawWindow( window->Window.Handle, NULL, NULL, RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW ); @@ -201,7 +228,7 @@ static void fghDisplayAll( void ) static void fghcbCheckJoystickPolls( SFG_Window *window, SFG_Enumerator *enumerator ) { - long int checkTime = fgElapsedTime(); + long int checkTime = fgElapsedTime( ); if( window->State.JoystickLastPoll + window->State.JoystickPollRate <= checkTime ) @@ -231,7 +258,7 @@ static void fghCheckJoystickPolls( void ) */ static void fghCheckTimers( void ) { - long checkTime = fgElapsedTime(); + long checkTime = fgElapsedTime( ); SFG_Timer *timer, *next; SFG_List timedOut; @@ -278,9 +305,9 @@ long fgElapsedTime( void ) elapsed = (now.tv_usec - fgState.Time.Value.tv_usec) / 1000; elapsed += (now.tv_sec - fgState.Time.Value.tv_sec) * 1000; - return( elapsed ); + return elapsed; #elif TARGET_HOST_WIN32 - return (timeGetTime() - fgState.Time.Value); + return timeGetTime() - fgState.Time.Value; #endif } @@ -341,7 +368,7 @@ void fgWarning( const char *fmt, ... ) */ static void fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e) { - if( w->Callbacks.Joystick ) + if( FETCH_WCB( *w, Joystick ) ) { e->found = TRUE; e->data = w; @@ -409,15 +436,14 @@ static void fgSleepForEvents( void ) struct timeval wait; long msec; - if( fgState.IdleCallback || - fgHavePendingRedisplays() ) + if( fgState.IdleCallback || fgHavePendingRedisplays( ) ) return; socket = ConnectionNumber( fgDisplay.Display ); FD_ZERO( &fdset ); FD_SET( socket, &fdset ); - msec = fgNextTimer(); - if( fgHaveJoystick() ) + msec = fgNextTimer( ); + if( fgHaveJoystick( ) ) msec = MIN( msec, 10 ); wait.tv_sec = msec / 1000; @@ -431,10 +457,11 @@ static void fgSleepForEvents( void ) #endif } +#if TARGET_HOST_UNIX_X11 /* * Returns GLUT modifier mask for an XEvent. */ -int fgGetXModifiers(XEvent *event) +int fgGetXModifiers( XEvent *event ) { int ret = 0; @@ -447,6 +474,7 @@ int fgGetXModifiers(XEvent *event) return ret; } +#endif /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ @@ -480,14 +508,6 @@ void FGAPIENTRY glutMainLoopEvent( void ) switch( event.type ) { - case DestroyNotify: - /* - * This is sent to confirm the XDestroyWindow call. - * XXX WHY is this commented out? Should we re-enable it? - */ - /* fgAddToWindowDestroyList ( window, FALSE ); */ - break; - case ClientMessage: /* * Destroy the window when the WM_DELETE_WINDOW message arrives @@ -501,26 +521,6 @@ void FGAPIENTRY glutMainLoopEvent( void ) } break; - case MapNotify: - case UnmapNotify: - /* - * If we never do anything with this, can we just not ask to - * get these messages? - */ - break; - - case Expose: - /* - * We are too dumb to process partial exposes... - * XXX Well, we could do it. However, it seems to only - * XXX be potentially useful for single-buffered (since - * XXX double-buffered does not respect viewport when we - * XXX do a buffer-swap). - */ - if( event.xexpose.count == 0 ) - fghRedrawWindowByHandle( event.xexpose.window ); - break; - /* * CreateNotify causes a configure-event so that sub-windows are * handled compatibly with GLUT. Otherwise, your sub-windows @@ -543,6 +543,34 @@ void FGAPIENTRY glutMainLoopEvent( void ) ); break; + case DestroyNotify: + /* + * This is sent to confirm the XDestroyWindow call. + * XXX WHY is this commented out? Should we re-enable it? + */ + /* fgAddToWindowDestroyList ( window, FALSE ); */ + break; + + case Expose: + /* + * We are too dumb to process partial exposes... + * XXX Well, we could do it. However, it seems to only + * XXX be potentially useful for single-buffered (since + * XXX double-buffered does not respect viewport when we + * XXX do a buffer-swap). + */ + if( event.xexpose.count == 0 ) + fghRedrawWindowByHandle( event.xexpose.window ); + break; + + case MapNotify: + case UnmapNotify: + /* + * If we never do anything with this, can we just not ask to + * get these messages? + */ + break; + case MappingNotify: /* * Have the client's keyboard knowledge updated (xlib.ps, @@ -554,7 +582,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) case VisibilityNotify: { GETWINDOW( xvisibility ); - if( window->Callbacks.WindowStatus == NULL ) + if( ! FETCH_WCB( *window, WindowStatus ) ) break; fgSetWindow( window ); @@ -567,17 +595,18 @@ void FGAPIENTRY glutMainLoopEvent( void ) switch( event.xvisibility.state ) { case VisibilityUnobscured: - window->Callbacks.WindowStatus( GLUT_FULLY_RETAINED ); + INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) ); window->State.Visible = TRUE; break; case VisibilityPartiallyObscured: - window->Callbacks.WindowStatus( GLUT_PARTIALLY_RETAINED ); + INVOKE_WCB( *window, WindowStatus, + ( GLUT_PARTIALLY_RETAINED ) ); window->State.Visible = TRUE; break; case VisibilityFullyObscured: - window->Callbacks.WindowStatus( GLUT_FULLY_COVERED ); + INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_COVERED ) ); window->State.Visible = FALSE; break; @@ -590,28 +619,13 @@ void FGAPIENTRY glutMainLoopEvent( void ) break; case EnterNotify: - { - GETWINDOW( xcrossing ); - GETMOUSE( xcrossing ); - if( window->Callbacks.Entry ) - { - fgSetWindow( window ) ; - window->Callbacks.Entry( GLUT_ENTERED ); - } - } - break; - case LeaveNotify: - { GETWINDOW( xcrossing ); GETMOUSE( xcrossing ); - if( window->Callbacks.Entry ) - { - fgSetWindow( window ) ; - window->Callbacks.Entry( GLUT_LEFT ); - } - } - break; + INVOKE_WCB( *window, Entry, ( ( EnterNotify == event.type ) ? + GLUT_ENTERED : + GLUT_LEFT ) ); + break; case MotionNotify: { @@ -642,23 +656,11 @@ void FGAPIENTRY glutMainLoopEvent( void ) (event.xmotion.state & Button3Mask) || (event.xmotion.state & Button4Mask) || (event.xmotion.state & Button5Mask) ) - { - /* - * A mouse button was pressed during the movement... - * Is there a motion callback hooked to the window? - */ - if( window->Callbacks.Motion ) - { - fgSetWindow ( window ) ; - window->Callbacks.Motion( event.xmotion.x, - event.xmotion.y ); - } - } - else if( window->Callbacks.Passive ) - { - fgSetWindow ( window ) ; - window->Callbacks.Passive( event.xmotion.x, event.xmotion.y ); - } + INVOKE_WCB( *window, Motion, ( event.xmotion.x, + event.xmotion.y ) ); + else + INVOKE_WCB( *window, Passive, ( event.xmotion.x, + event.xmotion.y ) ); } break; @@ -688,6 +690,10 @@ void FGAPIENTRY glutMainLoopEvent( void ) button = event.xbutton.button - 1; /* + * XXX This comment is replicated in the WIN32 section and + * XXX maybe also in the menu code. Can we move the info + * XXX to one central place and *reference* it from here? + * * Do not execute the application's mouse callback if a menu * is hooked to this button. In that case an appropriate * private call should be generated. @@ -770,12 +776,10 @@ void FGAPIENTRY glutMainLoopEvent( void ) * Check if there is a mouse or mouse wheel callback hooked to the * window */ - if( ( window->Callbacks.Mouse == NULL ) && - ( window->Callbacks.MouseWheel == NULL ) ) + if( ! FETCH_WCB( *window, Mouse ) && + ! FETCH_WCB( *window, MouseWheel ) ) break; - fgSetWindow( window ); - /* * XXX Why don't we use {window}? Other code here does... */ @@ -786,67 +790,64 @@ void FGAPIENTRY glutMainLoopEvent( void ) * * XXX Use a symbolic constant, *not* "4"! */ - if( ( button < 4 ) || ( !( window->Callbacks.MouseWheel ) ) ) - { - if( window->Callbacks.Mouse ) - fgStructure.Window->Callbacks.Mouse( - button, - event.type == ButtonPress ? GLUT_DOWN : GLUT_UP, - event.xbutton.x, - event.xbutton.y - ); - } + if( ( button < 3 ) || ( ! FETCH_WCB( *window, MouseWheel ) ) ) + INVOKE_WCB( *window, Mouse, ( button, + pressed ? GLUT_DOWN : GLUT_UP, + event.xbutton.x, + event.xbutton.y ) + ); else { - if( ( button >= 4 ) && window->Callbacks.MouseWheel ) - { - /* - * Map 4 and 5 to wheel zero; EVEN to +1, ODD to -1 - * " 6 and 7 " " one; ... - * - * XXX This *should* be behind some variables/macros, - * XXX since the order and numbering isn't certain - * XXX See XFree86 configuration docs (even back in the - * XXX 3.x days, and especially with 4.x). - */ - int wheel_number = (button - 4) / 2; - int direction = (button & 1)*2 - 1; - - if( ButtonPress ) - fgStructure.Window->Callbacks.MouseWheel( - wheel_number, - direction, - event.xbutton.x, - event.xbutton.y - ); - } + /* + * Map 4 and 5 to wheel zero; EVEN to +1, ODD to -1 + * " 6 and 7 " " one; ... + * + * XXX This *should* be behind some variables/macros, + * XXX since the order and numbering isn't certain + * XXX See XFree86 configuration docs (even back in the + * XXX 3.x days, and especially with 4.x). + * + * XXX Note that {button} has already been decremeted + * XXX in mapping from X button numbering to GLUT. + */ + int wheel_number = (button - 3) / 2; + int direction = -1; + if( button % 2 ) + direction = 1; + + if( pressed ) + INVOKE_WCB( *window, MouseWheel, ( wheel_number, + direction, + event.xbutton.x, + event.xbutton.y ) + ); } /* * Trash the modifiers state */ fgStructure.Window->State.Modifiers = 0xffffffff; - break; } + break; case KeyRelease: case KeyPress: { - FGCBkeyboard keyboard_cb; - FGCBspecial special_cb; + FGCBKeyboard keyboard_cb; + FGCBSpecial special_cb; GETWINDOW( xkey ); GETMOUSE( xkey ); if( event.type == KeyPress ) { - keyboard_cb = window->Callbacks.Keyboard; - special_cb = window->Callbacks.Special; + keyboard_cb = FETCH_WCB( *window, Keyboard ); + special_cb = FETCH_WCB( *window, Special ); } else { - keyboard_cb = window->Callbacks.KeyboardUp; - special_cb = window->Callbacks.SpecialUp; + keyboard_cb = FETCH_WCB( *window, KeyboardUp ); + special_cb = FETCH_WCB( *window, SpecialUp ); } /* @@ -938,6 +939,9 @@ void FGAPIENTRY glutMainLoopEvent( void ) } break; + case ReparentNotify: + break; /* XXX Should disable this event */ + default: fgWarning ("Unknown X event type: %d", event.type); break; @@ -989,12 +993,11 @@ void FGAPIENTRY glutMainLoop( void ) */ while( window ) { - if ( window->Callbacks.Visibility ) + if ( FETCH_WCB( *window, Visibility ) ) { SFG_Window *current_window = fgStructure.Window ; - fgSetWindow( window ); - window->Callbacks.Visibility ( window->State.Visible ) ; + INVOKE_WCB( *window, Visibility, ( window->State.Visible ) ); fgSetWindow( current_window ); } @@ -1019,7 +1022,7 @@ void FGAPIENTRY glutMainLoop( void ) } { - fgExecutionState execState = fgState.ActionOnWindowClose; + fgExecutionState execState = fgState.ExecState; /* * When this loop terminates, destroy the display, state and structure @@ -1040,10 +1043,25 @@ void FGAPIENTRY glutLeaveMainLoop( void ) fgState.ExecState = GLUT_EXEC_STATE_STOP ; } + +#if TARGET_HOST_WIN32 +/* + * Determine a GLUT modifer mask based on MS-WINDOWS system info. + */ +int fgGetWin32Modifiers (void) +{ + return + ( ( ( 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 ); +} + /* * The window procedure for handling Win32 events */ -#if TARGET_HOST_WIN32 LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { @@ -1069,24 +1087,24 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->Window.Device = GetDC( hWnd ); if( fgState.BuildingAMenu ) { - 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( fgStructure.MenuContext ) - wglMakeCurrent( window->Window.Device, - fgStructure.MenuContext->Context ) ; - else - { - fgStructure.MenuContext = - (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) ); - fgStructure.MenuContext->Context = - wglCreateContext( window->Window.Device ); - } - - /* window->Window.Context = wglGetCurrentContext () ; */ - window->Window.Context = wglCreateContext( window->Window.Device ); + 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( fgStructure.MenuContext ) + wglMakeCurrent( window->Window.Device, + fgStructure.MenuContext->Context ) ; + else + { + fgStructure.MenuContext = + (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) ); + fgStructure.MenuContext->Context = + wglCreateContext( window->Window.Device ); + } + + /* window->Window.Context = wglGetCurrentContext () ; */ + window->Window.Context = wglCreateContext( window->Window.Device ); } else { @@ -1126,7 +1144,6 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* glutSetCursor( fgStructure.Window->State.Cursor ); */ printf("WM_ACTIVATE: glutSetCursor( %p, %d)\n", window, window->State.Cursor ); - glutSetCursor( window->State.Cursor ); } @@ -1143,32 +1160,38 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, (fgStructure.Window->State.Cursor == GLUT_CURSOR_NONE)) SetCursor( NULL ); #else + /* Set the cursor AND change it for this window class. */ -# define MAP_CURSOR(a,b) case a: SetCursor( LoadCursor( NULL, b ) ); \ - break; +#define MAP_CURSOR(a,b) \ + case a: \ + SetCursor( LoadCursor( NULL, b ) ); \ + break; + /* Nuke the cursor AND change it for this window class. */ -# define ZAP_CURSOR(a,b) case a: SetCursor( NULL ); \ - break; +#define ZAP_CURSOR(a,b) \ + case a: \ + SetCursor( NULL ); \ + break; if( LOWORD( lParam ) == HTCLIENT ) - switch( window->State.Cursor ) - { - MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW ); - MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW ); - MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HELP ); - MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS ); - MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP ); - MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL ); - MAP_CURSOR( GLUT_CURSOR_SPRAY, IDC_CROSS ); - MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT ); - MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_UPARROW ); - MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS ); - /* MAP_CURSOR( GLUT_CURSOR_NONE, IDC_NO ); */ - ZAP_CURSOR( GLUT_CURSOR_NONE, NULL ); - - default: - MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_ARROW ); - } + switch( window->State.Cursor ) + { + MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW ); + MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW ); + MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HELP ); + MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS ); + MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP ); + MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL ); + MAP_CURSOR( GLUT_CURSOR_SPRAY, IDC_CROSS ); + MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT ); + MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_UPARROW ); + MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS ); + /* MAP_CURSOR( GLUT_CURSOR_NONE, IDC_NO ); */ + ZAP_CURSOR( GLUT_CURSOR_NONE, NULL ); + + default: + MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_ARROW ); + } #endif else lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); @@ -1180,6 +1203,8 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, break; case WM_PAINT: + /* Turn on the visibility in case it was turned off somehow */ + window->State.Visible = GL_TRUE; BeginPaint( hWnd, &ps ); fghRedrawWindowByHandle( hWnd ); EndPaint( hWnd, &ps ); @@ -1216,7 +1241,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, * Put on a linked list of windows to be removed after all the * callbacks have returned */ - fgAddToWindowDestroyList( window, FALSE ) ; + fgAddToWindowDestroyList( window, FALSE ); DestroyWindow( hWnd ); break; @@ -1224,7 +1249,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* * The window already got destroyed, so don't bother with it. */ - return( 0 ); + return 0; case WM_MOUSEMOVE: { @@ -1233,44 +1258,21 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, if ( window->ActiveMenu ) { - window->State.Redisplay = TRUE ; - - /* - * Since the window is a menu, make the parent window current - */ - fgSetWindow ( window->ActiveMenu->ParentWindow ) ; - + window->State.Redisplay = TRUE; + fgSetWindow ( window->ActiveMenu->ParentWindow ); break; } - 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 ); + window->State.Modifiers = fgGetWin32Modifiers( ); if( ( wParam & MK_LBUTTON ) || ( wParam & MK_MBUTTON ) || ( wParam & MK_RBUTTON ) ) - { - if( window->Callbacks.Motion ) - { - fgSetWindow( window ); - window->Callbacks.Motion( window->State.MouseX, - window->State.MouseY ); - } - } + INVOKE_WCB( *window, Motion, ( window->State.MouseX, + window->State.MouseY ) ); else - { - if( window->Callbacks.Passive ) - { - fgSetWindow( window ); - window->Callbacks.Passive( window->State.MouseX, - window->State.MouseY ); - } - } + INVOKE_WCB( *window, Passive, ( window->State.MouseX, + window->State.MouseY ) ); window->State.Modifiers = 0xffffffff; } @@ -1373,7 +1375,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, break; } - if ( ( window->Menu[ button ] != NULL ) && ( pressed == TRUE ) ) + if ( ( window->Menu[ button ] ) && ( pressed == TRUE ) ) { window->State.Redisplay = TRUE; fgSetWindow( window ); @@ -1382,24 +1384,19 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, break; } - if( window->Callbacks.Mouse == NULL ) + if( ! FETCH_WCB( *window, Mouse ) ) break; fgSetWindow( window ); - - 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 ); - - window->Callbacks.Mouse( - button, - pressed == TRUE ? GLUT_DOWN : GLUT_UP, - window->State.MouseX, - window->State.MouseY + fgStructure.Window->State.Modifiers = fgGetWin32Modifiers( ); + + INVOKE_WCB( + *window, Mouse, + ( button, + pressed == TRUE ? GLUT_DOWN : GLUT_UP, + window->State.MouseX, + window->State.MouseY + ) ); fgStructure.Window->State.Modifiers = 0xffffffff; @@ -1409,9 +1406,9 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, case 0x020a: /* Should be WM_MOUSEWHEEL but my compiler doesn't recognize it */ { - int wheel_number = LOWORD( lParam ); + int wheel_number = LOWORD( wParam ); /* THIS IS SPECULATIVE -- John Fay, 10/2/03 */ - int ticks = HIWORD( lParam ) / 120; + short ticks = ( short )HIWORD( wParam ) / 120; /* Should be WHEEL_DELTA instead of 120 */ int direction = 1; @@ -1429,26 +1426,21 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* window->State.MouseY = HIWORD( lParam ); */ /* change "lParam" to other parameter */ - if( ( window->Callbacks.MouseWheel == NULL ) && - ( window->Callbacks.Mouse == NULL ) ) + if( ! FETCH_WCB( *window, MouseWheel ) && + ! FETCH_WCB( *window, Mouse ) ) break; fgSetWindow( window ); - 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 ); + fgStructure.Window->State.Modifiers = fgGetWin32Modifiers( ); while( ticks-- ) - if( window->Callbacks.MouseWheel ) - window->Callbacks.MouseWheel( - wheel_number, - direction, - window->State.MouseX, - window->State.MouseY + if( FETCH_WCB( *window, MouseWheel ) ) + INVOKE_WCB( *window, MouseWheel, + ( wheel_number, + direction, + window->State.MouseX, + window->State.MouseY + ) ); else /* No mouse wheel, call the mouse button callback twice */ { @@ -1457,13 +1449,16 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, * XXX buttons. Sorry. */ int button = wheel_number*2 + 4; - button += (1 + direction)/2; - window->Callbacks.Mouse( button, GLUT_DOWN, - window->State.MouseX, - window->State.MouseY ) ; - window->Callbacks.Mouse( button, GLUT_UP, - window->State.MouseX, - window->State.MouseY ) ; + if( direction > 0 ) + ++button; + INVOKE_WCB( *window, Mouse, + ( button, GLUT_DOWN, + window->State.MouseX, window->State.MouseY ) + ); + INVOKE_WCB( *window, Mouse, + ( button, GLUT_UP, + window->State.MouseX, window->State.MouseX ) + ); } fgStructure.Window->State.Modifiers = 0xffffffff; @@ -1483,13 +1478,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, * Remember the current modifiers state. This is done here in order * to make sure the VK_DELETE keyboard callback is executed properly. */ - 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 ); + window->State.Modifiers = fgGetWin32Modifiers( ); GetCursorPos( &mouse_pos ); ScreenToClient( window->Window.Handle, &mouse_pos ); @@ -1530,20 +1519,16 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* * The delete key should be treated as an ASCII keypress: */ - if( window->Callbacks.Keyboard ) - { - fgSetWindow( window ); - 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 ) - { - fgSetWindow( window ); - window->Callbacks.Special( keypress, window->State.MouseX, - window->State.MouseY ); - } + if( keypress != -1 ) + INVOKE_WCB( *window, Special, + ( keypress, + window->State.MouseX, window->State.MouseY ) + ); window->State.Modifiers = 0xffffffff; } @@ -1553,19 +1538,13 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, case WM_KEYUP: { int keypress = -1; - POINT mouse_pos ; + POINT mouse_pos; /* * Remember the current modifiers state. This is done here in order * to make sure the VK_DELETE keyboard callback is executed properly. */ - 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 ); + window->State.Modifiers = fgGetWin32Modifiers( ); GetCursorPos( &mouse_pos ); ScreenToClient( window->Window.Handle, &mouse_pos ); @@ -1606,13 +1585,9 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* * The delete key should be treated as an ASCII keypress: */ - if( window->Callbacks.KeyboardUp ) - { - fgSetWindow( window ); - window->Callbacks.KeyboardUp( 127, window->State.MouseX, - window->State.MouseY ); - } - + INVOKE_WCB( *window, KeyboardUp, + ( 127, window->State.MouseX, window->State.MouseY ) + ); break; default: @@ -1625,22 +1600,18 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, if( ToAscii( wParam, 0, state, code, 0 ) == 1 ) wParam=code[ 0 ]; - if( window->Callbacks.KeyboardUp ) - { - fgSetWindow( window ); - window->Callbacks.KeyboardUp( (char)wParam, - window->State.MouseX, - window->State.MouseY ); - } + INVOKE_WCB( *window, KeyboardUp, + ( (char)wParam, + window->State.MouseX, window->State.MouseY ) + ); } } - if( (keypress != -1) && window->Callbacks.SpecialUp ) - { - fgSetWindow( window ); - 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; } @@ -1652,19 +1623,19 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, if( fgState.IgnoreKeyRepeat && (lParam & KF_REPEAT) ) break; - if( window->Callbacks.Keyboard ) + /* + * XXX INVOKE_WCB() takes care of the callback-pointer check. + * XXX We could just uncoditionally find/trash the Modifiers + * XXX and get rid of the "if( ... ) {" and "}". Unconditinal + * XXX code is simpler code. (^& + */ + if( FETCH_WCB( *window, Keyboard ) ) { - fgSetWindow( window ); - 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 ); - - window->Callbacks.Keyboard( (char)wParam, window->State.MouseX, - window->State.MouseY ); + window->State.Modifiers = fgGetWin32Modifiers( ); + INVOKE_WCB( *window, Keyboard, + ( (char)wParam, + window->State.MouseX, window->State.MouseY ) + ); window->State.Modifiers = 0xffffffff; } } @@ -1672,12 +1643,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, case WM_CAPTURECHANGED: /* User has finished resizing the window, force a redraw */ - if( window->Callbacks.Display ) - { - fgSetWindow( window ); - - window->Callbacks.Display( ); - } + INVOKE_WCB( *window, Display, ( ) ); /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ) ; */ break; @@ -1721,6 +1687,75 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* Pass it on to "DefWindowProc" to repaint a standard border */ break; + case WM_SYSCOMMAND : /* 0x0112 */ + { + /* + * We have received a system command message. Try to act on it. + * The commands are passed in through the "lParam" parameter: + * Clicking on a corner to resize the window gives a "F004" message + * but this is not defined in my header file. + */ + switch ( lParam ) + { + case SC_SIZE : + break ; + + case SC_MOVE : + break ; + + case SC_MINIMIZE : + /* User has clicked on the "-" to minimize the window */ + /* Turn off the visibility */ + window->State.Visible = GL_FALSE ; + + break ; + + case SC_MAXIMIZE : + break ; + + case SC_NEXTWINDOW : + break ; + + case SC_PREVWINDOW : + break ; + + case SC_CLOSE : + /* Followed very closely by a WM_CLOSE message */ + break ; + + case SC_VSCROLL : + break ; + + case SC_HSCROLL : + break ; + + case SC_MOUSEMENU : + break ; + + case SC_KEYMENU : + break ; + + case SC_ARRANGE : + break ; + + case SC_RESTORE : + break ; + + case SC_TASKLIST : + break ; + + case SC_SCREENSAVE : + break ; + + case SC_HOTKEY : + break ; + } + } + + /* We need to pass the message on to the operating system as well */ + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + break; + default: /* * Handle unhandled messages @@ -1729,7 +1764,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, break; } - return lRet ; + return lRet; } #endif