now have function to get window style based on FreeGLUT's stateflag
[freeglut] / src / mswin / fg_window_mswin.c
index b09c008..9c69d2e 100644 (file)
@@ -371,39 +371,41 @@ void fgPlatformSetWindow ( SFG_Window *window )
 }
 
 
-void fghPlatformGetMousePos(SFG_XYUse *mouse_pos)
+void fghGetDefaultWindowStyle(DWORD *flags)
 {
-    POINT pos;
-    GetCursorPos(&pos);
-
-    mouse_pos->X = pos.x;
-    mouse_pos->Y = pos.y;
-    mouse_pos->Use = GL_TRUE;
+    if ( fgState.DisplayMode & GLUT_BORDERLESS )
+    {
+        /* no window decorations needed, no-op */
+    }
+    else if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
+        /* only window decoration is a border, no title bar or buttons */
+        (*flags) |= WS_DLGFRAME;
+    else
+        /* window decoration are a border, title bar and buttons. */
+        (*flags) |= WS_OVERLAPPEDWINDOW;
 }
 
-/* Returns the width of the window borders based on the window's style.
-*/
-void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth)
+/* Get window style and extended window style of a FreeGLUT window
+ * If the window pointer or the window handle is NULL, a fully
+ * decorated window (caption and border) is assumed.
+ */
+void fghGetStyleFromWindow( const SFG_Window *window, DWORD *windowStyle, DWORD *windowExStyle )
 {
-    if (windowStyle & WS_THICKFRAME)
-    {
-        *xBorderWidth = GetSystemMetrics(SM_CXSIZEFRAME);
-        *yBorderWidth = GetSystemMetrics(SM_CYSIZEFRAME);
-    }
-    else if (windowStyle & WS_DLGFRAME)
+    if (window && window->Window.Handle)
     {
-        *xBorderWidth = GetSystemMetrics(SM_CXFIXEDFRAME);
-        *yBorderWidth = GetSystemMetrics(SM_CYFIXEDFRAME);
+        *windowStyle   = GetWindowLong(window->Window.Handle, GWL_STYLE);
+        *windowExStyle = GetWindowLong(window->Window.Handle, GWL_EXSTYLE);
     }
     else
     {
-        *xBorderWidth = 0;
-        *yBorderWidth = 0;
+        *windowStyle   = 0;
+        fghGetDefaultWindowStyle(windowStyle);
+        /* WindowExStyle==0 is fine/default, exStyle is currently only used for menu windows */
+        *windowExStyle = 0;
     }
 }
 
 
-
 /* Computes position of corners of window Rect (outer position including
  * decorations) based on the provided client rect and based on the style
  * of the window in question.
@@ -413,35 +415,25 @@ void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderW
  * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
  * area.
  */
-void fghComputeWindowRectFromClientArea_UseStyle( const DWORD windowStyle, RECT *clientRect, BOOL posIsOutside )
+void fghComputeWindowRectFromClientArea_UseStyle( RECT *clientRect, const DWORD windowStyle, const DWORD windowExStyle, BOOL posIsOutside )
 {
-    int xBorderWidth = 0, yBorderWidth = 0;
+    RECT windowRect   = {0,0,0,0};
+    CopyRect(&windowRect,clientRect);
 
-    /* If window has title bar, correct rect for it */
-    if (windowStyle & WS_MAXIMIZEBOX) /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
-    {
-        if (posIsOutside)
-            clientRect->bottom += GetSystemMetrics( SM_CYCAPTION );
-        else
-            clientRect->top -= GetSystemMetrics( SM_CYCAPTION );
-    }
+    /* Get rect including non-client area */
+    AdjustWindowRectEx(&windowRect,windowStyle,FALSE,windowExStyle);
 
-    /* get width of window's borders (frame), correct rect for it.
-     * Note, borders can be of zero width if style does not specify borders
-     */
-    fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
+    /* Move window right and down by non-client area extent on left and top, if wanted */
     if (posIsOutside)
     {
-        clientRect->right  += xBorderWidth * 2;
-        clientRect->bottom += yBorderWidth * 2;
-    }
-    else
-    {
-        clientRect->left   -= xBorderWidth;
-        clientRect->right  += xBorderWidth;
-        clientRect->top    -= yBorderWidth;
-        clientRect->bottom += yBorderWidth;
+        windowRect.right   += clientRect->left-windowRect.left;
+        windowRect.bottom  += clientRect->top -windowRect.top;
+        windowRect.left     = clientRect->left;
+        windowRect.top      = clientRect->top;
     }
+    
+    /* done, copy windowRect to output */
+    CopyRect(clientRect,&windowRect);
 }
 
 /* Computes position of corners of window Rect (outer position including
@@ -454,68 +446,17 @@ void fghComputeWindowRectFromClientArea_UseStyle( const DWORD windowStyle, RECT
  * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
  * area.
 */
-void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside )
+void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside )
 {
-    DWORD windowStyle = 0;
-
-    if (window && window->Window.Handle)
-        windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
-    else
-        windowStyle = WS_OVERLAPPEDWINDOW;
+    DWORD windowStyle = 0, windowExStyle = 0;
+    fghGetStyleFromWindow(window,&windowStyle,&windowExStyle);
 
-    fghComputeWindowRectFromClientArea_UseStyle(windowStyle, clientRect, posIsOutside);
+    fghComputeWindowRectFromClientArea_UseStyle(clientRect, windowStyle, windowExStyle, posIsOutside);
 }
 
