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 #include <GL/freeglut.h>
29 #include "freeglut_internal.h"
31 #if defined(_WIN32_WCE)
32 # include <Aygshell.h>
33 # ifdef FREEGLUT_LIB_PRAGMAS
34 # pragma comment( lib, "Aygshell.lib" )
37 static wchar_t* fghWstrFromStr(const char* str)
39 int i,len=strlen(str);
40 wchar_t* wstr = (wchar_t*)malloc(2*len+2);
47 #endif /* defined(_WIN32_WCE) */
50 * TODO BEFORE THE STABLE RELEASE:
52 * fgChooseFBConfig() -- OK, but what about glutInitDisplayString()?
53 * fgSetupPixelFormat -- ignores the display mode settings
54 * fgOpenWindow() -- check the Win32 version, -iconic handling!
55 * fgCloseWindow() -- check the Win32 version
56 * glutCreateWindow() -- Check when default position and size is {-1,-1}
57 * glutCreateSubWindow() -- Check when default position and size is {-1,-1}
58 * glutDestroyWindow() -- check the Win32 version
59 * glutSetWindow() -- check the Win32 version
60 * glutGetWindow() -- OK
61 * glutSetWindowTitle() -- check the Win32 version
62 * glutSetIconTitle() -- check the Win32 version
63 * glutShowWindow() -- check the Win32 version
64 * glutHideWindow() -- check the Win32 version
65 * glutIconifyWindow() -- check the Win32 version
66 * glutReshapeWindow() -- check the Win32 version
67 * glutPositionWindow() -- check the Win32 version
68 * glutPushWindow() -- check the Win32 version
69 * glutPopWindow() -- check the Win32 version
72 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
75 * Chooses a visual basing on the current display mode settings
77 #if TARGET_HOST_POSIX_X11
79 GLXFBConfig* fgChooseFBConfig( void )
81 GLboolean wantIndexedMode = GL_FALSE;
85 /* First we have to process the display mode settings... */
87 * XXX Why is there a semi-colon in this #define? The code
88 * XXX that uses the macro seems to always add more semicolons...
90 #define ATTRIB(a) attributes[where++]=a;
91 #define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);}
93 if( fgState.DisplayMode & GLUT_INDEX )
95 ATTRIB_VAL( GLX_BUFFER_SIZE, 8 );
96 /* Buffer size is selected later. */
98 ATTRIB_VAL( GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT );
99 wantIndexedMode = GL_TRUE;
103 ATTRIB_VAL( GLX_RED_SIZE, 1 );
104 ATTRIB_VAL( GLX_GREEN_SIZE, 1 );
105 ATTRIB_VAL( GLX_BLUE_SIZE, 1 );
106 if( fgState.DisplayMode & GLUT_ALPHA )
107 ATTRIB_VAL( GLX_ALPHA_SIZE, 1 );
110 if( fgState.DisplayMode & GLUT_DOUBLE )
111 ATTRIB_VAL( GLX_DOUBLEBUFFER, True );
113 if( fgState.DisplayMode & GLUT_STEREO )
114 ATTRIB_VAL( GLX_STEREO, True );
116 if( fgState.DisplayMode & GLUT_DEPTH )
117 ATTRIB_VAL( GLX_DEPTH_SIZE, 1 );
119 if( fgState.DisplayMode & GLUT_STENCIL )
120 ATTRIB_VAL( GLX_STENCIL_SIZE, 1 );
122 if( fgState.DisplayMode & GLUT_ACCUM )
124 ATTRIB_VAL( GLX_ACCUM_RED_SIZE, 1 );
125 ATTRIB_VAL( GLX_ACCUM_GREEN_SIZE, 1 );
126 ATTRIB_VAL( GLX_ACCUM_BLUE_SIZE, 1 );
127 if( fgState.DisplayMode & GLUT_ALPHA )
128 ATTRIB_VAL( GLX_ACCUM_ALPHA_SIZE, 1 );
131 if ((fgState.DisplayMode & GLUT_AUX)
132 || (fgState.DisplayMode & GLUT_AUX1)
133 || (fgState.DisplayMode & GLUT_AUX2)
134 || (fgState.DisplayMode & GLUT_AUX3)
135 || (fgState.DisplayMode & GLUT_AUX4))
137 ATTRIB_VAL(GLX_AUX_BUFFERS, fgState.AuxiliaryBufferNumber)
140 if (fgState.DisplayMode & GLUT_MULTISAMPLE)
142 ATTRIB_VAL(GLX_SAMPLE_BUFFERS, 1)
143 ATTRIB_VAL(GLX_SAMPLES, fgState.SampleNumber)
146 /* Push a null at the end of the list */
150 GLXFBConfig * fbconfigArray; /* Array of FBConfigs */
151 GLXFBConfig * fbconfig; /* The FBConfig we want */
152 int fbconfigArraySize; /* Number of FBConfigs in the array */
155 /* Get all FBConfigs that match "attributes". */
156 fbconfigArray = glXChooseFBConfig( fgDisplay.Display,
159 &fbconfigArraySize );
161 if (fbconfigArray != NULL)
163 int result; /* Returned by glXGetFBConfigAttrib, not checked. */
166 if( wantIndexedMode )
169 * In index mode, we want the largest buffer size, i.e. visual
170 * depth. Here, FBConfigs are sorted by increasing buffer size
171 * first, so FBConfigs with the largest size come last.
174 int bufferSizeMin, bufferSizeMax;
176 /* Get bufferSizeMin. */
178 glXGetFBConfigAttrib( fgDisplay.Display,
182 /* Get bufferSizeMax. */
184 glXGetFBConfigAttrib( fgDisplay.Display,
185 fbconfigArray[fbconfigArraySize - 1],
189 if (bufferSizeMax > bufferSizeMin)
192 * Free and reallocate fbconfigArray, keeping only FBConfigs
193 * with the largest buffer size.
195 XFree(fbconfigArray);
197 /* Add buffer size token at the end of the list. */
199 ATTRIB_VAL( GLX_BUFFER_SIZE, bufferSizeMax );
202 fbconfigArray = glXChooseFBConfig( fgDisplay.Display,
205 &fbconfigArraySize );
210 * We now have an array of FBConfigs, the first one being the "best"
211 * one. So we should return only this FBConfig:
215 * - pick the XID of the FBConfig we want
216 * result = glXGetFBConfigAttrib( fgDisplay.Display,
222 * XFree(fbconfigArray);
224 * - reset "attributes" with the XID
226 * ATTRIB_VAL( GLX_FBCONFIG_ID, fbconfigXID );
229 * - get our FBConfig only
230 * fbconfig = glXChooseFBConfig( fgDisplay.Display,
233 * &fbconfigArraySize );
235 * However, for some configurations (for instance multisampling with
236 * Mesa 6.5.2 and ATI drivers), this does not work:
237 * glXChooseFBConfig returns NULL, whereas fbconfigXID is a valid
238 * XID. Further investigation is needed.
240 * So, for now, we return the whole array of FBConfigs. This should
241 * not produce any side effects elsewhere.
243 fbconfig = fbconfigArray;
256 * Setup the pixel format for a Win32 window
258 #if TARGET_HOST_MS_WINDOWS
259 /* The following include file is available from SGI but is not standard:
260 * #include <GL/wglext.h>
261 * So we copy the necessary parts out of it.
262 * XXX: should local definitions for extensions be put in a separate include file?
264 typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
266 typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
268 #define WGL_DRAW_TO_WINDOW_ARB 0x2001
269 #define WGL_ACCELERATION_ARB 0x2003
270 #define WGL_SUPPORT_OPENGL_ARB 0x2010
271 #define WGL_DOUBLE_BUFFER_ARB 0x2011
272 #define WGL_COLOR_BITS_ARB 0x2014
273 #define WGL_ALPHA_BITS_ARB 0x201B
274 #define WGL_DEPTH_BITS_ARB 0x2022
275 #define WGL_STENCIL_BITS_ARB 0x2023
276 #define WGL_FULL_ACCELERATION_ARB 0x2027
278 #define WGL_SAMPLE_BUFFERS_ARB 0x2041
279 #define WGL_SAMPLES_ARB 0x2042
282 GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
283 unsigned char layer_type )
285 #if defined(_WIN32_WCE)
288 PIXELFORMATDESCRIPTOR* ppfd, pfd;
289 int flags, pixelformat;
291 freeglut_return_val_if_fail( window != NULL, 0 );
292 flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
293 if( fgState.DisplayMode & GLUT_DOUBLE )
294 flags |= PFD_DOUBLEBUFFER;
296 if( fgState.DisplayMode & GLUT_STEREO )
299 #if defined(_MSC_VER)
300 #pragma message( "fgSetupPixelFormat(): there is still some work to do here!" )
303 /* Specify which pixel format do we opt for... */
304 pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
308 if( fgState.DisplayMode & GLUT_INDEX )
310 pfd.iPixelType = PFD_TYPE_COLORINDEX;
318 pfd.iPixelType = PFD_TYPE_RGBA;
322 if ( fgState.DisplayMode & GLUT_ALPHA )
334 pfd.cAccumRedBits = 0;
335 pfd.cAccumGreenBits = 0;
336 pfd.cAccumBlueBits = 0;
337 pfd.cAccumAlphaBits = 0;
340 pfd.cStencilBits = 0;
343 pfd.cStencilBits = 8;
345 if( fgState.DisplayMode & GLUT_AUX4 )
347 else if( fgState.DisplayMode & GLUT_AUX3 )
349 else if( fgState.DisplayMode & GLUT_AUX2 )
351 else if( fgState.DisplayMode & GLUT_AUX1 )
356 pfd.iLayerType = layer_type;
359 pfd.dwVisibleMask = 0;
360 pfd.dwDamageMask = 0;
362 pfd.cColorBits = (BYTE) GetDeviceCaps( window->Window.Device, BITSPIXEL );
365 pixelformat = ChoosePixelFormat( window->Window.Device, ppfd );
367 /* windows hack for multismapling */
368 if (fgState.DisplayMode&GLUT_MULTISAMPLE)
370 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetEntensionsStringARB=NULL;
371 HGLRC rc, rc_before=wglGetCurrentContext();
373 HDC hDC, hDC_before=wglGetCurrentDC();
377 /* create a dummy window */
378 ZeroMemory(&wndCls, sizeof(wndCls));
379 wndCls.lpfnWndProc = DefWindowProc;
380 wndCls.hInstance = fgDisplay.Instance;
381 wndCls.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
382 wndCls.lpszClassName = _T("FREEGLUT_dummy");
383 atom = RegisterClass( &wndCls );
385 hWnd=CreateWindow((LPCSTR)atom, _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW , 0,0,0,0, 0, 0, fgDisplay.Instance, 0 );
387 SetPixelFormat( hDC, pixelformat, ppfd );
389 rc = wglCreateContext( hDC );
390 wglMakeCurrent(hDC, rc);
392 wglGetEntensionsStringARB=(PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
393 if (wglGetEntensionsStringARB)
395 const char * pWglExtString=wglGetEntensionsStringARB(hDC);
398 if (strstr(pWglExtString, "WGL_ARB_multisample"))
400 int pAttributes[100];
404 float fAttributes[] = {0,0};
406 PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARBProc=NULL;
408 wglChoosePixelFormatARBProc=(PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
409 if ( wglChoosePixelFormatARBProc )
411 pAttributes[iCounter++]=WGL_DRAW_TO_WINDOW_ARB; pAttributes[iCounter++]=GL_TRUE;
412 pAttributes[iCounter++]=WGL_SUPPORT_OPENGL_ARB; pAttributes[iCounter++]=GL_TRUE;
413 pAttributes[iCounter++]=WGL_ACCELERATION_ARB; pAttributes[iCounter++]=WGL_FULL_ACCELERATION_ARB;
415 pAttributes[iCounter++]=WGL_COLOR_BITS_ARB; pAttributes[iCounter++]=pfd.cColorBits ;
416 pAttributes[iCounter++]=WGL_ALPHA_BITS_ARB; pAttributes[iCounter++]=pfd.cAlphaBits;
417 pAttributes[iCounter++]=WGL_DEPTH_BITS_ARB; pAttributes[iCounter++]=pfd.cDepthBits;
418 pAttributes[iCounter++]=WGL_STENCIL_BITS_ARB; pAttributes[iCounter++]=pfd.cStencilBits;
420 pAttributes[iCounter++]=WGL_DOUBLE_BUFFER_ARB; pAttributes[iCounter++]=(fgState.DisplayMode & GLUT_DOUBLE)!=0;
421 pAttributes[iCounter++]=WGL_SAMPLE_BUFFERS_ARB; pAttributes[iCounter++]=GL_TRUE;
422 pAttributes[iCounter++]=WGL_SAMPLES_ARB; pAttributes[iCounter++]=4;
423 pAttributes[iCounter++]=0; pAttributes[iCounter++]=0; /* terminator */
425 bValid = wglChoosePixelFormatARBProc(window->Window.Device,pAttributes,fAttributes,1,&iPixelFormat,&numFormats);
427 if (bValid && numFormats>0)
428 pixelformat=iPixelFormat;
431 wglMakeCurrent( hDC_before, rc_before);
432 wglDeleteContext(rc);
433 ReleaseDC(hWnd, hDC);
435 UnregisterClass(_T("FREEGLUT_dummy"), fgDisplay.Instance);
440 if( pixelformat == 0 )
445 return SetPixelFormat( window->Window.Device, pixelformat, ppfd );
446 #endif /* defined(_WIN32_WCE) */
448 #endif /* TARGET_HOST_MS_WINDOWS */
451 * Sets the OpenGL context and the fgStructure "Current Window" pointer to
452 * the window structure passed in.
454 void fgSetWindow ( SFG_Window *window )
456 #if TARGET_HOST_POSIX_X11
458 glXMakeContextCurrent(
460 window->Window.Handle,
461 window->Window.Handle,
462 window->Window.Context
464 #elif TARGET_HOST_MS_WINDOWS
465 if( fgStructure.CurrentWindow )
466 ReleaseDC( fgStructure.CurrentWindow->Window.Handle,
467 fgStructure.CurrentWindow->Window.Device );
471 window->Window.Device = GetDC( window->Window.Handle );
473 window->Window.Device,
474 window->Window.Context
478 fgStructure.CurrentWindow = window;
483 * Opens a window. Requires a SFG_Window object created and attached
484 * to the freeglut structure. OpenGL context is created here.
486 void fgOpenWindow( SFG_Window* window, const char* title,
487 GLboolean positionUse, int x, int y,
488 GLboolean sizeUse, int w, int h,
489 GLboolean gameMode, GLboolean isSubWindow )
491 #if TARGET_HOST_POSIX_X11
492 XVisualInfo * visualInfo;
493 XSetWindowAttributes winAttr;
494 XTextProperty textProperty;
495 XSizeHints sizeHints;
498 int renderType; /* GLX_RGBA_TYPE or GLX_COLOR_INDEX_TYPE */
499 unsigned int current_DisplayMode = fgState.DisplayMode ;
501 /* Save the display mode if we are creating a menu window */
502 if( window->IsMenu && ( ! fgStructure.MenuContext ) )
503 fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB ;
505 window->Window.FBConfig = fgChooseFBConfig( );
507 if( window->IsMenu && ( ! fgStructure.MenuContext ) )
508 fgState.DisplayMode = current_DisplayMode ;
510 if( ! window->Window.FBConfig )
513 * The "fgChooseFBConfig" returned a null meaning that the visual
514 * context is not available.
515 * Try a couple of variations to see if they will work.
517 if( !( fgState.DisplayMode & GLUT_DOUBLE ) )
519 fgState.DisplayMode |= GLUT_DOUBLE ;
520 window->Window.FBConfig = fgChooseFBConfig( );
521 fgState.DisplayMode &= ~GLUT_DOUBLE;
524 if( fgState.DisplayMode & GLUT_MULTISAMPLE )
526 fgState.DisplayMode &= ~GLUT_MULTISAMPLE ;
527 window->Window.FBConfig = fgChooseFBConfig( );
528 fgState.DisplayMode |= GLUT_MULTISAMPLE;
532 FREEGLUT_INTERNAL_ERROR_EXIT( window->Window.FBConfig != NULL,
533 "FBConfig with necessary capabilities not found", "fgOpenWindow" );
535 /* Get the X visual. */
536 visualInfo = glXGetVisualFromFBConfig( fgDisplay.Display,
537 *(window->Window.FBConfig) );
540 * XXX HINT: the masks should be updated when adding/removing callbacks.
541 * XXX This might speed up message processing. Is that true?
543 * XXX A: Not appreciably, but it WILL make it easier to debug.
544 * XXX Try tracing old GLUT and try tracing freeglut. Old GLUT
545 * XXX turns off events that it doesn't need and is a whole lot
546 * XXX more pleasant to trace. (Think mouse-motion! Tons of
547 * XXX ``bonus'' GUI events stream in.)
550 StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
551 ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
552 VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
553 PointerMotionMask | ButtonMotionMask;
554 winAttr.background_pixmap = None;
555 winAttr.background_pixel = 0;
556 winAttr.border_pixel = 0;
558 winAttr.colormap = XCreateColormap(
559 fgDisplay.Display, fgDisplay.RootWindow,
560 visualInfo->visual, AllocNone
563 mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
565 if( window->IsMenu || ( gameMode == GL_TRUE ) )
567 winAttr.override_redirect = True;
568 mask |= CWOverrideRedirect;
572 x = y = -1; /* default window position */
574 w = h = 300; /* default window size */
576 window->Window.Handle = XCreateWindow(
578 window->Parent == NULL ? fgDisplay.RootWindow :
579 window->Parent->Window.Handle,
581 visualInfo->depth, InputOutput,
582 visualInfo->visual, mask,
587 * The GLX context creation, possibly trying the direct context rendering
588 * or else use the current context if the user has so specified
591 /* Set renderType. */
592 if( window->IsMenu && ( ! fgStructure.MenuContext ) )
594 /* Display mode has been set to GLUT_RGB. */
595 renderType = GLX_RGBA_TYPE;
597 else if (fgState.DisplayMode & GLUT_INDEX)
599 renderType = GLX_COLOR_INDEX_TYPE;
603 renderType = GLX_RGBA_TYPE;
609 * If there isn't already an OpenGL rendering context for menu
612 if( !fgStructure.MenuContext )
614 fgStructure.MenuContext =
615 (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
616 fgStructure.MenuContext->MContext = glXCreateNewContext(
617 fgDisplay.Display, *(window->Window.FBConfig), renderType,
618 NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
622 /* window->Window.Context = fgStructure.MenuContext->MContext; */
623 window->Window.Context = glXCreateNewContext(
624 fgDisplay.Display, *(window->Window.FBConfig), renderType,
625 NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
628 else if( fgState.UseCurrentContext )
630 window->Window.Context = glXGetCurrentContext( );
632 if( ! window->Window.Context )
633 window->Window.Context = glXCreateNewContext(
634 fgDisplay.Display, *(window->Window.FBConfig), renderType,
635 NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
639 window->Window.Context = glXCreateNewContext(
640 fgDisplay.Display, *(window->Window.FBConfig), renderType,
641 NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
644 #if !defined( __FreeBSD__ ) && !defined( __NetBSD__ )
645 if( !glXIsDirect( fgDisplay.Display, window->Window.Context ) )
647 if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
648 fgError( "Unable to force direct context rendering for window '%s'",
650 else if( fgState.DirectContext == GLUT_TRY_DIRECT_CONTEXT )
651 fgWarning( "Unable to create direct context rendering for window '%s'\nThis may hurt performance.",
657 * XXX Assume the new window is visible by default
658 * XXX Is this a safe assumption?
660 window->State.Visible = GL_TRUE;
664 sizeHints.flags |= USPosition;
666 sizeHints.flags |= USSize;
669 * Fill in the size hints values now (the x, y, width and height
670 * settings are obsolete, are there any more WMs that support them?)
671 * Unless the X servers actually stop supporting these, we should
672 * continue to fill them in. It is *not* our place to tell the user
673 * that they should replace a window manager that they like, and which
674 * works, just because *we* think that it's not "modern" enough.
679 sizeHints.height = h;
681 wmHints.flags = StateHint;
682 wmHints.initial_state = fgState.ForceIconic ? IconicState : NormalState;
683 /* Prepare the window and iconified window names... */
684 XStringListToTextProperty( (char **) &title, 1, &textProperty );
688 window->Window.Handle,
697 XFree( textProperty.value );
699 XSetWMProtocols( fgDisplay.Display, window->Window.Handle,
700 &fgDisplay.DeleteWindow, 1 );
702 glXMakeContextCurrent(
704 window->Window.Handle,
705 window->Window.Handle,
706 window->Window.Context
709 XMapWindow( fgDisplay.Display, window->Window.Handle );
713 #elif TARGET_HOST_MS_WINDOWS
721 /* Grab the window class we have registered on glutInit(): */
722 atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc );
723 FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found",
728 FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL,
729 "Game mode being invoked on a subwindow",
733 * Set the window creation flags appropriately to make the window
736 flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
740 int worig = w, horig = h;
742 #if !defined(_WIN32_WCE)
743 if ( ( ! isSubWindow ) && ( ! window->IsMenu ) )
746 * Update the window dimensions, taking account of window
747 * decorations. "freeglut" is to create the window with the
748 * outside of its border at (x,y) and with dimensions (w,h).
750 w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
751 h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 +
752 GetSystemMetrics( SM_CYCAPTION );
754 #endif /* defined(_WIN32_WCE) */
761 /* setting State.Width/Height to call resize callback later */
764 if( ! window->IsMenu )
769 else /* fail safe - Windows can make a window of size (0, 0) */
770 w = h = 300; /* default window size */
771 window->State.Width = window->State.Height = -1;
775 window->State.Width = worig;
776 window->State.Height = horig;
780 * There's a small difference between creating the top, child and
783 flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
785 if ( window->IsMenu )
788 exFlags |= WS_EX_TOOLWINDOW;
790 #if !defined(_WIN32_WCE)
791 else if( window->Parent == NULL )
792 flags |= WS_OVERLAPPEDWINDOW;
798 #if defined(_WIN32_WCE)
800 wchar_t* wstr = fghWstrFromStr(title);
802 window->Window.Handle = CreateWindow(
805 WS_VISIBLE | WS_POPUP,
815 SHFullScreen(window->Window.Handle, SHFS_HIDESTARTICON);
816 SHFullScreen(window->Window.Handle, SHFS_HIDESIPBUTTON);
817 SHFullScreen(window->Window.Handle, SHFS_HIDETASKBAR);
818 MoveWindow(window->Window.Handle, 0, 0, 240, 320, TRUE);
819 ShowWindow(window->Window.Handle, SW_SHOW);
820 UpdateWindow(window->Window.Handle);
823 window->Window.Handle = CreateWindowEx(
829 (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
834 #endif /* defined(_WIN32_WCE) */
836 if( !( window->Window.Handle ) )
837 fgError( "Failed to create a window (%s)!", title );
839 /* Make a menu window always on top - fix Feature Request 947118 */
840 if( window->IsMenu || gameMode )
842 window->Window.Handle,
845 SWP_NOMOVE | SWP_NOSIZE
848 /* Hack to remove the caption (title bar) and/or border
849 * and all the system menu controls.
851 WindowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
852 if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
854 SetWindowLong ( window->Window.Handle, GWL_STYLE,
855 WindowStyle & ~(WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
857 else if ( fgState.DisplayMode & GLUT_BORDERLESS )
859 SetWindowLong ( window->Window.Handle, GWL_STYLE,
860 WindowStyle & ~(WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
862 /* SetWindowPos(window->Window.Handle, NULL, 0, 0, 0, 0,
863 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); */
866 #if defined(_WIN32_WCE)
867 ShowWindow( window->Window.Handle, SW_SHOW );
869 ShowWindow( window->Window.Handle,
870 fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW );
871 #endif /* defined(_WIN32_WCE) */
873 UpdateWindow( window->Window.Handle );
874 ShowCursor( TRUE ); /* XXX Old comments say "hide cursor"! */
878 fgSetWindow( window );
880 window->Window.DoubleBuffered =
881 ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0;
883 if ( ! window->Window.DoubleBuffered )
885 glDrawBuffer ( GL_FRONT );
886 glReadBuffer ( GL_FRONT );
891 * Closes a window, destroying the frame and OpenGL context
893 void fgCloseWindow( SFG_Window* window )
895 #if TARGET_HOST_POSIX_X11
897 glXDestroyContext( fgDisplay.Display, window->Window.Context );
898 XFree( window->Window.FBConfig );
899 XDestroyWindow( fgDisplay.Display, window->Window.Handle );
900 /* XFlush( fgDisplay.Display ); */ /* XXX Shouldn't need this */
902 #elif TARGET_HOST_MS_WINDOWS
904 /* Make sure we don't close a window with current context active */
905 if( fgStructure.CurrentWindow == window )
906 wglMakeCurrent( NULL, NULL );
909 * Step through the list of windows. If the rendering context
910 * is not being used by another window, then we delete it.
916 for( iter = (SFG_Window *)fgStructure.Windows.First;
918 iter = (SFG_Window *)iter->Node.Next )
920 if( ( iter->Window.Context == window->Window.Context ) &&
926 wglDeleteContext( window->Window.Context );
929 DestroyWindow( window->Window.Handle );
934 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
937 * Creates a new top-level freeglut window
939 int FGAPIENTRY glutCreateWindow( const char* title )
941 /* XXX GLUT does not exit; it simply calls "glutInit" quietly if the
942 * XXX application has not already done so. The "freeglut" community
943 * XXX decided not to go this route (freeglut-developer e-mail from
944 * XXX Steve Baker, 12/16/04, 4:22 PM CST, "Re: [Freeglut-developer]
945 * XXX Desired 'freeglut' behaviour when there is no current window"
947 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateWindow" );
949 return fgCreateWindow( NULL, title, fgState.Position.Use,
950 fgState.Position.X, fgState.Position.Y,
951 fgState.Size.Use, fgState.Size.X, fgState.Size.Y,
952 GL_FALSE, GL_FALSE )->ID;
956 * This function creates a sub window.
958 int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
961 SFG_Window* window = NULL;
962 SFG_Window* parent = NULL;
964 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateSubWindow" );
965 parent = fgWindowByID( parentID );
966 freeglut_return_val_if_fail( parent != NULL, 0 );
969 x = parent->State.Width + x ;
970 if ( w >= 0 ) x -= w ;
973 if ( w < 0 ) w = parent->State.Width - x + w ;
982 y = parent->State.Height + y ;
983 if ( h >= 0 ) y -= h ;
986 if ( h < 0 ) h = parent->State.Height - y + h ;
993 window = fgCreateWindow( parent, "", GL_TRUE, x, y, GL_TRUE, w, h, GL_FALSE, GL_FALSE );
1000 * Destroys a window and all of its subwindows
1002 void FGAPIENTRY glutDestroyWindow( int windowID )
1005 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyWindow" );
1006 window = fgWindowByID( windowID );
1007 freeglut_return_if_fail( window != NULL );
1009 fgExecutionState ExecState = fgState.ExecState;
1010 fgAddToWindowDestroyList( window );
1011 fgState.ExecState = ExecState;
1016 * This function selects the current window
1018 void FGAPIENTRY glutSetWindow( int ID )
1020 SFG_Window* window = NULL;
1022 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindow" );
1023 if( fgStructure.CurrentWindow != NULL )
1024 if( fgStructure.CurrentWindow->ID == ID )
1027 window = fgWindowByID( ID );
1028 if( window == NULL )
1030 fgWarning( "glutSetWindow(): window ID %d not found!", ID );
1034 fgSetWindow( window );
1038 * This function returns the ID number of the current window, 0 if none exists
1040 int FGAPIENTRY glutGetWindow( void )
1042 SFG_Window *win = fgStructure.CurrentWindow;
1044 * Since GLUT did not throw an error if this function was called without a prior call to
1045 * "glutInit", this function shouldn't do so here. Instead let us return a zero.
1046 * See Feature Request "[ 1307049 ] glutInit check".
1048 if ( ! fgState.Initialised )
1051 while ( win && win->IsMenu )
1053 return win ? win->ID : 0;
1057 * This function makes the current window visible
1059 void FGAPIENTRY glutShowWindow( void )
1061 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutShowWindow" );
1062 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutShowWindow" );
1064 #if TARGET_HOST_POSIX_X11
1066 XMapWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
1067 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1069 #elif TARGET_HOST_MS_WINDOWS
1071 ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_SHOW );
1075 fgStructure.CurrentWindow->State.Redisplay = GL_TRUE;
1079 * This function hides the current window
1081 void FGAPIENTRY glutHideWindow( void )
1083 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutHideWindow" );
1084 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutHideWindow" );
1086 #if TARGET_HOST_POSIX_X11
1088 if( fgStructure.CurrentWindow->Parent == NULL )
1089 XWithdrawWindow( fgDisplay.Display,
1090 fgStructure.CurrentWindow->Window.Handle,
1093 XUnmapWindow( fgDisplay.Display,
1094 fgStructure.CurrentWindow->Window.Handle );
1095 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1097 #elif TARGET_HOST_MS_WINDOWS
1099 ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_HIDE );
1103 fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
1107 * Iconify the current window (top-level windows only)
1109 void FGAPIENTRY glutIconifyWindow( void )
1111 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" );
1112 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" );
1114 fgStructure.CurrentWindow->State.Visible = GL_FALSE;
1115 #if TARGET_HOST_POSIX_X11
1117 XIconifyWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
1119 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1121 #elif TARGET_HOST_MS_WINDOWS
1123 ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_MINIMIZE );
1127 fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
1131 * Set the current window's title
1133 void FGAPIENTRY glutSetWindowTitle( const char* title )
1135 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowTitle" );
1136 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowTitle" );
1137 if( ! fgStructure.CurrentWindow->Parent )
1139 #if TARGET_HOST_POSIX_X11
1143 text.value = (unsigned char *) title;
1144 text.encoding = XA_STRING;
1146 text.nitems = strlen( title );
1150 fgStructure.CurrentWindow->Window.Handle,
1154 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1156 #elif TARGET_HOST_MS_WINDOWS
1159 wchar_t* wstr = fghWstrFromStr(title);
1160 SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr );
1164 SetWindowText( fgStructure.CurrentWindow->Window.Handle, title );
1172 * Set the current window's iconified title
1174 void FGAPIENTRY glutSetIconTitle( const char* title )
1176 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetIconTitle" );
1177 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetIconTitle" );
1179 if( ! fgStructure.CurrentWindow->Parent )
1181 #if TARGET_HOST_POSIX_X11
1185 text.value = (unsigned char *) title;
1186 text.encoding = XA_STRING;
1188 text.nitems = strlen( title );
1192 fgStructure.CurrentWindow->Window.Handle,
1196 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1198 #elif TARGET_HOST_MS_WINDOWS
1201 wchar_t* wstr = fghWstrFromStr(title);
1202 SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr );
1206 SetWindowText( fgStructure.CurrentWindow->Window.Handle, title );
1214 * Change the current window's size
1216 void FGAPIENTRY glutReshapeWindow( int width, int height )
1218 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeWindow" );
1219 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutReshapeWindow" );
1221 fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
1222 fgStructure.CurrentWindow->State.Width = width ;
1223 fgStructure.CurrentWindow->State.Height = height;
1227 * Change the current window's position
1229 void FGAPIENTRY glutPositionWindow( int x, int y )
1231 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPositionWindow" );
1232 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPositionWindow" );
1234 #if TARGET_HOST_POSIX_X11
1236 XMoveWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
1238 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1240 #elif TARGET_HOST_MS_WINDOWS
1245 /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
1246 GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
1248 fgStructure.CurrentWindow->Window.Handle,
1251 winRect.right - winRect.left,
1252 winRect.bottom - winRect.top,
1261 * Lowers the current window (by Z order change)
1263 void FGAPIENTRY glutPushWindow( void )
1265 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPushWindow" );
1266 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPushWindow" );
1268 #if TARGET_HOST_POSIX_X11
1270 XLowerWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
1272 #elif TARGET_HOST_MS_WINDOWS
1275 fgStructure.CurrentWindow->Window.Handle,
1278 SWP_NOSIZE | SWP_NOMOVE
1285 * Raises the current window (by Z order change)
1287 void FGAPIENTRY glutPopWindow( void )
1289 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPopWindow" );
1290 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPopWindow" );
1292 #if TARGET_HOST_POSIX_X11
1294 XRaiseWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
1296 #elif TARGET_HOST_MS_WINDOWS
1299 fgStructure.CurrentWindow->Window.Handle,
1302 SWP_NOSIZE | SWP_NOMOVE
1309 * Resize the current window so that it fits the whole screen
1311 void FGAPIENTRY glutFullScreen( void )
1313 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
1314 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
1317 #if TARGET_HOST_POSIX_X11
1323 fgStructure.CurrentWindow->Window.Handle,
1325 fgDisplay.ScreenWidth,
1326 fgDisplay.ScreenHeight
1329 XFlush( fgDisplay.Display ); /* This is needed */
1331 XTranslateCoordinates(
1333 fgStructure.CurrentWindow->Window.Handle,
1334 fgDisplay.RootWindow,
1342 fgStructure.CurrentWindow->Window.Handle,
1345 XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
1347 #elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: what about WinCE */
1350 /* For fullscreen mode, force the top-left corner to 0,0
1351 * and adjust the window rectangle so that the client area
1352 * covers the whole screen.
1357 rect.right = fgDisplay.ScreenWidth;
1358 rect.bottom = fgDisplay.ScreenHeight;
1360 AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
1361 WS_CLIPCHILDREN, FALSE );
1364 * SWP_NOACTIVATE Do not activate the window
1365 * SWP_NOOWNERZORDER Do not change position in z-order
1366 * SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message
1367 * SWP_NOZORDER Retains the current Z order (ignore 2nd param)
1370 SetWindowPos( fgStructure.CurrentWindow->Window.Handle,
1374 rect.right - rect.left,
1375 rect.bottom - rect.top,
1376 SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
1384 * A.Donev: Set and retrieve the window's user data
1386 void* FGAPIENTRY glutGetWindowData( void )
1388 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetWindowData" );
1389 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutGetWindowData" );
1390 return fgStructure.CurrentWindow->UserData;
1393 void FGAPIENTRY glutSetWindowData(void* data)
1395 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowData" );
1396 FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowData" );
1397 fgStructure.CurrentWindow->UserData = data;
1400 /*** END OF FILE ***/