freeglut_window.c
上传用户:gb3593
上传日期:2022-01-07
资源大小:3028k
文件大小:52k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /*
  2.  * freeglut_window.c
  3.  *
  4.  * Window management methods.
  5.  *
  6.  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
  7.  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
  8.  * Creation date: Fri Dec 3 1999
  9.  *
  10.  * Permission is hereby granted, free of charge, to any person obtaining a
  11.  * copy of this software and associated documentation files (the "Software"),
  12.  * to deal in the Software without restriction, including without limitation
  13.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  14.  * and/or sell copies of the Software, and to permit persons to whom the
  15.  * Software is furnished to do so, subject to the following conditions:
  16.  *
  17.  * The above copyright notice and this permission notice shall be included
  18.  * in all copies or substantial portions of the Software.
  19.  *
  20.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  21.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  23.  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  24.  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  25.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26.  */
  27. #define FREEGLUT_BUILDING_LIB
  28. #include <GL/freeglut.h>
  29. #include "freeglut_internal.h"
  30. #if TARGET_HOST_POSIX_X11
  31. #include <limits.h>  /* LONG_MAX */
  32. #endif
  33. #if defined(_WIN32_WCE)
  34. #   include <Aygshell.h>
  35. #   ifdef FREEGLUT_LIB_PRAGMAS
  36. #       pragma comment( lib, "Aygshell.lib" )
  37. #   endif
  38. static wchar_t* fghWstrFromStr(const char* str)
  39. {
  40.     int i,len=strlen(str);
  41.     wchar_t* wstr = (wchar_t*)malloc(2*len+2);
  42.     for(i=0; i<len; i++)
  43.         wstr[i] = str[i];
  44.     wstr[len] = 0;
  45.     return wstr;
  46. }
  47. #endif /* defined(_WIN32_WCE) */
  48. /* pushing attribute/value pairs into an array */
  49. #define ATTRIB(a) attributes[where++]=(a)
  50. #define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);}
  51. /*
  52.  * TODO BEFORE THE STABLE RELEASE:
  53.  *
  54.  *  fgChooseFBConfig()      -- OK, but what about glutInitDisplayString()?
  55.  *  fgSetupPixelFormat      -- ignores the display mode settings
  56.  *  fgOpenWindow()          -- check the Win32 version, -iconic handling!
  57.  *  fgCloseWindow()         -- check the Win32 version
  58.  *  glutCreateWindow()      -- Check when default position and size is {-1,-1}
  59.  *  glutCreateSubWindow()   -- Check when default position and size is {-1,-1}
  60.  *  glutDestroyWindow()     -- check the Win32 version
  61.  *  glutSetWindow()         -- check the Win32 version
  62.  *  glutGetWindow()         -- OK
  63.  *  glutSetWindowTitle()    -- check the Win32 version
  64.  *  glutSetIconTitle()      -- check the Win32 version
  65.  *  glutShowWindow()        -- check the Win32 version
  66.  *  glutHideWindow()        -- check the Win32 version
  67.  *  glutIconifyWindow()     -- check the Win32 version
  68.  *  glutReshapeWindow()     -- check the Win32 version
  69.  *  glutPositionWindow()    -- check the Win32 version
  70.  *  glutPushWindow()        -- check the Win32 version
  71.  *  glutPopWindow()         -- check the Win32 version
  72.  */
  73. /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
  74. static int fghIsLegacyContextVersionRequested( void )
  75. {
  76.   return fgState.MajorVersion == 1 && fgState.MinorVersion == 0;
  77. }
  78. static int fghIsLegacyContextRequested( void )
  79. {
  80.   return fghIsLegacyContextVersionRequested() &&
  81.          fgState.ContextFlags == 0 &&
  82.          fgState.ContextProfile == 0;
  83. }
  84. static int fghNumberOfAuxBuffersRequested( void )
  85. {
  86.   if ( fgState.DisplayMode & GLUT_AUX4 ) {
  87.     return 4;
  88.   }
  89.   if ( fgState.DisplayMode & GLUT_AUX3 ) {
  90.     return 3;
  91.   }
  92.   if ( fgState.DisplayMode & GLUT_AUX2 ) {
  93.     return 2;
  94.   }
  95.   if ( fgState.DisplayMode & GLUT_AUX1 ) { /* NOTE: Same as GLUT_AUX! */
  96.     return fgState.AuxiliaryBufferNumber;
  97.   }
  98.   return 0;
  99. }
  100. static int fghMapBit( int mask, int from, int to )
  101. {
  102.   return ( mask & from ) ? to : 0;
  103. }
  104. static void fghContextCreationError( void )
  105. {
  106.     fgError( "Unable to create OpenGL %d.%d context (flags %x, profile %x)",
  107.              fgState.MajorVersion, fgState.MinorVersion, fgState.ContextFlags,
  108.              fgState.ContextProfile );
  109. }
  110. /*
  111.  * Chooses a visual basing on the current display mode settings
  112.  */
  113. #if TARGET_HOST_POSIX_X11
  114. #ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
  115. #define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
  116. #endif
  117. GLXFBConfig* fgChooseFBConfig( void )
  118. {
  119.   GLboolean wantIndexedMode = GL_FALSE;
  120.   int attributes[ 100 ];
  121.   int where = 0, numAuxBuffers;
  122.   /* First we have to process the display mode settings... */
  123.   if( fgState.DisplayMode & GLUT_INDEX ) {
  124.     ATTRIB_VAL( GLX_BUFFER_SIZE, 8 );
  125.     /*  Buffer size is selected later.  */
  126.     ATTRIB_VAL( GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT );
  127.     wantIndexedMode = GL_TRUE;
  128.   } else {
  129.     ATTRIB_VAL( GLX_RED_SIZE,   1 );
  130.     ATTRIB_VAL( GLX_GREEN_SIZE, 1 );
  131.     ATTRIB_VAL( GLX_BLUE_SIZE,  1 );
  132.     if( fgState.DisplayMode & GLUT_ALPHA ) {
  133.       ATTRIB_VAL( GLX_ALPHA_SIZE, 1 );
  134.     }
  135.   }
  136.   if( fgState.DisplayMode & GLUT_DOUBLE ) {
  137.     ATTRIB_VAL( GLX_DOUBLEBUFFER, True );
  138.   }
  139.   if( fgState.DisplayMode & GLUT_STEREO ) {
  140.     ATTRIB_VAL( GLX_STEREO, True );
  141.   }
  142.   if( fgState.DisplayMode & GLUT_DEPTH ) {
  143.     ATTRIB_VAL( GLX_DEPTH_SIZE, 1 );
  144.   }
  145.   if( fgState.DisplayMode & GLUT_STENCIL ) {
  146.     ATTRIB_VAL( GLX_STENCIL_SIZE, 1 );
  147.   }
  148.   if( fgState.DisplayMode & GLUT_ACCUM ) {
  149.     ATTRIB_VAL( GLX_ACCUM_RED_SIZE, 1 );
  150.     ATTRIB_VAL( GLX_ACCUM_GREEN_SIZE, 1 );
  151.     ATTRIB_VAL( GLX_ACCUM_BLUE_SIZE, 1 );
  152.     if( fgState.DisplayMode & GLUT_ALPHA ) {
  153.       ATTRIB_VAL( GLX_ACCUM_ALPHA_SIZE, 1 );
  154.     }
  155.   }
  156.   numAuxBuffers = fghNumberOfAuxBuffersRequested();
  157.   if ( numAuxBuffers > 0 ) {
  158.     ATTRIB_VAL( GLX_AUX_BUFFERS, numAuxBuffers );
  159.   }
  160.   if( fgState.DisplayMode & GLUT_SRGB ) {
  161.     ATTRIB_VAL( GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, True );
  162.   }
  163.   if (fgState.DisplayMode & GLUT_MULTISAMPLE) {
  164.     ATTRIB_VAL(GLX_SAMPLE_BUFFERS, 1);
  165.     ATTRIB_VAL(GLX_SAMPLES, fgState.SampleNumber);
  166.   }
  167.   /* Push a terminator at the end of the list */
  168.   ATTRIB( None );
  169.     {
  170.         GLXFBConfig * fbconfigArray;  /*  Array of FBConfigs  */
  171.         GLXFBConfig * fbconfig;       /*  The FBConfig we want  */
  172.         int fbconfigArraySize;        /*  Number of FBConfigs in the array  */
  173.         /*  Get all FBConfigs that match "attributes".  */
  174.         fbconfigArray = glXChooseFBConfig( fgDisplay.Display,
  175.                                            fgDisplay.Screen,
  176.                                            attributes,
  177.                                            &fbconfigArraySize );
  178.         if (fbconfigArray != NULL)
  179.         {
  180.             int result;  /* Returned by glXGetFBConfigAttrib, not checked. */
  181.             if( wantIndexedMode )
  182.             {
  183.                 /*
  184.                  * In index mode, we want the largest buffer size, i.e. visual
  185.                  * depth.  Here, FBConfigs are sorted by increasing buffer size
  186.                  * first, so FBConfigs with the largest size come last.
  187.                  */
  188.                 int bufferSizeMin, bufferSizeMax;
  189.                 /*  Get bufferSizeMin.  */
  190.                 result =
  191.                   glXGetFBConfigAttrib( fgDisplay.Display,
  192.                                         fbconfigArray[0],
  193.                                         GLX_BUFFER_SIZE,
  194.                                         &bufferSizeMin );
  195.                 /*  Get bufferSizeMax.  */
  196.                 result =
  197.                   glXGetFBConfigAttrib( fgDisplay.Display,
  198.                                         fbconfigArray[fbconfigArraySize - 1],
  199.                                         GLX_BUFFER_SIZE,
  200.                                         &bufferSizeMax );
  201.                 if (bufferSizeMax > bufferSizeMin)
  202.                 {
  203.                     /* 
  204.                      * Free and reallocate fbconfigArray, keeping only FBConfigs
  205.                      * with the largest buffer size.
  206.                      */
  207.                     XFree(fbconfigArray);
  208.                     /*  Add buffer size token at the end of the list.  */
  209.                     where--;
  210.                     ATTRIB_VAL( GLX_BUFFER_SIZE, bufferSizeMax );
  211.                     ATTRIB( None );
  212.                     fbconfigArray = glXChooseFBConfig( fgDisplay.Display,
  213.                                                        fgDisplay.Screen,
  214.                                                        attributes,
  215.                                                        &fbconfigArraySize );
  216.                 }
  217.             }
  218.             /*
  219.              * We now have an array of FBConfigs, the first one being the "best"
  220.              * one.  So we should return only this FBConfig:
  221.              *
  222.              * int fbconfigXID;
  223.              *
  224.              *  - pick the XID of the FBConfig we want
  225.              * result = glXGetFBConfigAttrib( fgDisplay.Display,
  226.              *                                fbconfigArray[0],
  227.              *                                GLX_FBCONFIG_ID,
  228.              *                                &fbconfigXID );
  229.              *
  230.              * - free the array
  231.              * XFree(fbconfigArray);
  232.              *
  233.              * - reset "attributes" with the XID
  234.              * where = 0;
  235.              * ATTRIB_VAL( GLX_FBCONFIG_ID, fbconfigXID );
  236.              * ATTRIB( None );
  237.              *
  238.              * - get our FBConfig only
  239.              * fbconfig = glXChooseFBConfig( fgDisplay.Display,
  240.              *                               fgDisplay.Screen,
  241.              *                               attributes,
  242.              *                               &fbconfigArraySize );
  243.              *
  244.              * However, for some configurations (for instance multisampling with
  245.              * Mesa 6.5.2 and ATI drivers), this does not work:
  246.              * glXChooseFBConfig returns NULL, whereas fbconfigXID is a valid
  247.              * XID.  Further investigation is needed.
  248.              *
  249.              * So, for now, we return the whole array of FBConfigs.  This should
  250.              * not produce any side effects elsewhere.
  251.              */
  252.             fbconfig = fbconfigArray;
  253.         }
  254.         else
  255.         {
  256.            fbconfig = NULL;
  257.         }
  258.         return fbconfig;
  259.     }
  260. }
  261. #endif /* TARGET_HOST_POSIX_X11 */
  262. /*
  263.  * Setup the pixel format for a Win32 window
  264.  */
  265. #if TARGET_HOST_MS_WINDOWS
  266. /* The following include file is available from SGI but is not standard:
  267.  *   #include <GL/wglext.h>
  268.  * So we copy the necessary parts out of it.
  269.  * XXX: should local definitions for extensions be put in a separate include file?
  270.  */
  271. typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
  272. typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
  273. #define WGL_DRAW_TO_WINDOW_ARB         0x2001
  274. #define WGL_ACCELERATION_ARB           0x2003
  275. #define WGL_SUPPORT_OPENGL_ARB         0x2010
  276. #define WGL_DOUBLE_BUFFER_ARB          0x2011
  277. #define WGL_COLOR_BITS_ARB             0x2014
  278. #define WGL_ALPHA_BITS_ARB             0x201B
  279. #define WGL_DEPTH_BITS_ARB             0x2022
  280. #define WGL_STENCIL_BITS_ARB           0x2023
  281. #define WGL_FULL_ACCELERATION_ARB      0x2027
  282. #define WGL_SAMPLE_BUFFERS_ARB         0x2041
  283. #define WGL_SAMPLES_ARB                0x2042
  284. #define WGL_TYPE_RGBA_FLOAT_ARB        0x21A0
  285. #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
  286. #ifndef WGL_ARB_create_context
  287. #define WGL_ARB_create_context 1
  288. #ifdef WGL_WGLEXT_PROTOTYPES
  289. extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *);
  290. #endif /* WGL_WGLEXT_PROTOTYPES */
  291. typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
  292. #define WGL_CONTEXT_MAJOR_VERSION_ARB  0x2091
  293. #define WGL_CONTEXT_MINOR_VERSION_ARB  0x2092
  294. #define WGL_CONTEXT_LAYER_PLANE_ARB    0x2093
  295. #define WGL_CONTEXT_FLAGS_ARB          0x2094
  296. #define WGL_CONTEXT_PROFILE_MASK_ARB   0x9126
  297. #define WGL_CONTEXT_DEBUG_BIT_ARB      0x0001
  298. #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
  299. #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
  300. #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
  301. #define ERROR_INVALID_VERSION_ARB      0x2095
  302. #define ERROR_INVALID_PROFILE_ARB      0x2096
  303. #endif
  304. static void fghFillContextAttributes( int *attributes ) {
  305.   int where = 0, contextFlags, contextProfile;
  306.   if ( !fghIsLegacyContextVersionRequested() ) {
  307.     ATTRIB_VAL( WGL_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
  308.     ATTRIB_VAL( WGL_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
  309.   }
  310.   contextFlags =
  311.     fghMapBit( fgState.ContextFlags, GLUT_DEBUG, WGL_CONTEXT_DEBUG_BIT_ARB ) |
  312.     fghMapBit( fgState.ContextFlags, GLUT_FORWARD_COMPATIBLE, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB );
  313.   if ( contextFlags != 0 ) {
  314.     ATTRIB_VAL( WGL_CONTEXT_FLAGS_ARB, contextFlags );
  315.   }
  316.   contextProfile =
  317.     fghMapBit( fgState.ContextProfile, GLUT_CORE_PROFILE, WGL_CONTEXT_CORE_PROFILE_BIT_ARB ) |
  318.     fghMapBit( fgState.ContextProfile, GLUT_COMPATIBILITY_PROFILE, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB );
  319.   if ( contextProfile != 0 ) {
  320.     ATTRIB_VAL( WGL_CONTEXT_PROFILE_MASK_ARB, contextProfile );
  321.   }
  322.   ATTRIB( 0 );
  323. }
  324. static int fghIsExtensionSupported( HDC hdc, const char *extension ) {
  325.     const char *pWglExtString;
  326.     PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetEntensionsStringARB =
  327.       (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
  328.     if ( wglGetEntensionsStringARB == NULL )
  329.     {
  330.       return FALSE;
  331.     }
  332.     pWglExtString = wglGetEntensionsStringARB( hdc );
  333.     return ( pWglExtString != NULL ) && ( strstr(pWglExtString, extension) != NULL );
  334. }
  335. void fgNewWGLCreateContext( SFG_Window* window )
  336. {
  337.     HGLRC context;
  338.     int attributes[9];
  339.     PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
  340.     /* If nothing fancy has been required, leave the context as it is */
  341.     if ( fghIsLegacyContextRequested() )
  342.     {
  343.         return;
  344.     }
  345.     wglMakeCurrent( window->Window.Device, window->Window.Context );
  346.     if ( !fghIsExtensionSupported( window->Window.Device, "WGL_ARB_create_context" ) )
  347.     {
  348.         return;
  349.     }
  350.     /* new context creation */
  351.     fghFillContextAttributes( attributes );
  352.     wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress( "wglCreateContextAttribsARB" );
  353.     if ( wglCreateContextAttribsARB == NULL )
  354.     {
  355.         fgError( "wglCreateContextAttribsARB not found" );
  356.     }
  357.     context = wglCreateContextAttribsARB( window->Window.Device, 0, attributes );
  358.     if ( context == NULL )
  359.     {
  360.         fghContextCreationError();
  361.     }
  362.     wglMakeCurrent( NULL, NULL );
  363.     wglDeleteContext( window->Window.Context );
  364.     window->Window.Context = context;
  365. }
  366. #if !defined(_WIN32_WCE)
  367. static void fghFillPFD( PIXELFORMATDESCRIPTOR *ppfd, HDC hdc, unsigned char layer_type )
  368. {
  369.   int flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
  370.   if ( fgState.DisplayMode & GLUT_DOUBLE ) {
  371.         flags |= PFD_DOUBLEBUFFER;
  372.   }
  373.   if ( fgState.DisplayMode & GLUT_STEREO ) {
  374.     flags |= PFD_STEREO;
  375.   }
  376. #if defined(_MSC_VER)
  377. #pragma message( "fgSetupPixelFormat(): there is still some work to do here!" )
  378. #endif
  379.   /* Specify which pixel format do we opt for... */
  380.   ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
  381.   ppfd->nVersion = 1;
  382.   ppfd->dwFlags = flags;
  383.   if( fgState.DisplayMode & GLUT_INDEX ) {
  384.     ppfd->iPixelType = PFD_TYPE_COLORINDEX;
  385.     ppfd->cRedBits = 0;
  386.     ppfd->cGreenBits = 0;
  387.     ppfd->cBlueBits = 0;
  388.     ppfd->cAlphaBits = 0;
  389.   } else {
  390.     ppfd->iPixelType = PFD_TYPE_RGBA;
  391.     ppfd->cRedBits = 8;
  392.     ppfd->cGreenBits = 8;
  393.     ppfd->cBlueBits = 8;
  394.     ppfd->cAlphaBits = ( fgState.DisplayMode & GLUT_ALPHA ) ? 8 : 0;
  395.   }
  396.   ppfd->cColorBits = 24;
  397.   ppfd->cRedShift = 0;
  398.   ppfd->cGreenShift = 0;
  399.   ppfd->cBlueShift = 0;
  400.   ppfd->cAlphaShift = 0;
  401.   ppfd->cAccumBits = 0;
  402.   ppfd->cAccumRedBits = 0;
  403.   ppfd->cAccumGreenBits = 0;
  404.   ppfd->cAccumBlueBits = 0;
  405.   ppfd->cAccumAlphaBits = 0;
  406.   /* Hmmm, or 32/0 instead of 24/8? */
  407.   ppfd->cDepthBits = 24;
  408.   ppfd->cStencilBits = 8;
  409.   ppfd->cAuxBuffers = fghNumberOfAuxBuffersRequested();
  410.   ppfd->iLayerType = layer_type;
  411.   ppfd->bReserved = 0;
  412.   ppfd->dwLayerMask = 0;
  413.   ppfd->dwVisibleMask = 0;
  414.   ppfd->dwDamageMask = 0;
  415.   
  416.   ppfd->cColorBits = (BYTE) GetDeviceCaps( hdc, BITSPIXEL );
  417. }
  418. static void fghFillPixelFormatAttributes( int *attributes, const PIXELFORMATDESCRIPTOR *ppfd )
  419. {
  420.   int where = 0;
  421.   ATTRIB_VAL( WGL_DRAW_TO_WINDOW_ARB, GL_TRUE );
  422.   ATTRIB_VAL( WGL_SUPPORT_OPENGL_ARB, GL_TRUE );
  423.   ATTRIB_VAL( WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB );
  424.   ATTRIB_VAL( WGL_COLOR_BITS_ARB, ppfd->cColorBits );
  425.   ATTRIB_VAL( WGL_ALPHA_BITS_ARB, ppfd->cAlphaBits );
  426.   ATTRIB_VAL( WGL_DEPTH_BITS_ARB, ppfd->cDepthBits );
  427.   ATTRIB_VAL( WGL_STENCIL_BITS_ARB, ppfd->cStencilBits );
  428.   ATTRIB_VAL( WGL_DOUBLE_BUFFER_ARB, ( fgState.DisplayMode & GLUT_DOUBLE ) != 0 );
  429.   if ( fgState.DisplayMode & GLUT_SRGB ) {
  430.     ATTRIB_VAL( WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, TRUE );
  431.   }
  432.   ATTRIB_VAL( WGL_SAMPLE_BUFFERS_ARB, GL_TRUE );
  433.   ATTRIB_VAL( WGL_SAMPLES_ARB, fgState.SampleNumber );
  434.   ATTRIB( 0 );
  435. }
  436. #endif
  437. GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
  438.                               unsigned char layer_type )
  439. {
  440. #if defined(_WIN32_WCE)
  441.     return GL_TRUE;
  442. #else
  443.     PIXELFORMATDESCRIPTOR pfd;
  444.     PIXELFORMATDESCRIPTOR* ppfd = &pfd;
  445.     int pixelformat;
  446.     fghFillPFD( ppfd, window->Window.Device, layer_type );
  447.     pixelformat = ChoosePixelFormat( window->Window.Device, ppfd );
  448.     /* windows hack for multismapling/sRGB */
  449.     if ( ( fgState.DisplayMode & GLUT_MULTISAMPLE ) ||
  450.          ( fgState.DisplayMode & GLUT_SRGB ) )
  451.     {        
  452.         HGLRC rc, rc_before=wglGetCurrentContext();
  453.         HWND hWnd;
  454.         HDC hDC, hDC_before=wglGetCurrentDC();
  455.         WNDCLASS wndCls;
  456.         /* create a dummy window */
  457.         ZeroMemory(&wndCls, sizeof(wndCls));
  458.         wndCls.lpfnWndProc = DefWindowProc;
  459.         wndCls.hInstance = fgDisplay.Instance;
  460.         wndCls.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  461.         wndCls.lpszClassName = _T("FREEGLUT_dummy");
  462.         RegisterClass( &wndCls );
  463.         hWnd=CreateWindow(_T("FREEGLUT_dummy"), _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW , 0,0,0,0, 0, 0, fgDisplay.Instance, 0 );
  464.         hDC=GetDC(hWnd);
  465.         SetPixelFormat( hDC, pixelformat, ppfd );
  466.         
  467.         rc = wglCreateContext( hDC );
  468.         wglMakeCurrent(hDC, rc);
  469.         
  470.         if ( fghIsExtensionSupported( hDC, "WGL_ARB_multisample" ) )
  471.         {
  472.             PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARBProc =
  473.               (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB");
  474.             if ( wglChoosePixelFormatARBProc )
  475.             {
  476.                 int attributes[100];
  477.                 int iPixelFormat;
  478.                 BOOL bValid;
  479.                 float fAttributes[] = { 0, 0 };
  480.                 UINT numFormats;
  481.                 fghFillPixelFormatAttributes( attributes, ppfd );
  482.                 bValid = wglChoosePixelFormatARBProc(window->Window.Device, attributes, fAttributes, 1, &iPixelFormat, &numFormats);
  483.                 if ( bValid && numFormats > 0 )
  484.                 {
  485.                     pixelformat = iPixelFormat;
  486.                 }
  487.             }
  488.         }
  489.         wglMakeCurrent( hDC_before, rc_before);
  490.         wglDeleteContext(rc);
  491.         ReleaseDC(hWnd, hDC);
  492.         DestroyWindow(hWnd);
  493.         UnregisterClass(_T("FREEGLUT_dummy"), fgDisplay.Instance);
  494.     }
  495.     return ( pixelformat != 0 ) && ( checkOnly || SetPixelFormat( window->Window.Device, pixelformat, ppfd ) );
  496. #endif /* defined(_WIN32_WCE) */
  497. }
  498. #endif /* TARGET_HOST_MS_WINDOWS */
  499. /*
  500.  * Sets the OpenGL context and the fgStructure "Current Window" pointer to
  501.  * the window structure passed in.
  502.  */
  503. void fgSetWindow ( SFG_Window *window )
  504. {
  505. #if TARGET_HOST_POSIX_X11
  506.     if ( window )
  507.     {
  508.         glXMakeContextCurrent(
  509.             fgDisplay.Display,
  510.             window->Window.Handle,
  511.             window->Window.Handle,
  512.             window->Window.Context
  513.         );
  514.         /* also register this window to receive spaceball events */
  515.         fgSpaceballSetWindow(window);
  516.     }
  517. #elif TARGET_HOST_MS_WINDOWS
  518.     if( fgStructure.CurrentWindow )
  519.         ReleaseDC( fgStructure.CurrentWindow->Window.Handle,
  520.                    fgStructure.CurrentWindow->Window.Device );
  521.     if ( window )
  522.     {
  523.         window->Window.Device = GetDC( window->Window.Handle );
  524.         wglMakeCurrent(
  525.             window->Window.Device,
  526.             window->Window.Context
  527.         );
  528.     }
  529. #endif
  530.     fgStructure.CurrentWindow = window;
  531. }
  532. #if TARGET_HOST_POSIX_X11
  533. #ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
  534. #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
  535. #endif
  536. #ifndef GLX_CONTEXT_MINOR_VERSION_ARB
  537. #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
  538. #endif
  539. #ifndef GLX_CONTEXT_FLAGS_ARB
  540. #define GLX_CONTEXT_FLAGS_ARB 0x2094
  541. #endif
  542. #ifndef GLX_CONTEXT_PROFILE_MASK_ARB
  543. #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
  544. #endif
  545. #ifndef GLX_CONTEXT_DEBUG_BIT_ARB
  546. #define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
  547. #endif
  548. #ifndef GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
  549. #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
  550. #endif
  551. #ifndef GLX_CONTEXT_CORE_PROFILE_BIT_ARB
  552. #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
  553. #endif
  554. #ifndef GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
  555. #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
  556. #endif
  557. #ifndef GLX_RGBA_FLOAT_TYPE
  558. #define GLX_RGBA_FLOAT_TYPE 0x20B9
  559. #endif
  560. #ifndef GLX_RGBA_FLOAT_BIT
  561. #define GLX_RGBA_FLOAT_BIT 0x00000004
  562. #endif
  563. static void fghFillContextAttributes( int *attributes ) {
  564.   int where = 0, contextFlags, contextProfile;
  565.   if ( !fghIsLegacyContextVersionRequested() ) {
  566.     ATTRIB_VAL( GLX_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
  567.     ATTRIB_VAL( GLX_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
  568.   }
  569.   contextFlags =
  570.     fghMapBit( fgState.ContextFlags, GLUT_DEBUG, GLX_CONTEXT_DEBUG_BIT_ARB ) |
  571.     fghMapBit( fgState.ContextFlags, GLUT_FORWARD_COMPATIBLE, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB );
  572.   if ( contextFlags != 0 ) {
  573.     ATTRIB_VAL( GLX_CONTEXT_FLAGS_ARB, contextFlags );
  574.   }
  575.   contextProfile =
  576.     fghMapBit( fgState.ContextProfile, GLUT_CORE_PROFILE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB ) |
  577.     fghMapBit( fgState.ContextProfile, GLUT_COMPATIBILITY_PROFILE, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB );
  578.   if ( contextProfile != 0 ) {
  579.     ATTRIB_VAL( GLX_CONTEXT_PROFILE_MASK_ARB, contextProfile );
  580.   }
  581.   ATTRIB( 0 );
  582. }
  583. typedef GLXContext (*CreateContextAttribsProc)(Display *dpy, GLXFBConfig config,
  584.        GLXContext share_list, Bool direct,
  585.        const int *attrib_list);
  586. static GLXContext fghCreateNewContext( SFG_Window* window )
  587. {
  588.   /* for color model calculation */
  589.   int menu = ( window->IsMenu && !fgStructure.MenuContext );
  590.   int index_mode = ( fgState.DisplayMode & GLUT_INDEX );
  591.   /* "classic" context creation */
  592.   Display *dpy = fgDisplay.Display;
  593.   GLXFBConfig config = *(window->Window.FBConfig);
  594.   int render_type = ( !menu && index_mode ) ? GLX_COLOR_INDEX_TYPE : GLX_RGBA_TYPE;
  595.   GLXContext share_list = NULL;
  596.   Bool direct = ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT );
  597.   GLXContext context;
  598.   /* new context creation */
  599.   int attributes[9];
  600.   CreateContextAttribsProc createContextAttribs;
  601.   /* If nothing fancy has been required, simply use the old context creation GLX API entry */
  602.   if ( fghIsLegacyContextRequested() )
  603.   {
  604.     context = glXCreateNewContext( dpy, config, render_type, share_list, direct );
  605.     if ( context == NULL ) {
  606.       fghContextCreationError();
  607.     }
  608.     return context;
  609.   }
  610.   /* color index mode is not available anymore with OpenGL 3.0 */
  611.   if ( render_type == GLX_COLOR_INDEX_TYPE ) {
  612.     fgWarning( "color index mode is deprecated, using RGBA mode" );
  613.   }
  614.   fghFillContextAttributes( attributes );
  615.   createContextAttribs = (CreateContextAttribsProc) fghGetProcAddress( "glXCreateContextAttribsARB" );
  616.   if ( createContextAttribs == NULL ) {
  617.     fgError( "glXCreateContextAttribsARB not found" );
  618.   }
  619.   context = createContextAttribs( dpy, config, share_list, direct, attributes );
  620.   if ( context == NULL ) {
  621.     fghContextCreationError();
  622.   }
  623.   return context;
  624. }
  625. #endif
  626. /*
  627.  * Opens a window. Requires a SFG_Window object created and attached
  628.  * to the freeglut structure. OpenGL context is created here.
  629.  */
  630. void fgOpenWindow( SFG_Window* window, const char* title,
  631.                    GLboolean positionUse, int x, int y,
  632.                    GLboolean sizeUse, int w, int h,
  633.                    GLboolean gameMode, GLboolean isSubWindow )
  634. {
  635. #if TARGET_HOST_POSIX_X11
  636.     XVisualInfo * visualInfo;
  637.     XSetWindowAttributes winAttr;
  638.     XTextProperty textProperty;
  639.     XSizeHints sizeHints;
  640.     XWMHints wmHints;
  641.     unsigned long mask;
  642.     unsigned int current_DisplayMode = fgState.DisplayMode ;
  643.     /* Save the display mode if we are creating a menu window */
  644.     if( window->IsMenu && ( ! fgStructure.MenuContext ) )
  645.         fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB ;
  646.     window->Window.FBConfig = fgChooseFBConfig( );
  647.     if( window->IsMenu && ( ! fgStructure.MenuContext ) )
  648.         fgState.DisplayMode = current_DisplayMode ;
  649.     if( ! window->Window.FBConfig )
  650.     {
  651.         /*
  652.          * The "fgChooseFBConfig" returned a null meaning that the visual
  653.          * context is not available.
  654.          * Try a couple of variations to see if they will work.
  655.          */
  656.         if( !( fgState.DisplayMode & GLUT_DOUBLE ) )
  657.         {
  658.             fgState.DisplayMode |= GLUT_DOUBLE ;
  659.             window->Window.FBConfig = fgChooseFBConfig( );
  660.             fgState.DisplayMode &= ~GLUT_DOUBLE;
  661.         }
  662.         if( fgState.DisplayMode & GLUT_MULTISAMPLE )
  663.         {
  664.             fgState.DisplayMode &= ~GLUT_MULTISAMPLE ;
  665.             window->Window.FBConfig = fgChooseFBConfig( );
  666.             fgState.DisplayMode |= GLUT_MULTISAMPLE;
  667.         }
  668.     }
  669.     FREEGLUT_INTERNAL_ERROR_EXIT( window->Window.FBConfig != NULL,
  670.                                   "FBConfig with necessary capabilities not found", "fgOpenWindow" );
  671.     /*  Get the X visual.  */
  672.     visualInfo = glXGetVisualFromFBConfig( fgDisplay.Display,
  673.                                            *(window->Window.FBConfig) );
  674.     /*
  675.      * XXX HINT: the masks should be updated when adding/removing callbacks.
  676.      * XXX       This might speed up message processing. Is that true?
  677.      * XXX
  678.      * XXX A: Not appreciably, but it WILL make it easier to debug.
  679.      * XXX    Try tracing old GLUT and try tracing freeglut.  Old GLUT
  680.      * XXX    turns off events that it doesn't need and is a whole lot
  681.      * XXX    more pleasant to trace.  (Think mouse-motion!  Tons of
  682.      * XXX    ``bonus'' GUI events stream in.)
  683.      */
  684.     winAttr.event_mask        =
  685.         StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
  686.         ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
  687.         VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
  688.         PointerMotionMask | ButtonMotionMask;
  689.     winAttr.background_pixmap = None;
  690.     winAttr.background_pixel  = 0;
  691.     winAttr.border_pixel      = 0;
  692.     winAttr.colormap = XCreateColormap(
  693.         fgDisplay.Display, fgDisplay.RootWindow,
  694.         visualInfo->visual, AllocNone
  695.     );
  696.     mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
  697.     if( window->IsMenu || ( gameMode == GL_TRUE ) )
  698.     {
  699.         winAttr.override_redirect = True;
  700.         mask |= CWOverrideRedirect;
  701.     }
  702.     if( ! positionUse )
  703.         x = y = -1; /* default window position */
  704.     if( ! sizeUse )
  705.         w = h = 300; /* default window size */
  706.     window->Window.Handle = XCreateWindow(
  707.         fgDisplay.Display,
  708.         window->Parent == NULL ? fgDisplay.RootWindow :
  709.         window->Parent->Window.Handle,
  710.         x, y, w, h, 0,
  711.         visualInfo->depth, InputOutput,
  712.         visualInfo->visual, mask,
  713.         &winAttr
  714.     );
  715.     /*
  716.      * The GLX context creation, possibly trying the direct context rendering
  717.      *  or else use the current context if the user has so specified
  718.      */
  719.     if( window->IsMenu )
  720.     {
  721.         /*
  722.          * If there isn't already an OpenGL rendering context for menu
  723.          * windows, make one
  724.          */
  725.         if( !fgStructure.MenuContext )
  726.         {
  727.             fgStructure.MenuContext =
  728.                 (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
  729.             fgStructure.MenuContext->MContext = fghCreateNewContext( window );
  730.         }
  731.         /* window->Window.Context = fgStructure.MenuContext->MContext; */
  732.         window->Window.Context = fghCreateNewContext( window );
  733.     }
  734.     else if( fgState.UseCurrentContext )
  735.     {
  736.         window->Window.Context = glXGetCurrentContext( );
  737.         if( ! window->Window.Context )
  738.             window->Window.Context = fghCreateNewContext( window );
  739.     }
  740.     else
  741.         window->Window.Context = fghCreateNewContext( window );
  742. #if !defined( __FreeBSD__ ) && !defined( __NetBSD__ )
  743.     if(  !glXIsDirect( fgDisplay.Display, window->Window.Context ) )
  744.     {
  745.       if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
  746.         fgError( "Unable to force direct context rendering for window '%s'",
  747.                  title );
  748.     }
  749. #endif
  750.     /*
  751.      * XXX Assume the new window is visible by default
  752.      * XXX Is this a  safe assumption?
  753.      */
  754.     window->State.Visible = GL_TRUE;
  755.     sizeHints.flags = 0;
  756.     if ( positionUse )
  757.         sizeHints.flags |= USPosition;
  758.     if ( sizeUse )
  759.         sizeHints.flags |= USSize;
  760.     /*
  761.      * Fill in the size hints values now (the x, y, width and height
  762.      * settings are obsolete, are there any more WMs that support them?)
  763.      * Unless the X servers actually stop supporting these, we should
  764.      * continue to fill them in.  It is *not* our place to tell the user
  765.      * that they should replace a window manager that they like, and which
  766.      * works, just because *we* think that it's not "modern" enough.
  767.      */
  768.     sizeHints.x      = x;
  769.     sizeHints.y      = y;
  770.     sizeHints.width  = w;
  771.     sizeHints.height = h;
  772.     wmHints.flags = StateHint;
  773.     wmHints.initial_state = fgState.ForceIconic ? IconicState : NormalState;
  774.     /* Prepare the window and iconified window names... */
  775.     XStringListToTextProperty( (char **) &title, 1, &textProperty );
  776.     XSetWMProperties(
  777.         fgDisplay.Display,
  778.         window->Window.Handle,
  779.         &textProperty,
  780.         &textProperty,
  781.         0,
  782.         0,
  783.         &sizeHints,
  784.         &wmHints,
  785.         NULL
  786.     );
  787.     XFree( textProperty.value );
  788.     XSetWMProtocols( fgDisplay.Display, window->Window.Handle,
  789.                      &fgDisplay.DeleteWindow, 1 );
  790.     glXMakeContextCurrent(
  791.         fgDisplay.Display,
  792.         window->Window.Handle,
  793.         window->Window.Handle,
  794.         window->Window.Context
  795.     );
  796.     XMapWindow( fgDisplay.Display, window->Window.Handle );
  797.     XFree(visualInfo);
  798. #elif TARGET_HOST_MS_WINDOWS
  799.     WNDCLASS wc;
  800.     DWORD flags;
  801.     DWORD exFlags = 0;
  802.     ATOM atom;
  803.     int WindowStyle = 0;
  804.     /* Grab the window class we have registered on glutInit(): */
  805.     atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc );
  806.     FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found",
  807.                                    "fgOpenWindow" );
  808.     if( gameMode )
  809.     {
  810.         FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL,
  811.                                        "Game mode being invoked on a subwindow",
  812.                                        "fgOpenWindow" );
  813.         /*
  814.          * Set the window creation flags appropriately to make the window
  815.          * entirely visible:
  816.          */
  817.         flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
  818.     }
  819.     else
  820.     {
  821.         int worig = w, horig = h;
  822. #if !defined(_WIN32_WCE)
  823.         if ( ( ! isSubWindow ) && ( ! window->IsMenu ) )
  824.         {
  825.             /*
  826.              * Update the window dimensions, taking account of window
  827.              * decorations.  "freeglut" is to create the window with the
  828.              * outside of its border at (x,y) and with dimensions (w,h).
  829.              */
  830.             w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
  831.             h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 +
  832.                 GetSystemMetrics( SM_CYCAPTION );
  833.         }
  834. #endif /* defined(_WIN32_WCE) */
  835.         if( ! positionUse )
  836.         {
  837.             x = CW_USEDEFAULT;
  838.             y = CW_USEDEFAULT;
  839.         }
  840.         /* setting State.Width/Height to call resize callback later */
  841.         if( ! sizeUse )
  842.         {
  843.             if( ! window->IsMenu )
  844.             {
  845.                 w = CW_USEDEFAULT;
  846.                 h = CW_USEDEFAULT;
  847.             }
  848.             else /* fail safe - Windows can make a window of size (0, 0) */
  849.                 w = h = 300; /* default window size */
  850.             window->State.Width = window->State.Height = -1;
  851.         }
  852.         else
  853.         {
  854.             window->State.Width = worig;
  855.             window->State.Height = horig;
  856.         }
  857.         /*
  858.          * There's a small difference between creating the top, child and
  859.          * game mode windows
  860.          */
  861.         flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
  862.         if ( window->IsMenu )
  863.         {
  864.             flags |= WS_POPUP;
  865.             exFlags |= WS_EX_TOOLWINDOW;
  866.         }
  867. #if !defined(_WIN32_WCE)
  868.         else if( window->Parent == NULL )
  869.             flags |= WS_OVERLAPPEDWINDOW;
  870. #endif
  871.         else
  872.             flags |= WS_CHILD;
  873.     }
  874. #if defined(_WIN32_WCE)
  875.     {
  876.         wchar_t* wstr = fghWstrFromStr(title);
  877.         window->Window.Handle = CreateWindow(
  878.             _T("FREEGLUT"),
  879.             wstr,
  880.             WS_VISIBLE | WS_POPUP,
  881.             0,0, 240,320,
  882.             NULL,
  883.             NULL,
  884.             fgDisplay.Instance,
  885.             (LPVOID) window
  886.         );
  887.         free(wstr);
  888.         SHFullScreen(window->Window.Handle, SHFS_HIDESTARTICON);
  889.         SHFullScreen(window->Window.Handle, SHFS_HIDESIPBUTTON);
  890.         SHFullScreen(window->Window.Handle, SHFS_HIDETASKBAR);
  891.         MoveWindow(window->Window.Handle, 0, 0, 240, 320, TRUE);
  892.         ShowWindow(window->Window.Handle, SW_SHOW);
  893.         UpdateWindow(window->Window.Handle);
  894.     }
  895. #else
  896.     window->Window.Handle = CreateWindowEx(
  897.         exFlags,
  898.         _T("FREEGLUT"),
  899.         title,
  900.         flags,
  901.         x, y, w, h,
  902.         (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
  903.         (HMENU) NULL,
  904.         fgDisplay.Instance,
  905.         (LPVOID) window
  906.     );
  907. #endif /* defined(_WIN32_WCE) */
  908.     if( !( window->Window.Handle ) )
  909.         fgError( "Failed to create a window (%s)!", title );
  910.     /* Make a menu window always on top - fix Feature Request 947118 */
  911.     if( window->IsMenu || gameMode )
  912.         SetWindowPos(
  913.                         window->Window.Handle,
  914.                         HWND_TOPMOST,
  915.                         0, 0, 0, 0,
  916.                         SWP_NOMOVE | SWP_NOSIZE
  917.                     );
  918.     /* Hack to remove the caption (title bar) and/or border
  919.      * and all the system menu controls.
  920.      */
  921.     WindowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
  922.     if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
  923.     {
  924.         SetWindowLong ( window->Window.Handle, GWL_STYLE,
  925.                         WindowStyle & ~(WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
  926.     }
  927.     else if ( fgState.DisplayMode & GLUT_BORDERLESS )
  928.     {
  929.         SetWindowLong ( window->Window.Handle, GWL_STYLE,
  930.                         WindowStyle & ~(WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
  931.     }
  932. /*  SetWindowPos(window->Window.Handle, NULL, 0, 0, 0, 0,
  933.      SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); */
  934. #if defined(_WIN32_WCE)
  935.     ShowWindow( window->Window.Handle, SW_SHOW );
  936. #else
  937.     ShowWindow( window->Window.Handle,
  938.                 fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW );
  939. #endif /* defined(_WIN32_WCE) */
  940.     UpdateWindow( window->Window.Handle );
  941.     ShowCursor( TRUE );  /* XXX Old comments say "hide cursor"! */
  942. #endif
  943.     fgSetWindow( window );
  944.     window->Window.DoubleBuffered =
  945.         ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0;
  946.     if ( ! window->Window.DoubleBuffered )
  947.     {
  948.         glDrawBuffer ( GL_FRONT );
  949.         glReadBuffer ( GL_FRONT );
  950.     }
  951. }
  952. /*
  953.  * Closes a window, destroying the frame and OpenGL context
  954.  */
  955. void fgCloseWindow( SFG_Window* window )
  956. {
  957. #if TARGET_HOST_POSIX_X11
  958.     if( window->Window.Context )
  959.         glXDestroyContext( fgDisplay.Display, window->Window.Context );
  960.     XFree( window->Window.FBConfig );
  961.     XDestroyWindow( fgDisplay.Display, window->Window.Handle );
  962.     /* XFlush( fgDisplay.Display ); */ /* XXX Shouldn't need this */
  963. #elif TARGET_HOST_MS_WINDOWS
  964.     /* Make sure we don't close a window with current context active */
  965.     if( fgStructure.CurrentWindow == window )
  966.         wglMakeCurrent( NULL, NULL );
  967.     /*
  968.      * Step through the list of windows.  If the rendering context
  969.      * is not being used by another window, then we delete it.
  970.      */
  971.     {
  972.         int used = FALSE ;
  973.         SFG_Window *iter ;
  974.         for( iter = (SFG_Window *)fgStructure.Windows.First;
  975.              iter;
  976.              iter = (SFG_Window *)iter->Node.Next )
  977.         {
  978.             if( ( iter->Window.Context == window->Window.Context ) &&
  979.                 ( iter != window ) )
  980.                 used = TRUE;
  981.         }
  982.         if( ! used )
  983.             wglDeleteContext( window->Window.Context );
  984.     }
  985.     DestroyWindow( window->Window.Handle );
  986. #endif
  987. }
  988. /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
  989. /*
  990.  * Creates a new top-level freeglut window
  991.  */
  992. int FGAPIENTRY glutCreateWindow( const char* title )
  993. {
  994.     /* XXX GLUT does not exit; it simply calls "glutInit" quietly if the
  995.      * XXX application has not already done so.  The "freeglut" community
  996.      * XXX decided not to go this route (freeglut-developer e-mail from
  997.      * XXX Steve Baker, 12/16/04, 4:22 PM CST, "Re: [Freeglut-developer]
  998.      * XXX Desired 'freeglut' behaviour when there is no current window"
  999.      */
  1000.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateWindow" );
  1001.     return fgCreateWindow( NULL, title, fgState.Position.Use,
  1002.                            fgState.Position.X, fgState.Position.Y,
  1003.                            fgState.Size.Use, fgState.Size.X, fgState.Size.Y,
  1004.                            GL_FALSE, GL_FALSE )->ID;
  1005. }
  1006. #if TARGET_HOST_MS_WINDOWS
  1007. int FGAPIENTRY __glutCreateWindowWithExit( const char *title, void (__cdecl *exit_function)(int) )
  1008. {
  1009.   __glutExitFunc = exit_function;
  1010.   return glutCreateWindow( title );
  1011. }
  1012. #endif
  1013. /*
  1014.  * This function creates a sub window.
  1015.  */
  1016. int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
  1017. {
  1018.     int ret = 0;
  1019.     SFG_Window* window = NULL;
  1020.     SFG_Window* parent = NULL;
  1021.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateSubWindow" );
  1022.     parent = fgWindowByID( parentID );
  1023.     freeglut_return_val_if_fail( parent != NULL, 0 );
  1024.     if ( x < 0 )
  1025.     {
  1026.         x = parent->State.Width + x ;
  1027.         if ( w >= 0 ) x -= w ;
  1028.     }
  1029.     if ( w < 0 ) w = parent->State.Width - x + w ;
  1030.     if ( w < 0 )
  1031.     {
  1032.         x += w ;
  1033.         w = -w ;
  1034.     }
  1035.     if ( y < 0 )
  1036.     {
  1037.         y = parent->State.Height + y ;
  1038.         if ( h >= 0 ) y -= h ;
  1039.     }
  1040.     if ( h < 0 ) h = parent->State.Height - y + h ;
  1041.     if ( h < 0 )
  1042.     {
  1043.         y += h ;
  1044.         h = -h ;
  1045.     }
  1046.     window = fgCreateWindow( parent, "", GL_TRUE, x, y, GL_TRUE, w, h, GL_FALSE, GL_FALSE );
  1047.     ret = window->ID;
  1048.     return ret;
  1049. }
  1050. /*
  1051.  * Destroys a window and all of its subwindows
  1052.  */
  1053. void FGAPIENTRY glutDestroyWindow( int windowID )
  1054. {
  1055.     SFG_Window* window;
  1056.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyWindow" );
  1057.     window = fgWindowByID( windowID );
  1058.     freeglut_return_if_fail( window != NULL );
  1059.     {
  1060.         fgExecutionState ExecState = fgState.ExecState;
  1061.         fgAddToWindowDestroyList( window );
  1062.         fgState.ExecState = ExecState;
  1063.     }
  1064. }
  1065. /*
  1066.  * This function selects the current window
  1067.  */
  1068. void FGAPIENTRY glutSetWindow( int ID )
  1069. {
  1070.     SFG_Window* window = NULL;
  1071.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindow" );
  1072.     if( fgStructure.CurrentWindow != NULL )
  1073.         if( fgStructure.CurrentWindow->ID == ID )
  1074.             return;
  1075.     window = fgWindowByID( ID );
  1076.     if( window == NULL )
  1077.     {
  1078.         fgWarning( "glutSetWindow(): window ID %d not found!", ID );
  1079.         return;
  1080.     }
  1081.     fgSetWindow( window );
  1082. }
  1083. /*
  1084.  * This function returns the ID number of the current window, 0 if none exists
  1085.  */
  1086. int FGAPIENTRY glutGetWindow( void )
  1087. {
  1088.     SFG_Window *win = fgStructure.CurrentWindow;
  1089.     /*
  1090.      * Since GLUT did not throw an error if this function was called without a prior call to
  1091.      * "glutInit", this function shouldn't do so here.  Instead let us return a zero.
  1092.      * See Feature Request "[ 1307049 ] glutInit check".
  1093.      */
  1094.     if ( ! fgState.Initialised )
  1095.         return 0;
  1096.     while ( win && win->IsMenu )
  1097.         win = win->Parent;
  1098.     return win ? win->ID : 0;
  1099. }
  1100. /*
  1101.  * This function makes the current window visible
  1102.  */
  1103. void FGAPIENTRY glutShowWindow( void )
  1104. {
  1105.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutShowWindow" );
  1106.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutShowWindow" );
  1107. #if TARGET_HOST_POSIX_X11
  1108.     XMapWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
  1109.     XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
  1110. #elif TARGET_HOST_MS_WINDOWS
  1111.     ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_SHOW );
  1112. #endif
  1113.     fgStructure.CurrentWindow->State.Redisplay = GL_TRUE;
  1114. }
  1115. /*
  1116.  * This function hides the current window
  1117.  */
  1118. void FGAPIENTRY glutHideWindow( void )
  1119. {
  1120.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutHideWindow" );
  1121.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutHideWindow" );
  1122. #if TARGET_HOST_POSIX_X11
  1123.     if( fgStructure.CurrentWindow->Parent == NULL )
  1124.         XWithdrawWindow( fgDisplay.Display,
  1125.                          fgStructure.CurrentWindow->Window.Handle,
  1126.                          fgDisplay.Screen );
  1127.     else
  1128.         XUnmapWindow( fgDisplay.Display,
  1129.                       fgStructure.CurrentWindow->Window.Handle );
  1130.     XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
  1131. #elif TARGET_HOST_MS_WINDOWS
  1132.     ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_HIDE );
  1133. #endif
  1134.     fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
  1135. }
  1136. /*
  1137.  * Iconify the current window (top-level windows only)
  1138.  */
  1139. void FGAPIENTRY glutIconifyWindow( void )
  1140. {
  1141.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" );
  1142.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" );
  1143.     fgStructure.CurrentWindow->State.Visible   = GL_FALSE;
  1144. #if TARGET_HOST_POSIX_X11
  1145.     XIconifyWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
  1146.                     fgDisplay.Screen );
  1147.     XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
  1148. #elif TARGET_HOST_MS_WINDOWS
  1149.     ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_MINIMIZE );
  1150. #endif
  1151.     fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
  1152. }
  1153. /*
  1154.  * Set the current window's title
  1155.  */
  1156. void FGAPIENTRY glutSetWindowTitle( const char* title )
  1157. {
  1158.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowTitle" );
  1159.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowTitle" );
  1160.     if( ! fgStructure.CurrentWindow->Parent )
  1161.     {
  1162. #if TARGET_HOST_POSIX_X11
  1163.         XTextProperty text;
  1164.         text.value = (unsigned char *) title;
  1165.         text.encoding = XA_STRING;
  1166.         text.format = 8;
  1167.         text.nitems = strlen( title );
  1168.         XSetWMName(
  1169.             fgDisplay.Display,
  1170.             fgStructure.CurrentWindow->Window.Handle,
  1171.             &text
  1172.         );
  1173.         XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
  1174. #elif TARGET_HOST_MS_WINDOWS
  1175. #    ifdef _WIN32_WCE
  1176.         {
  1177.             wchar_t* wstr = fghWstrFromStr(title);
  1178.             SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr );
  1179.             free(wstr);
  1180.         }
  1181. #    else
  1182.         SetWindowText( fgStructure.CurrentWindow->Window.Handle, title );
  1183. #    endif
  1184. #endif
  1185.     }
  1186. }
  1187. /*
  1188.  * Set the current window's iconified title
  1189.  */
  1190. void FGAPIENTRY glutSetIconTitle( const char* title )
  1191. {
  1192.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetIconTitle" );
  1193.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetIconTitle" );
  1194.     if( ! fgStructure.CurrentWindow->Parent )
  1195.     {
  1196. #if TARGET_HOST_POSIX_X11
  1197.         XTextProperty text;
  1198.         text.value = (unsigned char *) title;
  1199.         text.encoding = XA_STRING;
  1200.         text.format = 8;
  1201.         text.nitems = strlen( title );
  1202.         XSetWMIconName(
  1203.             fgDisplay.Display,
  1204.             fgStructure.CurrentWindow->Window.Handle,
  1205.             &text
  1206.         );
  1207.         XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
  1208. #elif TARGET_HOST_MS_WINDOWS
  1209. #    ifdef _WIN32_WCE
  1210.         {
  1211.             wchar_t* wstr = fghWstrFromStr(title);
  1212.             SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr );
  1213.             free(wstr);
  1214.         }
  1215. #    else
  1216.         SetWindowText( fgStructure.CurrentWindow->Window.Handle, title );
  1217. #    endif
  1218. #endif
  1219.     }
  1220. }
  1221. /*
  1222.  * Change the current window's size
  1223.  */
  1224. void FGAPIENTRY glutReshapeWindow( int width, int height )
  1225. {
  1226.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeWindow" );
  1227.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutReshapeWindow" );
  1228.     if (glutGet(GLUT_FULL_SCREEN))
  1229.     {
  1230.       /*  Leave full screen state before resizing. */
  1231.       glutFullScreenToggle();
  1232.     }
  1233.     fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
  1234.     fgStructure.CurrentWindow->State.Width  = width ;
  1235.     fgStructure.CurrentWindow->State.Height = height;
  1236. }
  1237. /*
  1238.  * Change the current window's position
  1239.  */
  1240. void FGAPIENTRY glutPositionWindow( int x, int y )
  1241. {
  1242.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPositionWindow" );
  1243.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPositionWindow" );
  1244.     if (glutGet(GLUT_FULL_SCREEN))
  1245.     {
  1246.       /*  Leave full screen state before moving. */
  1247.       glutFullScreenToggle();
  1248.     }
  1249. #if TARGET_HOST_POSIX_X11
  1250.     XMoveWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
  1251.                  x, y );
  1252.     XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
  1253. #elif TARGET_HOST_MS_WINDOWS
  1254.     {
  1255.         RECT winRect;
  1256.         /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
  1257.         GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
  1258.         MoveWindow(
  1259.             fgStructure.CurrentWindow->Window.Handle,
  1260.             x,
  1261.             y,
  1262.             winRect.right - winRect.left,
  1263.             winRect.bottom - winRect.top,
  1264.             TRUE
  1265.         );
  1266.     }
  1267. #endif
  1268. }
  1269. /*
  1270.  * Lowers the current window (by Z order change)
  1271.  */
  1272. void FGAPIENTRY glutPushWindow( void )
  1273. {
  1274.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPushWindow" );
  1275.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPushWindow" );
  1276. #if TARGET_HOST_POSIX_X11
  1277.     XLowerWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
  1278. #elif TARGET_HOST_MS_WINDOWS
  1279.     SetWindowPos(
  1280.         fgStructure.CurrentWindow->Window.Handle,
  1281.         HWND_BOTTOM,
  1282.         0, 0, 0, 0,
  1283.         SWP_NOSIZE | SWP_NOMOVE
  1284.     );
  1285. #endif
  1286. }
  1287. /*
  1288.  * Raises the current window (by Z order change)
  1289.  */
  1290. void FGAPIENTRY glutPopWindow( void )
  1291. {
  1292.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPopWindow" );
  1293.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPopWindow" );
  1294. #if TARGET_HOST_POSIX_X11
  1295.     XRaiseWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
  1296. #elif TARGET_HOST_MS_WINDOWS
  1297.     SetWindowPos(
  1298.         fgStructure.CurrentWindow->Window.Handle,
  1299.         HWND_TOP,
  1300.         0, 0, 0, 0,
  1301.         SWP_NOSIZE | SWP_NOMOVE
  1302.     );
  1303. #endif
  1304. }
  1305. #if TARGET_HOST_POSIX_X11
  1306. static int ewmh_fullscr_toggle(void);
  1307. static int resize_fullscr_toogle(void);
  1308. static int toggle_fullscreen(void)
  1309. {
  1310.     /* first try the EWMH (_NET_WM_STATE) method ... */
  1311.     if(ewmh_fullscr_toggle() != -1) {
  1312.         return 0;
  1313.     }
  1314.     /* fall back to resizing the window */
  1315.     if(resize_fullscr_toogle() != -1) {
  1316.         return 0;
  1317.     }
  1318.     return -1;
  1319. }
  1320. #define _NET_WM_STATE_TOGGLE    2
  1321. static int ewmh_fullscr_toggle(void)
  1322. {
  1323.     XEvent xev;
  1324.     long evmask = SubstructureRedirectMask | SubstructureNotifyMask;
  1325.     if(!fgDisplay.State || !fgDisplay.StateFullScreen) {
  1326.         return -1;
  1327.     }
  1328.     xev.type = ClientMessage;
  1329.     xev.xclient.window = fgStructure.CurrentWindow->Window.Handle;
  1330.     xev.xclient.message_type = fgDisplay.State;
  1331.     xev.xclient.format = 32;
  1332.     xev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE;
  1333.     xev.xclient.data.l[1] = fgDisplay.StateFullScreen;
  1334.     xev.xclient.data.l[2] = 0; /* no second property to toggle */
  1335.     xev.xclient.data.l[3] = 1; /* source indication: application */
  1336.     xev.xclient.data.l[4] = 0; /* unused */
  1337.     if(!XSendEvent(fgDisplay.Display, fgDisplay.RootWindow, 0, evmask, &xev)) {
  1338.         return -1;
  1339.     }
  1340.     return 0;
  1341. }
  1342. static int resize_fullscr_toogle(void)
  1343. {
  1344.     XWindowAttributes attributes;
  1345.     if(glutGet(GLUT_FULL_SCREEN)) {
  1346.         /* restore original window size */
  1347.         SFG_Window *win = fgStructure.CurrentWindow;
  1348.         fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
  1349.         fgStructure.CurrentWindow->State.Width  = win->State.OldWidth;
  1350.         fgStructure.CurrentWindow->State.Height = win->State.OldHeight;
  1351.     } else {
  1352.         /* resize the window to cover the entire screen */
  1353.         XGetWindowAttributes(fgDisplay.Display,
  1354.                 fgStructure.CurrentWindow->Window.Handle,
  1355.                 &attributes);
  1356.         
  1357.         /*
  1358.          * The "x" and "y" members of "attributes" are the window's coordinates
  1359.          * relative to its parent, i.e. to the decoration window.
  1360.          */
  1361.         XMoveResizeWindow(fgDisplay.Display,
  1362.                 fgStructure.CurrentWindow->Window.Handle,
  1363.                 -attributes.x,
  1364.                 -attributes.y,
  1365.                 fgDisplay.ScreenWidth,
  1366.                 fgDisplay.ScreenHeight);
  1367.     }
  1368.     return 0;
  1369. }
  1370. #endif /* TARGET_HOST_POSIX_X11 */
  1371. /*
  1372.  * Resize the current window so that it fits the whole screen
  1373.  */
  1374. void FGAPIENTRY glutFullScreen( void )
  1375. {
  1376.     SFG_Window *win;
  1377.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
  1378.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
  1379.     win = fgStructure.CurrentWindow;
  1380. #if TARGET_HOST_POSIX_X11
  1381.     if(!glutGet(GLUT_FULL_SCREEN)) {
  1382.         if(toggle_fullscreen() != -1) {
  1383.             win->State.IsFullscreen = GL_TRUE;
  1384.         }
  1385.     }
  1386. #elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: what about WinCE */
  1387.     if (glutGet(GLUT_FULL_SCREEN))
  1388.     {
  1389.         /*  Leave full screen state before resizing. */
  1390.         glutFullScreenToggle();
  1391.     }
  1392.     {
  1393.         RECT rect;
  1394.         /* For fullscreen mode, force the top-left corner to 0,0
  1395.          * and adjust the window rectangle so that the client area
  1396.          * covers the whole screen.
  1397.          */
  1398.         rect.left   = 0;
  1399.         rect.top    = 0;
  1400.         rect.right  = fgDisplay.ScreenWidth;
  1401.         rect.bottom = fgDisplay.ScreenHeight;
  1402.         AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
  1403.                                   WS_CLIPCHILDREN, FALSE );
  1404.         /*
  1405.          * SWP_NOACTIVATE     Do not activate the window
  1406.          * SWP_NOOWNERZORDER  Do not change position in z-order
  1407.          * SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message
  1408.          * SWP_NOZORDER       Retains the current Z order (ignore 2nd param)
  1409.          */
  1410.         SetWindowPos( fgStructure.CurrentWindow->Window.Handle,
  1411.                       HWND_TOP,
  1412.                       rect.left,
  1413.                       rect.top,
  1414.                       rect.right  - rect.left,
  1415.                       rect.bottom - rect.top,
  1416.                       SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
  1417.                       SWP_NOZORDER
  1418.                     );
  1419.         
  1420.         win->State.IsFullscreen = GL_TRUE;
  1421.     }
  1422. #endif
  1423. }
  1424. /*
  1425.  * Toggle the window's full screen state.
  1426.  */
  1427. void FGAPIENTRY glutFullScreenToggle( void )
  1428. {
  1429.     SFG_Window *win;
  1430.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" );
  1431.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" );
  1432.     win = fgStructure.CurrentWindow;
  1433. #if TARGET_HOST_POSIX_X11
  1434.     if(toggle_fullscreen() != -1) {
  1435.         win->State.IsFullscreen = !win->State.IsFullscreen;
  1436.     }
  1437. #elif TARGET_HOST_MS_WINDOWS
  1438.     glutFullScreen();
  1439.     win->State.IsFullscreen = !win->State.IsFullscreen;
  1440. #endif
  1441. }
  1442. /*
  1443.  * A.Donev: Set and retrieve the window's user data
  1444.  */
  1445. void* FGAPIENTRY glutGetWindowData( void )
  1446. {
  1447.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetWindowData" );
  1448.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutGetWindowData" );
  1449.     return fgStructure.CurrentWindow->UserData;
  1450. }
  1451. void FGAPIENTRY glutSetWindowData(void* data)
  1452. {
  1453.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowData" );
  1454.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowData" );
  1455.     fgStructure.CurrentWindow->UserData = data;
  1456. }
  1457. /*** END OF FILE ***/