X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_main.c;h=7f62b84b6a55ef9c49a7006c074e589676d94e4c;hb=8ecffae5f6f461182f26b917777b9ef3e1b1905d;hp=7c214ddcc730481e67b043a588715dca24e29107;hpb=2c9161e532490d2623896ad4720fb5e7bb6480bb;p=freeglut diff --git a/src/freeglut_main.c b/src/freeglut_main.c index 7c214dd..7f62b84 100644 --- a/src/freeglut_main.c +++ b/src/freeglut_main.c @@ -27,13 +27,21 @@ #include #include "freeglut_internal.h" - -#include -#if TARGET_HOST_UNIX_X11 #include -#include -#elif TARGET_HOST_WIN32 -#elif TARGET_HOST_WINCE +#include +#if TARGET_HOST_WIN32 +# define VFPRINTF(s,f,a) vfprintf((s),(f),(a)) +#else +# if HAVE_VPRINTF +# define VFPRINTF(s,f,a) vfprintf((s),(f),(a)) +# elif HAVE_DOPRNT +# define VFPRINTF(s,f,a) _doprnt((f),(a),(s)) +# else +# define VFPRINTF(s,f,a) +# endif +#endif + +#if TARGET_HOST_WINCE typedef struct GXDisplayProperties GXDisplayProperties; typedef struct GXKeyList GXKeyList; @@ -49,8 +57,15 @@ struct GXKeyList gxKeyList; #endif -#ifndef MAX -#define MAX(a,b) (((a)>(b)) ? (a) : (b)) +/* + * Try to get the maximum value allowed for ints, falling back to the minimum + * guaranteed by ISO C99 if there is no suitable header. + */ +#if HAVE_LIMITS_H +# include +#endif +#ifndef INT_MAX +# define INT_MAX 32767 #endif #ifndef MIN @@ -78,7 +93,7 @@ struct GXKeyList gxKeyList; */ static void fghReshapeWindow ( SFG_Window *window, int width, int height ) { - SFG_Window *current_window = fgStructure.Window; + SFG_Window *current_window = fgStructure.CurrentWindow; freeglut_return_if_fail( window != NULL ); @@ -89,9 +104,7 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height ) width, height ); XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ -#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE - -#if !TARGET_HOST_WINCE +#elif TARGET_HOST_WIN32 { RECT winRect; int x, y, w, h; @@ -141,7 +154,7 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height ) SWP_NOZORDER ); } -#endif /* TARGET_HOST_WINCE */ +#endif /* * XXX Should update {window->State.OldWidth, window->State.OldHeight} @@ -155,8 +168,6 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height ) glViewport( 0, 0, width, height ); } -#endif - /* * Force a window redraw. In Windows at least this is only a partial * solution: if the window is increasing in size in either dimension, @@ -176,7 +187,7 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height ) */ static void fghRedrawWindow ( SFG_Window *window ) { - SFG_Window *current_window = fgStructure.Window; + SFG_Window *current_window = fgStructure.CurrentWindow; freeglut_return_if_fail( window ); freeglut_return_if_fail( FETCH_WCB ( *window, Display ) ); @@ -343,8 +354,8 @@ void fgError( const char *fmt, ... ) fprintf( stderr, "freeglut "); if( fgState.ProgramName ) - fprintf (stderr, "(%s): ", fgState.ProgramName); - vfprintf( stderr, fmt, ap ); + fprintf( stderr, "(%s): ", fgState.ProgramName ); + VFPRINTF( stderr, fmt, ap ); fprintf( stderr, "\n" ); va_end( ap ); @@ -364,7 +375,7 @@ void fgWarning( const char *fmt, ... ) fprintf( stderr, "freeglut "); if( fgState.ProgramName ) fprintf( stderr, "(%s): ", fgState.ProgramName ); - vfprintf( stderr, fmt, ap ); + VFPRINTF( stderr, fmt, ap ); fprintf( stderr, "\n" ); va_end( ap ); @@ -445,8 +456,10 @@ static void fghSleepForEvents( void ) return; msec = fghNextTimer( ); - if( fghHaveJoystick( ) ) /* XXX Use GLUT timers for joysticks... */ - msec = MIN( msec, 10 ); /* XXX Dumb; forces granularity to .01sec */ + /* XXX Use GLUT timers for joysticks... */ + /* XXX Dumb; forces granularity to .01sec */ + if( fghHaveJoystick( ) && ( msec > 10 ) ) + msec = 10; #if TARGET_HOST_UNIX_X11 /* @@ -472,7 +485,7 @@ static void fghSleepForEvents( void ) wait.tv_usec = (msec % 1000) * 1000; err = select( socket+1, &fdset, NULL, NULL, &wait ); - if( -1 == err ) + if( ( -1 == err ) && ( errno != EINTR ) ) fgWarning ( "freeglut select() error: %d", errno ); } #elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE @@ -575,6 +588,8 @@ void FGAPIENTRY glutMainLoopEvent( void ) if( ( width != window->State.OldWidth ) || ( height != window->State.OldHeight ) ) { + SFG_Window *current_window = fgStructure.CurrentWindow; + window->State.OldWidth = width; window->State.OldHeight = height; if( FETCH_WCB( *window, Reshape ) ) @@ -585,6 +600,8 @@ void FGAPIENTRY glutMainLoopEvent( void ) glViewport( 0, 0, width, height ); } glutPostRedisplay( ); + if( window->IsMenu ) + fgSetWindow( current_window ); } } break; @@ -611,8 +628,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) if( event.xexpose.count == 0 ) { GETWINDOW( xexpose ); - fgSetWindow( window ); - glutPostRedisplay( ); + window->State.Redisplay = GL_TRUE; } break; @@ -678,6 +694,10 @@ void FGAPIENTRY glutMainLoopEvent( void ) case LeaveNotify: GETWINDOW( xcrossing ); GETMOUSE( xcrossing ); + if( ( event.type == LeaveNotify ) && window->IsMenu && + window->ActiveMenu && window->ActiveMenu->IsActive ) + fgUpdateMenuHighlight( window->ActiveMenu ); + INVOKE_WCB( *window, Entry, ( ( EnterNotify == event.type ) ? GLUT_ENTERED : GLUT_LEFT ) ); @@ -697,8 +717,8 @@ void FGAPIENTRY glutMainLoopEvent( void ) window->ActiveMenu->Window->State.MouseY = event.xmotion.y_root - window->ActiveMenu->Y; } - window->ActiveMenu->Window->State.Redisplay = GL_TRUE ; - fgSetWindow( window->ActiveMenu->ParentWindow ); + + fgUpdateMenuHighlight( window->ActiveMenu ); break; } @@ -764,12 +784,8 @@ void FGAPIENTRY glutMainLoopEvent( void ) fgState.Modifiers = fghGetXModifiers( &event ); - /* - * Finally execute the mouse or mouse wheel callback - * - * XXX Use a symbolic constant, *not* "4"! ("3, sire!") - */ - if( ( button < 3 ) || ( ! FETCH_WCB( *window, MouseWheel ) ) ) + /* Finally execute the mouse or mouse wheel callback */ + if( ( button < glutDeviceGet ( GLUT_NUM_MOUSE_BUTTONS ) ) || ( ! FETCH_WCB( *window, MouseWheel ) ) ) INVOKE_WCB( *window, Mouse, ( button, pressed ? GLUT_DOWN : GLUT_UP, event.xbutton.x, @@ -789,7 +805,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) * XXX Note that {button} has already been decremeted * XXX in mapping from X button numbering to GLUT. */ - int wheel_number = (button - 3) / 2; + int wheel_number = (button - glutDeviceGet ( GLUT_NUM_MOUSE_BUTTONS )) / 2; int direction = -1; if( button % 2 ) direction = 1; @@ -849,13 +865,13 @@ void FGAPIENTRY glutMainLoopEvent( void ) if( event.type == KeyPress ) { - keyboard_cb = FETCH_WCB( *window, Keyboard ); - special_cb = FETCH_WCB( *window, Special ); + keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, Keyboard )); + special_cb = (FGCBSpecial) ( FETCH_WCB( *window, Special )); } else { - keyboard_cb = FETCH_WCB( *window, KeyboardUp ); - special_cb = FETCH_WCB( *window, SpecialUp ); + keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, KeyboardUp )); + special_cb = (FGCBSpecial) ( FETCH_WCB( *window, SpecialUp )); } /* Is there a keyboard/special callback hooked for this window? */ @@ -1012,7 +1028,7 @@ void FGAPIENTRY glutMainLoop( void ) { if ( FETCH_WCB( *window, Visibility ) ) { - SFG_Window *current_window = fgStructure.Window ; + SFG_Window *current_window = fgStructure.CurrentWindow ; INVOKE_WCB( *window, Visibility, ( window->State.Visible ) ); fgSetWindow( current_window ); @@ -1043,7 +1059,13 @@ void FGAPIENTRY glutMainLoop( void ) else { if( fgState.IdleCallback ) + { + if( fgStructure.CurrentWindow && + fgStructure.CurrentWindow->IsMenu ) + /* fail safe */ + fgSetWindow( window ); fgState.IdleCallback( ); + } fghSleepForEvents( ); } @@ -1210,57 +1232,19 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, case WM_ACTIVATE: if (LOWORD(wParam) != WA_INACTIVE) { - /* glutSetCursor( fgStructure.Window->State.Cursor ); */ -/* printf("WM_ACTIVATE: glutSetCursor( %p, %d)\n", window, +/* printf("WM_ACTIVATE: fgSetCursor( %p, %d)\n", window, window->State.Cursor ); */ - glutSetCursor( window->State.Cursor ); + fgSetCursor( window, window->State.Cursor ); } lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); break; #endif - /* - * XXX Why not re-use some common code with the glutSetCursor() - * XXX function (or perhaps invoke glutSetCursor())? - * XXX That is, why are we duplicating code, here, from - * XXX glutSetCursor()? The WIN32 code should be able to just - * XXX call glutSetCursor() instead of defining two macros - * XXX and implementing a nested case in-line. - */ case WM_SETCURSOR: - /* Set the cursor AND change it for this window class. */ -#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; - /* printf ( "Cursor event %x %x %x %x\n", window, window->State.Cursor, lParam, wParam ) ; */ 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 ); - } + fgSetCursor ( window, window->State.Cursor ) ; else lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); break; @@ -1290,6 +1274,20 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, */ return 0; + /* XXX For a future patch: we need a mouse entry event. Unfortunately Windows + * XXX doesn't give us one, so we will probably need a "MouseInWindow" flag in + * XXX the SFG_Window structure. Set it to true to begin with and then have the + * XXX WM_MOUSELEAVE code set it to false. Then when we get a WM_MOUSEMOVE event, + * XXX if the flag is false we invoke the Entry callback and set the flag to true. + */ + case 0x02a2: /* This is the message we get when the mouse is leaving the window */ + if( window->IsMenu && + window->ActiveMenu && window->ActiveMenu->IsActive ) + fgUpdateMenuHighlight( window->ActiveMenu ); + + INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) ); + break ; + case WM_MOUSEMOVE: { #if TARGET_HOST_WINCE @@ -1306,8 +1304,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, if ( window->ActiveMenu ) { - window->State.Redisplay = GL_TRUE; - fgSetWindow ( window->ActiveMenu->ParentWindow ); + fgUpdateMenuHighlight( window->ActiveMenu ); break; } @@ -1404,15 +1401,6 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->State.MouseX, window->State.MouseY ) ) break; - if( window->Menu[ button ] && pressed ) - { - window->State.Redisplay = GL_TRUE; - fgSetWindow( window ); - fgActivateMenu( window, button ); - - break; - } - /* Set capture so that the window captures all the mouse messages */ /* * XXX - Multiple button support: Under X11, the mouse is not released @@ -1489,11 +1477,14 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, else /* No mouse wheel, call the mouse button callback twice */ { /* + * Map wheel zero to button 3 and 4; +1 to 3, -1 to 4 + * " " one +1 to 5, -1 to 6, ... + * * XXX The below assumes that you have no more than 3 mouse * XXX buttons. Sorry. */ - int button = wheel_number*2 + 4; - if( direction > 0 ) + int button = wheel_number * 2 + 3; + if( direction < 0 ) ++button; INVOKE_WCB( *window, Mouse, ( button, GLUT_DOWN, @@ -1501,7 +1492,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, ); INVOKE_WCB( *window, Mouse, ( button, GLUT_UP, - window->State.MouseX, window->State.MouseX ) + window->State.MouseX, window->State.MouseY ) ); }