X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_main.c;h=e31ee1a027e5ba23f0e031ffd2b2aec5181a6ff5;hb=ded8742fba5a4622b49778679cc7e26d197d75c5;hp=b4cabb345a2c40c2fa139646d755faf18152da09;hpb=829150890f9ae5c95e3e8362f661697cec308fe7;p=freeglut diff --git a/src/freeglut_main.c b/src/freeglut_main.c index b4cabb3..e31ee1a 100644 --- a/src/freeglut_main.c +++ b/src/freeglut_main.c @@ -27,11 +27,13 @@ #include #include "freeglut_internal.h" -#include +#ifdef HAVE_ERRNO_H +# include +#endif #include -#if HAVE_VPRINTF +#ifdef HAVE_VFPRINTF # define VFPRINTF(s,f,a) vfprintf((s),(f),(a)) -#elif HAVE_DOPRNT +#elif defined(HAVE__DOPRNT) # define VFPRINTF(s,f,a) _doprnt((f),(a),(s)) #else # define VFPRINTF(s,f,a) @@ -57,7 +59,7 @@ struct GXKeyList gxKeyList; * 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 +#ifdef HAVE_LIMITS_H # include #endif #ifndef INT_MAX @@ -120,7 +122,8 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height ) if ( window->Parent == NULL ) { - if ( ! window->IsMenu && !window->State.IsGameMode ) + if ( ! window->IsMenu && (window != fgStructure.GameModeWindow) && + !( fgState.DisplayMode & GLUT_BORDERLESS )) { w += GetSystemMetrics( SM_CXSIZEFRAME ) * 2; h += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + @@ -301,46 +304,32 @@ static void fghCheckTimers( void ) } } -/* - * Elapsed Time - */ -long fgElapsedTime( void ) -{ - if ( fgState.Time.Set ) - { -#if TARGET_HOST_POSIX_X11 - struct timeval now; - long elapsed; - - gettimeofday( &now, NULL ); - - elapsed = (now.tv_usec - fgState.Time.Value.tv_usec) / 1000; - elapsed += (now.tv_sec - fgState.Time.Value.tv_sec) * 1000; - - return elapsed; + +/* Platform-dependent time in milliseconds, as an unsigned 32-bit integer. + * This value wraps every 49.7 days, but integer overflows cancel + * when subtracting an initial start time, unless the total time exceeds + * 32-bit, where the GLUT API return value is also overflowed. + */ +unsigned long fgSystemTime(void) { +#if TARGET_HOST_SOLARIS || HAVE_GETTIMEOFDAY + struct timeval now; + gettimeofday( &now, NULL ); + return now.tv_usec/1000 + now.tv_sec*1000; #elif TARGET_HOST_MS_WINDOWS # if defined(_WIN32_WCE) - return GetTickCount() - fgState.Time.Value; + return GetTickCount(); # else - return timeGetTime() - fgState.Time.Value; + return timeGetTime(); # endif #endif - } - else - { -#if TARGET_HOST_POSIX_X11 - gettimeofday( &fgState.Time.Value, NULL ); -#elif TARGET_HOST_MS_WINDOWS -# if defined(_WIN32_WCE) - fgState.Time.Value = GetTickCount(); -# else - fgState.Time.Value = timeGetTime (); -# endif -#endif - fgState.Time.Set = GL_TRUE ; - - return 0 ; - } +} + +/* + * Elapsed Time + */ +long fgElapsedTime( void ) +{ + return (long) (fgSystemTime() - fgState.Time); } /* @@ -350,37 +339,62 @@ void fgError( const char *fmt, ... ) { va_list ap; - va_start( ap, fmt ); + if (fgState.ErrorFunc) { + + va_start( ap, fmt ); - fprintf( stderr, "freeglut "); - if( fgState.ProgramName ) - fprintf( stderr, "(%s): ", fgState.ProgramName ); - VFPRINTF( stderr, fmt, ap ); - fprintf( stderr, "\n" ); + /* call user set error handler here */ + fgState.ErrorFunc(fmt, ap); - va_end( ap ); + va_end( ap ); - if ( fgState.Initialised ) - fgDeinitialize (); + } else { - exit( 1 ); + va_start( ap, fmt ); + + fprintf( stderr, "freeglut "); + if( fgState.ProgramName ) + fprintf( stderr, "(%s): ", fgState.ProgramName ); + VFPRINTF( stderr, fmt, ap ); + fprintf( stderr, "\n" ); + + va_end( ap ); + + if ( fgState.Initialised ) + fgDeinitialize (); + + exit( 1 ); + } } void fgWarning( const char *fmt, ... ) { va_list ap; - va_start( ap, fmt ); + if (fgState.WarningFunc) { - fprintf( stderr, "freeglut "); - if( fgState.ProgramName ) - fprintf( stderr, "(%s): ", fgState.ProgramName ); - VFPRINTF( stderr, fmt, ap ); - fprintf( stderr, "\n" ); + va_start( ap, fmt ); - va_end( ap ); + /* call user set warning handler here */ + fgState.WarningFunc(fmt, ap); + + va_end( ap ); + + } else { + + va_start( ap, fmt ); + + fprintf( stderr, "freeglut "); + if( fgState.ProgramName ) + fprintf( stderr, "(%s): ", fgState.ProgramName ); + VFPRINTF( stderr, fmt, ap ); + fprintf( stderr, "\n" ); + + va_end( ap ); + } } + /* * Indicates whether Joystick events are being used by ANY window. * @@ -485,8 +499,10 @@ static void fghSleepForEvents( void ) wait.tv_usec = (msec % 1000) * 1000; err = select( socket+1, &fdset, NULL, NULL, &wait ); +#ifdef HAVE_ERRNO_H if( ( -1 == err ) && ( errno != EINTR ) ) fgWarning ( "freeglut select() error: %d", errno ); +#endif } #elif TARGET_HOST_MS_WINDOWS MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLINPUT ); @@ -497,7 +513,7 @@ static void fghSleepForEvents( void ) /* * Returns GLUT modifier mask for the state field of an X11 event. */ -static int fghGetXModifiers( int state ) +int fghGetXModifiers( int state ) { int ret = 0; @@ -990,6 +1006,10 @@ void FGAPIENTRY glutMainLoopEvent( void ) switch( event.type ) { case ClientMessage: + if(fgIsSpaceballXEvent(&event)) { + fgSpaceballHandleXEvent(&event); + break; + } /* Destroy the window when the WM_DELETE_WINDOW message arrives */ if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.DeleteWindow ) { @@ -1173,15 +1193,15 @@ void FGAPIENTRY glutMainLoopEvent( void ) * XXX track ButtonPress/ButtonRelease events in our own * XXX bit-mask? */ - fgState.Modifiers = fghGetXModifiers( event.xmotion.state ); + fgState.Modifiers = fghGetXModifiers( event.xmotion.state ); if ( event.xmotion.state & ( Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) ) { INVOKE_WCB( *window, Motion, ( event.xmotion.x, event.xmotion.y ) ); } else { INVOKE_WCB( *window, Passive, ( event.xmotion.x, event.xmotion.y ) ); - } - fgState.Modifiers = INVALID_MODIFIERS; + } + fgState.Modifiers = INVALID_MODIFIERS; } break; @@ -1304,7 +1324,10 @@ void FGAPIENTRY glutMainLoopEvent( void ) /* Cease processing this event if it is auto repeated */ if (window->State.KeyRepeating) + { + if (event.type == KeyPress) window->State.KeyRepeating = GL_FALSE; break; + } if( event.type == KeyPress ) { @@ -1367,9 +1390,13 @@ void FGAPIENTRY glutMainLoopEvent( void ) case XK_F11: special = GLUT_KEY_F11; break; case XK_F12: special = GLUT_KEY_F12; break; + case XK_KP_Left: case XK_Left: special = GLUT_KEY_LEFT; break; + case XK_KP_Right: case XK_Right: special = GLUT_KEY_RIGHT; break; + case XK_KP_Up: case XK_Up: special = GLUT_KEY_UP; break; + case XK_KP_Down: case XK_Down: special = GLUT_KEY_DOWN; break; case XK_KP_Prior: @@ -1382,6 +1409,17 @@ void FGAPIENTRY glutMainLoopEvent( void ) case XK_End: special = GLUT_KEY_END; break; case XK_KP_Insert: case XK_Insert: special = GLUT_KEY_INSERT; break; + + case XK_Num_Lock : special = GLUT_KEY_NUM_LOCK; break; + case XK_KP_Begin : special = GLUT_KEY_BEGIN; break; + case XK_KP_Delete: special = GLUT_KEY_DELETE; break; + + case XK_Shift_L: special = GLUT_KEY_SHIFT_L; break; + case XK_Shift_R: special = GLUT_KEY_SHIFT_R; break; + case XK_Control_L: special = GLUT_KEY_CTRL_L; break; + case XK_Control_R: special = GLUT_KEY_CTRL_R; break; + case XK_Alt_L: special = GLUT_KEY_ALT_L; break; + case XK_Alt_R: special = GLUT_KEY_ALT_R; break; } /* @@ -1403,8 +1441,15 @@ void FGAPIENTRY glutMainLoopEvent( void ) case ReparentNotify: break; /* XXX Should disable this event */ + /* Not handled */ + case GravityNotify: + break; + default: - fgWarning ("Unknown X event type: %d\n", event.type); + /* enter handling of Extension Events here */ + #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H + fgHandleExtensionEvents( &event ); + #endif break; } } @@ -1557,9 +1602,12 @@ static int fghGetWin32Modifiers (void) LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { + static unsigned char lControl = 0, rControl = 0, lShift = 0, + rShift = 0, lAlt = 0, rAlt = 0; + SFG_Window* window; PAINTSTRUCT ps; - LONG lRet = 1; + LRESULT lRet = 1; FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ; @@ -1570,6 +1618,120 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0, uMsg, wParam, lParam ); */ + + if ( window ) + { + /* Checking for CTRL, ALT, and SHIFT key positions: Key Down! */ + if ( !lControl && GetAsyncKeyState ( VK_LCONTROL ) ) + { + INVOKE_WCB ( *window, Special, + ( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY ) + ); + + lControl = 1; + } + + if ( !rControl && GetAsyncKeyState ( VK_RCONTROL ) ) + { + INVOKE_WCB ( *window, Special, + ( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY ) + ); + + rControl = 1; + } + + if ( !lShift && GetAsyncKeyState ( VK_LSHIFT ) ) + { + INVOKE_WCB ( *window, Special, + ( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY ) + ); + + lShift = 1; + } + + if ( !rShift && GetAsyncKeyState ( VK_RSHIFT ) ) + { + INVOKE_WCB ( *window, Special, + ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY ) + ); + + rShift = 1; + } + + if ( !lAlt && GetAsyncKeyState ( VK_LMENU ) ) + { + INVOKE_WCB ( *window, Special, + ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY ) + ); + + lAlt = 1; + } + + if ( !rAlt && GetAsyncKeyState ( VK_RMENU ) ) + { + INVOKE_WCB ( *window, Special, + ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY ) + ); + + rAlt = 1; + } + + /* Checking for CTRL, ALT, and SHIFT key positions: Key Up! */ + if ( lControl && !GetAsyncKeyState ( VK_LCONTROL ) ) + { + INVOKE_WCB ( *window, SpecialUp, + ( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY ) + ); + + lControl = 0; + } + + if ( rControl && !GetAsyncKeyState ( VK_RCONTROL ) ) + { + INVOKE_WCB ( *window, SpecialUp, + ( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY ) + ); + + rControl = 0; + } + + if ( lShift && !GetAsyncKeyState ( VK_LSHIFT ) ) + { + INVOKE_WCB ( *window, SpecialUp, + ( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY ) + ); + + lShift = 0; + } + + if ( rShift && !GetAsyncKeyState ( VK_RSHIFT ) ) + { + INVOKE_WCB ( *window, SpecialUp, + ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY ) + ); + + rShift = 0; + } + + if ( lAlt && !GetAsyncKeyState ( VK_LMENU ) ) + { + INVOKE_WCB ( *window, SpecialUp, + ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY ) + ); + + lAlt = 0; + } + + if ( rAlt && !GetAsyncKeyState ( VK_RMENU ) ) + { + INVOKE_WCB ( *window, SpecialUp, + ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY ) + ); + + rAlt = 0; + } + } + switch( uMsg ) { case WM_CREATE: @@ -1620,11 +1782,22 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->Window.Context = wglCreateContext( window->Window.Device ); } + +#if !defined(_WIN32_WCE) + fgNewWGLCreateContext( window ); +#endif } window->State.NeedToResize = GL_TRUE; - window->State.Width = fgState.Size.X; - window->State.Height = fgState.Size.Y; + if( ( window->State.Width < 0 ) || ( window->State.Height < 0 ) ) + { + SFG_Window *current_window = fgStructure.CurrentWindow; + + fgSetWindow( window ); + window->State.Width = glutGet( GLUT_WINDOW_WIDTH ); + window->State.Height = glutGet( GLUT_WINDOW_HEIGHT ); + fgSetWindow( current_window ); + } ReleaseDC( window->Window.Handle, window->Window.Device ); @@ -1666,12 +1839,25 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, } break; -#if 0 + case WM_SETFOCUS: /* printf("WM_SETFOCUS: %p\n", window ); */ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) ); break; + case WM_KILLFOCUS: +/* printf("WM_KILLFOCUS: %p\n", window ); */ + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); + INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) ); + + if( window->IsMenu && + window->ActiveMenu && window->ActiveMenu->IsActive ) + fgUpdateMenuHighlight( window->ActiveMenu ); + + break; + +#if 0 case WM_ACTIVATE: if (LOWORD(wParam) != WA_INACTIVE) { @@ -1717,20 +1903,6 @@ 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 defined(_WIN32_WCE) @@ -1750,6 +1922,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, fgUpdateMenuHighlight( window->ActiveMenu ); break; } + SetFocus(window->Window.Handle); fgState.Modifiers = fghGetWin32Modifiers( ); @@ -1990,6 +2163,12 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, KEY( VK_RIGHT, GLUT_KEY_RIGHT ); KEY( VK_DOWN, GLUT_KEY_DOWN ); KEY( VK_INSERT, GLUT_KEY_INSERT ); + KEY( VK_LCONTROL, GLUT_KEY_CTRL_L ); + KEY( VK_RCONTROL, GLUT_KEY_CTRL_R ); + KEY( VK_LSHIFT, GLUT_KEY_SHIFT_L ); + KEY( VK_RSHIFT, GLUT_KEY_SHIFT_R ); + KEY( VK_LMENU, GLUT_KEY_ALT_L ); + KEY( VK_RMENU, GLUT_KEY_ALT_R ); case VK_DELETE: /* The delete key should be treated as an ASCII keypress: */ @@ -2076,6 +2255,12 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, KEY( VK_RIGHT, GLUT_KEY_RIGHT ); KEY( VK_DOWN, GLUT_KEY_DOWN ); KEY( VK_INSERT, GLUT_KEY_INSERT ); + KEY( VK_LCONTROL, GLUT_KEY_CTRL_L ); + KEY( VK_RCONTROL, GLUT_KEY_CTRL_R ); + KEY( VK_LSHIFT, GLUT_KEY_SHIFT_L ); + KEY( VK_RSHIFT, GLUT_KEY_SHIFT_R ); + KEY( VK_LMENU, GLUT_KEY_ALT_L ); + KEY( VK_RMENU, GLUT_KEY_ALT_R ); case VK_DELETE: /* The delete key should be treated as an ASCII keypress: */ @@ -2092,7 +2277,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, GetKeyboardState( state ); - if( ToAscii( wParam, 0, state, code, 0 ) == 1 ) + if( ToAscii( (UINT)wParam, 0, state, code, 0 ) == 1 ) wParam=code[ 0 ]; INVOKE_WCB( *window, KeyboardUp, @@ -2240,6 +2425,17 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, case SC_HOTKEY : break ; +#if(WINVER >= 0x0400) + case SC_DEFAULT : + break ; + + case SC_MONITORPOWER : + break ; + + case SC_CONTEXTHELP : + break ; +#endif /* WINVER >= 0x0400 */ + default: #if _DEBUG fgWarning( "Unknown wParam type 0x%x", wParam ); @@ -2253,6 +2449,41 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); break; +#ifdef WM_TOUCH + /* handle multi-touch messages */ + case WM_TOUCH: + { + unsigned int numInputs = (unsigned int)wParam; + unsigned int i = 0; + TOUCHINPUT* ti = (TOUCHINPUT*)malloc( sizeof(TOUCHINPUT)*numInputs); + if (GetTouchInputInfo( (HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT) )) { + /* Handle each contact point */ + for (i = 0; i < numInputs; ++i ) { + + POINT tp; + tp.x = TOUCH_COORD_TO_PIXEL(ti[i].x); + tp.y = TOUCH_COORD_TO_PIXEL(ti[i].y); + ScreenToClient( hWnd, &tp ); + + ti[i].dwID = ti[i].dwID * 2; + + if (ti[i].dwFlags & TOUCHEVENTF_DOWN) { + INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_ENTERED ) ); + INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_DOWN ) ); + } else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) { + INVOKE_WCB( *window, MultiMotion, ( ti[i].dwID, tp.x, tp.y ) ); + } else if (ti[i].dwFlags & TOUCHEVENTF_UP) { + INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_UP ) ); + INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_LEFT ) ); + } + } + } + CloseTouchInputHandle((HTOUCHINPUT)lParam); + free( (void*)ti ); + lRet = 0; /*DefWindowProc( hWnd, uMsg, wParam, lParam );*/ + break; + } +#endif default: /* Handle unhandled messages */ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );