Added subwindows to CallbackMaker demo, for testing and demonstration. Also figured...
[freeglut] / src / mswin / fg_window_mswin.c
index 9c69d2e..ae30001 100644 (file)
@@ -759,6 +759,74 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
 }
 
 
+void fgPlatformDisplayWindow ( SFG_Window *window )
+{
+    RedrawWindow(
+        window->Window.Handle, NULL, NULL,
+        RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW
+        );
+}
+
+
+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
+    );
+
+    /* Set new width and height so we can test for that in WM_SIZE message handler and don't do anything if not needed */
+    window->State.Width  = width;
+    window->State.Height = height;
+}
+
+
 /*
  * Closes a window, destroying the frame and OpenGL context
  */
@@ -912,7 +980,6 @@ void fgPlatformGlutFullScreen( SFG_Window *win )
 
     {
 #if(WINVER >= 0x0500) /* Windows 2000 or later */
-        DWORD s;
         RECT rect;
         HMONITOR hMonitor;
         MONITORINFO mi;
@@ -924,17 +991,25 @@ void fgPlatformGlutFullScreen( SFG_Window *win )
          */
 
         
-        /* store current window rect */
-        GetWindowRect( win->Window.Handle, &win->State.pWState.OldRect );
+        /* save current window rect, style, exstyle and maximized state */
+        win->State.pWState.OldMaximized = !!IsZoomed(win->Window.Handle);
+        if (win->State.pWState.OldMaximized)
+            /* We force the window into restored mode before going
+             * fullscreen because Windows doesn't seem to hide the
+             * taskbar if the window is in the maximized state.
+             */
+            SendMessage(win->Window.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
 
-        /* store current window style */
-        win->State.pWState.OldStyle = s = GetWindowLong(win->Window.Handle, GWL_STYLE);
+        GetWindowRect( win->Window.Handle, &win->State.pWState.OldRect );
+        win->State.pWState.OldStyle   = GetWindowLong(win->Window.Handle, GWL_STYLE);
+        win->State.pWState.OldStyleEx = GetWindowLong(win->Window.Handle, GWL_EXSTYLE);
 
-        /* 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);
+        /* remove decorations from style */
+        SetWindowLong(win->Window.Handle, GWL_STYLE,
+                      win->State.pWState.OldStyle & ~(WS_CAPTION | WS_THICKFRAME));
+        SetWindowLong(win->Window.Handle, GWL_EXSTYLE,
+                      win->State.pWState.OldStyleEx & ~(WS_EX_DLGMODALFRAME |
+                      WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
 
         /* For fullscreen mode, find the monitor that is covered the most
          * by the window and get its rect as the resize target.
@@ -996,7 +1071,7 @@ void fgPlatformGlutLeaveFullScreen( SFG_Window *win )
 
     /* restore style of window before making it fullscreen */
     SetWindowLong(win->Window.Handle, GWL_STYLE, win->State.pWState.OldStyle);
-    SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+    SetWindowLong(win->Window.Handle, GWL_EXSTYLE, win->State.pWState.OldStyleEx);
 
     /* Then resize */
     SetWindowPos(win->Window.Handle,
@@ -1009,6 +1084,9 @@ void fgPlatformGlutLeaveFullScreen( SFG_Window *win )
         SWP_NOZORDER
         );
 
+    if (win->State.pWState.OldMaximized)
+        SendMessage(win->Window.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
+
     win->State.IsFullscreen = GL_FALSE;
 #endif
 }