Changed all references to the 'freeglut-1.3' directory to 'src', copied 'freeglut...
[freeglut] / src / freeglut_window.c
1 /*
2  * freeglut_window.c
3  *
4  * Window management methods.
5  *
6  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
7  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
8  * Creation date: Fri Dec 3 1999
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #define  G_LOG_DOMAIN  "freeglut-window"
33
34 #include "../include/GL/freeglut.h"
35 #include "freeglut_internal.h"
36
37 /*
38  * TODO BEFORE THE STABLE RELEASE:
39  *
40  *  fgChooseVisual()        -- OK, but what about glutInitDisplayString()?
41  *  fgSetupPixelFormat      -- ignores the display mode settings
42  *  fgOpenWindow()          -- check the Win32 version, -iconic handling!
43  *  fgCloseWindow()         -- check the Win32 version
44  *  glutCreateWindow()      -- see what happens when default position and size is {-1,-1}
45  *  glutCreateSubWindow()   -- see what happens when default position and size is {-1,-1}
46  *  glutDestroyWindow()     -- check the Win32 version
47  *  glutSetWindow()         -- check the Win32 version
48  *  glutGetWindow()         -- OK
49  *  glutSetWindowTitle()    -- check the Win32 version
50  *  glutSetIconTitle()      -- check the Win32 version
51  *  glutShowWindow()        -- check the Win32 version
52  *  glutHideWindow()        -- check the Win32 version
53  *  glutIconifyWindow()     -- check the Win32 version
54  *  glutReshapeWindow()     -- check the Win32 version
55  *  glutPositionWindow()    -- check the Win32 version
56  *  glutPushWindow()        -- check the Win32 version
57  *  glutPopWindow()         -- check the Win32 version
58  */
59
60 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
61
62 /*
63  * Chooses a visual basing on the current display mode settings
64  */
65 #if TARGET_HOST_UNIX_X11
66 XVisualInfo* fgChooseVisual( void )
67 {
68     int bufferSize[] = { 16, 12, 8, 4, 2, 1 };
69     GLboolean wantIndexedMode = FALSE;
70     int attributes[ 32 ];
71     int where = 0;
72
73     /*
74      * First we have to process the display mode settings...
75      */
76 #   define ATTRIB(a) attributes[where++]=a;
77
78     /*
79      * Decide if we want a true or indexed color visual:
80      */
81     if( !(fgState.DisplayMode & GLUT_INDEX) )
82     {
83         /*
84          * We are sure that there will be R, B and B components requested:
85          */
86         ATTRIB( GLX_RGBA       );
87         ATTRIB( GLX_RED_SIZE   ); ATTRIB( 1 );
88         ATTRIB( GLX_GREEN_SIZE ); ATTRIB( 1 );
89         ATTRIB( GLX_BLUE_SIZE  ); ATTRIB( 1 );
90
91         /*
92          * Check if the A component is required, too:
93          */
94         if( fgState.DisplayMode & GLUT_ALPHA )
95         {
96             ATTRIB( GLX_ALPHA_SIZE ); ATTRIB( 1 );
97         }
98     }
99     else
100     {
101         /*
102          * We've got an indexed color request
103          */
104         ATTRIB( GLX_BUFFER_SIZE ); ATTRIB( 8 );
105
106         /*
107          * Set the 'I want indexed mode' switch
108          */
109         wantIndexedMode = TRUE;
110     }
111
112     /*
113      * We can have double or single buffered contexts created
114      */
115     if( fgState.DisplayMode & GLUT_DOUBLE )
116     {
117         ATTRIB( GLX_DOUBLEBUFFER );
118     }
119
120     /*
121      * Stereoscopy seems a nice thing to have
122      */
123     if( fgState.DisplayMode & GLUT_STEREO )
124     {
125         ATTRIB( GLX_STEREO );
126     }
127
128     /*
129      * Depth buffer is almost always required
130      */
131     if( fgState.DisplayMode & GLUT_DEPTH )
132     {
133         ATTRIB( GLX_DEPTH_SIZE ); ATTRIB( 1 );
134     }
135
136     /*
137      * Stenciling support
138      */
139     if( fgState.DisplayMode & GLUT_STENCIL )
140     {
141         ATTRIB( GLX_STENCIL_SIZE ); ATTRIB( 1 );
142     }
143
144     /*
145      * And finally the accumulation buffers
146      */
147     if( fgState.DisplayMode & GLUT_ACCUM )
148     {
149         ATTRIB( GLX_ACCUM_RED_SIZE );   ATTRIB( 1 );
150         ATTRIB( GLX_ACCUM_GREEN_SIZE ); ATTRIB( 1 );
151         ATTRIB( GLX_ACCUM_BLUE_SIZE );  ATTRIB( 1 );
152
153         /*
154          * Check if the A component is required, too:
155          */
156         if( fgState.DisplayMode & GLUT_ALPHA )
157         {
158             ATTRIB( GLX_ACCUM_ALPHA_SIZE ); ATTRIB( 1 );
159         }
160     }
161
162     /*
163      * Push a null at the end of the list
164      */
165     ATTRIB( None );
166
167     /*
168      * OKi now, we've got two cases -- RGB(A) and index mode visuals
169      */
170     if( wantIndexedMode == FALSE )
171     {
172         /*
173          * The easier one. And more common, too.
174          */
175         return( glXChooseVisual( fgDisplay.Display, fgDisplay.Screen, attributes ) );
176     }
177     else
178     {
179         XVisualInfo* visualInfo;
180         int i;
181
182         /*
183          * In indexed mode, we need to check how many bits of depth can we achieve
184          */
185         for( i=0; i<6; i++ )
186         {
187
188             /*
189              * The GLX_BUFFER_SIZE value comes always first, so:
190              */
191             attributes[ 1 ] = bufferSize[ i ];
192
193             /*
194              * Check if such visual is possible
195              */
196             visualInfo = glXChooseVisual( fgDisplay.Display, fgDisplay.Screen, attributes );
197
198             /*
199              * The buffer size are sorted in descendant order, so choose the first:
200              */
201             if( visualInfo != NULL )
202                 return( visualInfo );
203         }
204
205         /*
206          * If we are still here, it means that the visual info was not found
207          */
208         return( NULL );
209     }
210 }
211 #endif
212
213 /*
214  * Setup the pixel format for a Win32 window
215  */
216 #if TARGET_HOST_WIN32
217 GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly, unsigned char layer_type )
218 {
219         PIXELFORMATDESCRIPTOR* ppfd, pfd;
220         int flags, pixelformat;
221
222         /*
223          * Check if the window seems valid
224          */
225         freeglut_return_val_if_fail( window != NULL, 0 );
226
227         /*
228          * The pixel format should allow us to draw to the window using OpenGL
229          */
230         flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
231         
232         /*
233          * It might be the case for us to use double buffering
234          */
235   if( fgState.DisplayMode & GLUT_DOUBLE )
236         flags |= PFD_DOUBLEBUFFER;
237
238   /*
239    * Specify which pixel format do we opt for...
240    */
241 #       pragma message( "fgSetupPixelFormat(): there is still some work to do here!" )
242
243   pfd.nSize                             = sizeof(PIXELFORMATDESCRIPTOR);
244   pfd.nVersion                  = 1;
245   pfd.dwFlags                           = flags;
246   pfd.iPixelType                        = PFD_TYPE_RGBA;
247   pfd.cColorBits                        = 24;
248   pfd.cRedBits                  = 0;
249   pfd.cRedShift                 = 0;
250   pfd.cGreenBits                        = 0;
251   pfd.cGreenShift                       = 0;
252   pfd.cBlueBits                 = 0;
253   pfd.cBlueShift                        = 0;
254   pfd.cAlphaBits                        = 0;
255   pfd.cAlphaShift                       = 0;
256   pfd.cAccumBits                        = 0;
257   pfd.cAccumRedBits             = 0;
258   pfd.cAccumGreenBits           = 0;
259   pfd.cAccumBlueBits            = 0;
260   pfd.cAccumAlphaBits           = 0;
261 #if 0
262   pfd.cDepthBits                        = 32;
263   pfd.cStencilBits              = 0;
264 #else
265   pfd.cDepthBits                        = 24;
266   pfd.cStencilBits              = 8;
267 #endif
268   pfd.cAuxBuffers                       = 0;
269   pfd.iLayerType                        = layer_type;
270   pfd.bReserved                 = 0;
271   pfd.dwLayerMask                       = 0;
272   pfd.dwVisibleMask             = 0;
273   pfd.dwDamageMask              = 0;
274
275   /*
276    * Fill in the color bits...
277    */
278   pfd.cColorBits = (BYTE) GetDeviceCaps( window->Window.Device, BITSPIXEL );
279   ppfd = &pfd;
280
281         /*
282          * Choose the pixel format that matches our demand
283          */
284   pixelformat = ChoosePixelFormat( window->Window.Device, ppfd );
285         if( pixelformat == 0 )
286                 return( FALSE );
287
288         /*
289          * We might have been called to check if the pixel format exists only
290          */
291         if( checkOnly )
292                 return( TRUE );
293
294         /*
295          * Finally, set the window's pixel format
296          */
297         return ( SetPixelFormat( window->Window.Device, pixelformat, ppfd ) ) ;
298 }
299 #endif
300
301 /*
302  * Sets the OpenGL context and the fgStructure "Current Window" pointer to the window
303  * structure passed in.
304  */
305 void fgSetWindow ( SFG_Window *window )
306 {
307 #if TARGET_HOST_UNIX_X11
308     /*
309          * Make the selected window's GLX context the current one
310      */
311     glXMakeCurrent(
312         fgDisplay.Display,
313         window->Window.Handle,
314         window->Window.Context
315     );
316
317 #elif TARGET_HOST_WIN32
318         /*
319          * Release the previous' context's device context
320          */
321         if( fgStructure.Window != NULL )
322                 ReleaseDC( fgStructure.Window->Window.Handle, fgStructure.Window->Window.Device );
323
324   if ( window )
325   {
326         /*
327            * We will care about releasing the device context later
328            */
329         window->Window.Device = GetDC( window->Window.Handle );
330
331         /*
332            * Set the new current context:
333            */
334         wglMakeCurrent( 
335                 window->Window.Device, 
336                   window->Window.Context 
337         );
338   }
339 #endif
340
341     /*
342      * Remember that we have changed the current window state
343      */
344     fgStructure.Window = window;
345 }
346
347
348 /*
349  * Opens a window. Requires a SFG_Window object created and attached
350  * to the freeglut structure. OpenGL context is created here.
351  */
352 void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, int h, GLboolean gameMode, int isSubWindow )
353 {
354 #if TARGET_HOST_UNIX_X11
355     XSetWindowAttributes winAttr;
356     XTextProperty textProperty;
357     XSizeHints sizeHints;
358     XWMHints wmHints;
359     unsigned long mask;
360
361     freeglut_assert_ready;
362
363     /*
364      * Here we are upon the stage. Have the visual selected.
365      */
366     window->Window.VisualInfo = fgChooseVisual();
367     if ( ! window->Window.VisualInfo )
368     {
369       /*
370        * The "fgChooseVisual" returned a null meaning that the visual context is not available.
371        * Try a couple of variations to see if they will work.
372        */
373       if ( ! ( fgState.DisplayMode & GLUT_DOUBLE ) )
374       {
375         /*
376          * Single buffering--try it doubled
377          */
378         fgState.DisplayMode |= GLUT_DOUBLE ;
379         window->Window.VisualInfo = fgChooseVisual();
380       }
381
382       /*
383        * GLUT also checks for multi-sampling, but I don't see that anywhere else in FREEGLUT
384        * so I won't bother with it for the moment.
385        */
386     }
387
388     assert( window->Window.VisualInfo != NULL );
389
390     /*
391      * Have the windows attributes set
392      *
393      * HINT: the masks should be updated when adding/removing callbacks.
394      *       This might speed up message processing. Is that true?
395      */
396     winAttr.event_mask        = StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
397                                 ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyRelease |
398                                 VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
399                                 PointerMotionMask | ButtonMotionMask;
400     winAttr.background_pixmap = None;
401     winAttr.background_pixel  = 0;
402     winAttr.border_pixel      = 0;
403
404     /*
405      * The color map is required, too
406      */
407     winAttr.colormap = XCreateColormap(
408         fgDisplay.Display, fgDisplay.RootWindow,
409         window->Window.VisualInfo->visual, AllocNone
410     );
411
412     /*
413      * This tells the XCreateWindow() what attributes are we supplying it with
414      */
415     mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
416
417     /*
418      * Have the window created now
419      */
420     window->Window.Handle = XCreateWindow(
421         fgDisplay.Display,
422         window->Parent == NULL ? fgDisplay.RootWindow : window->Parent->Window.Handle,
423         x, y, w, h, 0,
424         window->Window.VisualInfo->depth, InputOutput,
425         window->Window.VisualInfo->visual, mask,
426         &winAttr
427     );
428
429     /*
430      * The GLX context creation, possibly trying the direct context rendering
431      */
432     window->Window.Context = glXCreateContext(
433         fgDisplay.Display, window->Window.VisualInfo,
434         NULL, fgState.ForceDirectContext | fgState.TryDirectContext
435     );
436
437     /*
438      * Make sure the context is direct when the user wants it forced
439      */
440     if( fgState.ForceDirectContext && !glXIsDirect( fgDisplay.Display, window->Window.Context ) )
441         fgError( "unable to force direct context rendering for window '%s'", title );
442
443     /*
444      * Set the new context as the current one. That's all about the window creation.
445      */
446     glXMakeCurrent(
447         fgDisplay.Display,
448         window->Window.Handle,
449         window->Window.Context
450     );
451
452     /*
453      * Assume the new window is visible by default
454      */
455     window->State.Visible = TRUE;
456
457     /*
458      * For the position and size hints -- make sure we are passing valid values
459      */
460     sizeHints.flags = 0;
461
462     if (fgState.Position.Use == TRUE) sizeHints.flags |= USPosition;
463     if (fgState.Size.Use     == TRUE) sizeHints.flags |= USSize;
464
465     /*
466      * Fill in the size hints values now (the x, y, width and height
467      * settings are obsolote, are there any more WMs that support them?)
468      */
469     sizeHints.x      = x; sizeHints.y      = y;
470     sizeHints.width  = w; sizeHints.height = h;
471
472     /*
473      * We can have forced all new windows start in iconified state:
474      */
475     wmHints.flags = StateHint;
476     wmHints.initial_state = (fgState.ForceIconic == FALSE) ? NormalState : IconicState;
477
478     /*
479      * Prepare the window and iconified window names...
480      */
481     XStringListToTextProperty( (char **) &title, 1, &textProperty );
482
483     /*
484      * Set the window's properties now
485      */
486     XSetWMProperties(
487         fgDisplay.Display,
488         window->Window.Handle,
489         &textProperty,
490         &textProperty,
491         0,
492         0,
493         &sizeHints,
494         &wmHints,
495         NULL
496     );
497
498     /*
499      * Make sure we are informed about the window deletion commands
500      */
501     XSetWMProtocols( fgDisplay.Display, window->Window.Handle, &fgDisplay.DeleteWindow, 1 );
502
503     /*
504      * Finally, have the window mapped to our display
505      */
506     XMapWindow( fgDisplay.Display, window->Window.Handle );
507
508     /*
509      * In game mode, move the viewport a bit to hide the decorations.
510      * This code depends on the XFree86 video mode extensions.
511      */
512     if( gameMode == TRUE )
513     {
514         /*
515          * This somehow fixes the glutGet() GLUT_WINDOW_X and GLUT_WINDOW_Y problem...
516          */
517         XMoveWindow( fgDisplay.Display, window->Window.Handle, x, y );
518
519 #       ifdef X_XF86VidModeSetViewPort
520
521         /*
522          * Set the newly created window as the current one...
523          */
524         fgSetWindow( window );
525
526         /*
527          * Move the viewport a bit down and right from top-left corner to hide the decorations
528          */
529         XF86VidModeSetViewPort(
530             fgDisplay.Display,
531             fgDisplay.Screen,
532             glutGet( GLUT_WINDOW_X ),
533             glutGet( GLUT_WINDOW_Y )
534         );
535
536 #       endif
537     }
538
539 #elif TARGET_HOST_WIN32
540
541         WNDCLASS wc;
542         int flags;
543         ATOM atom;
544
545     freeglut_assert_ready;
546
547         /*
548          * Grab the window class we have registered on glutInit():
549          */
550         atom = GetClassInfo( fgDisplay.Instance, "FREEGLUT", &wc );
551         assert( atom != 0 );
552
553     if( gameMode == FALSE )
554     {
555       if ( !isSubWindow )
556       {
557         /*
558          * Update the window dimensions, taking account of window decorations.
559          * "freeglut" is to create the window with the outside of its border at (x,y)
560          * and with dimensions (w,h).
561          */
562                 w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
563                 h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 + GetSystemMetrics( SM_CYCAPTION );
564       }
565
566       /*
567              * Check if the user wants us to use the default position/size
568              */
569             if( fgState.Position.Use == FALSE ) { x = CW_USEDEFAULT; y = CW_USEDEFAULT; }
570             if( fgState.Size    .Use == FALSE ) { w = CW_USEDEFAULT; h = CW_USEDEFAULT; }
571
572             /*
573              * There's a small difference between creating the top, child and game mode windows
574              */
575             flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
576
577             if( window->Parent == NULL )
578                     flags |= WS_OVERLAPPEDWINDOW;
579             else
580                     flags |= WS_CHILD;
581     }
582     else
583     {
584         /*
585          * In game mode, the story is a little bit different...
586          */
587         assert( window->Parent == NULL );
588
589         /*
590          * Set the window creation flags appropriately to make the window entirely visible:
591          */
592         flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
593     }
594
595     /*
596      * Create the window now, passing the freeglut window structure as the parameter
597      */
598         window->Window.Handle = CreateWindow( 
599                 "FREEGLUT",
600         title,
601                 flags,
602         x, y, w, h,
603                 (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
604                 (HMENU) NULL,
605                 fgDisplay.Instance,
606                 (LPVOID) window
607         );
608
609         /*
610      * Make sure window was created
611      */
612         assert( window->Window.Handle != NULL );
613
614     /*
615      * Show and update the main window. Hide the mouse cursor.
616      */
617     ShowWindow( window->Window.Handle, fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW );
618     UpdateWindow( window->Window.Handle );
619     ShowCursor( TRUE );
620
621 #endif
622
623     /*
624      * Save the window's single- or double-buffering state
625      */
626     window->Window.DoubleBuffered = ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0 ;
627
628     /*
629      * If it's not double-buffered, make sure the rendering is done to the front buffer.
630      */
631     if ( ! window->Window.DoubleBuffered )
632     {
633       glDrawBuffer ( GL_FRONT ) ;
634       glReadBuffer ( GL_FRONT ) ;
635     }
636
637     /*
638      * Set the newly created window as the current one
639      */
640     fgSetWindow( window );
641 }
642
643 /*
644  * Closes a window, destroying the frame and OpenGL context
645  */
646 void fgCloseWindow( SFG_Window* window )
647 {
648     freeglut_assert_ready;
649
650 #if TARGET_HOST_UNIX_X11
651     /*
652      * As easy as kill bunnies with axes. Destroy the context first:
653      */
654     glXDestroyContext( fgDisplay.Display, window->Window.Context );
655
656     /*
657      * Then have the window killed:
658      */
659     XDestroyWindow( fgDisplay.Display, window->Window.Handle );
660
661     /*
662      * Finally, flush the rests down the stream
663      */
664     XFlush( fgDisplay.Display );
665
666 #elif TARGET_HOST_WIN32
667         /*
668          * Send the WM_CLOSE message to the window now
669          */
670         SendMessage( 
671                 window->Window.Handle,
672                 WM_CLOSE,
673                 0,
674                 0
675         );
676
677 #endif
678 }
679
680
681 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
682
683 /*
684  * Creates a new top-level freeglut window
685  */
686 int FGAPIENTRY glutCreateWindow( const char* title )
687 {
688     /*
689      * Create a new window and return its unique ID number
690      */
691     return( fgCreateWindow( NULL, title, fgState.Position.X, fgState.Position.Y,
692                             fgState.Size.X, fgState.Size.Y, FALSE )->ID );
693 }
694
695 /*
696  * This function creates a sub window.
697  */
698 int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
699 {
700     SFG_Window* window = NULL;
701     SFG_Window* parent = NULL;
702
703     freeglut_assert_ready;
704
705     /*
706      * Find a parent to the newly created window...
707      */
708     parent = fgWindowByID( parentID );
709
710     /*
711      * Fail if the parent has not been found
712      */
713     freeglut_return_val_if_fail( parent != NULL, 0 );
714
715     /*
716      * Create the new window
717      */
718     window = fgCreateWindow( parent, "", x, y, w, h, FALSE );
719
720     /*
721      * Return the new window's ID
722      */
723     return( window->ID );
724 }
725
726 /*
727  * Destroys a window and all of its subwindows
728  */
729 void FGAPIENTRY glutDestroyWindow( int windowID )
730 {
731   fgExecutionState ExecState = fgState.ExecState ;
732
733   /*
734    * Grab the freeglut window pointer from the structure
735    */
736   SFG_Window* window = fgWindowByID( windowID );
737   freeglut_return_if_fail( window != NULL );
738
739   /*
740    * There is a function that performs all needed steps
741    * defined in freeglut_structure.c. Let's use it:
742    */
743   fgAddToWindowDestroyList( window, TRUE );
744
745   /*
746    * Since the "fgAddToWindowDestroyList" function could easily have set the "ExecState"
747    * to stop, let's set it back to what it was.
748    */
749   fgState.ExecState = ExecState ;
750 }
751
752 /*
753  * This function selects the current window
754  */
755 void FGAPIENTRY glutSetWindow( int ID )
756 {
757     SFG_Window* window = NULL;
758
759     /*
760      * Make sure we don't get called too early
761      */
762     freeglut_assert_ready;
763
764     /*
765      * Be wise. Be wise. Be wise. Be quick.
766      */
767     if( fgStructure.Window != NULL )
768         if( fgStructure.Window->ID == ID )
769             return;
770
771     /*
772      * Now we are sure there is sense in looking for the window
773      */
774     window = fgWindowByID( ID );
775
776     /*
777      * In the case of an utter failure...
778      */
779     if( window == NULL )
780     {
781         /*
782          * ...issue a warning message and keep rolling on
783          */
784         fgWarning( "glutSetWindow(): window ID %i not found!", ID );
785         return;
786     }
787
788     fgSetWindow ( window ) ;
789 }
790
791 /*
792  * This function returns the ID number of the current window, 0 if none exists
793  */
794 int FGAPIENTRY glutGetWindow( void )
795 {
796     freeglut_assert_ready;
797
798     /*
799      * Do we have a current window selected?
800      */
801     if( fgStructure.Window == NULL )
802     {
803         /*
804          * Nope. Return zero to mark the state.
805          */
806         return( 0 );
807     }
808
809     /*
810      * Otherwise, return the ID of the current window
811      */
812     return( fgStructure.Window->ID );
813 }
814
815 /*
816  * This function makes the current window visible
817  */
818 void FGAPIENTRY glutShowWindow( void )
819 {
820     freeglut_assert_ready; freeglut_assert_window;
821
822 #if TARGET_HOST_UNIX_X11
823     /*
824      * Showing the window is done via mapping under X
825      */
826     XMapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
827     XFlush( fgDisplay.Display );
828
829 #elif TARGET_HOST_WIN32
830         /*
831          * Restore the window's originial position and size
832          */
833         ShowWindow( fgStructure.Window->Window.Handle, SW_SHOW );
834
835 #endif
836 }
837
838 /*
839  * This function hides the current window
840  */
841 void FGAPIENTRY glutHideWindow( void )
842 {
843     freeglut_assert_ready; freeglut_assert_window;
844
845 #if TARGET_HOST_UNIX_X11
846     /*
847      * The way we hide a window depends on if we're dealing
848      * with a top-level or children one...
849      */
850     if( fgStructure.Window->Parent == NULL )
851     {
852         /*
853          * This is a top-level window
854          */
855         XWithdrawWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, fgDisplay.Screen );
856     }
857     else
858     {
859         /*
860          * Nope, it's a child window
861          */
862         XUnmapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
863     }
864
865     /*
866      * Flush the X state now
867      */
868     XFlush( fgDisplay.Display );
869
870 #elif TARGET_HOST_WIN32
871         /*
872          * Hide the window
873          */
874         ShowWindow( fgStructure.Window->Window.Handle, SW_HIDE );
875
876 #endif
877 }
878
879 /*
880  * Iconify the current window (top-level windows only)
881  */
882 void FGAPIENTRY glutIconifyWindow( void )
883 {
884     freeglut_assert_ready; freeglut_assert_window;
885
886 #if TARGET_HOST_UNIX_X11
887     /*
888      * Iconify the window and flush the X state
889      */
890     XIconifyWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, fgDisplay.Screen );
891     XFlush( fgDisplay.Display );
892
893 #elif TARGET_HOST_WIN32
894         /*
895          * Minimize the current window (this should be the same as X window iconifying)
896          */
897         ShowWindow( fgStructure.Window->Window.Handle, SW_MINIMIZE );
898
899 #endif
900 }
901
902 /*
903  * Set the current window's title
904  */
905 void FGAPIENTRY glutSetWindowTitle( const char* title )
906 {
907         freeglut_assert_ready; freeglut_assert_window;
908
909     /*
910      * Works only for top-level windows
911      */
912     if( fgStructure.Window->Parent != NULL )
913         return;
914
915 #if TARGET_HOST_UNIX_X11
916         {
917                 XTextProperty text;
918
919                 /*
920                  * Prepare the text properties
921                  */
922                 text.value = (unsigned char *) title;
923                 text.encoding = XA_STRING;
924                 text.format = 8;
925                 text.nitems = strlen( title );
926
927                 /*
928                  * Set the title now
929                  */
930                 XSetWMName(
931                         fgDisplay.Display,
932                         fgStructure.Window->Window.Handle,
933                         &text
934                 );
935
936                 /*
937                  * Have the X display state flushed
938                  */
939                 XFlush( fgDisplay.Display );
940         }
941
942 #elif TARGET_HOST_WIN32
943         /*
944          * This seems to be a bit easier under Win32
945          */
946         SetWindowText( fgStructure.Window->Window.Handle, title );
947
948 #endif
949 }
950
951 /*
952  * Set the current window's iconified title
953  */
954 void FGAPIENTRY glutSetIconTitle( const char* title )
955 {
956     freeglut_assert_ready; freeglut_assert_window;
957
958     /*
959      * Works only for top-level windows
960      */
961     if( fgStructure.Window->Parent != NULL )
962         return;
963
964 #if TARGET_HOST_UNIX_X11
965         {
966                 XTextProperty text;
967
968                 /*
969                  * Prepare the text properties
970                  */
971                 text.value = (unsigned char *) title;
972                 text.encoding = XA_STRING;
973                 text.format = 8;
974                 text.nitems = strlen( title );
975
976                 /*
977                  * Set the title now
978                  */
979                 XSetWMIconName(
980                         fgDisplay.Display,
981                         fgStructure.Window->Window.Handle,
982                         &text
983                 );
984
985                 /*
986                  * Have the X display state flushed
987                  */
988                 XFlush( fgDisplay.Display );
989         }
990
991 #elif TARGET_HOST_WIN32
992         /*
993          * This seems to be a bit easier under Win32
994          */
995         SetWindowText( fgStructure.Window->Window.Handle, title );
996
997 #endif
998 }
999
1000 /*
1001  * Change the current window's size
1002  */
1003 void FGAPIENTRY glutReshapeWindow( int width, int height )
1004 {
1005     freeglut_assert_ready; freeglut_assert_window;
1006
1007 #if TARGET_HOST_UNIX_X11
1008     /*
1009      * Resize the window and flush the X state
1010      */
1011     XResizeWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, width, height );
1012     XFlush( fgDisplay.Display );
1013
1014 #elif TARGET_HOST_WIN32
1015         {
1016                 RECT winRect;
1017     int x, y ;
1018
1019                 /*
1020                  * First off, grab the current window's position
1021                  */
1022                 GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
1023     x = winRect.left ;
1024     y = winRect.top ;
1025
1026     if ( fgStructure.Window->Parent == NULL )  /* If this is not a subwindow ... */
1027     {
1028       /*
1029        * Adjust the size of the window to allow for the size of the frame
1030        */
1031                 width += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
1032                 height += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + GetSystemMetrics( SM_CYCAPTION );
1033     }
1034     else  /* This is a subwindow, get the parent window's position and subtract it off */
1035     {
1036       GetWindowRect ( fgStructure.Window->Parent->Window.Handle, &winRect ) ;
1037       x -= winRect.left + GetSystemMetrics( SM_CXSIZEFRAME ) ;
1038       y -= winRect.top + GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ) ;
1039     }
1040
1041                 /*
1042                  * Resize the window, forcing a redraw to happen
1043                  */
1044                 MoveWindow(
1045                         fgStructure.Window->Window.Handle,
1046                         x,
1047                         y,
1048                         width,
1049                         height,
1050                         TRUE
1051                 );
1052         }
1053 #endif
1054 }
1055
1056 /*
1057  * Change the current window's position
1058  */
1059 void FGAPIENTRY glutPositionWindow( int x, int y )
1060 {
1061     freeglut_assert_ready; freeglut_assert_window;
1062
1063 #if TARGET_HOST_UNIX_X11
1064     /*
1065      * Reposition the window and flush the X state
1066      */
1067     XMoveWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, x, y );
1068     XFlush( fgDisplay.Display );
1069
1070 #elif TARGET_HOST_WIN32
1071         {
1072                 RECT winRect;
1073
1074                 /*
1075                  * First off, grab the current window's position
1076                  */
1077                 GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
1078
1079     /*
1080                  * Reposition the window, forcing a redraw to happen
1081                  */
1082                 MoveWindow(
1083                         fgStructure.Window->Window.Handle,
1084                         x,
1085                         y,
1086                         winRect.right - winRect.left,
1087                         winRect.bottom - winRect.top,
1088                         TRUE
1089                 );
1090         }
1091
1092 #endif
1093 }
1094
1095 /*
1096  * Lowers the current window (by Z order change)
1097  */
1098 void FGAPIENTRY glutPushWindow( void )
1099 {
1100     freeglut_assert_ready; freeglut_assert_window;
1101
1102 #if TARGET_HOST_UNIX_X11
1103     /*
1104      * Lower the current window
1105      */
1106     XLowerWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
1107
1108 #elif TARGET_HOST_WIN32
1109         /*
1110          * Set the new window's Z position, not affecting the rest of the settings:
1111          */
1112         SetWindowPos(
1113                 fgStructure.Window->Window.Handle,
1114                 HWND_BOTTOM,
1115                 0, 0, 0, 0,
1116                 SWP_NOSIZE | SWP_NOMOVE
1117         );
1118
1119 #endif
1120 }
1121
1122 /*
1123  * Raises the current window (by Z order change)
1124  */
1125 void FGAPIENTRY glutPopWindow( void )
1126 {
1127     freeglut_assert_ready; freeglut_assert_window;
1128
1129 #if TARGET_HOST_UNIX_X11
1130     /*
1131      * Raise the current window
1132      */
1133     XRaiseWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
1134
1135 #elif TARGET_HOST_WIN32
1136         /*
1137          * Set the new window's Z position, not affecting the rest of the settings:
1138          */
1139         SetWindowPos(
1140                 fgStructure.Window->Window.Handle,
1141                 HWND_TOP,
1142                 0, 0, 0, 0,
1143                 SWP_NOSIZE | SWP_NOMOVE
1144         );
1145
1146 #endif
1147 }
1148
1149 /*
1150  * Resize the current window so that it fits the whole screen
1151  */
1152 void FGAPIENTRY glutFullScreen( void )
1153 {
1154     freeglut_assert_ready; freeglut_assert_window;
1155
1156     /*
1157      * Just have the window repositioned and resized
1158      */
1159     glutPositionWindow( 0, 0 );
1160
1161     glutReshapeWindow(
1162         fgDisplay.ScreenWidth,
1163         fgDisplay.ScreenHeight
1164     );
1165 }
1166
1167 /*
1168  * A.Donev: Set and retrieve the window's user data
1169  */
1170 void* FGAPIENTRY glutGetWindowData( void )
1171 {
1172    return(fgStructure.Window->UserData);
1173 }
1174
1175 void FGAPIENTRY glutSetWindowData(void* data)
1176 {
1177   fgStructure.Window->UserData=data;
1178 }
1179
1180 /*** END OF FILE ***/
1181
1182
1183
1184
1185
1186
1187
1188
1189