4 * Window management methods.
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
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:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
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.
28 #define FREEGLUT_BUILDING_LIB
29 #include <GL/freeglut.h>
30 #include "freeglut_internal.h"
32 #if TARGET_HOST_POSIX_X11
33 #include <limits.h> /* LONG_MAX */
36 #if defined(_WIN32_WCE)
37 # include <Aygshell.h>
38 # ifdef FREEGLUT_LIB_PRAGMAS
39 # pragma comment( lib, "Aygshell.lib" )
42 static wchar_t* fghWstrFromStr(const char* str)
44 int i,len=strlen(str);
45 wchar_t* wstr = (wchar_t*)malloc(2*len+2);
52 #endif /* defined(_WIN32_WCE) */
54 /* pushing attribute/value pairs into an array */
55 #define ATTRIB(a) attributes[where++]=(a)
56 #define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);}
59 * TODO BEFORE THE STABLE RELEASE:
61 * fgChooseFBConfig() -- OK, but what about glutInitDisplayString()?
62 * fgSetupPixelFormat -- ignores the display mode settings
63 * fgOpenWindow() -- check the Win32 version, -iconic handling!
64 * fgCloseWindow() -- check the Win32 version
65 * glutCreateWindow() -- Check when default position and size is {-1,-1}
66 * glutCreateSubWindow() -- Check when default position and size is {-1,-1}
67 * glutDestroyWindow() -- check the Win32 version
68 * glutSetWindow() -- check the Win32 version
69 * glutGetWindow() -- OK
70 * glutSetWindowTitle() -- check the Win32 version
71 * glutSetIconTitle() -- check the Win32 version
72 * glutShowWindow() -- check the Win32 version
73 * glutHideWindow() -- check the Win32 version
74 * glutIconifyWindow() -- check the Win32 version
75 * glutReshapeWindow() -- check the Win32 version
76 * glutPositionWindow() -- check the Win32 version
77 * glutPushWindow() -- check the Win32 version
78 * glutPopWindow() -- check the Win32 version
81 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
83 static int fghIsLegacyContextVersionRequested( void )
85 return fgState.MajorVersion == 1 && fgState.MinorVersion == 0;
88 static int fghIsLegacyContextRequested( void )
90 return fghIsLegacyContextVersionRequested() &&
91 fgState.ContextFlags == 0 &&
92 fgState.ContextProfile == 0;
95 static int fghNumberOfAuxBuffersRequested( void )
97 if ( fgState.DisplayMode & GLUT_AUX4 ) {
100 if ( fgState.DisplayMode & GLUT_AUX3 ) {
103 if ( fgState.DisplayMode & GLUT_AUX2 ) {
106 if ( fgState.DisplayMode & GLUT_AUX1 ) { /* NOTE: Same as GLUT_AUX! */
107 return fgState.AuxiliaryBufferNumber;
112 static int fghMapBit( int mask, int from, int to )
114 return ( mask & from ) ? to : 0;
118 static void fghContextCreationError( void )
120 fgError( "Unable to create OpenGL %d.%d context (flags %x, profile %x)",
121 fgState.MajorVersion, fgState.MinorVersion, fgState.ContextFlags,
122 fgState.ContextProfile );
126 * Chooses a visual basing on the current display mode settings
128 #if TARGET_HOST_POSIX_X11
130 #ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
131 #define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
134 GLXFBConfig* fgChooseFBConfig( void )
136 GLboolean wantIndexedMode = GL_FALSE;
137 int attributes[ 100 ];
138 int where = 0, numAuxBuffers;
140 /* First we have to process the display mode settings... */
141 if( fgState.DisplayMode & GLUT_INDEX ) {
142 ATTRIB_VAL( GLX_BUFFER_SIZE, 8 );
143 /* Buffer size is selected later. */
145 ATTRIB_VAL( GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT );
146 wantIndexedMode = GL_TRUE;
148 ATTRIB_VAL( GLX_RED_SIZE, 1 );
149 ATTRIB_VAL( GLX_GREEN_SIZE, 1 );
150 ATTRIB_VAL( GLX_BLUE_SIZE, 1 );
151 if( fgState.DisplayMode & GLUT_ALPHA ) {
152 ATTRIB_VAL( GLX_ALPHA_SIZE, 1 );
156 if( fgState.DisplayMode & GLUT_DOUBLE ) {
157 ATTRIB_VAL( GLX_DOUBLEBUFFER, True );
160 if( fgState.DisplayMode & GLUT_STEREO ) {
161 ATTRIB_VAL( GLX_STEREO, True );
164 if( fgState.DisplayMode & GLUT_DEPTH ) {
165 ATTRIB_VAL( GLX_DEPTH_SIZE, 1 );
168 if( fgState.DisplayMode & GLUT_STENCIL ) {
169 ATTRIB_VAL( GLX_STENCIL_SIZE, 1 );
172 if( fgState.DisplayMode & GLUT_ACCUM ) {
173 ATTRIB_VAL( GLX_ACCUM_RED_SIZE, 1 );
174 ATTRIB_VAL( GLX_ACCUM_GREEN_SIZE, 1 );
175 ATTRIB_VAL( GLX_ACCUM_BLUE_SIZE, 1 );
176 if( fgState.DisplayMode & GLUT_ALPHA ) {
177 ATTRIB_VAL( GLX_ACCUM_ALPHA_SIZE, 1 );
181 numAuxBuffers = fghNumberOfAuxBuffersRequested();
182 if ( numAuxBuffers > 0 ) {
183 ATTRIB_VAL( GLX_AUX_BUFFERS, numAuxBuffers );
186 if( fgState.DisplayMode & GLUT_SRGB ) {
187 ATTRIB_VAL( GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, True );
190 if (fgState.DisplayMode & GLUT_MULTISAMPLE) {
191 ATTRIB_VAL(GLX_SAMPLE_BUFFERS, 1);
192 ATTRIB_VAL(GLX_SAMPLES, fgState.SampleNumber);
195 /* Push a terminator at the end of the list */
199 GLXFBConfig * fbconfigArray; /* Array of FBConfigs */
200 GLXFBConfig * fbconfig; /* The FBConfig we want */
201 int fbconfigArraySize; /* Number of FBConfigs in the array */
204 /* Get all FBConfigs that match "attributes". */
205 fbconfigArray = glXChooseFBConfig( fgDisplay.Display,
208 &fbconfigArraySize );
210 if (fbconfigArray != NULL)
212 int result; /* Returned by glXGetFBConfigAttrib, not checked. */
215 if( wantIndexedMode )
218 * In index mode, we want the largest buffer size, i.e. visual
219 * depth. Here, FBConfigs are sorted by increasing buffer size
220 * first, so FBConfigs with the largest size come last.
223 int bufferSizeMin, bufferSizeMax;
225 /* Get bufferSizeMin. */
227 glXGetFBConfigAttrib( fgDisplay.Display,
231 /* Get bufferSizeMax. */
233 glXGetFBConfigAttrib( fgDisplay.Display,
234 fbconfigArray[fbconfigArraySize - 1],
238 if (bufferSizeMax > bufferSizeMin)
241 * Free and reallocate fbconfigArray, keeping only FBConfigs
242 * with the largest buffer size.
244 XFree(fbconfigArray);
246 /* Add buffer size token at the end of the list. */
248 ATTRIB_VAL( GLX_BUFFER_SIZE, bufferSizeMax );
251 fbconfigArray = glXChooseFBConfig( fgDisplay.Display,
254 &fbconfigArraySize );
259 * We now have an array of FBConfigs, the first one being the "best"
260 * one. So we should return only this FBConfig:
264 * - pick the XID of the FBConfig we want
265 * result = glXGetFBConfigAttrib( fgDisplay.Display,
271 * XFree(fbconfigArray);
273 * - reset "attributes" with the XID
275 * ATTRIB_VAL( GLX_FBCONFIG_ID, fbconfigXID );
278 * - get our FBConfig only
279 * fbconfig = glXChooseFBConfig( fgDisplay.Display,
282 * &fbconfigArraySize );
284 * However, for some configurations (for instance multisampling with
285 * Mesa 6.5.2 and ATI drivers), this does not work:
286 * glXChooseFBConfig returns NULL, whereas fbconfigXID is a valid
287 * XID. Further investigation is needed.
289 * So, for now, we return the whole array of FBConfigs. This should
290 * not produce any side effects elsewhere.
292 fbconfig = fbconfigArray;
302 #endif /* TARGET_HOST_POSIX_X11 */
305 * Setup the pixel format for a Win32 window
307 #if TARGET_HOST_MS_WINDOWS
308 /* The following include file is available from SGI but is not standard:
309 * #include <GL/wglext.h>
310 * So we copy the necessary parts out of it.
311 * XXX: should local definitions for extensions be put in a separate include file?
313 typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
315 typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
317 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
318 #define WGL_ACCELERATION_ARB 0x2003
319 #define WGL_SUPPORT_OPENGL_ARB 0x2010
320 #define WGL_DOUBLE_BUFFER_ARB 0x2011
321 #define WGL_COLOR_BITS_ARB 0x2014
322 #define WGL_ALPHA_BITS_ARB 0x201B
323 #define WGL_DEPTH_BITS_ARB 0x2022
324 #define WGL_STENCIL_BITS_ARB 0x2023
325 #define WGL_FULL_ACCELERATION_ARB 0x2027
327 #define WGL_SAMPLE_BUFFERS_ARB 0x2041
328 #define WGL_SAMPLES_ARB 0x2042
330 #define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
332 #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
334 #ifndef WGL_ARB_create_context
335 #define WGL_ARB_create_context 1
336 #ifdef WGL_WGLEXT_PROTOTYPES
337 extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *);
338 #endif /* WGL_WGLEXT_PROTOTYPES */
339 typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
341 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
342 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
343 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
344 #define WGL_CONTEXT_FLAGS_ARB 0x2094
345 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
347 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
348 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
350 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
351 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
353 #define ERROR_INVALID_VERSION_ARB 0x2095
354 #define ERROR_INVALID_PROFILE_ARB 0x2096
357 static void fghFillContextAttributes( int *attributes ) {
358 int where = 0, contextFlags, contextProfile;
360 if ( !fghIsLegacyContextVersionRequested() ) {
361 ATTRIB_VAL( WGL_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
362 ATTRIB_VAL( WGL_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
366 fghMapBit( fgState.ContextFlags, GLUT_DEBUG, WGL_CONTEXT_DEBUG_BIT_ARB ) |
367 fghMapBit( fgState.ContextFlags, GLUT_FORWARD_COMPATIBLE, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB );
368 if ( contextFlags != 0 ) {
369 ATTRIB_VAL( WGL_CONTEXT_FLAGS_ARB, contextFlags );
373 fghMapBit( fgState.ContextProfile, GLUT_CORE_PROFILE, WGL_CONTEXT_CORE_PROFILE_BIT_ARB ) |
374 fghMapBit( fgState.ContextProfile, GLUT_COMPATIBILITY_PROFILE, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB );
375 if ( contextProfile != 0 ) {
376 ATTRIB_VAL( WGL_CONTEXT_PROFILE_MASK_ARB, contextProfile );
382 static int fghIsExtensionSupported( HDC hdc, const char *extension ) {
383 const char *pWglExtString;
384 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetEntensionsStringARB =
385 (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
386 if ( wglGetEntensionsStringARB == NULL )
390 pWglExtString = wglGetEntensionsStringARB( hdc );
391 return ( pWglExtString != NULL ) && ( strstr(pWglExtString, extension) != NULL );
394 void fgNewWGLCreateContext( SFG_Window* window )
398 PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
400 /* If nothing fancy has been required, leave the context as it is */
401 if ( fghIsLegacyContextRequested() )
406 wglMakeCurrent( window->Window.Device, window->Window.Context );
408 if ( !fghIsExtensionSupported( window->Window.Device, "WGL_ARB_create_context" ) )
413 /* new context creation */
414 fghFillContextAttributes( attributes );
416 wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress( "wglCreateContextAttribsARB" );
417 if ( wglCreateContextAttribsARB == NULL )
419 fgError( "wglCreateContextAttribsARB not found" );
422 context = wglCreateContextAttribsARB( window->Window.Device, 0, attributes );
423 if ( context == NULL )
425 fghContextCreationError();
428 wglMakeCurrent( NULL, NULL );
429 wglDeleteContext( window->Window.Context );
430 window->Window.Context = context;
433 #if !defined(_WIN32_WCE)
435 static void fghFillPFD( PIXELFORMATDESCRIPTOR *ppfd, HDC hdc, unsigned char layer_type )
437 int flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
438 if ( fgState.DisplayMode & GLUT_DOUBLE ) {
439 flags |= PFD_DOUBLEBUFFER;
441 if ( fgState.DisplayMode & GLUT_STEREO ) {
445 #if defined(_MSC_VER)
446 #pragma message( "fgSetupPixelFormat(): there is still some work to do here!" )
449 /* Specify which pixel format do we opt for... */
450 ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
452 ppfd->dwFlags = flags;
454 if( fgState.DisplayMode & GLUT_INDEX ) {
455 ppfd->iPixelType = PFD_TYPE_COLORINDEX;
457 ppfd->cGreenBits = 0;
459 ppfd->cAlphaBits = 0;
461 ppfd->iPixelType = PFD_TYPE_RGBA;
463 ppfd->cGreenBits = 8;
465 ppfd->cAlphaBits = ( fgState.DisplayMode & GLUT_ALPHA ) ? 8 : 0;
468 ppfd->cColorBits = 24;
470 ppfd->cGreenShift = 0;
471 ppfd->cBlueShift = 0;
472 ppfd->cAlphaShift = 0;
473 ppfd->cAccumBits = 0;
474 ppfd->cAccumRedBits = 0;
475 ppfd->cAccumGreenBits = 0;
476 ppfd->cAccumBlueBits = 0;
477 ppfd->cAccumAlphaBits = 0;
479 /* Hmmm, or 32/0 instead of 24/8? */
480 ppfd->cDepthBits = 24;
481 ppfd->cStencilBits = 8;
483 ppfd->cAuxBuffers = fghNumberOfAuxBuffersRequested();
484 ppfd->iLayerType = layer_type;
486 ppfd->dwLayerMask = 0;
487 ppfd->dwVisibleMask = 0;
488 ppfd->dwDamageMask = 0;
490 ppfd->cColorBits = (BYTE) GetDeviceCaps( hdc, BITSPIXEL );
493 static void fghFillPixelFormatAttributes( int *attributes, const PIXELFORMATDESCRIPTOR *ppfd )
497 ATTRIB_VAL( WGL_DRAW_TO_WINDOW_ARB, GL_TRUE );
498 ATTRIB_VAL( WGL_SUPPORT_OPENGL_ARB, GL_TRUE );
499 ATTRIB_VAL( WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB );
501 ATTRIB_VAL( WGL_COLOR_BITS_ARB, ppfd->cColorBits );
502 ATTRIB_VAL( WGL_ALPHA_BITS_ARB, ppfd->cAlphaBits );
503 ATTRIB_VAL( WGL_DEPTH_BITS_ARB, ppfd->cDepthBits );
504 ATTRIB_VAL( WGL_STENCIL_BITS_ARB, ppfd->cStencilBits );
506 ATTRIB_VAL( WGL_DOUBLE_BUFFER_ARB, ( fgState.DisplayMode & GLUT_DOUBLE ) != 0 );
508 if ( fgState.DisplayMode & GLUT_SRGB ) {
509 ATTRIB_VAL( WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, TRUE );
512 ATTRIB_VAL( WGL_SAMPLE_BUFFERS_ARB, GL_TRUE );
513 ATTRIB_VAL( WGL_SAMPLES_ARB, fgState.SampleNumber );
518 GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
519 unsigned char layer_type )
521 #if defined(_WIN32_WCE)
524 PIXELFORMATDESCRIPTOR pfd;
525 PIXELFORMATDESCRIPTOR* ppfd = &pfd;
528 fghFillPFD( ppfd, window->Window.Device, layer_type );
529 pixelformat = ChoosePixelFormat( window->Window.Device, ppfd );
531 /* windows hack for multismapling/sRGB */
532 if ( ( fgState.DisplayMode & GLUT_MULTISAMPLE ) ||
533 ( fgState.DisplayMode & GLUT_SRGB ) )
535 HGLRC rc, rc_before=wglGetCurrentContext();
537 HDC hDC, hDC_before=wglGetCurrentDC();
540 /* create a dummy window */
541 ZeroMemory(&wndCls, sizeof(wndCls));
542 wndCls.lpfnWndProc = DefWindowProc;
543 wndCls.hInstance = fgDisplay.Instance;
544 wndCls.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
545 wndCls.lpszClassName = _T("FREEGLUT_dummy");
546 RegisterClass( &wndCls );
548 hWnd=CreateWindow(_T("FREEGLUT_dummy"), _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW , 0,0,0,0, 0, 0, fgDisplay.Instance, 0 );
550 SetPixelFormat( hDC, pixelformat, ppfd );
552 rc = wglCreateContext( hDC );
553 wglMakeCurrent(hDC, rc);
555 if ( fghIsExtensionSupported( hDC, "WGL_ARB_multisample" ) )
557 PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARBProc =
558 (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB");
559 if ( wglChoosePixelFormatARBProc )
564 float fAttributes[] = { 0, 0 };
566 fghFillPixelFormatAttributes( attributes, ppfd );
567 bValid = wglChoosePixelFormatARBProc(window->Window.Device, attributes, fAttributes, 1, &iPixelFormat, &numFormats);
569 if ( bValid && numFormats > 0 )
571 pixelformat = iPixelFormat;
576 wglMakeCurrent( hDC_before, rc_before);
577 wglDeleteContext(rc);
578 ReleaseDC(hWnd, hDC);
580 UnregisterClass(_T("FREEGLUT_dummy"), fgDisplay.Instance);
583 return ( pixelformat != 0 ) && ( checkOnly || SetPixelFormat( window->Window.Device, pixelformat, ppfd ) );
584 #endif /* defined(_WIN32_WCE) */
586 #endif /* TARGET_HOST_MS_WINDOWS */
589 * Sets the OpenGL context and the fgStructure "Current Window" pointer to
590 * the window structure passed in.
592 void fgSetWindow ( SFG_Window *window )
594 #if TARGET_HOST_POSIX_X11
597 glXMakeContextCurrent(
599 window->Window.Handle,
600 window->Window.Handle,
601 window->Window.Context
604 /* also register this window to receive spaceball events */
605 fgSpaceballSetWindow(window);
607 #elif TARGET_HOST_MS_WINDOWS
608 if( fgStructure.CurrentWindow )
609 ReleaseDC( fgStructure.CurrentWindow->Window.Handle,
610 fgStructure.CurrentWindow->Window.Device );
614 window->Window.Device = GetDC( window->Window.Handle );
616 window->Window.Device,
617 window->Window.Context
621 fgStructure.CurrentWindow = window;
626 #if TARGET_HOST_POSIX_X11
628 #ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
629 #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
632 #ifndef GLX_CONTEXT_MINOR_VERSION_ARB
633 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
636 #ifndef GLX_CONTEXT_FLAGS_ARB
637 #define GLX_CONTEXT_FLAGS_ARB 0x2094
640 #ifndef GLX_CONTEXT_PROFILE_MASK_ARB
641 #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
644 #ifndef GLX_CONTEXT_DEBUG_BIT_ARB
645 #define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
648 #ifndef GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
649 #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
652 #ifndef GLX_CONTEXT_CORE_PROFILE_BIT_ARB
653 #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
656 #ifndef GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
657 #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
660 #ifndef GLX_RGBA_FLOAT_TYPE
661 #define GLX_RGBA_FLOAT_TYPE 0x20B9
664 #ifndef GLX_RGBA_FLOAT_BIT
665 #define GLX_RGBA_FLOAT_BIT 0x00000004
668 static void fghFillContextAttributes( int *attributes ) {
669 int where = 0, contextFlags, contextProfile;
671 if ( !fghIsLegacyContextVersionRequested() ) {
672 ATTRIB_VAL( GLX_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
673 ATTRIB_VAL( GLX_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
677 fghMapBit( fgState.ContextFlags, GLUT_DEBUG, GLX_CONTEXT_DEBUG_BIT_ARB ) |
678 fghMapBit( fgState.ContextFlags, GLUT_FORWARD_COMPATIBLE, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB );
679 if ( contextFlags != 0 ) {
680 ATTRIB_VAL( GLX_CONTEXT_FLAGS_ARB, contextFlags );
684 fghMapBit( fgState.ContextProfile, GLUT_CORE_PROFILE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB ) |
685 fghMapBit( fgState.ContextProfile, GLUT_COMPATIBILITY_PROFILE, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB );
686 if ( contextProfile != 0 ) {
687 ATTRIB_VAL( GLX_CONTEXT_PROFILE_MASK_ARB, contextProfile );
693 typedef GLXContext (*CreateContextAttribsProc)(Display *dpy, GLXFBConfig config,
694 GLXContext share_list, Bool direct,
695 const int *attrib_list);
697 static GLXContext fghCreateNewContext( SFG_Window* window )
699 /* for color model calculation */
700 int menu = ( window->IsMenu && !fgStructure.MenuContext );
701 int index_mode = ( fgState.DisplayMode & GLUT_INDEX );
703 /* "classic" context creation */
704 Display *dpy = fgDisplay.Display;
705 GLXFBConfig config = *(window->Window.FBConfig);
706 int render_type = ( !menu && index_mode ) ? GLX_COLOR_INDEX_TYPE : GLX_RGBA_TYPE;
707 GLXContext share_list = NULL;
708 Bool direct = ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT );
711 /* new context creation */
713 CreateContextAttribsProc createContextAttribs;
715 /* If nothing fancy has been required, simply use the old context creation GLX API entry */
716 if ( fghIsLegacyContextRequested() )
718 context = glXCreateNewContext( dpy, config, render_type, share_list, direct );
719 if ( context == NULL ) {
720 fghContextCreationError();
725 /* color index mode is not available anymore with OpenGL 3.0 */
726 if ( render_type == GLX_COLOR_INDEX_TYPE ) {
727 fgWarning( "color index mode is deprecated, using RGBA mode" );
730 fghFillContextAttributes( attributes );
732 createContextAttribs = (CreateContextAttribsProc) fghGetProcAddress( "glXCreateContextAttribsARB" );
733 if ( createContextAttribs == NULL ) {
734 fgError( "glXCreateContextAttribsARB not found" );
737 context = createContextAttribs( dpy, config, share_list, direct, attributes );
738 if ( context == NULL ) {
739 fghContextCreationError();
747 * Opens a window. Requires a SFG_Window object created and attached
748 * to the freeglut structure. OpenGL context is created here.
750 void fgOpenWindow( SFG_Window* window, const char* title,
751 GLboolean positionUse, int x, int y,
752 GLboolean sizeUse, int w, int h,
753 GLboolean gameMode, GLboolean isSubWindow )
755 #if TARGET_HOST_POSIX_X11
756 XVisualInfo * visualInfo;
757 XSetWindowAttributes winAttr;
758 XTextProperty textProperty;
759 XSizeHints sizeHints;
762 unsigned int current_DisplayMode = fgState.DisplayMode ;
764 /* Save the display mode if we are creating a menu window */
765 if( window->IsMenu && ( ! fgStructure.MenuContext ) )
766 fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB ;
768 window->Window.FBConfig = fgChooseFBConfig( );
770 if( window->IsMenu && ( ! fgStructure.MenuContext ) )
771 fgState.DisplayMode = current_DisplayMode ;
773 if( ! window->Window.FBConfig )
776 * The "fgChooseFBConfig" returned a null meaning that the visual
777 * context is not available.
778 * Try a couple of variations to see if they will work.
780 if( !( fgState.DisplayMode & GLUT_DOUBLE ) )
782 fgState.DisplayMode |= GLUT_DOUBLE ;
783 window->Window.FBConfig = fgChooseFBConfig( );
784 fgState.DisplayMode &= ~GLUT_DOUBLE;
787 if( fgState.DisplayMode & GLUT_MULTISAMPLE )
789 fgState.DisplayMode &= ~GLUT_MULTISAMPLE ;
790 window->Window.FBConfig = fgChooseFBConfig( );
791 fgState.DisplayMode |= GLUT_MULTISAMPLE;
795 FREEGLUT_INTERNAL_ERROR_EXIT( window->Window.FBConfig != NULL,
796 "FBConfig with necessary capabilities not found", "fgOpenWindow" );
798 /* Get the X visual. */
799 visualInfo = glXGetVisualFromFBConfig( fgDisplay.Display,
800 *(window->Window.FBConfig) );
803 * XXX HINT: the masks should be updated when adding/removing callbacks.
804 * XXX This might speed up message processing. Is that true?
806 * XXX A: Not appreciably, but it WILL make it easier to debug.
807 * XXX Try tracing old GLUT and try tracing freeglut. Old GLUT
808 * XXX turns off events that it doesn't need and is a whole lot
809 * XXX more pleasant to trace. (Think mouse-motion! Tons of
810 * XXX ``bonus'' GUI events stream in.)
813 StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
814 ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
815 VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
816 PointerMotionMask | ButtonMotionMask;
817 winAttr.background_pixmap = None;
818 winAttr.background_pixel = 0;
819 winAttr.border_pixel = 0;
821 winAttr.colormap = XCreateColormap(
822 fgDisplay.Display, fgDisplay.RootWindow,
823 visualInfo->visual, AllocNone
826 mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
828 if( window->IsMenu || ( gameMode == GL_TRUE ) )
830 winAttr.override_redirect = True;
831 mask |= CWOverrideRedirect;
835 x = y = -1; /* default window position */
837 w = h = 300; /* default window size */
839 window->Window.Handle = XCreateWindow(
841 window->Parent == NULL ? fgDisplay.RootWindow :
842 window->Parent->Window.Handle,
844 visualInfo->depth, InputOutput,
845 visualInfo->visual, mask,
850 * The GLX context creation, possibly trying the direct context rendering
851 * or else use the current context if the user has so specified
857 * If there isn't already an OpenGL rendering context for menu
860 if( !fgStructure.MenuContext )
862 fgStructure.MenuContext =
863 (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
864 fgStructure.MenuContext->MContext = fghCreateNewContext( window );
867 /* window->Window.Context = fgStructure.MenuContext->MContext; */
868 window->Window.Context = fghCreateNewContext( window );
870 else if( fgState.UseCurrentContext )
872 window->Window.Context = glXGetCurrentContext( );
874 if( ! window->Window.Context )
875 window->Window.Context = fghCreateNewContext( window );
878 window->Window.Context = fghCreateNewContext( window );
880 #if !defined( __FreeBSD__ ) && !defined( __NetBSD__ )
881 if( !glXIsDirect( fgDisplay.Display, window->Window.Context ) )
883 if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
884 fgError( "Unable to force direct context rendering for window '%s'",
890 * XXX Assume the new window is visible by default
891 * XXX Is this a safe assumption?
893 window->State.Visible = GL_TRUE;
897 sizeHints.flags |= USPosition;
899 sizeHints.flags |= USSize;
902 * Fill in the size hints values now (the x, y, width and height
903 * settings are obsolete, are there any more WMs that support them?)
904 * Unless the X servers actually stop supporting these, we should
905 * continue to fill them in. It is *not* our place to tell the user
906 * that they should replace a window manager that they like, and which
907 * works, just because *we* think that it's not "modern" enough.
912 sizeHints.height = h;
914 wmHints.flags = StateHint;
915 wmHints.initial_state = fgState.ForceIconic ? IconicState : NormalState;
916 /* Prepare the window and iconified window names... */
917 XStringListToTextProperty( (char **) &title, 1, &textProperty );
921 window->Window.Handle,
930 XFree( textProperty.value );
932 XSetWMProtocols( fgDisplay.Display, window->Window.Handle,
933 &fgDisplay.DeleteWindow, 1 );
935 glXMakeContextCurrent(
937 window->Window.Handle,
938 window->Window.Handle,
939 window->Window.Context
942 XMapWindow( fgDisplay.Display, window->Window.Handle );
946 #elif TARGET_HOST_MS_WINDOWS
954 /* Grab the window class we have registered on glutInit(): */
955 atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc );
956 FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found",
961 FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL,
962 "Game mode being invoked on a subwindow",
966 * Set the window creation flags appropriately to make the window
969 flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
973 int worig = w, horig = h;
975 #if !defined(_WIN32_WCE)
976 if ( ( ! isSubWindow ) && ( ! window->IsMenu ) )
979 * Update the window dimensions, taking account of window
980 * decorations. "freeglut" is to create the window with the
981 * outside of its border at (x,y) and with dimensions (w,h).
983 w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
984 h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 +
985 GetSystemMetrics( SM_CYCAPTION );
987 #endif /* defined(_WIN32_WCE) */
994 /* setting State.Width/Height to call resize callback later */
997 if( ! window->IsMenu )
1002 else /* fail safe - Windows can make a window of size (0, 0) */
1003 w = h = 300; /* default window size */
1004 window->State.Width = window->State.Height = -1;
1008 window->State.Width = worig;
1009 window->State.Height = horig;
1013 * There's a small difference between creating the top, child and
1016 flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
1018 if ( window->IsMenu )
1021 exFlags |= WS_EX_TOOLWINDOW;
1023 #if !defined(_WIN32_WCE)
1024 else if( window->Parent == NULL )
1025 flags |= WS_OVERLAPPEDWINDOW;
1031 #if defined(_WIN32_WCE)
1033 wchar_t* wstr = fghWstrFromStr(title);
1035 window->Window.Handle = CreateWindow(
1038 WS_VISIBLE | WS_POPUP,
1048 SHFullScreen(window->Window.Handle, SHFS_HIDESTARTICON);
1049 SHFullScreen(window->Window.Handle, SHFS_HIDESIPBUTTON);
1050 SHFullScreen(window->Window.Handle, SHFS_HIDETASKBAR);
1051 MoveWindow(window->Window.Handle, 0, 0, 240, 320, TRUE);
1052 ShowWindow(window->Window.Handle, SW_SHOW);
1053 UpdateWindow(window->Window.Handle);
1056 window->Window.Handle = CreateWindowEx(
1062 (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
1067 #endif /* defined(_WIN32_WCE) */
1069 if( !( window->Window.Handle ) )
1070 fgError( "Failed to create a window (%s)!", title );
1072 /* Make a menu window always on top - fix Feature Request 947118 */
1073 if( window->IsMenu || gameMode )
1075 window->Window.Handle,
1078 SWP_NOMOVE | SWP_NOSIZE
1081 /* Hack to remove the caption (title bar) and/or border
1082 * and all the system menu controls.
1084 WindowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
1085 if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
1087 SetWindowLong ( window->Window.Handle, GWL_STYLE,
1088 WindowStyle & ~(WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
1090 else if ( fgState.DisplayMode & GLUT_BORDERLESS )
1092 SetWindowLong ( window->Window.Handle, GWL_STYLE,
1093 WindowStyle & ~(WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
1095 /* SetWindowPos(window->Window.Handle, NULL, 0, 0, 0, 0,
1096 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); */
1099 #if defined(_WIN32_WCE)
1100 ShowWindow( window->Window.Handle, SW_SHOW );
1102 ShowWindow( window->Window.Handle,
1103 fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW );
1104 #endif /* defined(_WIN32_WCE) */
1106 UpdateWindow( window->Window.Handle );
1107 ShowCursor( TRUE ); /* XXX Old comments say "hide cursor"! */
1111 fgSetWindow( window );
1113 window->Window.DoubleBuffered =
1114 ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0;
1116 if ( ! window->Window.DoubleBuffered )
1118 glDrawBuffer ( GL_FRONT );
1119 glReadBuffer ( GL_FRONT );
1124 * Closes a window, destroying the frame and OpenGL context
1126 void fgCloseWindow( SFG_Window* window )
1128 #if TARGET_HOST_POSIX_X11
1130 if( window->Window.Context )
1131 glXDestroyContext( fgDisplay.Display, window->Window.Context );
1132 XFree( window->Window.FBConfig );
1133 XDestroyWindow( fgDisplay.Display, window->Window.Handle );
1134 /* XFlush( fgDisplay.Display ); */ /* XXX Shouldn't need this */
1136 #elif TARGET_HOST_MS_WINDOWS
1138 /* Make sure we don't close a window with current context active */
1139 if( fgStructure.CurrentWindow == window )
1140 wglMakeCurrent( NULL, NULL );
1143 * Step through the list of windows. If the rendering context
1144 * is not being used by another window, then we delete it.
1150 for( iter = (SFG_Window *)fgStructure.Windows.First;
1152 iter = (SFG_Window *)iter->Node.Next )
1154 if( ( iter->Window.Context == window->Window.Context ) &&
1155 ( iter != window ) )
1160 wglDeleteContext( window->Window.Context );
1163 DestroyWindow( window->Window.Handle );
1168 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
1171 * Creates a new top-level freeglut window
1173 int FGAPIENTRY glutCreateWindow( const char* title )
1175 /* XXX GLUT does not exit; it simply calls "glutInit" quietly if the
1176 * XXX application has not already done so. The "freeglut" community
1177 * XXX decided not to go this route (freeglut-developer e-mail from
1178 * XXX Steve Baker, 12/16/04, 4:22 PM CST, "Re: [Freeglut-developer]
1179 * XXX Desired 'freeglut' behaviour when there is no current window"
1181 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateWindow" );
1183 return fgCreateWindow( NULL, title, fgState.Position.Use,
1184 fgState.Position.X, fgState.Position.Y,
1185 fgState.Size.Use, fgState.Size.X, fgState.Size.Y,
1186 GL_FALSE, GL_FALSE )->ID;
1189 #if TARGET_HOST_MS_WINDOWS
1190 int FGAPIENTRY __glutCreateWindowWithExit( const char *title, void (__cdecl *exit_function)(int) )
1192 __glutExitFunc = exit_function;
1193 return glutCreateWindow( title );
1198 * This function creates a sub window.
1200 int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
1203 SFG_Window* window = NULL;
1204 SFG_Window* parent = NULL;
1206 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateSubWindow" );
1207 parent = fgWindowByID( parentID );
1208 freeglut_return_val_if_fail( parent != NULL, 0 );
1211 x = parent->State.Width + x ;
1212 if ( w >= 0 ) x -= w ;
1215 if ( w < 0 ) w = parent->State.Width - x + w ;
1224 y = parent->State.Height + y ;
1225 if ( h >= 0 ) y -= h ;
1228 if ( h < 0 ) h = parent->State.Height - y + h ;
1235 window = fgCreateWindow( parent, "", GL_TRUE, x, y, GL_TRUE, w, h, GL_FALSE, GL_FALSE );
1242 * Destroys a window and all of its subwindows
1244 void FGAPIENTRY glutDestroyWindow( int windowID )
1247 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyWindow" );
1248 window = fgWindowByID( windowID );
1249 freeglut_return_if_fail( window != NULL );
1251 fgExecutionState ExecState = fgState.ExecState;
1252 fgAddToWindowDestroyList( window );
1253 fgState.ExecState = ExecState;
1258 * This function selects the current window
1260 void FGAPIENTRY glutSetWindow( int ID )
1262 SFG_Window* window = NULL;
1264 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindow" );
1265 if( fgStructure.CurrentWindow != NULL )
1266 if( fgStructure.CurrentWindow->ID == ID )
1269 window = fgWindowByID( ID );
1270 if( window == NULL )
1272 fgWarning( "glutSetWindow(): window ID %d not found!", ID );
1276 fgSetWindow( window );
1280 * This function returns the ID number of the current window, 0 if none exists
1282 int FGAPIENTRY glutGetWindow( void )
1284 SFG_Window *win = fgStructure.CurrentWindow;
1286 * Since GLUT did not throw an error if this function was called without a prior call to
1287 * "glutInit", this function shouldn't do so here. Instead let us return a zero.
1288 * See Feature Request "[ 1307049 ] glutInit check".
1290 if ( ! fgState.Initialised )
1293 while ( win && win->IsMenu )
1295 return win ? win->ID : 0;
1299 * This function makes the current window visible
1301 void FGAPIENTRY glutShowWindow( void )
1303 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutShowWindow" );
1304 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutShowWindow" );
1306 #if TARGET_HOST_POSIX_X11
1308 XMapWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
1309 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1311 #elif TARGET_HOST_MS_WINDOWS
1313 ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_SHOW );
1317 fgStructure.CurrentWindow->State.Redisplay = GL_TRUE;
1321 * This function hides the current window
1323 void FGAPIENTRY glutHideWindow( void )
1325 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutHideWindow" );
1326 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutHideWindow" );
1328 #if TARGET_HOST_POSIX_X11
1330 if( fgStructure.CurrentWindow->Parent == NULL )
1331 XWithdrawWindow( fgDisplay.Display,
1332 fgStructure.CurrentWindow->Window.Handle,
1335 XUnmapWindow( fgDisplay.Display,
1336 fgStructure.CurrentWindow->Window.Handle );
1337 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1339 #elif TARGET_HOST_MS_WINDOWS
1341 ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_HIDE );
1345 fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
1349 * Iconify the current window (top-level windows only)
1351 void FGAPIENTRY glutIconifyWindow( void )
1353 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" );
1354 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" );
1356 fgStructure.CurrentWindow->State.Visible = GL_FALSE;
1357 #if TARGET_HOST_POSIX_X11
1359 XIconifyWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
1361 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1363 #elif TARGET_HOST_MS_WINDOWS
1365 ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_MINIMIZE );
1369 fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
1373 * Set the current window's title
1375 void FGAPIENTRY glutSetWindowTitle( const char* title )
1377 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowTitle" );
1378 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowTitle" );
1379 if( ! fgStructure.CurrentWindow->Parent )
1381 #if TARGET_HOST_POSIX_X11
1385 text.value = (unsigned char *) title;
1386 text.encoding = XA_STRING;
1388 text.nitems = strlen( title );
1392 fgStructure.CurrentWindow->Window.Handle,
1396 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1398 #elif TARGET_HOST_MS_WINDOWS
1401 wchar_t* wstr = fghWstrFromStr(title);
1402 SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr );
1406 SetWindowText( fgStructure.CurrentWindow->Window.Handle, title );
1414 * Set the current window's iconified title
1416 void FGAPIENTRY glutSetIconTitle( const char* title )
1418 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetIconTitle" );
1419 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetIconTitle" );
1421 if( ! fgStructure.CurrentWindow->Parent )
1423 #if TARGET_HOST_POSIX_X11
1427 text.value = (unsigned char *) title;
1428 text.encoding = XA_STRING;
1430 text.nitems = strlen( title );
1434 fgStructure.CurrentWindow->Window.Handle,
1438 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1440 #elif TARGET_HOST_MS_WINDOWS
1443 wchar_t* wstr = fghWstrFromStr(title);
1444 SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr );
1448 SetWindowText( fgStructure.CurrentWindow->Window.Handle, title );
1456 * Change the current window's size
1458 void FGAPIENTRY glutReshapeWindow( int width, int height )
1460 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeWindow" );
1461 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutReshapeWindow" );
1463 if (glutGet(GLUT_FULL_SCREEN))
1465 /* Leave full screen state before resizing. */
1466 glutFullScreenToggle();
1469 fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
1470 fgStructure.CurrentWindow->State.Width = width ;
1471 fgStructure.CurrentWindow->State.Height = height;
1475 * Change the current window's position
1477 void FGAPIENTRY glutPositionWindow( int x, int y )
1479 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPositionWindow" );
1480 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPositionWindow" );
1482 if (glutGet(GLUT_FULL_SCREEN))
1484 /* Leave full screen state before moving. */
1485 glutFullScreenToggle();
1488 #if TARGET_HOST_POSIX_X11
1490 XMoveWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
1492 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1494 #elif TARGET_HOST_MS_WINDOWS
1499 /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
1500 GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
1502 fgStructure.CurrentWindow->Window.Handle,
1505 winRect.right - winRect.left,
1506 winRect.bottom - winRect.top,
1515 * Lowers the current window (by Z order change)
1517 void FGAPIENTRY glutPushWindow( void )
1519 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPushWindow" );
1520 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPushWindow" );
1522 #if TARGET_HOST_POSIX_X11
1524 XLowerWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
1526 #elif TARGET_HOST_MS_WINDOWS
1529 fgStructure.CurrentWindow->Window.Handle,
1532 SWP_NOSIZE | SWP_NOMOVE
1539 * Raises the current window (by Z order change)
1541 void FGAPIENTRY glutPopWindow( void )
1543 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPopWindow" );
1544 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPopWindow" );
1546 #if TARGET_HOST_POSIX_X11
1548 XRaiseWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
1550 #elif TARGET_HOST_MS_WINDOWS
1553 fgStructure.CurrentWindow->Window.Handle,
1556 SWP_NOSIZE | SWP_NOMOVE
1563 * Resize the current window so that it fits the whole screen
1565 void FGAPIENTRY glutFullScreen( void )
1567 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
1568 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
1570 if (glutGet(GLUT_FULL_SCREEN))
1572 /* Leave full screen state before resizing. */
1573 glutFullScreenToggle();
1577 #if TARGET_HOST_POSIX_X11
1579 Status status; /* Returned by XGetWindowAttributes(), not checked. */
1580 XWindowAttributes attributes;
1582 status = XGetWindowAttributes(fgDisplay.Display,
1583 fgStructure.CurrentWindow->Window.Handle,
1586 * The "x" and "y" members of "attributes" are the window's coordinates
1587 * relative to its parent, i.e. to the decoration window.
1589 XMoveResizeWindow(fgDisplay.Display,
1590 fgStructure.CurrentWindow->Window.Handle,
1593 fgDisplay.ScreenWidth,
1594 fgDisplay.ScreenHeight);
1596 #elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: what about WinCE */
1599 /* For fullscreen mode, force the top-left corner to 0,0
1600 * and adjust the window rectangle so that the client area
1601 * covers the whole screen.
1606 rect.right = fgDisplay.ScreenWidth;
1607 rect.bottom = fgDisplay.ScreenHeight;
1609 AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
1610 WS_CLIPCHILDREN, FALSE );
1613 * SWP_NOACTIVATE Do not activate the window
1614 * SWP_NOOWNERZORDER Do not change position in z-order
1615 * SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message
1616 * SWP_NOZORDER Retains the current Z order (ignore 2nd param)
1619 SetWindowPos( fgStructure.CurrentWindow->Window.Handle,
1623 rect.right - rect.left,
1624 rect.bottom - rect.top,
1625 SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
1633 * Toggle the window's full screen state.
1635 void FGAPIENTRY glutFullScreenToggle( void )
1637 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" );
1638 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" );
1641 #if TARGET_HOST_POSIX_X11
1643 if (fgDisplay.StateFullScreen != None)
1649 xevent.type = ClientMessage;
1650 xevent.xclient.type = ClientMessage;
1651 xevent.xclient.serial = 0;
1652 xevent.xclient.send_event = True;
1653 xevent.xclient.display = fgDisplay.Display;
1654 xevent.xclient.window = fgStructure.CurrentWindow->Window.Handle;
1655 xevent.xclient.message_type = fgDisplay.State;
1656 xevent.xclient.format = 32;
1657 xevent.xclient.data.l[0] = 2; /* _NET_WM_STATE_TOGGLE */
1658 xevent.xclient.data.l[1] = fgDisplay.StateFullScreen;
1659 xevent.xclient.data.l[2] = 0;
1660 xevent.xclient.data.l[3] = 0;
1661 xevent.xclient.data.l[4] = 0;
1663 /*** Don't really understand how event masks work... ***/
1664 event_mask = SubstructureRedirectMask | SubstructureNotifyMask;
1666 status = XSendEvent(fgDisplay.Display,
1667 fgDisplay.RootWindow,
1671 FREEGLUT_INTERNAL_ERROR_EXIT(status != 0,
1672 "XSendEvent failed",
1673 "glutFullScreenToggle");
1679 * If the window manager is not Net WM compliant, fall back to legacy
1688 * A.Donev: Set and retrieve the window's user data
1690 void* FGAPIENTRY glutGetWindowData( void )
1692 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetWindowData" );
1693 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutGetWindowData" );
1694 return fgStructure.CurrentWindow->UserData;
1697 void FGAPIENTRY glutSetWindowData(void* data)
1699 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowData" );
1700 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowData" );
1701 fgStructure.CurrentWindow->UserData = data;
1704 /*** END OF FILE ***/