X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_main.c;h=5f9b0a5d21b3f61acb789f94d5aa45dcc6bdafa3;hb=e6b149a66a5d6f7539855ca7922791cd22348f43;hp=7b53ea4c30500d998c8341e6c4663840f4a8e10f;hpb=25797e0fc9db283528048a34d4e4e4b43763bd19;p=freeglut diff --git a/src/freeglut_main.c b/src/freeglut_main.c index 7b53ea4..5f9b0a5 100644 --- a/src/freeglut_main.c +++ b/src/freeglut_main.c @@ -27,21 +27,19 @@ #include #include "freeglut_internal.h" -#include +#ifdef HAVE_ERRNO_H +# include +#endif #include -#if TARGET_HOST_WIN32 +#ifdef HAVE_VFPRINTF # define VFPRINTF(s,f,a) vfprintf((s),(f),(a)) +#elif defined(HAVE__DOPRNT) +# define VFPRINTF(s,f,a) _doprnt((f),(a),(s)) #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 +# define VFPRINTF(s,f,a) #endif -#if TARGET_HOST_WINCE +#ifdef _WIN32_WCE typedef struct GXDisplayProperties GXDisplayProperties; typedef struct GXKeyList GXKeyList; @@ -55,13 +53,13 @@ GXOPENINPUT GXOpenInput_ = NULL; struct GXKeyList gxKeyList; -#endif +#endif /* _WIN32_WCE */ /* * 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 @@ -69,9 +67,15 @@ struct GXKeyList gxKeyList; #endif #ifndef MIN -#define MIN(a,b) (((a)<(b)) ? (a) : (b)) +# define MIN(a,b) (((a)<(b)) ? (a) : (b)) #endif +#ifdef WM_TOUCH + typedef BOOL (WINAPI *pGetTouchInputInfo)(HTOUCHINPUT,UINT,PTOUCHINPUT,int); + typedef BOOL (WINAPI *pCloseTouchInputHandle)(HTOUCHINPUT); + static pGetTouchInputInfo fghGetTouchInputInfo = (pGetTouchInputInfo)0xDEADBEEF; + static pCloseTouchInputHandle fghCloseTouchInputHandle = (pCloseTouchInputHandle)0xDEADBEEF; +#endif /* * TODO BEFORE THE STABLE RELEASE: @@ -97,17 +101,15 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height ) freeglut_return_if_fail( window != NULL ); - -#if TARGET_HOST_UNIX_X11 +#if TARGET_HOST_POSIX_X11 XResizeWindow( fgDisplay.Display, window->Window.Handle, width, height ); XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ -#elif TARGET_HOST_WIN32 +#elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) { - RECT winRect; - int x, y, w, h; + RECT windowRect; /* * For windowed mode, get the current position of the @@ -116,50 +118,43 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height ) */ /* "GetWindowRect" returns the pixel coordinates of the outside of the window */ - GetWindowRect( window->Window.Handle, &winRect ); - x = winRect.left; - y = winRect.top; - w = width; - h = height; + GetWindowRect( window->Window.Handle, &windowRect ); - if ( window->Parent == NULL ) - { - if ( ! window->IsMenu && !window->State.IsGameMode ) - { - w += GetSystemMetrics( SM_CXSIZEFRAME ) * 2; - h += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + - GetSystemMetrics( SM_CYCAPTION ); - } - } + /* Create rect in FreeGLUT format, (X,Y) topleft outside window, WxH of client area */ + windowRect.right = windowRect.left+width; + windowRect.bottom = windowRect.top+height; + + if (window->Parent == NULL) + /* get the window rect from this to feed to SetWindowPos, correct for window decorations */ + fghComputeWindowRectFromClientArea_QueryWindow(window,&windowRect,TRUE); else { + /* correct rect for position client area of parent window + * (SetWindowPos input for child windows is in coordinates + * relative to the parent's client area). + * Child windows don't have decoration, so no need to correct + * for them. + */ RECT parentRect; - GetWindowRect( window->Parent->Window.Handle, &parentRect ); - x -= parentRect.left + GetSystemMetrics( SM_CXSIZEFRAME ) * 2; - y -= parentRect.top + GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + - GetSystemMetrics( SM_CYCAPTION ); + parentRect = fghGetClientArea( window->Parent, FALSE ); + windowRect.left -= parentRect.left; + windowRect.right -= parentRect.left; + windowRect.top -= parentRect.top; + windowRect.bottom -= parentRect.top; } - - /* - * SWP_NOACTIVATE Do not activate the window - * SWP_NOOWNERZORDER Do not change position in z-order - * SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message - * SWP_NOZORDER Retains the current Z order (ignore 2nd param) - */ - + + /* Do the actual resizing */ SetWindowPos( window->Window.Handle, HWND_TOP, - x, y, w, h, + windowRect.left, windowRect.top, + windowRect.right - windowRect.left, + windowRect.bottom- windowRect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER ); } #endif - /* - * XXX Should update {window->State.OldWidth, window->State.OldHeight} - * XXX to keep in lockstep with UNIX_X11 code. - */ if( FETCH_WCB( *window, Reshape ) ) INVOKE_WCB( *window, Reshape, ( width, height ) ); else @@ -225,9 +220,10 @@ static void fghcbDisplayWindow( SFG_Window *window, { window->State.Redisplay = GL_FALSE; -#if TARGET_HOST_UNIX_X11 +#if TARGET_HOST_POSIX_X11 fghRedrawWindow ( window ) ; -#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE +#elif TARGET_HOST_MS_WINDOWS + RedrawWindow( window->Window.Handle, NULL, NULL, RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW @@ -262,9 +258,9 @@ static void fghcbCheckJoystickPolls( SFG_Window *window, if( window->State.JoystickLastPoll + window->State.JoystickPollRate <= checkTime ) { -#if !TARGET_HOST_WINCE +#if !defined(_WIN32_WCE) fgJoystickPollWindow( window ); -#endif /* !TARGET_HOST_WINCE */ +#endif /* !defined(_WIN32_WCE) */ window->State.JoystickLastPoll = checkTime; } @@ -305,42 +301,32 @@ static void fghCheckTimers( void ) } } + +/* 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(); +# else + return timeGetTime(); +# endif +#endif +} + /* * Elapsed Time */ long fgElapsedTime( void ) { - if ( fgState.Time.Set ) - { -#if TARGET_HOST_UNIX_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; -#elif TARGET_HOST_WIN32 - return timeGetTime() - fgState.Time.Value; -#elif TARGET_HOST_WINCE - return GetTickCount() - fgState.Time.Value; -#endif - } - else - { -#if TARGET_HOST_UNIX_X11 - gettimeofday( &fgState.Time.Value, NULL ); -#elif TARGET_HOST_WIN32 - fgState.Time.Value = timeGetTime (); -#elif TARGET_HOST_WINCE - fgState.Time.Value = GetTickCount(); -#endif - fgState.Time.Set = GL_TRUE ; - - return 0 ; - } + return (long) (fgSystemTime() - fgState.Time); } /* @@ -350,37 +336,62 @@ void fgError( const char *fmt, ... ) { va_list ap; - va_start( ap, fmt ); + if (fgState.ErrorFunc) { + + va_start( ap, fmt ); + + /* call user set error handler here */ + fgState.ErrorFunc(fmt, ap); + + va_end( ap ); + + } else { - 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 ); + fprintf( stderr, "freeglut "); + if( fgState.ProgramName ) + fprintf( stderr, "(%s): ", fgState.ProgramName ); + VFPRINTF( stderr, fmt, ap ); + fprintf( stderr, "\n" ); - if ( fgState.Initialised ) - fgDeinitialize (); + va_end( ap ); - exit( 1 ); + if ( fgState.Initialised ) + fgDeinitialize (); + + exit( 1 ); + } } void fgWarning( const char *fmt, ... ) { va_list ap; - va_start( ap, fmt ); + if (fgState.WarningFunc) { + + va_start( ap, fmt ); + + /* call user set warning handler here */ + fgState.WarningFunc(fmt, ap); - fprintf( stderr, "freeglut "); - if( fgState.ProgramName ) - fprintf( stderr, "(%s): ", fgState.ProgramName ); - VFPRINTF( stderr, fmt, ap ); - fprintf( stderr, "\n" ); + va_end( 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. * @@ -413,7 +424,7 @@ static int fghHaveJoystick( void ) } static void fghHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e) { - if( w->State.Redisplay ) + if( w->State.Redisplay && w->State.Visible ) { e->found = GL_TRUE; e->data = w; @@ -461,7 +472,7 @@ static void fghSleepForEvents( void ) if( fghHaveJoystick( ) && ( msec > 10 ) ) msec = 10; -#if TARGET_HOST_UNIX_X11 +#if TARGET_HOST_POSIX_X11 /* * Possibly due to aggressive use of XFlush() and friends, * it is possible to have our socket drained but still have @@ -485,27 +496,29 @@ 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_WIN32 || TARGET_HOST_WINCE - MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLEVENTS ); +#elif TARGET_HOST_MS_WINDOWS + MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLINPUT ); #endif } -#if TARGET_HOST_UNIX_X11 +#if TARGET_HOST_POSIX_X11 /* - * Returns GLUT modifier mask for an XEvent. + * Returns GLUT modifier mask for the state field of an X11 event. */ -static int fghGetXModifiers( XEvent *event ) +int fghGetXModifiers( int state ) { int ret = 0; - if( event->xkey.state & ( ShiftMask | LockMask ) ) + if( state & ( ShiftMask | LockMask ) ) ret |= GLUT_ACTIVE_SHIFT; - if( event->xkey.state & ControlMask ) + if( state & ControlMask ) ret |= GLUT_ACTIVE_CTRL; - if( event->xkey.state & Mod1Mask ) + if( state & Mod1Mask ) ret |= GLUT_ACTIVE_ALT; return ret; @@ -513,7 +526,7 @@ static int fghGetXModifiers( XEvent *event ) #endif -#if TARGET_HOST_UNIX_X11 && _DEBUG +#if TARGET_HOST_POSIX_X11 && _DEBUG static const char* fghTypeToString( int type ) { @@ -964,7 +977,7 @@ static void fghPrintEvent( XEvent *event ) */ void FGAPIENTRY glutMainLoopEvent( void ) { -#if TARGET_HOST_UNIX_X11 +#if TARGET_HOST_POSIX_X11 SFG_Window* window; XEvent event; @@ -990,6 +1003,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 ) { @@ -1085,7 +1102,6 @@ void FGAPIENTRY glutMainLoopEvent( void ) case UnmapNotify: /* We get this when iconifying a window. */ GETWINDOW( xunmap ); - fgSetWindow( window ); INVOKE_WCB( *window, WindowStatus, ( GLUT_HIDDEN ) ); window->State.Visible = GL_FALSE; break; @@ -1100,14 +1116,6 @@ void FGAPIENTRY glutMainLoopEvent( void ) case VisibilityNotify: { - GETWINDOW( xvisibility ); - /* - * XXX INVOKE_WCB() does this check for us. - */ - if( ! FETCH_WCB( *window, WindowStatus ) ) - break; - fgSetWindow( window ); - /* * Sending this event, the X server can notify us that the window * has just acquired one of the three possible visibility states: @@ -1116,6 +1124,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) * VisibilityNotify event when iconifying a window, we only get an * UnmapNotify then. */ + GETWINDOW( xvisibility ); switch( event.xvisibility.state ) { case VisibilityUnobscured: @@ -1181,14 +1190,15 @@ void FGAPIENTRY glutMainLoopEvent( void ) * XXX track ButtonPress/ButtonRelease events in our own * XXX bit-mask? */ -#define BUTTON_MASK \ - ( Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) - if ( event.xmotion.state & BUTTON_MASK ) + 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 + } else { INVOKE_WCB( *window, Passive, ( event.xmotion.x, event.xmotion.y ) ); + } + fgState.Modifiers = INVALID_MODIFIERS; } break; @@ -1234,7 +1244,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) ! FETCH_WCB( *window, MouseWheel ) ) break; - fgState.Modifiers = fghGetXModifiers( &event ); + fgState.Modifiers = fghGetXModifiers( event.xbutton.state ); /* Finally execute the mouse or mouse wheel callback */ if( ( button < glutDeviceGet ( GLUT_NUM_MOUSE_BUTTONS ) ) || ( ! FETCH_WCB( *window, MouseWheel ) ) ) @@ -1254,8 +1264,10 @@ void FGAPIENTRY glutMainLoopEvent( void ) * 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 Note that {button} has already been decremented * XXX in mapping from X button numbering to GLUT. + * + * XXX Should add support for partial wheel turns as Windows does -- 5/27/11 */ int wheel_number = (button - glutDeviceGet ( GLUT_NUM_MOUSE_BUTTONS )) / 2; int direction = -1; @@ -1269,9 +1281,7 @@ void FGAPIENTRY glutMainLoopEvent( void ) event.xbutton.y ) ); } - - /* Trash the modifiers state */ - fgState.Modifiers = 0xffffffff; + fgState.Modifiers = INVALID_MODIFIERS; } break; @@ -1313,7 +1323,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 ) { @@ -1346,11 +1359,11 @@ void FGAPIENTRY glutMainLoopEvent( void ) if( keyboard_cb ) { fgSetWindow( window ); - fgState.Modifiers = fghGetXModifiers( &event ); + fgState.Modifiers = fghGetXModifiers( event.xkey.state ); keyboard_cb( asciiCode[ 0 ], event.xkey.x, event.xkey.y ); - fgState.Modifiers = 0xffffffff; + fgState.Modifiers = INVALID_MODIFIERS; } } else @@ -1376,9 +1389,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: @@ -1391,6 +1408,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; } /* @@ -1400,9 +1428,9 @@ void FGAPIENTRY glutMainLoopEvent( void ) if( special_cb && (special != -1) ) { fgSetWindow( window ); - fgState.Modifiers = fghGetXModifiers( &event ); + fgState.Modifiers = fghGetXModifiers( event.xkey.state ); special_cb( special, event.xkey.x, event.xkey.y ); - fgState.Modifiers = 0xffffffff; + fgState.Modifiers = INVALID_MODIFIERS; } } } @@ -1412,13 +1440,20 @@ void FGAPIENTRY glutMainLoopEvent( void ) case ReparentNotify: break; /* XXX Should disable this event */ + /* Not handled */ + case GravityNotify: + break; + default: - fgWarning ("Unknown X event type: %d", event.type); + /* enter handling of Extension Events here */ + #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H + fgHandleExtensionEvents( &event ); + #endif break; } } -#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE +#elif TARGET_HOST_MS_WINDOWS MSG stMsg; @@ -1460,13 +1495,13 @@ void FGAPIENTRY glutMainLoop( void ) { int action; -#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE +#if TARGET_HOST_MS_WINDOWS SFG_Window *window = (SFG_Window *)fgStructure.Windows.First ; #endif FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoop" ); -#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE +#if TARGET_HOST_MS_WINDOWS /* * Processing before the main loop: If there is a window which is open and * which has a visibility callback, call it. I know this is an ugly hack, @@ -1545,7 +1580,7 @@ void FGAPIENTRY glutLeaveMainLoop( void ) } -#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE +#if TARGET_HOST_MS_WINDOWS /* * Determine a GLUT modifer mask based on MS-WINDOWS system info. */ @@ -1566,9 +1601,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" ) ; @@ -1579,10 +1617,124 @@ 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: - /* The window structure is passed as the creation structure paramter... */ + /* The window structure is passed as the creation structure parameter... */ window = (SFG_Window *) (((LPCREATESTRUCT) lParam)->lpCreateParams); FREEGLUT_INTERNAL_ERROR_EXIT ( ( window != NULL ), "Cannot create window", "fgWindowProc" ); @@ -1593,20 +1745,20 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, { unsigned int current_DisplayMode = fgState.DisplayMode; fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH; -#if !TARGET_HOST_WINCE +#if !defined(_WIN32_WCE) fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE ); #endif fgState.DisplayMode = current_DisplayMode; if( fgStructure.MenuContext ) wglMakeCurrent( window->Window.Device, - fgStructure.MenuContext->Context + fgStructure.MenuContext->MContext ); else { fgStructure.MenuContext = (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) ); - fgStructure.MenuContext->Context = + fgStructure.MenuContext->MContext = wglCreateContext( window->Window.Device ); } @@ -1615,7 +1767,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, } else { -#if !TARGET_HOST_WINCE +#if !defined(_WIN32_WCE) fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE ); #endif @@ -1629,15 +1781,30 @@ 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 we used CW_USEDEFAULT (thats a negative value) for the size + * of the window, query the window now for the size at which it + * was created. + */ + 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 ); -#if TARGET_HOST_WINCE +#if defined(_WIN32_WCE) /* Take over button handling */ { HINSTANCE dxDllLib=LoadLibrary(_T("gx.dll")); @@ -1653,7 +1820,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, gxKeyList = (*GXGetDefaultKeys_)(GX_LANDSCAPEKEYS); } -#endif /* TARGET_HOST_WINCE */ +#endif /* defined(_WIN32_WCE) */ break; case WM_SIZE: @@ -1665,22 +1832,35 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, if( window->State.Visible ) { window->State.NeedToResize = GL_TRUE; -#if TARGET_HOST_WINCE +#if defined(_WIN32_WCE) window->State.Width = HIWORD(lParam); window->State.Height = LOWORD(lParam); #else window->State.Width = LOWORD(lParam); window->State.Height = HIWORD(lParam); -#endif /* TARGET_HOST_WINCE */ +#endif /* defined(_WIN32_WCE) */ } 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) { @@ -1726,29 +1906,15 @@ 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 +#if defined(_WIN32_WCE) window->State.MouseX = 320-HIWORD( lParam ); window->State.MouseY = LOWORD( lParam ); #else window->State.MouseX = LOWORD( lParam ); window->State.MouseY = HIWORD( lParam ); -#endif /* TARGET_HOST_WINCE */ +#endif /* defined(_WIN32_WCE) */ /* Restrict to [-32768, 32767] to match X11 behaviour */ /* See comment in "freeglut_developer" mailing list 10/4/04 */ if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536; @@ -1759,6 +1925,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, fgUpdateMenuHighlight( window->ActiveMenu ); break; } + SetFocus(window->Window.Handle); fgState.Modifiers = fghGetWin32Modifiers( ); @@ -1771,7 +1938,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, INVOKE_WCB( *window, Passive, ( window->State.MouseX, window->State.MouseY ) ); - fgState.Modifiers = 0xffffffff; + fgState.Modifiers = INVALID_MODIFIERS; } break; @@ -1785,13 +1952,13 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, GLboolean pressed = GL_TRUE; int button; -#if TARGET_HOST_WINCE +#if defined(_WIN32_WCE) window->State.MouseX = 320-HIWORD( lParam ); window->State.MouseY = LOWORD( lParam ); #else window->State.MouseX = LOWORD( lParam ); window->State.MouseY = HIWORD( lParam ); -#endif /* TARGET_HOST_WINCE */ +#endif /* defined(_WIN32_WCE) */ /* Restrict to [-32768, 32767] to match X11 behaviour */ /* See comment in "freeglut_developer" mailing list 10/4/04 */ @@ -1830,7 +1997,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, break; } -#if !TARGET_HOST_WINCE +#if !defined(_WIN32_WCE) if( GetSystemMetrics( SM_SWAPBUTTON ) ) { if( button == GLUT_LEFT_BUTTON ) @@ -1839,7 +2006,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, if( button == GLUT_RIGHT_BUTTON ) button = GLUT_LEFT_BUTTON; } -#endif /* !TARGET_HOST_WINCE */ +#endif /* !defined(_WIN32_WCE) */ if( button == -1 ) return DefWindowProc( hWnd, uMsg, lParam, wParam ); @@ -1881,74 +2048,74 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, ) ); - fgState.Modifiers = 0xffffffff; + fgState.Modifiers = INVALID_MODIFIERS; } break; case 0x020a: /* Should be WM_MOUSEWHEEL but my compiler doesn't recognize it */ { - /* - * XXX THIS IS SPECULATIVE -- John Fay, 10/2/03 - * XXX Should use WHEEL_DELTA instead of 120 - */ int wheel_number = LOWORD( wParam ); - short ticks = ( short )HIWORD( wParam ) / 120; - int direction = 1; - - if( ticks < 0 ) - { - direction = -1; - ticks = -ticks; - } + short ticks = ( short )HIWORD( wParam ); + fgState.MouseWheelTicks += ticks; /* - * The mouse cursor has moved. Remember the new mouse cursor's position + * XXX Should use WHEEL_DELTA instead of 120 */ - /* window->State.MouseX = LOWORD( lParam ); */ - /* Need to adjust by window position, */ - /* window->State.MouseY = HIWORD( lParam ); */ - /* change "lParam" to other parameter */ + if ( abs ( fgState.MouseWheelTicks ) > 120 ) + { + int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1; - if( ! FETCH_WCB( *window, MouseWheel ) && - ! FETCH_WCB( *window, Mouse ) ) - break; + if( ! FETCH_WCB( *window, MouseWheel ) && + ! FETCH_WCB( *window, Mouse ) ) + break; - fgSetWindow( window ); - fgState.Modifiers = fghGetWin32Modifiers( ); + fgSetWindow( window ); + fgState.Modifiers = fghGetWin32Modifiers( ); + + /* + * XXX Should use WHEEL_DELTA instead of 120 + */ + while( abs ( fgState.MouseWheelTicks ) > 120 ) + { + 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 */ + { + /* + * 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 + 3; + 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.MouseY ) + ); + } - while( ticks-- ) - 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 */ - { /* - * 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. + * XXX Should use WHEEL_DELTA instead of 120 */ - int button = wheel_number * 2 + 3; - 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.MouseY ) - ); - } + fgState.MouseWheelTicks -= 120 * direction; + } - fgState.Modifiers = 0xffffffff; + fgState.Modifiers = INVALID_MODIFIERS; + } } break ; @@ -1999,6 +2166,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: */ @@ -2007,7 +2180,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, ); } -#if TARGET_HOST_WINCE +#if defined(_WIN32_WCE) if(!(lParam & 0x40000000)) /* Prevent auto-repeat */ { if(wParam==(unsigned)gxKeyList.vkRight) @@ -2035,7 +2208,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->State.MouseX, window->State.MouseY ) ); - fgState.Modifiers = 0xffffffff; + fgState.Modifiers = INVALID_MODIFIERS; } break; @@ -2085,6 +2258,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: */ @@ -2095,20 +2274,20 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, default: { -#if !TARGET_HOST_WINCE +#if !defined(_WIN32_WCE) BYTE state[ 256 ]; WORD code[ 2 ]; 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, ( (char)wParam, window->State.MouseX, window->State.MouseY ) ); -#endif /* !TARGET_HOST_WINCE */ +#endif /* !defined(_WIN32_WCE) */ } } @@ -2118,7 +2297,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->State.MouseX, window->State.MouseY ) ); - fgState.Modifiers = 0xffffffff; + fgState.Modifiers = INVALID_MODIFIERS; } break; @@ -2133,7 +2312,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, ( (char)wParam, window->State.MouseX, window->State.MouseY ) ); - fgState.Modifiers = 0xffffffff; + fgState.Modifiers = INVALID_MODIFIERS; } break; @@ -2168,7 +2347,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); break; -#if !TARGET_HOST_WINCE +#if !defined(_WIN32_WCE) case WM_SYNCPAINT: /* 0x0088 */ /* Another window has moved, need to update this one */ window->State.Redisplay = GL_TRUE; @@ -2249,6 +2428,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 ); @@ -2256,12 +2446,58 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, break; } } -#endif /* !TARGET_HOST_WINCE */ +#endif /* !defined(_WIN32_WCE) */ /* We need to pass the message on to the operating system as well */ 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 (fghGetTouchInputInfo == (pGetTouchInputInfo)0xDEADBEEF) { + fghGetTouchInputInfo = (pGetTouchInputInfo)GetProcAddress(GetModuleHandle("user32"),"GetTouchInputInfo"); + fghCloseTouchInputHandle = (pCloseTouchInputHandle)GetProcAddress(GetModuleHandle("user32"),"CloseTouchInputHandle"); + } + + if (!fghGetTouchInputInfo) { + free( (void*)ti ); + break; + } + + if (fghGetTouchInputInfo( (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 ) ); + } + } + } + fghCloseTouchInputHandle((HTOUCHINPUT)lParam); + free( (void*)ti ); + lRet = 0; /*DefWindowProc( hWnd, uMsg, wParam, lParam );*/ + break; + } +#endif default: /* Handle unhandled messages */ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );