Putting in Diederick Niehorster's fullstreen patch per e-mail from him dated 6/9...
authorJohn F. Fay <johnffay@nettally.com>
Sun, 4 Sep 2011 19:38:32 +0000 (19:38 +0000)
committerJohn F. Fay <johnffay@nettally.com>
Sun, 4 Sep 2011 19:38:32 +0000 (19:38 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@929 7f0cb862-5218-0410-a997-914c9d46530a

include/GL/freeglut_ext.h
src/freeglut_ext.c
src/freeglut_internal.h
src/freeglut_main.c
src/freeglut_state.c
src/freeglut_structure.c
src/freeglut_window.c
src/freeglutdll.def

index c0fddbf..6bf84b8 100644 (file)
@@ -127,6 +127,7 @@ FGAPI void    FGAPIENTRY glutExit         ( void );
  * Window management functions, see freeglut_window.c
  */
 FGAPI void    FGAPIENTRY glutFullScreenToggle( void );
+FGAPI void    FGAPIENTRY glutLeaveFullScreen( void );
 
 /*
  * Window-specific callback functions, see freeglut_callbacks.c
index 927cb4e..d8aca45 100644 (file)
@@ -166,6 +166,7 @@ static GLUTproc fghGetGLUTProcAddress( const char* procName )
     CHECK_NAME(glutWMCloseFunc);
     CHECK_NAME(glutMenuDestroyFunc);
     CHECK_NAME(glutFullScreenToggle);
+    CHECK_NAME(glutLeaveFullScreen);
     CHECK_NAME(glutSetOption);
     CHECK_NAME(glutGetModeValues);
     CHECK_NAME(glutSetWindowData);
index 2a8d89a..0a6ece4 100644 (file)
@@ -449,10 +449,16 @@ struct tagSFG_Context
 typedef struct tagSFG_WindowState SFG_WindowState;
 struct tagSFG_WindowState
 {
+    /* Note that on Windows, sizes always refer to the client area, thus without the window decorations */
     int             Width;              /* Window's width in pixels          */
     int             Height;             /* The same about the height         */
+#if TARGET_HOST_POSIX_X11
     int             OldWidth;           /* Window width from before a resize */
     int             OldHeight;          /*   "    height  "    "    "   "    */
+#elif TARGET_HOST_MS_WINDOWS
+    RECT            OldRect;            /* window rect - stored before the window is made fullscreen */
+    DWORD           OldStyle;           /* window style - stored before the window is made fullscreen */
+#endif
 
     GLboolean       Redisplay;          /* Do we have to redisplay?          */
     GLboolean       Visible;            /* Is the window visible now         */
@@ -926,6 +932,17 @@ void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator );
 void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
                        SFG_Enumerator* enumerator );
 
+/* 
+ * 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).
+ */
+void fghComputeWindowRectFromClientArea_UseStyle   ( const DWORD windowStyle , RECT *clientRect, BOOL posIsOutside );
+void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside );
+void fghComputeClientAreaFromWindowRect            ( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside );
+RECT fghGetClientArea                              ( const SFG_Window *window,                   BOOL wantPosOutside );
+void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth);
+
 /*
  * fgWindowByHandle returns a (SFG_Window *) value pointing to the
  * first window in the queue matching the specified window handle.
index 5d18440..5f9b0a5 100644 (file)
@@ -109,8 +109,7 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height )
 
 #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
@@ -119,51 +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 != fgStructure.GameModeWindow) &&
-              !( fgState.DisplayMode & GLUT_BORDERLESS ))
-            {
-                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 POSIX_X11 code.
-     */
     if( FETCH_WCB( *window, Reshape ) )
         INVOKE_WCB( *window, Reshape, ( width, height ) );
     else
index 1cabb9d..9e3a627 100644 (file)
@@ -64,16 +64,6 @@ static int fghGetConfig( int attribute )
 }
 #endif
 
-/* Check if the window is in full screen state. */
-static int fghCheckFullScreen(void)
-{
-#if TARGET_HOST_POSIX_X11
-    return fgStructure.CurrentWindow->State.IsFullscreen;
-#else
-    return 0;
-#endif
-}
-
 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
 
 /*
@@ -458,25 +448,11 @@ int FGAPIENTRY glutGet( GLenum eWhat )
 
         freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
 
-        /*
-         * We need to call GetWindowRect() first...
-         *  (this returns the pixel coordinates of the outside of the window)
-         */
+#if defined(_WIN32_WCE)
         GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
-
-        /* ...then we've got to correct the results we've just received... */
-
-#if !defined(_WIN32_WCE)
-        if ( ( fgStructure.GameModeWindow != fgStructure.CurrentWindow ) && ( fgStructure.CurrentWindow->Parent == NULL ) &&
-             ( ! fgStructure.CurrentWindow->IsMenu ) &&
-            !( fgState.DisplayMode & GLUT_BORDERLESS ))
-        {
-          winRect.left   += GetSystemMetrics( SM_CXSIZEFRAME );
-          winRect.right  -= GetSystemMetrics( SM_CXSIZEFRAME );
-          winRect.top    += GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION );
-          winRect.bottom -= GetSystemMetrics( SM_CYSIZEFRAME );
-        }
-#endif /* !defined(_WIN32_WCE) */
+#else
+        winRect = fghGetClientArea(fgStructure.CurrentWindow, FALSE);
+#endif /* defined(_WIN32_WCE) */
 
         switch( eWhat )
         {
@@ -489,21 +465,32 @@ int FGAPIENTRY glutGet( GLenum eWhat )
     break;
 
     case GLUT_WINDOW_BORDER_WIDTH :
-#if defined(_WIN32_WCE)
-        return 0;
-#else
-       if ( fgState.DisplayMode & GLUT_BORDERLESS )
-         return 0;
-        return GetSystemMetrics( SM_CXSIZEFRAME );
-#endif /* !defined(_WIN32_WCE) */
-
     case GLUT_WINDOW_HEADER_HEIGHT :
 #if defined(_WIN32_WCE)
         return 0;
 #else
-       if ( fgState.DisplayMode & GLUT_BORDERLESS )
-         return 0;
-        return GetSystemMetrics( SM_CYCAPTION );
+        {
+            DWORD windowStyle;
+
+            if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle)
+                windowStyle = GetWindowLong(fgStructure.CurrentWindow->Window.Handle, GWL_STYLE);
+            else
+                /* If no window, return sizes for a default window with title bar and border */
+                windowStyle = WS_OVERLAPPEDWINDOW;
+            
+            switch( eWhat )
+            {
+            case GLUT_WINDOW_BORDER_WIDTH:
+                {
+                    int xBorderWidth, yBorderWidth;
+                    fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
+                    return xBorderWidth;
+                }
+            case GLUT_WINDOW_HEADER_HEIGHT:
+                /* 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... */
+                return (windowStyle & WS_MAXIMIZEBOX)? GetSystemMetrics( SM_CYCAPTION ) : 0;
+            }
+        }
 #endif /* defined(_WIN32_WCE) */
 
     case GLUT_DISPLAY_MODE_POSSIBLE:
@@ -559,7 +546,7 @@ int FGAPIENTRY glutGet( GLenum eWhat )
         return fgState.DirectContext;
 
     case GLUT_FULL_SCREEN:
-        return fghCheckFullScreen();
+        return fgStructure.CurrentWindow->State.IsFullscreen;
 
     case GLUT_AUX:
       return fgState.AuxiliaryBufferNumber;
index ce3869b..c5a2d73 100644 (file)
@@ -79,7 +79,9 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title,
 
     /* Initialize the object properties */
     window->ID = ++fgStructure.WindowID;
+#if TARGET_HOST_POSIX_X11
     window->State.OldHeight = window->State.OldWidth = -1;
+#endif
 
     fgListInit( &window->Children );
     if( parent )
index f3c509a..897b03c 100644 (file)
@@ -850,12 +850,167 @@ void fgSetWindow ( SFG_Window *window )
 
 #if TARGET_HOST_MS_WINDOWS
 
+/* 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.
+ * If posIsOutside is set to true, the input client Rect is taken to follow
+ * freeGLUT's window specification convention in which the top-left corner
+ * is at the outside of the window, while the size
+ * (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 )
+{
+    int xBorderWidth = 0, yBorderWidth = 0;
+
+    /* 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 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 (posIsOutside)
+    {
+        clientRect->right  += xBorderWidth * 2;
+        clientRect->bottom += yBorderWidth * 2;
+    }
+    else
+    {
+        clientRect->left   -= xBorderWidth;
+        clientRect->right  += xBorderWidth;
+        clientRect->top    -= yBorderWidth;
+        clientRect->bottom += yBorderWidth;
+    }
+}
+
+/* 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. If the window pointer or the window handle
+ * is NULL, a fully decorated window (caption and border) is assumed.
+ * Furthermore, if posIsOutside is set to true, the input client Rect is
+ * taken to follow freeGLUT's window specification convention in which the
+ * top-left corner is at the outside of the window, while the size
+ * (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 )
+{
+    DWORD windowStyle = 0;
+
+    if (window && window->Window.Handle)
+        windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
+    else
+        windowStyle = WS_OVERLAPPEDWINDOW;
+
+    fghComputeWindowRectFromClientArea_UseStyle(windowStyle, clientRect, 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.
+ * 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
+ * top-left corner is at the outside of the window, while the size
+ * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
+ * area.
+ */
+RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside )
+{
+    RECT windowRect = {0,0,0,0};
+
+    freeglut_return_val_if_fail((window && window->Window.Handle),windowRect);
+    
+    /*
+     * call GetWindowRect()
+     * (this returns the pixel coordinates of the outside of the window)
+     */
+    GetWindowRect( window->Window.Handle, &windowRect );
+
+    /* Then correct the results */
+    fghComputeClientAreaFromWindowRect(window, &windowRect, wantPosOutside);
+
+    return windowRect;
+}
+
+/* Returns the width of the window borders based on the window's style.
+ */
+void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth)
+{
+    if (windowStyle & WS_THICKFRAME)
+    {
+        *xBorderWidth = GetSystemMetrics(SM_CXSIZEFRAME);
+        *yBorderWidth = GetSystemMetrics(SM_CYSIZEFRAME);
+    }
+    else if (windowStyle & WS_DLGFRAME)
+    {
+        *xBorderWidth = GetSystemMetrics(SM_CXFIXEDFRAME);
+        *yBorderWidth = GetSystemMetrics(SM_CYFIXEDFRAME);
+    }
+    else
+    {
+        *xBorderWidth = 0;
+        *yBorderWidth = 0;
+    }
+}
+
 #if(WINVER >= 0x500)
