Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

FreeGLUT patch

By: a guest on Jun 9th, 2011  |  syntax: Diff  |  size: 32.56 KB  |  views: 105  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. Index: src/freeglut_window.c
  2.  
  3. ===================================================================
  4.  
  5. --- src/freeglut_window.c       (revision 922)
  6.  
  7. +++ src/freeglut_window.c       (working copy)
  8.  
  9. @@ -850,12 +850,167 @@
  10.  
  11.  
  12.  #if TARGET_HOST_MS_WINDOWS
  13.  
  14. +/* Computes position of corners of window Rect (outer position including
  15. + * decorations) based on the provided client rect and based on the style
  16. + * of the window in question.
  17. + * If posIsOutside is set to true, the input client Rect is taken to follow
  18. + * freeGLUT's window specification convention in which the top-left corner
  19. + * is at the outside of the window, while the size
  20. + * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
  21. + * area.
  22. + */
  23. +void fghComputeWindowRectFromClientArea_UseStyle( const DWORD windowStyle, RECT *clientRect, BOOL posIsOutside )
  24. +{
  25. +    int xBorderWidth = 0, yBorderWidth = 0;
  26. +
  27. +    /* If window has title bar, correct rect for it */
  28. +    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... */
  29. +        if (posIsOutside)
  30. +            clientRect->bottom += GetSystemMetrics( SM_CYCAPTION );
  31. +        else
  32. +            clientRect->top -= GetSystemMetrics( SM_CYCAPTION );
  33. +
  34. +    /* get width of window's borders (frame), correct rect for it.
  35. +     * Note, borders can be of zero width if style does not specify borders
  36. +     */
  37. +    fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
  38. +    if (posIsOutside)
  39. +    {
  40. +        clientRect->right  += xBorderWidth * 2;
  41. +        clientRect->bottom += yBorderWidth * 2;
  42. +    }
  43. +    else
  44. +    {
  45. +        clientRect->left   -= xBorderWidth;
  46. +        clientRect->right  += xBorderWidth;
  47. +        clientRect->top    -= yBorderWidth;
  48. +        clientRect->bottom += yBorderWidth;
  49. +    }
  50. +}
  51. +
  52. +/* Computes position of corners of window Rect (outer position including
  53. + * decorations) based on the provided client rect and based on the style
  54. + * of the window in question. If the window pointer or the window handle
  55. + * is NULL, a fully decorated window (caption and border) is assumed.
  56. + * Furthermore, if posIsOutside is set to true, the input client Rect is
  57. + * taken to follow freeGLUT's window specification convention in which the
  58. + * top-left corner is at the outside of the window, while the size
  59. + * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
  60. + * area.
  61. +*/
  62. +void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside )
  63. +{
  64. +    DWORD windowStyle = 0;
  65. +
  66. +    if (window && window->Window.Handle)
  67. +        windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
  68. +    else
  69. +        windowStyle = WS_OVERLAPPEDWINDOW;
  70. +
  71. +    fghComputeWindowRectFromClientArea_UseStyle(windowStyle, clientRect, posIsOutside);
  72. +}
  73. +
  74. +/* Computes position of corners of client area (drawable area) of a window
  75. + * based on the provided window Rect (outer position including decorations)
  76. + * and based on the style of the window in question. If the window pointer
  77. + * or the window handle is NULL, a fully decorated window (caption and
  78. + * border) is assumed.
  79. + * Furthermore, if wantPosOutside is set to true, the output client Rect
  80. + * will follow freeGLUT's window specification convention in which the
  81. + * top-left corner is at the outside of the window, the size
  82. + * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
  83. + * area.
  84. + */
  85. +void fghComputeClientAreaFromWindowRect( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside )
  86. +{
  87. +    DWORD windowStyle = 0;
  88. +    int xBorderWidth = 0, yBorderWidth = 0;
  89. +
  90. +    if (window && window->Window.Handle)
  91. +        windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
  92. +    else
  93. +        windowStyle = WS_OVERLAPPEDWINDOW;
  94. +
  95. +    /* If window has title bar, correct rect for it */
  96. +    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... */
  97. +        if (wantPosOutside)
  98. +            windowRect->bottom -= GetSystemMetrics( SM_CYCAPTION );
  99. +        else
  100. +            windowRect->top    += GetSystemMetrics( SM_CYCAPTION );
  101. +
  102. +    /* get width of window's borders (frame), correct rect for it.
  103. +     * Note, borders can be of zero width if style does not specify borders
  104. +     */
  105. +    fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
  106. +    if (wantPosOutside)
  107. +    {
  108. +        windowRect->right  -= xBorderWidth * 2;
  109. +        windowRect->bottom -= yBorderWidth * 2;
  110. +    }
  111. +    else
  112. +    {
  113. +        windowRect->left   += xBorderWidth;
  114. +        windowRect->right  -= xBorderWidth;
  115. +        windowRect->top    += yBorderWidth;
  116. +        windowRect->bottom -= yBorderWidth;
  117. +    }
  118. +}
  119. +
  120. +/* Gets the rect describing the client area (drawable area) of the
  121. + * specified window.
  122. + * Returns an empty rect if window pointer or window handle is NULL.
  123. + * If wantPosOutside is set to true, the output client Rect
  124. + * will follow freeGLUT's window specification convention in which the
  125. + * top-left corner is at the outside of the window, while the size
  126. + * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
  127. + * area.
  128. + */
  129. +RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside )
  130. +{
  131. +    RECT windowRect = {0,0,0,0};
  132. +
  133. +    freeglut_return_val_if_fail((window && window->Window.Handle),windowRect);
  134. +    
  135. +    /*
  136. +     * call GetWindowRect()
  137. +     * (this returns the pixel coordinates of the outside of the window)
  138. +     */
  139. +    GetWindowRect( window->Window.Handle, &windowRect );
  140. +
  141. +    /* Then correct the results */
  142. +    fghComputeClientAreaFromWindowRect(window, &windowRect, wantPosOutside);
  143. +
  144. +    return windowRect;
  145. +}
  146. +
  147. +/* Returns the width of the window borders based on the window's style.
  148. + */
  149. +void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth)
  150. +{
  151. +    if (windowStyle & WS_THICKFRAME)
  152. +    {
  153. +        *xBorderWidth = GetSystemMetrics(SM_CXSIZEFRAME);
  154. +        *yBorderWidth = GetSystemMetrics(SM_CYSIZEFRAME);
  155. +    }
  156. +    else if (windowStyle & WS_DLGFRAME)
  157. +    {
  158. +        *xBorderWidth = GetSystemMetrics(SM_CXFIXEDFRAME);
  159. +        *yBorderWidth = GetSystemMetrics(SM_CYFIXEDFRAME);
  160. +    }
  161. +    else
  162. +    {
  163. +        *xBorderWidth = 0;
  164. +        *yBorderWidth = 0;
  165. +    }
  166. +}
  167. +
  168.  #if(WINVER >= 0x500)
  169. -typedef struct {
  170. +typedef struct
  171. +{
  172.        int *x;
  173.        int *y;
  174.        const char *name;
  175. -}m_proc_t ;
  176. +} m_proc_t;
  177.  
  178.  static BOOL CALLBACK m_proc(HMONITOR mon,
  179.                             HDC hdc,
  180. @@ -869,7 +1024,7 @@
  181.  
  182.        res=GetMonitorInfo(mon,(LPMONITORINFO)&info);
  183.        if( res )
  184.        {
  185. -          if( !strcmp(dp->name,info.szDevice) )
  186. +          if( strcmp(dp->name,info.szDevice)==0 )
  187.            {
  188.                *(dp->x)=info.rcMonitor.left;
  189.                *(dp->y)=info.rcMonitor.top;
  190. @@ -880,13 +1035,18 @@
  191.  
  192.  }
  193.  
  194.  /*
  195. - * this function is only used in fgOpenWindow. Currently it only sets
  196. - * its output parameters, if the DisplayName is set in fgDisplay
  197. - * (and if it is able to recognize the display)
  198. + * this function returns the origin of the screen identified by
  199. + * fgDisplay.DisplayName, and 0 otherwise.
  200. + * This is used in fgOpenWindow to open the gamemode window on the screen
  201. + * identified by the -display command line argument. The function should
  202. + * not be called otherwise.
  203.   */
  204.  
  205.  static void get_display_origin(int *xp,int *yp)
  206.  {
  207. +    *xp = 0;
  208. +    *yp = 0;
  209. +
  210.      if( fgDisplay.DisplayName )
  211.      {
  212.          m_proc_t st;
  213. @@ -894,13 +1054,16 @@
  214.  
  215.          st.y=yp;
  216.          st.name=fgDisplay.DisplayName;
  217.          EnumDisplayMonitors(0,0,m_proc,(LPARAM)&st);
  218. -     }
  219. +    }
  220.  }
  221.  #else
  222.  #pragma message( "-display parameter only works if compiled with WINVER >= 0x0500")
  223.  
  224.  static void get_display_origin(int *xp,int *yp)
  225.  {
  226. +    *xp = 0;
  227. +    *yp = 0;
  228. +
  229.      if( fgDisplay.DisplayName )
  230.      {
  231.          fgWarning( "for working -display support FreeGLUT must be compiled with WINVER >= 0x0500");
  232. @@ -1139,16 +1302,16 @@
  233.  
  234.  #elif TARGET_HOST_MS_WINDOWS
  235.  
  236.      WNDCLASS wc;
  237. -    DWORD flags;
  238. +    DWORD flags   = 0;
  239.      DWORD exFlags = 0;
  240.      ATOM atom;
  241. -    int WindowStyle = 0;
  242.  
  243.      /* Grab the window class we have registered on glutInit(): */
  244.      atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc );
  245.      FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found",
  246.                                     "fgOpenWindow" );
  247.  
  248. +    /* Determine window style flags*/
  249.      if( gameMode )
  250.      {
  251.          FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL,
  252. @@ -1163,64 +1326,100 @@
  253.  
  254.      }
  255.      else
  256.      {
  257. -        int worig = w, horig = h;
  258. +        flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
  259.  
  260. -#if !defined(_WIN32_WCE)
  261. -        if ( ( ! isSubWindow ) && ( ! window->IsMenu ) )
  262. -        {
  263. -            /*
  264. -             * Update the window dimensions, taking account of window
  265. -             * decorations.  "freeglut" is to create the window with the
  266. -             * outside of its border at (x,y) and with dimensions (w,h).
  267. -             */
  268. -            w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
  269. -            h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 +
  270. -                GetSystemMetrics( SM_CYCAPTION );
  271. -        }
  272. -#endif /* defined(_WIN32_WCE) */
  273. -
  274. -        if( ! positionUse )
  275. -        {
  276. -            x = CW_USEDEFAULT;
  277. -            y = CW_USEDEFAULT;
  278. -        }
  279. -        /* setting State.Width/Height to call resize callback later */
  280. -        if( ! sizeUse )
  281. -        {
  282. -            if( ! window->IsMenu )
  283. -            {
  284. -                w = CW_USEDEFAULT;
  285. -                h = CW_USEDEFAULT;
  286. -            }
  287. -            else /* fail safe - Windows can make a window of size (0, 0) */
  288. -                w = h = 300; /* default window size */
  289. -            window->State.Width = window->State.Height = -1;
  290. -        }
  291. -        else
  292. -        {
  293. -            window->State.Width = worig;
  294. -            window->State.Height = horig;
  295. -        }
  296. -
  297.          /*
  298.           * There's a small difference between creating the top, child and
  299. -         * game mode windows
  300. +         * menu windows
  301.           */
  302. -        flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
  303. -
  304.          if ( window->IsMenu )
  305.          {
  306.              flags |= WS_POPUP;
  307.              exFlags |= WS_EX_TOOLWINDOW;
  308.          }
  309. -#if !defined(_WIN32_WCE)
  310. +#if defined(_WIN32_WCE)
  311. +        /* no decorations for windows CE */
  312. +#else
  313. +        /* if this is not a subwindow (child), set its style based on the requested display mode */
  314.          else if( window->Parent == NULL )
  315. -            flags |= WS_OVERLAPPEDWINDOW;
  316. +            if ( fgState.DisplayMode & GLUT_BORDERLESS )
  317. +            {
  318. +                /* no window decorations needed */
  319. +            }
  320. +            else if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
  321. +                /* only window decoration is a border, no title bar or buttons */
  322. +                flags |= WS_DLGFRAME;
  323. +            else
  324. +                /* window decoration are a border, title bar and buttons.
  325. +                 * NB: we later query whether the window has a title bar or
  326. +                 * not by testing for the maximize button, as the test for
  327. +                 * WS_CAPTION can be true without the window having a title
  328. +                 * bar. This style WS_OVERLAPPEDWINDOW gives you a maximize
  329. +                 * button. */
  330. +                flags |= WS_OVERLAPPEDWINDOW;
  331.  #endif
  332.          else
  333. +            /* subwindows always have no decoration, but are marked as a child window to the OS */
  334.              flags |= WS_CHILD;
  335.      }
  336.  
  337. +    /* determine window size and position */
  338. +    if( gameMode )
  339. +    {
  340. +        /* if in gamemode, query the origin of specified by the -display
  341. +         * parameter command line (if any) and offset the upper-left corner
  342. +         * of the window so we create the window on that screen.
  343. +         * The -display argument doesn't do anything if not trying to enter
  344. +         * gamemode.
  345. +         */
  346. +        int xoff=0, yoff=0;
  347. +        get_display_origin(&xoff,&yoff);
  348. +        x += xoff;
  349. +        y += yoff;
  350. +    }
  351. +    if( !positionUse )
  352. +    {
  353. +        x = CW_USEDEFAULT;
  354. +        y = CW_USEDEFAULT;
  355. +    }
  356. +    if( !sizeUse )
  357. +    {
  358. +        if( ! window->IsMenu )
  359. +        {
  360. +            w = CW_USEDEFAULT;
  361. +            h = CW_USEDEFAULT;
  362. +        }
  363. +        else /* fail safe - Windows can make a window of size (0, 0) */
  364. +            w = h = 300; /* default window size */
  365. +    }
  366. +    /* store requested client area width and height */
  367. +    window->State.Width = w;
  368. +    window->State.Height = h;
  369. +
  370. +#if !defined(_WIN32_WCE)    /* no decorations for windows CE */
  371. +    if( sizeUse )
  372. +    {
  373. +        RECT windowRect;
  374. +        /*
  375. +         * Update the window dimensions, taking the window decorations
  376. +         * into account.  FreeGLUT is to create the window with the
  377. +         * topleft outside corner at (x,y) and with client area
  378. +         * dimensions (w,h).
  379. +         * note: don't need to do this when w=h=CW_USEDEFAULT, so in the
  380. +         * if( sizeUse ) here is convenient.
  381. +         */
  382. +        windowRect.left     = x;
  383. +        windowRect.top      = y;
  384. +        windowRect.right    = x+w;
  385. +        windowRect.bottom   = y+h;
  386. +
  387. +        fghComputeWindowRectFromClientArea_UseStyle(flags,&windowRect,TRUE);
  388. +
  389. +        w = windowRect.right - windowRect.left;
  390. +        h = windowRect.bottom- windowRect.top;
  391. +    }
  392. +#endif /* !defined(_WIN32_WCE) */
  393. +
  394.  #if defined(_WIN32_WCE)
  395.      {
  396.          wchar_t* wstr = fghWstrFromStr(title);
  397. @@ -1246,29 +1445,28 @@
  398.  
  399.          UpdateWindow(window->Window.Handle);
  400.      }
  401.  #else
  402. -    {
  403. -      /* xoff and yoff are used to place window relative to current display */
  404. -      /* The operation of gamemode also depends on this */
  405. -        int xoff=0,yoff=0;
  406. -        get_display_origin(&xoff,&yoff);
  407. -
  408. -        window->Window.Handle = CreateWindowEx(
  409. -            exFlags,
  410. -            _T("FREEGLUT"),
  411. -            title,
  412. -            flags,
  413. -            x+xoff, y+yoff, w, h,
  414. -            (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
  415. -            (HMENU) NULL,
  416. -            fgDisplay.Instance,
  417. -            (LPVOID) window
  418. -        );
  419. -    }
  420. +    window->Window.Handle = CreateWindowEx(
  421. +        exFlags,
  422. +        _T("FREEGLUT"),
  423. +        title,
  424. +        flags,
  425. +        x, y, w, h,
  426. +        (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
  427. +        (HMENU) NULL,
  428. +        fgDisplay.Instance,
  429. +        (LPVOID) window
  430. +    );
  431.  #endif /* defined(_WIN32_WCE) */
  432.  
  433.      if( !( window->Window.Handle ) )
  434.          fgError( "Failed to create a window (%s)!", title );
  435.  
  436. +#if !defined(_WIN32_WCE)
  437. +    /* Need to set requested style again, apparently Windows doesn't listen when requesting windows without title bar or borders */
  438. +    SetWindowLong(window->Window.Handle, GWL_STYLE, flags);
  439. +    SetWindowPos(window->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
  440. +#endif /* defined(_WIN32_WCE) */
  441. +
  442.      /* Make a menu window always on top - fix Feature Request 947118 */
  443.      if( window->IsMenu || gameMode )
  444.          SetWindowPos(
  445. @@ -1278,23 +1476,6 @@
  446.  
  447.                          SWP_NOMOVE | SWP_NOSIZE
  448.                      );
  449.  
  450. -    /* Hack to remove the caption (title bar) and/or border
  451. -     * and all the system menu controls.
  452. -     */
  453. -    WindowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
  454. -    if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
  455. -    {
  456. -        SetWindowLong ( window->Window.Handle, GWL_STYLE,
  457. -                        WindowStyle & ~(WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
  458. -    }
  459. -    else if ( fgState.DisplayMode & GLUT_BORDERLESS )
  460. -    {
  461. -        SetWindowLong ( window->Window.Handle, GWL_STYLE,
  462. -                        WindowStyle & ~(WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_DLGFRAME | WS_SIZEBOX));
  463. -    }
  464. -/*  SetWindowPos(window->Window.Handle, NULL, 0, 0, 0, 0,
  465. -     SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); */
  466. -
  467.      /* Enable multitouch: additional flag TWF_FINETOUCH, TWF_WANTPALM */
  468.      #ifdef WM_TOUCH
  469.          if (fghRegisterTouchWindow == (pRegisterTouchWindow)0xDEADBEEF)
  470. @@ -1680,7 +1861,7 @@
  471.  
  472.      if (glutGet(GLUT_FULL_SCREEN))
  473.      {
  474.        /*  Leave full screen state before resizing. */
  475. -      glutFullScreenToggle();
  476. +      glutLeaveFullScreen();
  477.      }
  478.  
  479.      fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
  480. @@ -1699,7 +1880,7 @@
  481.  
  482.      if (glutGet(GLUT_FULL_SCREEN))
  483.      {
  484.        /*  Leave full screen state before moving. */
  485. -      glutFullScreenToggle();
  486. +      glutLeaveFullScreen();
  487.      }
  488.  
  489.  #if TARGET_HOST_POSIX_X11
  490. @@ -1799,34 +1980,51 @@
  491.  
  492.  
  493.      if (glutGet(GLUT_FULL_SCREEN))
  494.      {
  495. -        /*  Leave full screen state before resizing. */
  496. -        glutFullScreenToggle();
  497. +        /*  Leave full screen state before entering fullscreen again (resizing?) */
  498. +        glutLeaveFullScreen();
  499.      }
  500.  
  501.      {
  502. +        DWORD s;
  503.          RECT rect;
  504. +        HMONITOR hMonitor;
  505. +        MONITORINFO mi;
  506.  
  507. -        /* For fullscreen mode, force the top-left corner to 0,0
  508. -         * and adjust the window rectangle so that the client area
  509. -         * covers the whole screen.
  510. +        /* For fullscreen mode, first remove all window decoration
  511. +         * and set style to popup so it will overlap the taskbar
  512. +         * then force to maximize on the screen on which it has the most
  513. +         * overlap.
  514.           */
  515.  
  516. -        rect.left   = 0;
  517. -        rect.top    = 0;
  518. -       get_display_origin(&rect.left,&rect.top);
  519. -        rect.right  = fgDisplay.ScreenWidth+rect.left;
  520. -        rect.bottom = fgDisplay.ScreenHeight+rect.top;
  521. +        
  522. +        /* store current window rect */
  523. +        GetWindowRect( win->Window.Handle, &win->State.OldRect );
  524.  
  525. -        AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
  526. -                                  WS_CLIPCHILDREN, FALSE );
  527. +        /* store current window style */
  528. +        win->State.OldStyle = s = GetWindowLong(win->Window.Handle, GWL_STYLE);
  529.  
  530. +        /* remove decorations from style */
  531. +        s &= ~WS_OVERLAPPEDWINDOW;
  532. +        if (!win->Parent)
  533. +            s |= WS_POPUP;  // can't combine WS_POPUP with WS_CHILD
  534. +        SetWindowLong(win->Window.Handle, GWL_STYLE, s);
  535. +        SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
  536. +
  537. +        /* For fullscreen mode, find the monitor that is covered the most
  538. +         * by the window and get its rect as the resize target.
  539. +            */
  540. +        hMonitor= MonitorFromRect(&win->State.OldRect, MONITOR_DEFAULTTONEAREST);
  541. +        mi.cbSize = sizeof(mi);
  542. +        GetMonitorInfo(hMonitor, &mi);
  543. +        rect = mi.rcMonitor;
  544. +
  545.          /*
  546. +         * then resize window
  547.           * SWP_NOACTIVATE     Do not activate the window
  548.           * SWP_NOOWNERZORDER  Do not change position in z-order
  549. -         * SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message
  550. +         * SWP_NOSENDCHANGING Suppress WM_WINDOWPOSCHANGING message
  551.           * SWP_NOZORDER       Retains the current Z order (ignore 2nd param)
  552.           */
  553. -
  554.          SetWindowPos( fgStructure.CurrentWindow->Window.Handle,
  555.                        HWND_TOP,
  556.                        rect.left,
  557. @@ -1843,6 +2041,51 @@
  558.  
  559.  }
  560.  
  561.  /*
  562. + * If we are fullscreen, resize the current window back to its original size
  563. + */
  564. +void FGAPIENTRY glutLeaveFullScreen( void )
  565. +{
  566. +    SFG_Window *win;
  567. +
  568. +    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
  569. +    FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
  570. +
  571. +    win = fgStructure.CurrentWindow;
  572. +
  573. +#if TARGET_HOST_POSIX_X11
  574. +    if(glutGet(GLUT_FULL_SCREEN)) {
  575. +        if(fghToggleFullscreen() != -1) {
  576. +            win->State.IsFullscreen = GL_FALSE;
  577. +        }
  578. +    }
  579. +
  580. +#elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: what about WinCE */
  581. +    if (!glutGet(GLUT_FULL_SCREEN))
  582. +    {
  583. +        /* nothing to do */
  584. +        return;
  585. +    }
  586. +
  587. +    /* restore style of window before making it fullscreen */
  588. +    SetWindowLong(win->Window.Handle, GWL_STYLE, win->State.OldStyle);
  589. +    SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
  590. +
  591. +    /* Then resize */
  592. +    SetWindowPos(win->Window.Handle,
  593. +        HWND_TOP,
  594. +        win->State.OldRect.left,
  595. +        win->State.OldRect.top,
  596. +        win->State.OldRect.right  - win->State.OldRect.left,
  597. +        win->State.OldRect.bottom - win->State.OldRect.top,
  598. +        SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
  599. +        SWP_NOZORDER
  600. +        );
  601. +
  602. +    win->State.IsFullscreen = GL_FALSE;
  603. +#endif
  604. +}
  605. +
  606. +/*
  607.   * Toggle the window's full screen state.
  608.   */
  609.  void FGAPIENTRY glutFullScreenToggle( void )
  610. @@ -1859,8 +2102,10 @@
  611.  
  612.          win->State.IsFullscreen = !win->State.IsFullscreen;
  613.      }
  614.  #elif TARGET_HOST_MS_WINDOWS
  615. -    glutFullScreen();
  616. -    win->State.IsFullscreen = !win->State.IsFullscreen;
  617. +    if (!win->State.IsFullscreen)
  618. +        glutFullScreen();
  619. +    else
  620. +        glutLeaveFullScreen();
  621.  #endif
  622.  }
  623.  
  624. Index: src/freeglut_state.c
  625.  
  626. ===================================================================
  627.  
  628. --- src/freeglut_state.c        (revision 922)
  629.  
  630. +++ src/freeglut_state.c        (working copy)
  631.  
  632. @@ -64,16 +64,6 @@
  633.  
  634.  }
  635.  #endif
  636.  
  637. -/* Check if the window is in full screen state. */
  638. -static int fghCheckFullScreen(void)
  639. -{
  640. -#if TARGET_HOST_POSIX_X11
  641. -    return fgStructure.CurrentWindow->State.IsFullscreen;
  642. -#else
  643. -    return 0;
  644. -#endif
  645. -}
  646. -
  647.  /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
  648.  
  649.  /*
  650. @@ -458,26 +448,12 @@
  651.  
  652.  
  653.          freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
  654.  
  655. -        /*
  656. -         * We need to call GetWindowRect() first...
  657. -         *  (this returns the pixel coordinates of the outside of the window)
  658. -         */
  659. +#if defined(_WIN32_WCE)
  660.          GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
  661. +#else
  662. +        winRect = fghGetClientArea(fgStructure.CurrentWindow, FALSE);
  663. +#endif /* defined(_WIN32_WCE) */
  664.  
  665. -        /* ...then we've got to correct the results we've just received... */
  666. -
  667. -#if !defined(_WIN32_WCE)
  668. -        if ( ( fgStructure.GameModeWindow != fgStructure.CurrentWindow ) && ( fgStructure.CurrentWindow->Parent == NULL ) &&
  669. -             ( ! fgStructure.CurrentWindow->IsMenu ) &&
  670. -            !( fgState.DisplayMode & GLUT_BORDERLESS ))
  671. -        {
  672. -          winRect.left   += GetSystemMetrics( SM_CXSIZEFRAME );
  673. -          winRect.right  -= GetSystemMetrics( SM_CXSIZEFRAME );
  674. -          winRect.top    += GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION );
  675. -          winRect.bottom -= GetSystemMetrics( SM_CYSIZEFRAME );
  676. -        }
  677. -#endif /* !defined(_WIN32_WCE) */
  678. -
  679.          switch( eWhat )
  680.          {
  681.          case GLUT_WINDOW_X:      return winRect.left                ;
  682. @@ -489,21 +465,26 @@
  683.  
  684.      break;
  685.  
  686.      case GLUT_WINDOW_BORDER_WIDTH :
  687. -#if defined(_WIN32_WCE)
  688. -        return 0;
  689. -#else
  690. -       if ( fgState.DisplayMode & GLUT_BORDERLESS )
  691. -         return 0;
  692. -        return GetSystemMetrics( SM_CXSIZEFRAME );
  693. -#endif /* !defined(_WIN32_WCE) */
  694. -
  695.      case GLUT_WINDOW_HEADER_HEIGHT :
  696.  #if defined(_WIN32_WCE)
  697.          return 0;
  698.  #else
  699. -       if ( fgState.DisplayMode & GLUT_BORDERLESS )
  700. -         return 0;
  701. -        return GetSystemMetrics( SM_CYCAPTION );
  702. +        {
  703. +            DWORD windowStyle = GetWindowLong(fgStructure.CurrentWindow->Window.Handle, GWL_STYLE);
  704. +            
  705. +            switch( eWhat )
  706. +            {
  707. +            case GLUT_WINDOW_BORDER_WIDTH:
  708. +                {
  709. +                    int xBorderWidth, yBorderWidth;
  710. +                    fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
  711. +                    return xBorderWidth;
  712. +                }
  713. +            case GLUT_WINDOW_HEADER_HEIGHT:
  714. +                /* 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... */
  715. +                return (windowStyle & WS_MAXIMIZEBOX)? GetSystemMetrics( SM_CYCAPTION ) : 0;
  716. +            }
  717. +        }
  718.  #endif /* defined(_WIN32_WCE) */
  719.  
  720.      case GLUT_DISPLAY_MODE_POSSIBLE:
  721. @@ -559,7 +540,7 @@
  722.  
  723.          return fgState.DirectContext;
  724.  
  725.      case GLUT_FULL_SCREEN:
  726. -        return fghCheckFullScreen();
  727. +        return fgStructure.CurrentWindow->State.IsFullscreen;
  728.  
  729.      case GLUT_AUX:
  730.        return fgState.AuxiliaryBufferNumber;
  731. Index: src/freeglut_internal.h
  732.  
  733. ===================================================================
  734.  
  735. --- src/freeglut_internal.h     (revision 922)
  736.  
  737. +++ src/freeglut_internal.h     (working copy)
  738.  
  739. @@ -449,10 +449,16 @@
  740.  
  741.  typedef struct tagSFG_WindowState SFG_WindowState;
  742.  struct tagSFG_WindowState
  743.  {
  744. +    /* Note that on Windows, sizes always refer to the client area, thus without the window decorations */
  745.      int             Width;              /* Window's width in pixels          */
  746.      int             Height;             /* The same about the height         */
  747. +#if TARGET_HOST_POSIX_X11
  748.      int             OldWidth;           /* Window width from before a resize */
  749.      int             OldHeight;          /*   "    height  "    "    "   "    */
  750. +#elif TARGET_HOST_MS_WINDOWS
  751. +    RECT            OldRect;            /* window rect - stored before the window is made fullscreen */
  752. +    DWORD           OldStyle;           /* window style - stored before the window is made fullscreen */
  753. +#endif
  754.  
  755.      GLboolean       Redisplay;          /* Do we have to redisplay?          */
  756.      GLboolean       Visible;            /* Is the window visible now         */
  757. @@ -926,6 +932,17 @@
  758.  
  759.  void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
  760.                         SFG_Enumerator* enumerator );
  761.  
  762. +/*
  763. + * Helper functions for getting client area from the window rect
  764. + * and the window rect from the client area given the style of the window
  765. + * (or a valid window pointer from which the style can be queried).
  766. + */
  767. +void fghComputeWindowRectFromClientArea_UseStyle   ( const DWORD windowStyle , RECT *clientRect, BOOL posIsOutside );
  768. +void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside );
  769. +void fghComputeClientAreaFromWindowRect            ( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside );
  770. +RECT fghGetClientArea                              ( const SFG_Window *window,                   BOOL wantPosOutside );
  771. +void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth);
  772. +
  773.  /*
  774.   * fgWindowByHandle returns a (SFG_Window *) value pointing to the
  775.   * first window in the queue matching the specified window handle.
  776. Index: src/freeglut_main.c
  777.  
  778. ===================================================================
  779.  
  780. --- src/freeglut_main.c (revision 922)
  781.  
  782. +++ src/freeglut_main.c (working copy)
  783.  
  784. @@ -101,7 +101,6 @@
  785.  
  786.  
  787.      freeglut_return_if_fail( window != NULL );
  788.  
  789. -
  790.  #if TARGET_HOST_POSIX_X11
  791.  
  792.      XResizeWindow( fgDisplay.Display, window->Window.Handle,
  793. @@ -110,8 +109,7 @@
  794.  
  795.  
  796.  #elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
  797.      {
  798. -        RECT winRect;
  799. -        int x, y, w, h;
  800. +        RECT windowRect;
  801.  
  802.          /*
  803.           * For windowed mode, get the current position of the
  804. @@ -120,51 +118,43 @@
  805.  
  806.           */
  807.  
  808.          /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
  809. -        GetWindowRect( window->Window.Handle, &winRect );
  810. -        x = winRect.left;
  811. -        y = winRect.top;
  812. -        w = width;
  813. -        h = height;
  814. +        GetWindowRect( window->Window.Handle, &windowRect );
  815.  
  816. -        if ( window->Parent == NULL )
  817. -        {
  818. -          if ( ! window->IsMenu && (window != fgStructure.GameModeWindow) &&
  819. -              !( fgState.DisplayMode & GLUT_BORDERLESS ))
  820. -            {
  821. -                w += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
  822. -                h += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 +
  823. -                     GetSystemMetrics( SM_CYCAPTION );
  824. -            }
  825. -        }
  826. +        /* Create rect in FreeGLUT format, (X,Y) topleft outside window, WxH of client area */
  827. +        windowRect.right    = windowRect.left+width;
  828. +        windowRect.bottom   = windowRect.top+height;
  829. +
  830. +        if (window->Parent == NULL)
  831. +            /* get the window rect from this to feed to SetWindowPos, correct for window decorations */
  832. +            fghComputeWindowRectFromClientArea_QueryWindow(window,&windowRect,TRUE);
  833.          else
  834.          {
  835. +            /* correct rect for position client area of parent window
  836. +             * (SetWindowPos input for child windows is in coordinates
  837. +             * relative to the parent's client area).
  838. +             * Child windows don't have decoration, so no need to correct
  839. +             * for them.
  840. +             */
  841.              RECT parentRect;
  842. -            GetWindowRect( window->Parent->Window.Handle, &parentRect );
  843. -            x -= parentRect.left + GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
  844. -            y -= parentRect.top  + GetSystemMetrics( SM_CYSIZEFRAME ) * 2 +
  845. -                                   GetSystemMetrics( SM_CYCAPTION );
  846. +            parentRect = fghGetClientArea( window->Parent, FALSE );
  847. +            windowRect.left   -= parentRect.left;
  848. +            windowRect.right  -= parentRect.left;
  849. +            windowRect.top    -= parentRect.top;
  850. +            windowRect.bottom -= parentRect.top;
  851.          }
  852. -
  853. -        /*
  854. -         * SWP_NOACTIVATE      Do not activate the window
  855. -         * SWP_NOOWNERZORDER   Do not change position in z-order
  856. -         * SWP_NOSENDCHANGING  Supress WM_WINDOWPOSCHANGING message
  857. -         * SWP_NOZORDER        Retains the current Z order (ignore 2nd param)
  858. -         */
  859. -
  860. +        
  861. +        /* Do the actual resizing */
  862.          SetWindowPos( window->Window.Handle,
  863.                        HWND_TOP,
  864. -                      x, y, w, h,
  865. +                      windowRect.left, windowRect.top,
  866. +                      windowRect.right - windowRect.left,
  867. +                      windowRect.bottom- windowRect.top,
  868.                        SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
  869.                        SWP_NOZORDER
  870.          );
  871.      }
  872.  #endif
  873.  
  874. -    /*
  875. -     * XXX Should update {window->State.OldWidth, window->State.OldHeight}
  876. -     * XXX to keep in lockstep with POSIX_X11 code.
  877. -     */
  878.      if( FETCH_WCB( *window, Reshape ) )
  879.          INVOKE_WCB( *window, Reshape, ( width, height ) );
  880.      else
  881. @@ -233,6 +223,7 @@
  882.  
  883.  #if TARGET_HOST_POSIX_X11
  884.          fghRedrawWindow ( window ) ;
  885.  #elif TARGET_HOST_MS_WINDOWS
  886. +
  887.          RedrawWindow(
  888.              window->Window.Handle, NULL, NULL,
  889.              RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW
  890. @@ -1797,6 +1788,10 @@
  891.  
  892.          }
  893.  
  894.          window->State.NeedToResize = GL_TRUE;
  895. +        /* if we used CW_USEDEFAULT (thats a negative value) for the size
  896. +         * of the window, query the window now for the size at which it
  897. +         * was created.
  898. +         */
  899.          if( ( window->State.Width < 0 ) || ( window->State.Height < 0 ) )
  900.          {
  901.              SFG_Window *current_window = fgStructure.CurrentWindow;
  902. Index: src/freeglutdll.def
  903.  
  904. ===================================================================
  905.  
  906. --- src/freeglutdll.def (revision 922)
  907.  
  908. +++ src/freeglutdll.def (working copy)
  909.  
  910. @@ -139,6 +139,7 @@
  911.  
  912.         glutGetProcAddress
  913.         glutExit
  914.         glutFullScreenToggle
  915. +       glutLeaveFullScreen
  916.         glutGetModeValues
  917.         glutInitContextFlags
  918.         glutInitContextVersion
  919. Index: src/freeglut_ext.c
  920.  
  921. ===================================================================
  922.  
  923. --- src/freeglut_ext.c  (revision 922)
  924.  
  925. +++ src/freeglut_ext.c  (working copy)
  926.  
  927. @@ -166,6 +166,7 @@
  928.  
  929.      CHECK_NAME(glutWMCloseFunc);
  930.      CHECK_NAME(glutMenuDestroyFunc);
  931.      CHECK_NAME(glutFullScreenToggle);
  932. +    CHECK_NAME(glutLeaveFullScreen);
  933.      CHECK_NAME(glutSetOption);
  934.      CHECK_NAME(glutGetModeValues);
  935.      CHECK_NAME(glutSetWindowData);
  936. Index: src/freeglut_structure.c
  937.  
  938. ===================================================================
  939.  
  940. --- src/freeglut_structure.c    (revision 922)
  941.  
  942. +++ src/freeglut_structure.c    (working copy)
  943.  
  944. @@ -79,7 +79,9 @@
  945.  
  946.  
  947.      /* Initialize the object properties */
  948.      window->ID = ++fgStructure.WindowID;
  949. +#if TARGET_HOST_POSIX_X11
  950.      window->State.OldHeight = window->State.OldWidth = -1;
  951. +#endif
  952.  
  953.      fgListInit( &window->Children );
  954.      if( parent )