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( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside );
-extern RECT fghGetClientArea ( const SFG_Window *window, BOOL wantPosOutside );
-
-void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
+/* 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()
{
- RECT windowRect;
-
- /*
- * For windowed mode, get the current position of the
- * window and resize taking the size of the frame
- * decorations into account.
- */
-
- /* "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(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;
- parentRect = fghGetClientArea( window->Parent, FALSE );
- windowRect.left -= parentRect.left;
- windowRect.right -= parentRect.left;
- windowRect.top -= parentRect.top;
- windowRect.bottom -= 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 )
-{
- 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;
}
/*
- * Determine a GLUT modifer mask based on MS-WINDOWS system info.
+ * Determine a GLUT modifier mask based on MS-WINDOWS system info.
*/
static int fgPlatformGetModifiers (void)
{
if (hwnd) /* can be NULL if mouse outside parent by the time we get here */
{
temp_window = fgWindowByHandle(hwnd);
- if (temp_window->Parent) /* Verify we got a child window */
+ if (temp_window && temp_window->Parent) /* Verify we got a child window */
child_window = temp_window;
}
}
fgState.Modifiers = fgPlatformGetModifiers( );
/* Checking for CTRL, ALT, and SHIFT key positions: Key Down! */
- if ( !lControl && GetAsyncKeyState ( VK_LCONTROL ) )
- {
- INVOKE_WCB ( *temp_window, Special,
- ( GLUT_KEY_CTRL_L, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- lControl = 1;
+#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;\
}
- if ( !rControl && GetAsyncKeyState ( VK_RCONTROL ) )
- {
- INVOKE_WCB ( *temp_window, Special,
- ( GLUT_KEY_CTRL_R, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- rControl = 1;
- }
-
- if ( !lShift && GetAsyncKeyState ( VK_LSHIFT ) )
- {
- INVOKE_WCB ( *temp_window, Special,
- ( GLUT_KEY_SHIFT_L, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- lShift = 1;
- }
-
- if ( !rShift && GetAsyncKeyState ( VK_RSHIFT ) )
- {
- INVOKE_WCB ( *temp_window, Special,
- ( GLUT_KEY_SHIFT_R, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- rShift = 1;
- }
-
- if ( !lAlt && GetAsyncKeyState ( VK_LMENU ) )
- {
- INVOKE_WCB ( *temp_window, Special,
- ( GLUT_KEY_ALT_L, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- lAlt = 1;
- }
-
- if ( !rAlt && GetAsyncKeyState ( VK_RMENU ) )
- {
- INVOKE_WCB ( *temp_window, Special,
- ( GLUT_KEY_ALT_R, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- rAlt = 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! */
- if ( lControl && !GetAsyncKeyState ( VK_LCONTROL ) )
- {
- INVOKE_WCB ( *temp_window, SpecialUp,
- ( GLUT_KEY_CTRL_L, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- lControl = 0;
- }
-
- if ( rControl && !GetAsyncKeyState ( VK_RCONTROL ) )
- {
- INVOKE_WCB ( *temp_window, SpecialUp,
- ( GLUT_KEY_CTRL_R, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- rControl = 0;
- }
-
- if ( lShift && !GetAsyncKeyState ( VK_LSHIFT ) )
- {
- INVOKE_WCB ( *temp_window, SpecialUp,
- ( GLUT_KEY_SHIFT_L, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- lShift = 0;
- }
-
- if ( rShift && !GetAsyncKeyState ( VK_RSHIFT ) )
- {
- INVOKE_WCB ( *temp_window, SpecialUp,
- ( GLUT_KEY_SHIFT_R, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- rShift = 0;
+#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;\
}
- if ( lAlt && !GetAsyncKeyState ( VK_LMENU ) )
- {
- INVOKE_WCB ( *temp_window, SpecialUp,
- ( GLUT_KEY_ALT_L, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- lAlt = 0;
- }
-
- if ( rAlt && !GetAsyncKeyState ( VK_RMENU ) )
- {
- INVOKE_WCB ( *temp_window, SpecialUp,
- ( GLUT_KEY_ALT_R, temp_window->State.MouseX, temp_window->State.MouseY )
- );
-
- rAlt = 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;
}
*/
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);
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 ); */
if (child_window)
{
- /* If child should have focus instead, set it here. */
+ /* If we're dealing with a child window, make sure it has input focus instead, set it here. */
SetFocus(child_window->Window.Handle);
SetActiveWindow( child_window->Window.Handle );
INVOKE_WCB( *child_window, Entry, ( GLUT_ENTERED ) );
case WM_PAINT:
/* Turn on the visibility in case it was turned off somehow */
window->State.Visible = GL_TRUE;
- InvalidateRect( hWnd, NULL, GL_FALSE ); /* Make sure whole window is repainted. Bit of a hack, but a safe on from what google turns up... */
+ InvalidateRect( hWnd, NULL, GL_FALSE ); /* Make sure whole window is repainted. Bit of a hack, but a safe one from what google turns up... */
BeginPaint( hWnd, &ps );
fghRedrawWindow( window );
EndPaint( hWnd, &ps );
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;
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,
);
}
- /*
- * XXX Should use WHEEL_DELTA instead of 120
- */
- fgState.MouseWheelTicks -= 120 * direction;
+ fgState.MouseWheelTicks -= WHEEL_DELTA * direction;
}
fgState.Modifiers = INVALID_MODIFIERS;