-typedef struct {
+typedef struct
+{
       int *x;
       int *y;
       const char *name;
-}m_proc_t ;
+} m_proc_t;
 
 static BOOL CALLBACK m_proc(HMONITOR mon,
                            HDC hdc,
@@ -869,7 +1024,7 @@ static BOOL CALLBACK m_proc(HMONITOR mon,
       res=GetMonitorInfo(mon,(LPMONITORINFO)&info);
       if( res )
       {
-          if( !strcmp(dp->name,info.szDevice) )
+          if( strcmp(dp->name,info.szDevice)==0 )
           {
               *(dp->x)=info.rcMonitor.left;
               *(dp->y)=info.rcMonitor.top;
@@ -880,13 +1035,18 @@ static BOOL CALLBACK m_proc(HMONITOR mon,
 }
 
 /* 
- * this function is only used in fgOpenWindow. Currently it only sets 
- * its output parameters, if the DisplayName is set in fgDisplay 
- * (and if it is able to recognize the display)
+ * this function returns the origin of the screen identified by
+ * fgDisplay.DisplayName, and 0 otherwise.
+ * This is used in fgOpenWindow to open the gamemode window on the screen
+ * identified by the -display command line argument. The function should
+ * not be called otherwise.
  */
 
 static void get_display_origin(int *xp,int *yp)
 {
+    *xp = 0;
+    *yp = 0;
+
     if( fgDisplay.DisplayName )
     {
         m_proc_t st;
@@ -894,13 +1054,16 @@ static void get_display_origin(int *xp,int *yp)
         st.y=yp;
         st.name=fgDisplay.DisplayName;
         EnumDisplayMonitors(0,0,m_proc,(LPARAM)&st);
-     }
+    }
 }
 #else
 #pragma message( "-display parameter only works if compiled with WINVER >= 0x0500")
 
 static void get_display_origin(int *xp,int *yp)
 {
+    *xp = 0;
+    *yp = 0;
+
     if( fgDisplay.DisplayName )
     {
         fgWarning( "for working -display support FreeGLUT must be compiled with WINVER >= 0x0500");
@@ -1139,16 +1302,16 @@ void fgOpenWindow( SFG_Window* window, const char* title,
 #elif TARGET_HOST_MS_WINDOWS
 
     WNDCLASS wc;
-    DWORD flags;
+    DWORD flags   = 0;
     DWORD exFlags = 0;
     ATOM atom;
-    int WindowStyle = 0;
 
     /* Grab the window class we have registered on glutInit(): */
     atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc );
     FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found",
                                    "fgOpenWindow" );
 
+    /* Determine window style flags*/
     if( gameMode )
     {
         FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL,
@@ -1163,64 +1326,100 @@ void fgOpenWindow( SFG_Window* window, const char* title,
     }
     else
     {
-        int worig = w, horig = h;
-
-#if !defined(_WIN32_WCE)
-        if ( ( ! isSubWindow ) && ( ! window->IsMenu ) )
-        {
-            /*
-             * Update the window dimensions, taking account of window
-             * decorations.  "freeglut" is to create the window with the
-             * outside of its border at (x,y) and with dimensions (w,h).
-             */
-            w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
-            h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 +
-                GetSystemMetrics( SM_CYCAPTION );
-        }
-#endif /* defined(_WIN32_WCE) */
-
-        if( ! positionUse )
-        {
-            x = CW_USEDEFAULT;
-            y = CW_USEDEFAULT;
-        }
-        /* setting State.Width/Height to call resize callback later */
-        if( ! sizeUse )
-        {
-            if( ! window->IsMenu )
-            {
-                w = CW_USEDEFAULT;
-                h = CW_USEDEFAULT;
-            }
-            else /* fail safe - Windows can make a window of size (0, 0) */
-                w = h = 300; /* default window size */
-            window->State.Width = window->State.Height = -1;
-        }
-        else
-        {
-            window->State.Width = worig;
-            window->State.Height = horig;
-        }
+        flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
 
         /*
          * There's a small difference between creating the top, child and
-         * game mode windows
+         * menu windows
          */
-        flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
-
         if ( window->IsMenu )
         {
             flags |= WS_POPUP;
             exFlags |= WS_EX_TOOLWINDOW;
         }
-#if !defined(_WIN32_WCE)
+#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 */
         else if( window->Parent == NULL )
-            flags |= WS_OVERLAPPEDWINDOW;
+            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;
 #endif
         else
+            /* subwindows always have no decoration, but are marked as a child window to the OS */
             flags |= WS_CHILD;
     }
 
+    /* determine window size and position */
+    if( gameMode )
+    {
+        /* if in gamemode, query the origin of specified by the -display
+         * parameter command line (if any) and offset the upper-left corner
+         * of the window so we create the window on that screen.
+         * The -display argument doesn't do anything if not trying to enter
+         * gamemode.
+         */
+        int xoff=0, yoff=0;
+        get_display_origin(&xoff,&yoff);
+        x += xoff;
+        y += yoff;
+    }
+    if( !positionUse )
+    {
+        x = CW_USEDEFAULT;
+        y = CW_USEDEFAULT;
+    }
+    if( !sizeUse )
+    {
+        if( ! window->IsMenu )
+        {
+            w = CW_USEDEFAULT;
+            h = CW_USEDEFAULT;
+        }
+        else /* fail safe - Windows can make a window of size (0, 0) */
+            w = h = 300; /* default window size */
+    }
+    /* store requested client area width and height */
+    window->State.Width = w;
+    window->State.Height = h;
+
+#if !defined(_WIN32_WCE)    /* no decorations for windows CE */
+    if( sizeUse )
+    {
+        RECT windowRect;
+        /*
+         * Update the window dimensions, taking the window decorations
+         * into account.  FreeGLUT is to create the window with the
+         * topleft outside corner at (x,y) and with client area
+         * dimensions (w,h).
+         * note: don't need to do this when w=h=CW_USEDEFAULT, so in the
+         * if( sizeUse ) here is convenient.
+         */
+        windowRect.left     = x;
+        windowRect.top      = y;
+        windowRect.right    = x+w;
+        windowRect.bottom   = y+h;
+
+        fghComputeWindowRectFromClientArea_UseStyle(flags,&windowRect,TRUE);
+
+        w = windowRect.right - windowRect.left;
+        h = windowRect.bottom- windowRect.top;
+    }
+#endif /* !defined(_WIN32_WCE) */
+
 #if defined(_WIN32_WCE)
     {
         wchar_t* wstr = fghWstrFromStr(title);
@@ -1246,29 +1445,28 @@ void fgOpenWindow( SFG_Window* window, const char* title,
         UpdateWindow(window->Window.Handle);
     }
 #else
-    {
-      /* xoff and yoff are used to place window relative to current display */
-      /* The operation of gamemode also depends on this */
-        int xoff=0,yoff=0;
-        get_display_origin(&xoff,&yoff);
-
-        window->Window.Handle = CreateWindowEx(
-            exFlags,
-            _T("FREEGLUT"),
-            title,
-            flags,
-            x+xoff, y+yoff, w, h,
-            (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
-            (HMENU) NULL,
-            fgDisplay.Instance,
-            (LPVOID) window
-        );
-    }
+    window->Window.Handle = CreateWindowEx(
+        exFlags,
+        _T("FREEGLUT"),
+        title,
+        flags,
+        x, y, w, h,
+        (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
+        (HMENU) NULL,
+        fgDisplay.Instance,
+        (LPVOID) window
+    );
 #endif /* defined(_WIN32_WCE) */
 
     if( !( window->Window.Handle ) )
         fgError( "Failed to create a window (%s)!", title );
 
+#if !defined(_WIN32_WCE)
+    /* Need to set requested style again, apparently Windows doesn't listen when requesting windows without title bar or borders */
+    SetWindowLong(window->Window.Handle, GWL_STYLE, flags);
+    SetWindowPos(window->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+#endif /* defined(_WIN32_WCE) */
+
     /* Make a menu window always on top - fix Feature Request 947118 */
     if( window->IsMenu || gameMode )
         SetWindowPos(
@@ -1278,23 +1476,6 @@ void fgOpenWindow( SFG_Window* window, const char* title,
                         SWP_NOMOVE | SWP_NOSIZE
                     );
 
-    /* Hack to remove the caption (title bar) and/or border
-     * and all the system menu controls.
-     */
-    WindowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
-    if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
-    {
-        SetWindowLong ( window->Window.Handle, GWL_STYLE,
-                        WindowStyle & ~(WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
-    }
-    else if ( fgState.DisplayMode & GLUT_BORDERLESS )
-    {
-        SetWindowLong ( window->Window.Handle, GWL_STYLE,
-                        WindowStyle & ~(WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_DLGFRAME | WS_SIZEBOX));
-    }
-/*  SetWindowPos(window->Window.Handle, NULL, 0, 0, 0, 0,
-     SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); */
-
     /* Enable multitouch: additional flag TWF_FINETOUCH, TWF_WANTPALM */
     #ifdef WM_TOUCH
         if (fghRegisterTouchWindow == (pRegisterTouchWindow)0xDEADBEEF) 
@@ -1680,7 +1861,7 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
     if (glutGet(GLUT_FULL_SCREEN))
     {
       /*  Leave full screen state before resizing. */
-      glutFullScreenToggle();
+      glutLeaveFullScreen();
     }
 
     fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
@@ -1699,7 +1880,7 @@ void FGAPIENTRY glutPositionWindow( int x, int y )
     if (glutGet(GLUT_FULL_SCREEN))
     {
       /*  Leave full screen state before moving. */
-      glutFullScreenToggle();
+      glutLeaveFullScreen();
     }
 
 #if TARGET_HOST_POSIX_X11
@@ -1788,6 +1969,21 @@ void FGAPIENTRY glutFullScreen( void )
 
     win = fgStructure.CurrentWindow;
 
+    if (win->Parent)
+    {
+        /* Child windows cannot be made fullscreen, consistent with GLUT's behavior
+         * Also, what would it mean for a child window to be fullscreen, given that it
+         * is confined to its parent?
+         */
+        fgWarning("glutFullScreen called on a child window, ignoring...");
+        return;
+    }
+    else if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==win->ID)
+    {
+        /* Ignore fullscreen call on GameMode window, those are always fullscreen already */
+        return;
+    }
+
 #if TARGET_HOST_POSIX_X11
     if(!glutGet(GLUT_FULL_SCREEN)) {
         if(fghToggleFullscreen() != -1) {
@@ -1799,34 +1995,50 @@ void FGAPIENTRY glutFullScreen( void )
 
     if (glutGet(GLUT_FULL_SCREEN))
     {
-        /*  Leave full screen state before resizing. */
-        glutFullScreenToggle();
+        /*  Leave full screen state before entering fullscreen again (resizing?) */
+        glutLeaveFullScreen();
     }
 
     {
+        DWORD s;
         RECT rect;
+        HMONITOR hMonitor;
+        MONITORINFO mi;
 
-        /* For fullscreen mode, force the top-left corner to 0,0
-         * and adjust the window rectangle so that the client area
-         * covers the whole screen.
+        /* For fullscreen mode, first remove all window decoration
+         * and set style to popup so it will overlap the taskbar
+         * then force to maximize on the screen on which it has the most
+         * overlap.
          */
 
-        rect.left   = 0;
-        rect.top    = 0;
-       get_display_origin(&rect.left,&rect.top);
-        rect.right  = fgDisplay.ScreenWidth+rect.left;
-        rect.bottom = fgDisplay.ScreenHeight+rect.top;
-
-        AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
-                                  WS_CLIPCHILDREN, FALSE );
+        
+        /* store current window rect */
+        GetWindowRect( win->Window.Handle, &win->State.OldRect );
+
+        /* store current window style */
+        win->State.OldStyle = s = GetWindowLong(win->Window.Handle, GWL_STYLE);
+
+        /* remove decorations from style and add popup style*/
+        s &= ~WS_OVERLAPPEDWINDOW;
+        s |= WS_POPUP;
+        SetWindowLong(win->Window.Handle, GWL_STYLE, s);
+        SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+
+        /* For fullscreen mode, find the monitor that is covered the most
+         * by the window and get its rect as the resize target.
+            */
+        hMonitor= MonitorFromRect(&win->State.OldRect, MONITOR_DEFAULTTONEAREST);
+        mi.cbSize = sizeof(mi);
+        GetMonitorInfo(hMonitor, &mi);
+        rect = mi.rcMonitor;
 
         /*
+         * then resize window
          * SWP_NOACTIVATE     Do not activate the window
          * SWP_NOOWNERZORDER  Do not change position in z-order
-         * SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message
+         * SWP_NOSENDCHANGING Suppress WM_WINDOWPOSCHANGING message
          * SWP_NOZORDER       Retains the current Z order (ignore 2nd param)
          */
-
         SetWindowPos( fgStructure.CurrentWindow->Window.Handle,
                       HWND_TOP,
                       rect.left,
@@ -1843,6 +2055,51 @@ void FGAPIENTRY glutFullScreen( void )
 }
 
 /*
+ * If we are fullscreen, resize the current window back to its original size
+ */
+void FGAPIENTRY glutLeaveFullScreen( void )
+{
+    SFG_Window *win;
+
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
+    FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
+
+    win = fgStructure.CurrentWindow;
+
+#if TARGET_HOST_POSIX_X11
+    if(glutGet(GLUT_FULL_SCREEN)) {
+        if(fghToggleFullscreen() != -1) {
+            win->State.IsFullscreen = GL_FALSE;
+        }
+    }
+
+#elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: what about WinCE */
+    if (!glutGet(GLUT_FULL_SCREEN))
+    {
+        /* nothing to do */
+        return;
+    }
+
+    /* restore style of window before making it fullscreen */
+    SetWindowLong(win->Window.Handle, GWL_STYLE, win->State.OldStyle);
+    SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+
+    /* Then resize */
+    SetWindowPos(win->Window.Handle,
+        HWND_TOP,
+        win->State.OldRect.left,
+        win->State.OldRect.top,
+        win->State.OldRect.right  - win->State.OldRect.left,
+        win->State.OldRect.bottom - win->State.OldRect.top,
+        SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
+        SWP_NOZORDER
+        );
+
+    win->State.IsFullscreen = GL_FALSE;
+#endif
+}
+
+/*
  * Toggle the window's full screen state.
  */
 void FGAPIENTRY glutFullScreenToggle( void )
@@ -1859,8 +2116,10 @@ void FGAPIENTRY glutFullScreenToggle( void )
         win->State.IsFullscreen = !win->State.IsFullscreen;
     }
 #elif TARGET_HOST_MS_WINDOWS
-    glutFullScreen();
-    win->State.IsFullscreen = !win->State.IsFullscreen;
+    if (!win->State.IsFullscreen)
+        glutFullScreen();
+    else
+        glutLeaveFullScreen();
 #endif
 }
 
index c538c0d..d46ecb6 100644 (file)
@@ -139,6 +139,7 @@ EXPORTS
        glutGetProcAddress
        glutExit
        glutFullScreenToggle
+       glutLeaveFullScreen
        glutGetModeValues
        glutInitContextFlags
        glutInitContextVersion