-void fgPlatformMainLoopPreliminaryWork ( void )
+static void fghUpdateWindowStatus(SFG_Window *window, GLboolean visState)
{
- SFG_Window *window = (SFG_Window *)fgStructure.Windows.First ;
-
- /*
- * 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,
- * but I'm not sure what else to do about it. Ideally we should leave
- * something uninitialized in the create window code and initialize it in
- * the main loop, and have that initialization create a "WM_ACTIVATE"
- * message. Then we would put the visibility callback code in the
- * "case WM_ACTIVATE" block below. - John Fay -- 10/24/02
- */
- while( window )
+ SFG_Window* child;
+
+ if (window->State.Visible != visState)
{
- if ( FETCH_WCB( *window, WindowStatus ) )
- {
- SFG_Window *current_window = fgStructure.CurrentWindow ;
+ window->State.Visible = visState;
+ /* On win32 we only have two states, window displayed and window not displayed (iconified)
+ * We map these to GLUT_FULLY_RETAINED and GLUT_HIDDEN respectively.
+ */
+ INVOKE_WCB( *window, WindowStatus, ( visState ? GLUT_FULLY_RETAINED:GLUT_HIDDEN ) );
- INVOKE_WCB( *window, WindowStatus, ( window->State.Visible?GLUT_FULLY_RETAINED:GLUT_HIDDEN ) );
- fgSetWindow( current_window );
+ /* If top level window (not a subwindow/child), and icon title text available, switch titles based on visibility state */
+ if (!window->Parent && window->State.pWState.IconTitle)
+ {
+ if (visState)
+ /* visible, set window title */
+ SetWindowText( window->Window.Handle, window->State.pWState.WindowTitle );
+ else
+ /* not visible, set icon title */
+ SetWindowText( window->Window.Handle, window->State.pWState.IconTitle );
}
+ }
- window = (SFG_Window *)window->Node.Next ;
+ /* Also set visibility state for children */
+ for( child = ( SFG_Window * )window->Children.First;
+ child;
+ child = ( SFG_Window * )child->Node.Next )
+ {
+ fghUpdateWindowStatus(child, visState);
}
}
+void fghNotifyWindowStatus(SFG_Window *window)
+{
+ INVOKE_WCB( *window, WindowStatus, ( window->State.Visible?GLUT_FULLY_RETAINED:GLUT_HIDDEN ) );
+
+ /* Don't notify children, they get their own just before first time they're drawn */
+}
+
+void fgPlatformMainLoopPreliminaryWork ( void )
+{
+ /* no-op */
+}
+
/*
* Determine a GLUT modifier mask based on MS-WINDOWS system info.
*/
if (window && window->Children.First) /* This window has childs */
{
- SFG_WindowHandleType hwnd;
+ HWND hwnd;
SFG_Window* child_window;
/* Get mouse position at time of message */
break;
case WM_SIZE:
- /*
- * If the window is visible, then it is the user manually resizing it.
- * If it is not, then it is the system sending us a dummy resize with
- * zero dimensions on a "glutIconifyWindow" call.
- */
+ /* printf("WM_SIZE (ID: %i): wParam: %i, new size: %ix%i \n",window->ID,wParam,LOWORD(lParam),HIWORD(lParam)); */
+
+ /* Update visibility state of the window */
+ if (wParam==SIZE_MINIMIZED)
+ fghUpdateWindowStatus(window,GL_FALSE);
+ else if (wParam==SIZE_RESTORED && !window->State.Visible)
+ fghUpdateWindowStatus(window,GL_TRUE);
+
+ /* Check window visible, we don't want to resize when the user or glutIconifyWindow minimized the window */
if( window->State.Visible )
{
/* get old values first to compare to below */
window->State.NeedToResize = GL_TRUE;
}
+ /* according to docs, should return 0 */
+ lRet = 0;
break;
case WM_MOVE:
{
SFG_Window* saved_window = fgStructure.CurrentWindow;
RECT windowRect;
- GetWindowRect( window->Window.Handle, &windowRect );
-
- if (window->Parent)
+
+ /* Check window is minimized, we don't want to call the position callback when the user or glutIconifyWindow minimized the window */
+ if (!IsIconic(window->Window.Handle))
{
- /* 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;
- }
+ /* Get top-left of non-client area of window, matching coordinates of
+ * glutInitPosition and glutPositionWindow, but not those of
+ * glutGet(GLUT_WINDOW_X) and glutGet(GLUT_WINDOW_Y), which return
+ * top-left of client area.
+ */
+ 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};
- INVOKE_WCB( *window, Position, ( windowRect.left, windowRect.top ) );
- fgSetWindow(saved_window);
+ 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);
+ }
}
+
+ /* according to docs, should return 0 */
+ lRet = 0;
break;
case WM_SETFOCUS:
#if 0
case WM_ACTIVATE:
- //printf("WM_ACTIVATE: %x %d %d\n",lParam, HIWORD(wParam), LOWORD(wParam));
+ //printf("WM_ACTIVATE: %x (ID: %i) %d %d\n",lParam, window->ID, HIWORD(wParam), LOWORD(wParam));
if (LOWORD(wParam) != WA_INACTIVE)
{
/* printf("WM_ACTIVATE: fgSetCursor( %p, %d)\n", window,
*/
if (FETCH_WCB( *window, Entry ))
{
+ SFG_Window* saved_window = fgStructure.CurrentWindow;
INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
+ fgSetWindow(saved_window);
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
break;
case WM_SHOWWINDOW:
- window->State.Visible = GL_TRUE;
- window->State.Redisplay = GL_TRUE;
+ /* printf("WM_SHOWWINDOW, shown? %i, source: %i\n",wParam,lParam); */
+ if (wParam)
+ {
+ fghUpdateWindowStatus(window, GL_TRUE);
+ window->State.Redisplay = GL_TRUE;
+ }
+ else
+ {
+ fghUpdateWindowStatus(window, GL_FALSE);
+ window->State.Redisplay = GL_FALSE;
+ }
break;
case WM_PAINT:
{
- PAINTSTRUCT ps;
- /* 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 one from what google turns up... */
- BeginPaint( hWnd, &ps );
- fghRedrawWindow( window );
- EndPaint( hWnd, &ps );
+ RECT rect;
+
+ if (GetUpdateRect(hWnd,&rect,FALSE))
+ {
+ /* As per docs, upon receiving WM_PAINT, first check if the update region is not empty before you call BeginPaint */
+ PAINTSTRUCT ps;
+
+ /* Turn on the visibility in case it was turned off somehow */
+ window->State.Visible = GL_TRUE;
+
+ InvalidateRect( hWnd, NULL, GL_FALSE );
+ BeginPaint( hWnd, &ps );
+ fghRedrawWindow( window );
+ EndPaint( hWnd, &ps );
+ }
+ lRet = 0; /* As per docs, should return 0 */
}
break;
case WM_MOUSEMOVE:
{
+ /* Per docs, use LOWORD/HIWORD for WinCE and GET_X_LPARAM/GET_Y_LPARAM for desktop windows */
#if defined(_WIN32_WCE)
- window->State.MouseX = 320-HIWORD( lParam );
+ window->State.MouseX = 320-HIWORD( lParam ); /* XXX: Docs say x should be loword and y hiword? */
window->State.MouseY = LOWORD( lParam );
#else
- window->State.MouseX = LOWORD( lParam );
- window->State.MouseY = HIWORD( lParam );
+ window->State.MouseX = GET_X_LPARAM( lParam );
+ window->State.MouseY = GET_Y_LPARAM( lParam );
#endif /* defined(_WIN32_WCE) */
/* Restrict to [-32768, 32767] to match X11 behaviour */
/* See comment in "freeglut_developer" mailing list 10/4/04 */
GLboolean pressed = GL_TRUE;
int button;
+ /* Per docs, use LOWORD/HIWORD for WinCE and GET_X_LPARAM/GET_Y_LPARAM for desktop windows */
#if defined(_WIN32_WCE)
- window->State.MouseX = 320-HIWORD( lParam );
+ window->State.MouseX = 320-HIWORD( lParam ); /* XXX: Docs say x should be loword and y hiword? */
window->State.MouseY = LOWORD( lParam );
#else
- window->State.MouseX = LOWORD( lParam );
- window->State.MouseY = HIWORD( lParam );
+ window->State.MouseX = GET_X_LPARAM( lParam );
+ window->State.MouseY = GET_Y_LPARAM( lParam );
#endif /* defined(_WIN32_WCE) */
/* Restrict to [-32768, 32767] to match X11 behaviour */
case WM_MOUSEWHEEL:
{
- SFG_Window *child_window = NULL;
- int wheel_number = LOWORD( wParam );
- short ticks = ( short )HIWORD( wParam );
+ int wheel_number = 0; /* Only one scroll wheel on windows */
+#if defined(_WIN32_WCE)
+ int modkeys = LOWORD(wParam);
+ short ticks = (short)HIWORD(wParam);
+ /* commented out as should not be needed here, mouse motion is processed in WM_MOUSEMOVE first:
+ xPos = LOWORD(lParam); -- straight from docs, not consistent with mouse nutton and mouse motion above (which i think is wrong)
+ yPos = HIWORD(lParam);
+ */
+#else
+ /* int modkeys = GET_KEYSTATE_WPARAM( wParam ); */
+ short ticks = GET_WHEEL_DELTA_WPARAM( wParam );
+ /* commented out as should not be needed here, mouse motion is processed in WM_MOUSEMOVE first:
+ window->State.MouseX = GET_X_LPARAM( lParam );
+ window->State.MouseY = GET_Y_LPARAM( lParam );
+ */
+#endif /* defined(_WIN32_WCE) */
window = fghWindowUnderCursor(window);
fgState.Modifiers = INVALID_MODIFIERS;
}
+ /* Per docs, should return zero */
+ lRet = 0;
}
break ;
lRet = 0; /* Per docs, should return zero */
break;
- /* Other messages that I have seen and which are not handled already */
- case WM_SETTEXT: /* 0x000c */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- /* Pass it on to "DefWindowProc" to set the window text */
- break;
-
- case WM_GETTEXT: /* 0x000d */
- /* Ideally we would copy the title of the window into "lParam" */
- /* strncpy ( (char *)lParam, "Window Title", wParam );
- lRet = ( wParam > 12 ) ? 12 : wParam; */
- /* the number of characters copied */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- break;
-
- case WM_GETTEXTLENGTH: /* 0x000e */
- /* Ideally we would get the length of the title of the window */
- lRet = 12;
- /* the number of characters in "Window Title\0" (see above) */
- break;
-
- case WM_ERASEBKGND: /* 0x0014 */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- break;
-
#if !defined(_WIN32_WCE)
case WM_SYNCPAINT: /* 0x0088 */
/* Another window has moved, need to update this one */
/* Help screen says this message must be passed to "DefWindowProc" */
break;
- case WM_NCPAINT: /* 0x0085 */
- /* Need to update the border of this window */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- /* Pass it on to "DefWindowProc" to repaint a standard border */
- break;
-
case WM_SYSCOMMAND : /* 0x0112 */
{
/*
case SC_MINIMIZE :
/* User has clicked on the "-" to minimize the window */
- /* Turn off the visibility */
- window->State.Visible = GL_FALSE ;
+ /* Turning off the visibility is handled in WM_SIZE handler */
break ;