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 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #include "../include/GL/freeglut.h"
33 #include "freeglut_internal.h"
34 
35 /*
36  * TODO BEFORE THE STABLE RELEASE:
37  *
38  *  fgChooseVisual()        -- OK, but what about glutInitDisplayString()?
39  *  fgSetupPixelFormat      -- ignores the display mode settings
40  *  fgOpenWindow()          -- check the Win32 version, -iconic handling!
41  *  fgCloseWindow()         -- check the Win32 version
42  *  glutCreateWindow()      -- Check when default position and size is {-1,-1}
43  *  glutCreateSubWindow()   -- Check when default position and size is {-1,-1}
44  *  glutDestroyWindow()     -- check the Win32 version
45  *  glutSetWindow()         -- check the Win32 version
46  *  glutGetWindow()         -- OK
47  *  glutSetWindowTitle()    -- check the Win32 version
48  *  glutSetIconTitle()      -- check the Win32 version
49  *  glutShowWindow()        -- check the Win32 version
50  *  glutHideWindow()        -- check the Win32 version
51  *  glutIconifyWindow()     -- check the Win32 version
52  *  glutReshapeWindow()     -- check the Win32 version
53  *  glutPositionWindow()    -- check the Win32 version
54  *  glutPushWindow()        -- check the Win32 version
55  *  glutPopWindow()         -- check the Win32 version
56  */
57 
58 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
59 
60 /*
61  * Chooses a visual basing on the current display mode settings
62  */
63 #if TARGET_HOST_UNIX_X11
64 
fgChooseVisual(void)65 XVisualInfo* fgChooseVisual( void )
66 {
67 #define BUFFER_SIZES 6
68     int bufferSize[BUFFER_SIZES] = { 16, 12, 8, 4, 2, 1 };
69     GLboolean wantIndexedMode = GL_FALSE;
70     int attributes[ 32 ];
71     int where = 0;
72 
73     /*
74      * First we have to process the display mode settings...
75      */
76 /*
77  * Why is there a semi-colon in this #define?  The code
78  * that uses the macro seems to always add more semicolons...
79  */
80 #define ATTRIB(a) attributes[where++]=a;
81 #define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);}
82 
83     if( fgState.DisplayMode & GLUT_INDEX )
84     {
85         ATTRIB_VAL( GLX_BUFFER_SIZE, 8 );
86         wantIndexedMode = GL_TRUE;
87     }
88     else
89     {
90         ATTRIB( GLX_RGBA );
91         ATTRIB_VAL( GLX_RED_SIZE,   1 );
92         ATTRIB_VAL( GLX_GREEN_SIZE, 1 );
93         ATTRIB_VAL( GLX_BLUE_SIZE,  1 );
94         if( fgState.DisplayMode & GLUT_ALPHA )
95             ATTRIB_VAL( GLX_ALPHA_SIZE, 1 );
96     }
97 
98     if( fgState.DisplayMode & GLUT_DOUBLE )
99         ATTRIB( GLX_DOUBLEBUFFER );
100 
101     if( fgState.DisplayMode & GLUT_STEREO )
102         ATTRIB( GLX_STEREO );
103 
104     if( fgState.DisplayMode & GLUT_DEPTH )
105         ATTRIB_VAL( GLX_DEPTH_SIZE, 1 );
106 
107     if( fgState.DisplayMode & GLUT_STENCIL )
108         ATTRIB_VAL( GLX_STENCIL_SIZE, 1 );
109 
110     if( fgState.DisplayMode & GLUT_ACCUM )
111     {
112         ATTRIB_VAL( GLX_ACCUM_RED_SIZE,   1 );
113         ATTRIB_VAL( GLX_ACCUM_GREEN_SIZE, 1 );
114         ATTRIB_VAL( GLX_ACCUM_BLUE_SIZE,  1 );
115         if( fgState.DisplayMode & GLUT_ALPHA )
116             ATTRIB_VAL( GLX_ACCUM_ALPHA_SIZE, 1 );
117     }
118 
119     /*
120      * Push a null at the end of the list
121      */
122     ATTRIB( None );
123 
124     if( ! wantIndexedMode )
125         return glXChooseVisual( fgDisplay.Display, fgDisplay.Screen,
126                                 attributes );
127     else
128     {
129         XVisualInfo* visualInfo;
130         int i;
131 
132         /*
133          * In indexed mode, we need to check how many bits of depth can we
134          * achieve.  We do this by trying each possibility from the list
135          * given in the {bufferSize} array.  If we match, we return to caller.
136          */
137         for( i=0; i<BUFFER_SIZES; i++ )
138         {
139             attributes[ 1 ] = bufferSize[ i ];
140             visualInfo = glXChooseVisual( fgDisplay.Display, fgDisplay.Screen,
141                                           attributes );
142             if( visualInfo != NULL )
143                 return visualInfo;
144         }
145         return NULL;
146     }
147 }
148 #endif
149 
150 /*
151  * Setup the pixel format for a Win32 window
152  */
153 #if TARGET_HOST_WIN32
fgSetupPixelFormat(SFG_Window * window,GLboolean checkOnly,unsigned char layer_type)154 GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
155                               unsigned char layer_type )
156 {
157     PIXELFORMATDESCRIPTOR* ppfd, pfd;
158     int flags, pixelformat;
159 
160     freeglut_return_val_if_fail( window != NULL, 0 );
161     flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
162     if( fgState.DisplayMode & GLUT_DOUBLE )
163         flags |= PFD_DOUBLEBUFFER;
164 
165 #pragma message( "fgSetupPixelFormat(): there is still some work to do here!" )
166 
167     /*
168      * Specify which pixel format do we opt for...
169      */
170     pfd.nSize           = sizeof(PIXELFORMATDESCRIPTOR);
171     pfd.nVersion        = 1;
172     pfd.dwFlags         = flags;
173     pfd.iPixelType      = PFD_TYPE_RGBA;
174     pfd.cColorBits      = 24;
175     pfd.cRedBits        = 0;
176     pfd.cRedShift       = 0;
177     pfd.cGreenBits      = 0;
178     pfd.cGreenShift     = 0;
179     pfd.cBlueBits       = 0;
180     pfd.cBlueShift      = 0;
181     pfd.cAlphaBits      = 0;
182     pfd.cAlphaShift     = 0;
183     pfd.cAccumBits      = 0;
184     pfd.cAccumRedBits   = 0;
185     pfd.cAccumGreenBits = 0;
186     pfd.cAccumBlueBits  = 0;
187     pfd.cAccumAlphaBits = 0;
188 #if 0
189     pfd.cDepthBits      = 32;
190     pfd.cStencilBits    = 0;
191 #else
192     pfd.cDepthBits      = 24;
193     pfd.cStencilBits    = 8;
194 #endif
195     pfd.cAuxBuffers     = 0;
196     pfd.iLayerType      = layer_type;
197     pfd.bReserved       = 0;
198     pfd.dwLayerMask     = 0;
199     pfd.dwVisibleMask   = 0;
200     pfd.dwDamageMask    = 0;
201 
202     pfd.cColorBits = (BYTE) GetDeviceCaps( window->Window.Device, BITSPIXEL );
203     ppfd = &pfd;
204 
205     pixelformat = ChoosePixelFormat( window->Window.Device, ppfd );
206     if( pixelformat == 0 )
207         return GL_FALSE;
208 
209     if( checkOnly )
210         return GL_TRUE;
211     return SetPixelFormat( window->Window.Device, pixelformat, ppfd );
212 }
213 #endif
214 
215 /*
216  * Sets the OpenGL context and the fgStructure "Current Window" pointer to
217  * the window structure passed in.
218  */
fgSetWindow(SFG_Window * window)219 void fgSetWindow ( SFG_Window *window )
220 {
221 #if TARGET_HOST_UNIX_X11
222     if ( window )
223         glXMakeCurrent(
224             fgDisplay.Display,
225             window->Window.Handle,
226             window->Window.Context
227         );
228 #elif TARGET_HOST_WIN32
229     if( fgStructure.Window )
230         ReleaseDC( fgStructure.Window->Window.Handle,
231                    fgStructure.Window->Window.Device );
232 
233     if ( window )
234     {
235         window->Window.Device = GetDC( window->Window.Handle );
236         wglMakeCurrent(
237             window->Window.Device,
238             window->Window.Context
239         );
240     }
241 #endif
242     fgStructure.Window = window;
243 }
244 
245 
246 /*
247  * Opens a window. Requires a SFG_Window object created and attached
248  * to the freeglut structure. OpenGL context is created here.
249  */
fgOpenWindow(SFG_Window * window,const char * title,int x,int y,int w,int h,GLboolean gameMode,GLboolean isSubWindow)250 void fgOpenWindow( SFG_Window* window, const char* title,
251                    int x, int y, int w, int h,
252                    GLboolean gameMode, GLboolean isSubWindow )
253 {
254 #if TARGET_HOST_UNIX_X11
255     XSetWindowAttributes winAttr;
256     XTextProperty textProperty;
257     XSizeHints sizeHints;
258     XWMHints wmHints;
259     unsigned long mask;
260 
261     freeglut_assert_ready;
262 
263     /*
264      * XXX fgChooseVisual() is a common part of all three.
265      * XXX With a little thought, we should be able to greatly
266      * XXX simplify this.
267      */
268     if ( !window->IsMenu )
269       window->Window.VisualInfo = fgChooseVisual();
270     else if ( fgStructure.MenuContext )
271         window->Window.VisualInfo = fgChooseVisual();
272     else
273     {
274         unsigned int current_DisplayMode = fgState.DisplayMode ;
275         fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ;
276         window->Window.VisualInfo = fgChooseVisual();
277         fgState.DisplayMode = current_DisplayMode ;
278     }
279 
280     if ( ! window->Window.VisualInfo )
281     {
282         /*
283          * The "fgChooseVisual" returned a null meaning that the visual
284          * context is not available.
285          * Try a couple of variations to see if they will work.
286          */
287         if ( ! ( fgState.DisplayMode & GLUT_DOUBLE ) )
288         {
289             fgState.DisplayMode |= GLUT_DOUBLE ;
290             window->Window.VisualInfo = fgChooseVisual();
291             fgState.DisplayMode &= ~GLUT_DOUBLE ;
292         }
293 
294         /*
295          * GLUT also checks for multi-sampling, but I don't see that
296          * anywhere else in FREEGLUT so I won't bother with it for the moment.
297          */
298     }
299 
300     assert( window->Window.VisualInfo != NULL );
301 
302     /*
303      * XXX HINT: the masks should be updated when adding/removing callbacks.
304      * XXX       This might speed up message processing. Is that true?
305      * XXX
306      * XXX A: Not appreciably, but it WILL make it easier to debug.
307      * XXX    Try tracing old GLUT and try tracing freeglut.  Old GLUT
308      * XXX    turns off events that it doesn't need and is a whole lot
309      * XXX    more pleasant to trace.  (Hint: Think mouse-motion!)
310      * XXX
311      * XXX    It may make a difference in networked environments or on
312      * XXX    some very slow systems, but I think that that is secondary
313      * XXX    to making debugging easier.
314      */
315     winAttr.event_mask        = StructureNotifyMask | SubstructureNotifyMask |
316         ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask |
317         KeyRelease | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
318         PointerMotionMask | ButtonMotionMask;
319     winAttr.background_pixmap = None;
320     winAttr.background_pixel  = 0;
321     winAttr.border_pixel      = 0;
322 
323     winAttr.colormap = XCreateColormap(
324         fgDisplay.Display, fgDisplay.RootWindow,
325         window->Window.VisualInfo->visual, AllocNone
326     );
327 
328     mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
329 
330     if ( window->IsMenu )
331     {
332         winAttr.override_redirect = True;
333         mask |= CWOverrideRedirect;
334     }
335 
336     window->Window.Handle = XCreateWindow(
337         fgDisplay.Display,
338         window->Parent == NULL ? fgDisplay.RootWindow :
339                                  window->Parent->Window.Handle,
340         x, y, w, h, 0,
341         window->Window.VisualInfo->depth, InputOutput,
342         window->Window.VisualInfo->visual, mask,
343         &winAttr
344     );
345 
346     /*
347      * The GLX context creation, possibly trying the direct context rendering
348      *  or else use the current context if the user has so specified
349      */
350     if ( window->IsMenu )
351     {
352         /*
353          * If there isn't already an OpenGL rendering context for menu
354          * windows, make one
355          */
356         if ( !fgStructure.MenuContext )
357         {
358             fgStructure.MenuContext =
359                 (SFG_MenuContext *)malloc ( sizeof(SFG_MenuContext) );
360             fgStructure.MenuContext->VisualInfo = window->Window.VisualInfo;
361             fgStructure.MenuContext->Context = glXCreateContext(
362                 fgDisplay.Display, fgStructure.MenuContext->VisualInfo,
363                 NULL, fgState.ForceDirectContext | fgState.TryDirectContext
364             );
365         }
366 
367 /*      window->Window.Context = fgStructure.MenuContext->Context ; */
368         window->Window.Context = glXCreateContext(
369             fgDisplay.Display, window->Window.VisualInfo,
370             NULL, fgState.ForceDirectContext | fgState.TryDirectContext
371         );
372     }
373     else if ( fgState.UseCurrentContext )
374     {
375       window->Window.Context = glXGetCurrentContext();
376 
377       if ( ! window->Window.Context )
378         window->Window.Context = glXCreateContext(
379             fgDisplay.Display, window->Window.VisualInfo,
380             NULL, fgState.ForceDirectContext | fgState.TryDirectContext
381         );
382     }
383     else
384         window->Window.Context = glXCreateContext(
385             fgDisplay.Display, window->Window.VisualInfo,
386             NULL, fgState.ForceDirectContext | fgState.TryDirectContext
387         );
388 
389     if( fgState.ForceDirectContext &&
390         !glXIsDirect( fgDisplay.Display, window->Window.Context ) )
391         fgError( "unable to force direct context rendering for window '%s'",
392                  title );
393 
394     glXMakeCurrent(
395         fgDisplay.Display,
396         window->Window.Handle,
397         window->Window.Context
398     );
399 
400     /*
401      * XXX Assume the new window is visible by default
402      * XXX Is this a  safe assumption?
403      */
404     window->State.Visible = GL_TRUE;
405 
406     sizeHints.flags = 0;
407     if ( fgState.Position.Use )
408         sizeHints.flags |= USPosition;
409     if ( fgState.Size.Use )
410         sizeHints.flags |= USSize;
411 
412     /*
413      * Fill in the size hints values now (the x, y, width and height
414      * settings are obsolote, are there any more WMs that support them?)
415      * Unless the X servers actually stop supporting these, we should
416      * continue to fill them in.  It is *not* our place to tell the user
417      * that they should replace a window manager that they like, and which
418      * works, just because *we* think that it's not "modern" enough.
419      */
420     sizeHints.x      = x;
421     sizeHints.y      = y;
422     sizeHints.width  = w;
423     sizeHints.height = h;
424 
425     wmHints.flags = StateHint;
426     wmHints.initial_state = fgState.ForceIconic ? IconicState : NormalState;
427 
428     /*
429      * Prepare the window and iconified window names...
430      */
431     XStringListToTextProperty( (char **) &title, 1, &textProperty );
432 
433     XSetWMProperties(
434         fgDisplay.Display,
435         window->Window.Handle,
436         &textProperty,
437         &textProperty,
438         0,
439         0,
440         &sizeHints,
441         &wmHints,
442         NULL
443     );
444     XSetWMProtocols( fgDisplay.Display, window->Window.Handle,
445                      &fgDisplay.DeleteWindow, 1 );
446     XMapWindow( fgDisplay.Display, window->Window.Handle );
447 
448 #elif TARGET_HOST_WIN32
449 
450     WNDCLASS wc;
451     int flags;
452     ATOM atom;
453 
454     freeglut_assert_ready;
455 
456     /*
457      * Grab the window class we have registered on glutInit():
458      */
459     atom = GetClassInfo( fgDisplay.Instance, "FREEGLUT", &wc );
460     assert( atom != 0 );
461 
462     if( gameMode )
463     {
464         assert( window->Parent == NULL );
465 
466         /*
467          * Set the window creation flags appropriately to make the window
468          * entirely visible:
469          */
470         flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
471     }
472     else
473     {
474         if ( ( ! isSubWindow ) && ( ! window->IsMenu ) )
475         {
476             /*
477              * Update the window dimensions, taking account of window
478              * decorations.  "freeglut" is to create the window with the
479              * outside of its border at (x,y) and with dimensions (w,h).
480              */
481             w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
482             h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 +
483                 GetSystemMetrics( SM_CYCAPTION );
484         }
485 
486         if( ! fgState.Position.Use )
487         {
488             x = CW_USEDEFAULT;
489             y = CW_USEDEFAULT;
490         }
491         if( ! fgState.Size.Use )
492         {
493             w = CW_USEDEFAULT;
494             h = CW_USEDEFAULT;
495         }
496 
497         /*
498          * There's a small difference between creating the top, child and
499          * game mode windows
500          */
501         flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
502 
503         if ( window->IsMenu )
504             flags |= WS_POPUP ;
505         else if( window->Parent == NULL )
506             flags |= WS_OVERLAPPEDWINDOW;
507         else
508             flags |= WS_CHILD;
509     }
510 
511     window->Window.Handle = CreateWindow(
512         "FREEGLUT",
513         title,
514         flags,
515         x, y, w, h,
516         (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
517         (HMENU) NULL,
518         fgDisplay.Instance,
519         (LPVOID) window
520     );
521     if( !( window->Window.Handle ) )
522         fgError( "Failed to create a window (%s)!", title );
523 
524     ShowWindow( window->Window.Handle,
525                 fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW );
526     UpdateWindow( window->Window.Handle );
527     ShowCursor( TRUE );  /* XXX Old comments say "hide cusror"! */
528 
529 #endif
530 
531     window->Window.DoubleBuffered =
532         ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0;
533 
534     if ( ! window->Window.DoubleBuffered )
535     {
536         glDrawBuffer ( GL_FRONT );
537         glReadBuffer ( GL_FRONT );
538     }
539     fgSetWindow( window );
540 }
541 
542 /*
543  * Closes a window, destroying the frame and OpenGL context
544  */
fgCloseWindow(SFG_Window * window)545 void fgCloseWindow( SFG_Window* window )
546 {
547     freeglut_assert_ready;
548 
549 #if TARGET_HOST_UNIX_X11
550 
551     glXDestroyContext( fgDisplay.Display, window->Window.Context );
552     XDestroyWindow( fgDisplay.Display, window->Window.Handle );
553     XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
554 
555 #elif TARGET_HOST_WIN32
556 
557     /*
558      * Make sure we don't close a window with current context active
559      */
560     if( fgStructure.Window == window )
561         wglMakeCurrent( NULL, NULL );
562 
563     /*
564      * Step through the list of windows.  If the rendering context
565      * is not being used by another window, then we delete it.
566      */
567     {
568         int used = FALSE ;
569         SFG_Window *iter ;
570 
571         for( iter = (SFG_Window *)fgStructure.Windows.First;
572              iter;
573              iter = (SFG_Window *)iter->Node.Next )
574         {
575             if( ( iter->Window.Context == window->Window.Context ) &&
576                 ( iter != window ) )
577                 used = TRUE;
578         }
579 
580         if( ! used )
581             wglDeleteContext( window->Window.Context );
582     }
583 
584     DestroyWindow( window->Window.Handle );
585 #endif
586 }
587 
588 
589 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
590 
591 /*
592  * Creates a new top-level freeglut window
593  */
glutCreateWindow(const char * title)594 int  glutCreateWindow( const char* title )
595 {
596     return fgCreateWindow( NULL, title, fgState.Position.X, fgState.Position.Y,
597                            fgState.Size.X, fgState.Size.Y, GL_FALSE,
598                            GL_FALSE )->ID;
599 }
600 
601 /*
602  * This function creates a sub window.
603  */
glutCreateSubWindow(int parentID,int x,int y,int w,int h)604 int  glutCreateSubWindow( int parentID, int x, int y, int w, int h )
605 {
606     SFG_Window* window = NULL;
607     SFG_Window* parent = NULL;
608 
609     freeglut_assert_ready;
610     parent = fgWindowByID( parentID );
611     freeglut_return_val_if_fail( parent != NULL, 0 );
612     window = fgCreateWindow( parent, "", x, y, w, h, GL_FALSE, GL_FALSE );
613     return window->ID;
614 }
615 
616 /*
617  * Destroys a window and all of its subwindows
618  */
glutDestroyWindow(int windowID)619 void  glutDestroyWindow( int windowID )
620 {
621     SFG_Window* window = fgWindowByID( windowID );
622     freeglut_return_if_fail( window != NULL );
623     {
624         fgExecutionState ExecState = fgState.ExecState;
625         fgAddToWindowDestroyList( window );
626         fgState.ExecState = ExecState;
627     }
628 }
629 
630 /*
631  * This function selects the current window
632  */
glutSetWindow(int ID)633 void  glutSetWindow( int ID )
634 {
635     SFG_Window* window = NULL;
636 
637     freeglut_assert_ready;
638     if( fgStructure.Window != NULL )
639         if( fgStructure.Window->ID == ID )
640             return;
641 
642     window = fgWindowByID( ID );
643     if( window == NULL )
644     {
645         fgWarning( "glutSetWindow(): window ID %i not found!", ID );
646         return;
647     }
648 
649     fgSetWindow( window );
650 }
651 
652 /*
653  * This function returns the ID number of the current window, 0 if none exists
654  */
glutGetWindow(void)655 int  glutGetWindow( void )
656 {
657     freeglut_assert_ready;
658     if( fgStructure.Window == NULL )
659         return 0;
660     return fgStructure.Window->ID;
661 }
662 
663 /*
664  * This function makes the current window visible
665  */
glutShowWindow(void)666 void  glutShowWindow( void )
667 {
668     freeglut_assert_ready;
669     freeglut_assert_window;
670 
671 #if TARGET_HOST_UNIX_X11
672 
673     XMapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
674     XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
675 
676 #elif TARGET_HOST_WIN32
677 
678     ShowWindow( fgStructure.Window->Window.Handle, SW_SHOW );
679 
680 #endif
681 
682     fgStructure.Window->State.Redisplay = GL_TRUE;
683 }
684 
685 /*
686  * This function hides the current window
687  */
glutHideWindow(void)688 void  glutHideWindow( void )
689 {
690     freeglut_assert_ready;
691     freeglut_assert_window;
692 
693 #if TARGET_HOST_UNIX_X11
694 
695     if( fgStructure.Window->Parent == NULL )
696         XWithdrawWindow( fgDisplay.Display, fgStructure.Window->Window.Handle,
697                          fgDisplay.Screen );
698     else
699         XUnmapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
700     XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
701 
702 #elif TARGET_HOST_WIN32
703 
704     ShowWindow( fgStructure.Window->Window.Handle, SW_HIDE );
705 
706 #endif
707 
708     fgStructure.Window->State.Redisplay = GL_FALSE;
709 }
710 
711 /*
712  * Iconify the current window (top-level windows only)
713  */
glutIconifyWindow(void)714 void  glutIconifyWindow( void )
715 {
716     freeglut_assert_ready;
717     freeglut_assert_window;
718 
719 #if TARGET_HOST_UNIX_X11
720 
721     XIconifyWindow( fgDisplay.Display, fgStructure.Window->Window.Handle,
722                     fgDisplay.Screen );
723     XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
724 
725 #elif TARGET_HOST_WIN32
726 
727     ShowWindow( fgStructure.Window->Window.Handle, SW_MINIMIZE );
728 
729 #endif
730 
731     fgStructure.Window->State.Redisplay = GL_FALSE;
732 }
733 
734 /*
735  * Set the current window's title
736  */
glutSetWindowTitle(const char * title)737 void  glutSetWindowTitle( const char* title )
738 {
739     freeglut_assert_ready;
740     freeglut_assert_window;
741     if( fgStructure.Window->Parent != NULL )
742         return;
743 
744 #if TARGET_HOST_UNIX_X11
745 
746     {
747         XTextProperty text;
748 
749         text.value = (unsigned char *) title;
750         text.encoding = XA_STRING;
751         text.format = 8;
752         text.nitems = strlen( title );
753 
754         XSetWMName(
755             fgDisplay.Display,
756             fgStructure.Window->Window.Handle,
757             &text
758         );
759 
760         XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
761     }
762 
763 #elif TARGET_HOST_WIN32
764 
765     SetWindowText( fgStructure.Window->Window.Handle, title );
766 
767 #endif
768 
769 }
770 
glutSetWindowAcceptsFiles(int accept)771 void  glutSetWindowAcceptsFiles(int accept)
772 {
773 #if TARGET_HOST_WIN32
774 	DragAcceptFiles(fgStructure.Window->Window.Handle, accept);
775 #endif
776 }
777 
778 /*
779  * Set the current window's iconified title
780  */
glutSetIconTitle(const char * title)781 void  glutSetIconTitle( const char* title )
782 {
783     freeglut_assert_ready;
784     freeglut_assert_window;
785 
786     if( fgStructure.Window->Parent != NULL )
787         return;
788 
789 #if TARGET_HOST_UNIX_X11
790 
791     {
792         XTextProperty text;
793 
794         text.value = (unsigned char *) title;
795         text.encoding = XA_STRING;
796         text.format = 8;
797         text.nitems = strlen( title );
798 
799         XSetWMIconName(
800             fgDisplay.Display,
801             fgStructure.Window->Window.Handle,
802             &text
803         );
804 
805         XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
806     }
807 
808 #elif TARGET_HOST_WIN32
809 
810     SetWindowText( fgStructure.Window->Window.Handle, title );
811 
812 #endif
813 
814 }
815 
816 /*
817  * Change the current window's size
818  */
glutReshapeWindow(int width,int height)819 void  glutReshapeWindow( int width, int height )
820 {
821     freeglut_assert_ready;
822     freeglut_assert_window;
823 
824     fgStructure.Window->State.NeedToResize = GL_TRUE;
825     fgStructure.Window->State.Width  = width ;
826     fgStructure.Window->State.Height = height;
827 }
828 
829 /*
830  * Change the current window's position
831  */
glutPositionWindow(int x,int y)832 void  glutPositionWindow( int x, int y )
833 {
834     freeglut_assert_ready;
835     freeglut_assert_window;
836 
837 #if TARGET_HOST_UNIX_X11
838 
839     XMoveWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, x, y );
840     XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
841 
842 #elif TARGET_HOST_WIN32
843 
844     {
845         RECT winRect;
846 
847         GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
848         MoveWindow(
849             fgStructure.Window->Window.Handle,
850             x,
851             y,
852             winRect.right - winRect.left,
853             winRect.bottom - winRect.top,
854             TRUE
855         );
856     }
857 
858 #endif
859 
860 }
861 
862 /*
863  * Lowers the current window (by Z order change)
864  */
glutPushWindow(void)865 void  glutPushWindow( void )
866 {
867     freeglut_assert_ready;
868     freeglut_assert_window;
869 
870 #if TARGET_HOST_UNIX_X11
871 
872     XLowerWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
873 
874 #elif TARGET_HOST_WIN32
875 
876     SetWindowPos(
877         fgStructure.Window->Window.Handle,
878         HWND_BOTTOM,
879         0, 0, 0, 0,
880         SWP_NOSIZE | SWP_NOMOVE
881     );
882 
883 #endif
884 
885 }
886 
887 /*
888  * Raises the current window (by Z order change)
889  */
glutPopWindow(void)890 void  glutPopWindow( void )
891 {
892     freeglut_assert_ready;
893     freeglut_assert_window;
894 
895 #if TARGET_HOST_UNIX_X11
896 
897     XRaiseWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
898 
899 #elif TARGET_HOST_WIN32
900 
901     SetWindowPos(
902         fgStructure.Window->Window.Handle,
903         HWND_TOP,
904         0, 0, 0, 0,
905         SWP_NOSIZE | SWP_NOMOVE
906     );
907 
908 #endif
909 
910 }
911 
912 /*
913  * Resize the current window so that it fits the whole screen
914  */
glutFullScreen(void)915 void  glutFullScreen( void )
916 {
917     freeglut_assert_ready;
918     freeglut_assert_window;
919 
920 #if TARGET_HOST_UNIX_X11
921     {
922         int x, y;
923         Window w;
924 
925         XMoveResizeWindow(
926             fgDisplay.Display,
927             fgStructure.Window->Window.Handle,
928             0, 0,
929             fgDisplay.ScreenWidth,
930             fgDisplay.ScreenHeight
931         );
932 
933         XFlush( fgDisplay.Display ); /* This is needed */
934 
935         XTranslateCoordinates(
936             fgDisplay.Display,
937             fgStructure.Window->Window.Handle,
938             fgDisplay.RootWindow,
939             0, 0, &x, &y, &w
940         );
941 
942         if (x || y)
943         {
944             XMoveWindow(
945                 fgDisplay.Display,
946                 fgStructure.Window->Window.Handle,
947                 -x, -y
948             );
949             XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
950         }
951     }
952 #elif TARGET_HOST_WIN32
953     {
954         RECT rect;
955 
956         /* For fullscreen mode, force the top-left corner to 0,0
957          * and adjust the window rectangle so that the client area
958          * covers the whole screen.
959          */
960 
961         rect.left   = 0;
962         rect.top    = 0;
963         rect.right  = fgDisplay.ScreenWidth;
964         rect.bottom = fgDisplay.ScreenHeight;
965 
966         AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
967                                   WS_CLIPCHILDREN, FALSE );
968 
969         /*
970          * SWP_NOACTIVATE	Do not activate the window
971          * SWP_NOOWNERZORDER	Do not change position in z-order
972          * SWP_NOSENDCHANGING	Supress WM_WINDOWPOSCHANGING message
973          * SWP_NOZORDER		Retains the current Z order (ignore 2nd param)
974          */
975 
976         SetWindowPos( fgStructure.Window->Window.Handle,
977                       HWND_TOP,
978                       rect.left,
979                       rect.top,
980                       rect.right  - rect.left,
981                       rect.bottom - rect.top,
982                       SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
983                       SWP_NOZORDER
984                     );
985     }
986 #endif
987 }
988 
989 /*
990  * A.Donev: Set and retrieve the window's user data
991  */
glutGetWindowData(void)992 void*  glutGetWindowData( void )
993 {
994     return fgStructure.Window->UserData;
995 }
996 
glutSetWindowData(void * data)997 void  glutSetWindowData(void* data)
998 {
999     fgStructure.Window->UserData=data;
1000 }
1001 
1002 /*** END OF FILE ***/
1003