-/* Computes position of corners of client area (drawable area) of a window
- * based on the provided window Rect (outer position including decorations)
- * and based on the style of the window in question. If the window pointer
- * or the window handle is NULL, a fully decorated window (caption and
- * border) is assumed.
- * Furthermore, if wantPosOutside is set to true, the output client Rect
- * will follow freeGLUT's window specification convention in which the
- * top-left corner is at the outside of the window, the size
- * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
- * area.
- */
-void fghComputeClientAreaFromWindowRect( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside )
-{
-    DWORD windowStyle = 0;
-    int xBorderWidth = 0, yBorderWidth = 0;
-
-    if (window && window->Window.Handle)
-        windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
-    else
-        windowStyle = WS_OVERLAPPEDWINDOW;
-
-    /* If window has title bar, correct rect for it */
-    if (windowStyle & WS_MAXIMIZEBOX) /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
-    {
-        if (wantPosOutside)
-            windowRect->bottom -= GetSystemMetrics( SM_CYCAPTION );
-        else
-            windowRect->top    += GetSystemMetrics( SM_CYCAPTION );
-    }
-
-    /* get width of window's borders (frame), correct rect for it.
-     * Note, borders can be of zero width if style does not specify borders
-     */
-    fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
-    if (wantPosOutside)
-    {
-        windowRect->right  -= xBorderWidth * 2;
-        windowRect->bottom -= yBorderWidth * 2;
-    }
-    else
-    {
-        windowRect->left   += xBorderWidth;
-        windowRect->right  -= xBorderWidth;
-        windowRect->top    += yBorderWidth;
-        windowRect->bottom -= yBorderWidth;
-    }
-}
 
 /* Gets the rect describing the client area (drawable area) of the
- * specified window.
+ * specified window. Output is position of corners of client area (drawable area) on the screen.
  * Returns an empty rect if window pointer or window handle is NULL.
  * If wantPosOutside is set to true, the output client Rect
  * will follow freeGLUT's window specification convention in which the
@@ -523,22 +464,38 @@ void fghComputeClientAreaFromWindowRect( const SFG_Window *window, RECT *windowR
  * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
  * area.
  */
-RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside )
+void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL wantPosOutside )
 {
-    RECT windowRect = {0,0,0,0};
+    POINT topLeftClient = {0,0};
+    POINT topLeftWindow = {0,0};
 
-    freeglut_return_val_if_fail((window && window->Window.Handle),windowRect);
+    freeglut_return_if_fail((window && window->Window.Handle));
     
     /*
      * call GetWindowRect()
      * (this returns the pixel coordinates of the outside of the window)
+     * cannot use GetClientRect as it returns a rect relative to
+     * the top-left point of the client area (.top and .left are thus always 0)
+     * and is thus only useful for querying the size of the client area, not
+     * its position.
      */
-    GetWindowRect( window->Window.Handle, &windowRect );
-
-    /* Then correct the results */
-    fghComputeClientAreaFromWindowRect(window, &windowRect, wantPosOutside);
-
-    return windowRect;
+    GetWindowRect( window->Window.Handle, clientRect );
+    topLeftWindow.x = clientRect->top;
+    topLeftWindow.y = clientRect->left;
+    
+    /* Get size of client rect */
+    GetClientRect(window->Window.Handle, clientRect);
+    /* Get position of top-left of client area on the screen */
+    ClientToScreen(window->Window.Handle,&topLeftClient);
+    /* Add top-left offset */
+    OffsetRect(clientRect,topLeftClient.x,topLeftClient.y);
+
+    /* replace top and left with top and left of window, if wanted */
+    if (wantPosOutside)
+    {
+        clientRect->left = topLeftWindow.x;
+        clientRect->top  = topLeftWindow.y;
+    }
 }
 
 #if(WINVER >= 0x500)
@@ -659,23 +616,9 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
 #if defined(_WIN32_WCE)
         /* no decorations for windows CE */
 #else
-        /* if this is not a subwindow (child), set its style based on the requested display mode */
+        /* if this is not a subwindow (child), set its style based on the requested window decorations */
         else if( window->Parent == NULL )
-            if ( fgState.DisplayMode & GLUT_BORDERLESS )
-            {
-                /* no window decorations needed */
-            }
-            else if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
-                /* only window decoration is a border, no title bar or buttons */
-                flags |= WS_DLGFRAME;
-            else
-                /* window decoration are a border, title bar and buttons.
-                 * NB: we later query whether the window has a title bar or
-                 * not by testing for the maximize button, as the test for
-                 * WS_CAPTION can be true without the window having a title
-                 * bar. This style WS_OVERLAPPEDWINDOW gives you a maximize
-                 * button. */
-                flags |= WS_OVERLAPPEDWINDOW;
+            fghGetDefaultWindowStyle(&flags);
 #endif
         else
             /* subwindows always have no decoration, but are marked as a child window to the OS */
@@ -732,8 +675,9 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
         windowRect.right    = x+w;
         windowRect.bottom   = y+h;
 
-        fghComputeWindowRectFromClientArea_UseStyle(flags,&windowRect,TRUE);
+        fghComputeWindowRectFromClientArea_UseStyle(&windowRect,flags,exFlags,TRUE);
 
+        /* NB: w and h are now width and height of window including non-client area! */
         w = windowRect.right - windowRect.left;
         h = windowRect.bottom- windowRect.top;
     }