X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fmswin%2Ffg_main_mswin.c;h=daa8fdc25004740bacc81805b4858a9c42fb4384;hb=cc8230fde8220aeab13bbc2457cb32c0fcc19d5e;hp=22a1d4413cc4c0a6c4c31db9cec8ad81ef9070fd;hpb=25a96752f76c571c447b00e376f0002568389bad;p=freeglut diff --git a/src/mswin/fg_main_mswin.c b/src/mswin/fg_main_mswin.c index 22a1d44..daa8fdc 100644 --- a/src/mswin/fg_main_mswin.c +++ b/src/mswin/fg_main_mswin.c @@ -58,94 +58,39 @@ GXOPENINPUT GXOpenInput_ = NULL; struct GXKeyList gxKeyList; #endif /* _WIN32_WCE */ -/* - * Helper functions for getting client area from the window rect - * and the window rect from the client area given the style of the window - * (or a valid window pointer from which the style can be queried). - */ -extern void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ); -extern void fghGetClientArea ( RECT *clientRect, const SFG_Window *window, BOOL wantPosOutside ); - - -void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) -{ - RECT windowRect; - - /* - * For windowed mode, get the current position of the - * window and resize taking the size of the frame - * decorations into account. - * - * Note on maximizing behavior of Windows: the resize borders are off - * the screen such that the client area extends all the way from the - * leftmost corner to the rightmost corner to maximize screen real - * estate. A caption is still shown however to allow interaction with - * the window controls. This is default behavior of Windows that - * FreeGLUT sticks with. To alter, one would have to check if - * WS_MAXIMIZE style is set when a resize event is triggered, and - * then manually correct the windowRect to put the borders back on - * screen. - */ - - /* "GetWindowRect" returns the pixel coordinates of the outside of the window */ - GetWindowRect( window->Window.Handle, &windowRect ); - - /* 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(&windowRect,window,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; - fghGetClientArea( &parentRect, window->Parent, FALSE ); - OffsetRect(&windowRect,-parentRect.left,-parentRect.top); - } - - /* Do the actual resizing */ - SetWindowPos( window->Window.Handle, - HWND_TOP, - windowRect.left, windowRect.top, - windowRect.right - windowRect.left, - windowRect.bottom- windowRect.top, - SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | - SWP_NOZORDER - ); -} - -void fgPlatformDisplayWindow ( SFG_Window *window ) +/* Get system time, taking special precautions against 32bit timer wrap. + We use timeGetTime and not GetTickCount because of its better stability, + and because we can increase its granularity (to 1 ms in + fgPlatformInitialize). For that reason we can't use GetTickCount64 which + wouldn't have the wrap issue. + Credit: this is based on code in glibc (https://mail.gnome.org/archives/commits-list/2011-November/msg04588.html) + */ +static fg_time_t lastTime32 = 0; +static fg_time_t timeEpoch = 0; +void fgPlatformInitSystemTime() { - RedrawWindow( - window->Window.Handle, NULL, NULL, - RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW - ); +#if defined(_WIN32_WCE) + lastTime32 = GetTickCount(); +#else + lastTime32 = timeGetTime(); +#endif } - - fg_time_t fgPlatformSystemTime ( void ) { + fg_time_t currTime32; #if defined(_WIN32_WCE) - return GetTickCount(); + currTime32 = GetTickCount(); #else - /* TODO: do this with QueryPerformanceCounter as timeGetTime has - * insufficient resolution (only about 5 ms on system under low load). - * See: - * http://msdn.microsoft.com/en-us/library/windows/desktop/dd757629(v=vs.85).aspx - * Or maybe QueryPerformanceCounter is not a good idea either, see - * http://old.nabble.com/Re%3A-glutTimerFunc-does-not-detect-if-system-time-moved-backward-p33479674.html - * for some other ideas (at bottom)... - */ - return timeGetTime(); + currTime32 = timeGetTime(); #endif + /* Check if we just wrapped */ + if (currTime32 < lastTime32) + timeEpoch++; + + lastTime32 = currTime32; + + return currTime32 | timeEpoch << 32; } @@ -225,33 +170,168 @@ static int fgPlatformGetModifiers (void) ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 ); } -/* - * The window procedure for handling Win32 events - */ -LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, - LPARAM lParam ) +static LRESULT fghWindowProcKeyPress(SFG_Window *window, UINT uMsg, GLboolean keydown, WPARAM wParam, LPARAM lParam) { - static unsigned char lControl = 0, rControl = 0, lShift = 0, - rShift = 0, lAlt = 0, rAlt = 0; + static unsigned char lControl = 0, lShift = 0, lAlt = 0, + rControl = 0, rShift = 0, rAlt = 0; - SFG_Window *window, *child_window = NULL; - PAINTSTRUCT ps; - LRESULT lRet = 1; + int keypress = -1; + POINT mouse_pos ; + + /* if keydown, check for repeat */ + /* If repeat is globally switched off, it cannot be switched back on per window. + * But if it is globally switched on, it can be switched off per window. This matches + * GLUT's behavior on X11, but not Nate Robbins' win32 GLUT, as he didn't implement the + * global state switch. + */ + if( keydown && ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) ) + return 1; + + /* Remember the current modifiers state so user can query it from their callback */ + fgState.Modifiers = fgPlatformGetModifiers( ); - FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ; + /* Get mouse position roughly at time of keypress */ + GetCursorPos( &mouse_pos ); + ScreenToClient( window->Window.Handle, &mouse_pos ); + window->State.MouseX = mouse_pos.x; + window->State.MouseY = mouse_pos.y; - window = fgWindowByHandle( hWnd ); + /* Convert the Win32 keystroke codes to GLUTtish way */ +# define KEY(a,b) case a: keypress = b; break; - if ( ( window == NULL ) && ( uMsg != WM_CREATE ) ) - return DefWindowProc( hWnd, uMsg, wParam, lParam ); + switch( wParam ) + { + KEY( VK_F1, GLUT_KEY_F1 ); + KEY( VK_F2, GLUT_KEY_F2 ); + KEY( VK_F3, GLUT_KEY_F3 ); + KEY( VK_F4, GLUT_KEY_F4 ); + KEY( VK_F5, GLUT_KEY_F5 ); + KEY( VK_F6, GLUT_KEY_F6 ); + KEY( VK_F7, GLUT_KEY_F7 ); + KEY( VK_F8, GLUT_KEY_F8 ); + KEY( VK_F9, GLUT_KEY_F9 ); + KEY( VK_F10, GLUT_KEY_F10 ); + KEY( VK_F11, GLUT_KEY_F11 ); + KEY( VK_F12, GLUT_KEY_F12 ); + KEY( VK_PRIOR, GLUT_KEY_PAGE_UP ); + KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN ); + KEY( VK_HOME, GLUT_KEY_HOME ); + KEY( VK_END, GLUT_KEY_END ); + KEY( VK_LEFT, GLUT_KEY_LEFT ); + KEY( VK_UP, GLUT_KEY_UP ); + KEY( VK_RIGHT, GLUT_KEY_RIGHT ); + KEY( VK_DOWN, GLUT_KEY_DOWN ); + KEY( VK_INSERT, GLUT_KEY_INSERT ); + + /* handle control, alt and shift. For GLUT, we want to distinguish between left and right presses. + * The VK_L* & VK_R* left and right Alt, Ctrl and Shift virtual keys are however only used as parameters to GetAsyncKeyState() and GetKeyState() + * so when we get an alt, shift or control keypress here, we manually check whether it was the left or the right + */ +#define ASYNC_KEY_EVENT(winKey,glutKey,keyStateVar)\ + if (!keyStateVar && GetAsyncKeyState ( winKey ))\ + {\ + keypress = glutKey;\ + keyStateVar = 1;\ + }\ + else if (keyStateVar && !GetAsyncKeyState ( winKey ))\ + {\ + keypress = glutKey;\ + keyStateVar = 0;\ + } + case VK_CONTROL: + ASYNC_KEY_EVENT(VK_LCONTROL,GLUT_KEY_CTRL_L,lControl); + ASYNC_KEY_EVENT(VK_RCONTROL,GLUT_KEY_CTRL_R,rControl); + break; + case VK_SHIFT: + ASYNC_KEY_EVENT(VK_LSHIFT,GLUT_KEY_SHIFT_L,lShift); + ASYNC_KEY_EVENT(VK_RSHIFT,GLUT_KEY_SHIFT_R,rShift); + break; + case VK_MENU: + ASYNC_KEY_EVENT(VK_LMENU,GLUT_KEY_ALT_L,lAlt); + ASYNC_KEY_EVENT(VK_RMENU,GLUT_KEY_ALT_R,rAlt); + break; +#undef ASYNC_KEY_EVENT - /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0, - uMsg, wParam, lParam ); */ + case VK_DELETE: + /* The delete key should be treated as an ASCII keypress: */ + if (keydown) + INVOKE_WCB( *window, Keyboard, + ( 127, window->State.MouseX, window->State.MouseY ) + ); + else + INVOKE_WCB( *window, KeyboardUp, + ( 127, window->State.MouseX, window->State.MouseY ) + ); + break; - /* Some events only sent to main window. Check if the current window that - * the mouse is over is a child window. Below when handling some messages, - * we make sure that we process callbacks on the child window instead. - * This mirrors how GLUT does things. +#if !defined(_WIN32_WCE) + default: + /* keydown displayable characters are handled with WM_CHAR message, but no corresponding up is generated. So get that here. */ + if (!keydown) + { + BYTE state[ 256 ]; + WORD code[ 2 ]; + + GetKeyboardState( state ); + + 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 + } + +#if defined(_WIN32_WCE) + if(keydown && !(lParam & 0x40000000)) /* Prevent auto-repeat */ + { + if(wParam==(unsigned)gxKeyList.vkRight) + keypress = GLUT_KEY_RIGHT; + else if(wParam==(unsigned)gxKeyList.vkLeft) + keypress = GLUT_KEY_LEFT; + else if(wParam==(unsigned)gxKeyList.vkUp) + keypress = GLUT_KEY_UP; + else if(wParam==(unsigned)gxKeyList.vkDown) + keypress = GLUT_KEY_DOWN; + else if(wParam==(unsigned)gxKeyList.vkA) + keypress = GLUT_KEY_F1; + else if(wParam==(unsigned)gxKeyList.vkB) + keypress = GLUT_KEY_F2; + else if(wParam==(unsigned)gxKeyList.vkC) + keypress = GLUT_KEY_F3; + else if(wParam==(unsigned)gxKeyList.vkStart) + keypress = GLUT_KEY_F4; + } +#endif + + if( keypress != -1 ) + if (keydown) + INVOKE_WCB( *window, Special, + ( keypress, + window->State.MouseX, window->State.MouseY ) + ); + else + INVOKE_WCB( *window, SpecialUp, + ( keypress, + window->State.MouseX, window->State.MouseY ) + ); + + fgState.Modifiers = INVALID_MODIFIERS; + + /* SYSKEY events should be sent to default window proc for system to handle them */ + if (uMsg==WM_SYSKEYDOWN || uMsg==WM_SYSKEYUP) + return DefWindowProc( window->Window.Handle, uMsg, wParam, lParam ); + else + return 1; +} + +void fghWindowUnderCursor(SFG_Window *window, SFG_Window **child_window) +{ + /* Check if the current window that the mouse is over is a child window + * of the window the message was sent to. */ if (window && window->Children.First) { @@ -262,59 +342,45 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, GetCursorPos( &mouse_pos ); ScreenToClient( window->Window.Handle, &mouse_pos ); hwnd = ChildWindowFromPoint(window->Window.Handle, mouse_pos); - if (hwnd) /* can be NULL if mouse outside parent by the time we get here */ + if (hwnd && hwnd!=window->Window.Handle) /* can be NULL if mouse outside parent by the time we get here, or can be same as parent if we didn't find a child */ { temp_window = fgWindowByHandle(hwnd); - if (temp_window->Parent) /* Verify we got a child window */ - child_window = temp_window; + if (temp_window) /* Verify we got a FreeGLUT window */ + { + *child_window = temp_window; + /* ChildWindowFromPoint only searches immediate children, so search again to see if actually in grandchild or further descendant */ + fghWindowUnderCursor(temp_window,child_window); + } } } +} - if ( window ) - { - SFG_Window* temp_window = child_window?child_window:window; - - fgState.Modifiers = fgPlatformGetModifiers( ); - - /* Checking for CTRL, ALT, and SHIFT key positions: Key Down! */ -#define SPECIAL_KEY_DOWN(winKey,glutKey,winProcVar)\ - if ( !winProcVar && GetAsyncKeyState ( winKey ) )\ - {\ - INVOKE_WCB ( *temp_window, Special,\ - ( glutKey, temp_window->State.MouseX, temp_window->State.MouseY )\ - );\ - winProcVar = 1;\ - } - - SPECIAL_KEY_DOWN(VK_LCONTROL,GLUT_KEY_CTRL_L ,lControl); - SPECIAL_KEY_DOWN(VK_RCONTROL,GLUT_KEY_CTRL_R ,rControl); - SPECIAL_KEY_DOWN(VK_LSHIFT ,GLUT_KEY_SHIFT_L,lShift); - SPECIAL_KEY_DOWN(VK_RSHIFT ,GLUT_KEY_SHIFT_R,rShift); - SPECIAL_KEY_DOWN(VK_LMENU ,GLUT_KEY_ALT_L ,lAlt); - SPECIAL_KEY_DOWN(VK_RMENU ,GLUT_KEY_ALT_R ,rAlt); -#undef SPECIAL_KEY_DOWN - - /* Checking for CTRL, ALT, and SHIFT key positions: Key Up! */ -#define SPECIAL_KEY_UP(winKey,glutKey,winProcVar)\ - if ( winProcVar && !GetAsyncKeyState ( winKey ) )\ - {\ - INVOKE_WCB ( *temp_window, SpecialUp,\ - ( glutKey, temp_window->State.MouseX, temp_window->State.MouseY )\ - );\ - winProcVar = 0;\ - } - - SPECIAL_KEY_UP(VK_LCONTROL,GLUT_KEY_CTRL_L ,lControl); - SPECIAL_KEY_UP(VK_RCONTROL,GLUT_KEY_CTRL_R ,rControl); - SPECIAL_KEY_UP(VK_LSHIFT ,GLUT_KEY_SHIFT_L,lShift); - SPECIAL_KEY_UP(VK_RSHIFT ,GLUT_KEY_SHIFT_R,rShift); - SPECIAL_KEY_UP(VK_LMENU ,GLUT_KEY_ALT_L ,lAlt); - SPECIAL_KEY_UP(VK_RMENU ,GLUT_KEY_ALT_R ,rAlt); -#undef SPECIAL_KEY_UP - - fgState.Modifiers = INVALID_MODIFIERS; - } +/* + * The window procedure for handling Win32 events + */ +LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + SFG_Window *window, *child_window = NULL; + PAINTSTRUCT ps; + LRESULT lRet = 1; + + FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ; + window = fgWindowByHandle( hWnd ); + + if ( ( window == NULL ) && ( uMsg != WM_CREATE ) ) + return DefWindowProc( hWnd, uMsg, wParam, lParam ); + + /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0, + uMsg, wParam, lParam ); */ + + /* Some events only sent to main window. Check if the current window that + * the mouse is over is a child window. Below when handling some messages, + * we make sure that we process callbacks on the child window instead. + * This mirrors how GLUT does things. + */ + fghWindowUnderCursor(window, &child_window); + switch( uMsg ) { case WM_CREATE: @@ -415,7 +481,8 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, */ if( window->State.Visible ) { - window->State.NeedToResize = GL_TRUE; + /* get old values first to compare to below */ + int width = window->State.Width, height=window->State.Height; #if defined(_WIN32_WCE) window->State.Width = HIWORD(lParam); window->State.Height = LOWORD(lParam); @@ -423,10 +490,37 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->State.Width = LOWORD(lParam); window->State.Height = HIWORD(lParam); #endif /* defined(_WIN32_WCE) */ + + if (width!=window->State.Width || height!=window->State.Height) + /* Something changed, need to resize */ + window->State.NeedToResize = GL_TRUE; } break; + case WM_MOVE: + { + SFG_Window* saved_window = fgStructure.CurrentWindow; + RECT windowRect; + GetWindowRect( window->Window.Handle, &windowRect ); + + if (window->Parent) + { + /* For child window, we should return relative to upper-left + * of parent's client area. + */ + POINT topleft = {windowRect.left,windowRect.top}; + + ScreenToClient(window->Parent->Window.Handle,&topleft); + windowRect.left = topleft.x; + windowRect.top = topleft.y; + } + + INVOKE_WCB( *window, Position, ( windowRect.left, windowRect.top ) ); + fgSetWindow(saved_window); + } + break; + case WM_SETFOCUS: /* printf("WM_SETFOCUS: %p\n", window ); */ @@ -661,10 +755,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, short ticks = ( short )HIWORD( wParam ); fgState.MouseWheelTicks += ticks; - /* - * XXX Should use WHEEL_DELTA instead of 120 - */ - if ( abs ( fgState.MouseWheelTicks ) >= 120 ) + if ( abs ( fgState.MouseWheelTicks ) >= WHEEL_DELTA ) { int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1; @@ -675,10 +766,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, fgSetWindow( window ); fgState.Modifiers = fgPlatformGetModifiers( ); - /* - * XXX Should use WHEEL_DELTA instead of 120 - */ - while( abs ( fgState.MouseWheelTicks ) >= 120 ) + while( abs ( fgState.MouseWheelTicks ) >= WHEEL_DELTA ) { if( FETCH_WCB( *window, MouseWheel ) ) INVOKE_WCB( *window, MouseWheel, @@ -710,10 +798,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, ); } - /* - * XXX Should use WHEEL_DELTA instead of 120 - */ - fgState.MouseWheelTicks -= 120 * direction; + fgState.MouseWheelTicks -= WHEEL_DELTA * direction; } fgState.Modifiers = INVALID_MODIFIERS; @@ -723,190 +808,16 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, case WM_SYSKEYDOWN: case WM_KEYDOWN: - { - int keypress = -1; - POINT mouse_pos ; - if (child_window) window = child_window; - - if( ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) ) - break; - - /* - * Remember the current modifiers state. This is done here in order - * to make sure the VK_DELETE keyboard callback is executed properly. - */ - fgState.Modifiers = fgPlatformGetModifiers( ); - - GetCursorPos( &mouse_pos ); - ScreenToClient( window->Window.Handle, &mouse_pos ); - - window->State.MouseX = mouse_pos.x; - window->State.MouseY = mouse_pos.y; - - /* Convert the Win32 keystroke codes to GLUTtish way */ -# define KEY(a,b) case a: keypress = b; break; - - switch( wParam ) - { - KEY( VK_F1, GLUT_KEY_F1 ); - KEY( VK_F2, GLUT_KEY_F2 ); - KEY( VK_F3, GLUT_KEY_F3 ); - KEY( VK_F4, GLUT_KEY_F4 ); - KEY( VK_F5, GLUT_KEY_F5 ); - KEY( VK_F6, GLUT_KEY_F6 ); - KEY( VK_F7, GLUT_KEY_F7 ); - KEY( VK_F8, GLUT_KEY_F8 ); - KEY( VK_F9, GLUT_KEY_F9 ); - KEY( VK_F10, GLUT_KEY_F10 ); - KEY( VK_F11, GLUT_KEY_F11 ); - KEY( VK_F12, GLUT_KEY_F12 ); - KEY( VK_PRIOR, GLUT_KEY_PAGE_UP ); - KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN ); - KEY( VK_HOME, GLUT_KEY_HOME ); - KEY( VK_END, GLUT_KEY_END ); - KEY( VK_LEFT, GLUT_KEY_LEFT ); - KEY( VK_UP, GLUT_KEY_UP ); - KEY( VK_RIGHT, GLUT_KEY_RIGHT ); - KEY( VK_DOWN, GLUT_KEY_DOWN ); - KEY( VK_INSERT, GLUT_KEY_INSERT ); - - case VK_LCONTROL: case VK_RCONTROL: case VK_CONTROL: - case VK_LSHIFT: case VK_RSHIFT: case VK_SHIFT: - case VK_LMENU: case VK_RMENU: case VK_MENU: - /* These keypresses and releases are handled earlier in the function */ - break; - - case VK_DELETE: - /* The delete key should be treated as an ASCII keypress: */ - INVOKE_WCB( *window, Keyboard, - ( 127, window->State.MouseX, window->State.MouseY ) - ); - } - -#if defined(_WIN32_WCE) - if(!(lParam & 0x40000000)) /* Prevent auto-repeat */ - { - if(wParam==(unsigned)gxKeyList.vkRight) - keypress = GLUT_KEY_RIGHT; - else if(wParam==(unsigned)gxKeyList.vkLeft) - keypress = GLUT_KEY_LEFT; - else if(wParam==(unsigned)gxKeyList.vkUp) - keypress = GLUT_KEY_UP; - else if(wParam==(unsigned)gxKeyList.vkDown) - keypress = GLUT_KEY_DOWN; - else if(wParam==(unsigned)gxKeyList.vkA) - keypress = GLUT_KEY_F1; - else if(wParam==(unsigned)gxKeyList.vkB) - keypress = GLUT_KEY_F2; - else if(wParam==(unsigned)gxKeyList.vkC) - keypress = GLUT_KEY_F3; - else if(wParam==(unsigned)gxKeyList.vkStart) - keypress = GLUT_KEY_F4; - } -#endif - - if( keypress != -1 ) - INVOKE_WCB( *window, Special, - ( keypress, - window->State.MouseX, window->State.MouseY ) - ); - - fgState.Modifiers = INVALID_MODIFIERS; - } + lRet = fghWindowProcKeyPress(window,uMsg,GL_TRUE,wParam,lParam); break; case WM_SYSKEYUP: case WM_KEYUP: - { - int keypress = -1; - POINT mouse_pos; - if (child_window) window = child_window; - - /* - * Remember the current modifiers state. This is done here in order - * to make sure the VK_DELETE keyboard callback is executed properly. - */ - fgState.Modifiers = fgPlatformGetModifiers( ); - - GetCursorPos( &mouse_pos ); - ScreenToClient( window->Window.Handle, &mouse_pos ); - - window->State.MouseX = mouse_pos.x; - window->State.MouseY = mouse_pos.y; - - /* - * Convert the Win32 keystroke codes to GLUTtish way. - * "KEY(a,b)" was defined under "WM_KEYDOWN" - */ - - switch( wParam ) - { - KEY( VK_F1, GLUT_KEY_F1 ); - KEY( VK_F2, GLUT_KEY_F2 ); - KEY( VK_F3, GLUT_KEY_F3 ); - KEY( VK_F4, GLUT_KEY_F4 ); - KEY( VK_F5, GLUT_KEY_F5 ); - KEY( VK_F6, GLUT_KEY_F6 ); - KEY( VK_F7, GLUT_KEY_F7 ); - KEY( VK_F8, GLUT_KEY_F8 ); - KEY( VK_F9, GLUT_KEY_F9 ); - KEY( VK_F10, GLUT_KEY_F10 ); - KEY( VK_F11, GLUT_KEY_F11 ); - KEY( VK_F12, GLUT_KEY_F12 ); - KEY( VK_PRIOR, GLUT_KEY_PAGE_UP ); - KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN ); - KEY( VK_HOME, GLUT_KEY_HOME ); - KEY( VK_END, GLUT_KEY_END ); - KEY( VK_LEFT, GLUT_KEY_LEFT ); - KEY( VK_UP, GLUT_KEY_UP ); - KEY( VK_RIGHT, GLUT_KEY_RIGHT ); - KEY( VK_DOWN, GLUT_KEY_DOWN ); - KEY( VK_INSERT, GLUT_KEY_INSERT ); - - case VK_LCONTROL: case VK_RCONTROL: case VK_CONTROL: - case VK_LSHIFT: case VK_RSHIFT: case VK_SHIFT: - case VK_LMENU: case VK_RMENU: case VK_MENU: - /* These keypresses and releases are handled earlier in the function */ - break; - - case VK_DELETE: - /* The delete key should be treated as an ASCII keypress: */ - INVOKE_WCB( *window, KeyboardUp, - ( 127, window->State.MouseX, window->State.MouseY ) - ); - break; - - default: - { -#if !defined(_WIN32_WCE) - BYTE state[ 256 ]; - WORD code[ 2 ]; - - GetKeyboardState( state ); - - 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 /* !defined(_WIN32_WCE) */ - } - } - - if( keypress != -1 ) - INVOKE_WCB( *window, SpecialUp, - ( keypress, - window->State.MouseX, window->State.MouseY ) - ); - - fgState.Modifiers = INVALID_MODIFIERS; - } + lRet = fghWindowProcKeyPress(window,uMsg,GL_FALSE,wParam,lParam); break; case WM_SYSCHAR: