943b0276db60cef5cfcdd9ea282a70dca5276347
[freeglut] / freeglut-1.3 / 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 "../include/GL/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 )
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     pfd.cDepthBits                      = 32;
262     pfd.cStencilBits            = 0;
263     pfd.cAuxBuffers                     = 0;
264     pfd.iLayerType                      = PFD_MAIN_PLANE;
265     pfd.bReserved                       = 0;
266     pfd.dwLayerMask                     = 0;
267     pfd.dwVisibleMask           = 0;
268     pfd.dwDamageMask            = 0;
269
270     /*
271      * Fill in the color bits...
272      */
273     pfd.cColorBits = (BYTE) GetDeviceCaps( window->Window.Device, BITSPIXEL );
274     ppfd = &pfd;
275
276         /*
277          * Choose the pixel format that matches our demand
278          */
279     pixelformat = ChoosePixelFormat( window->Window.Device, ppfd );
280         if( pixelformat == 0 )
281                 return( FALSE );
282
283         /*
284          * We might have been called to check if the pixel format exists only
285          */
286         if( checkOnly )
287                 return( TRUE );
288
289         /*
290          * Finally, set the window's pixel format
291          */
292         if( SetPixelFormat( window->Window.Device, pixelformat, ppfd ) == FALSE )
293                 return( FALSE );
294
295     return( TRUE );
296 }
297 #endif
298
299 /*
300  * Opens a window. Requires a SFG_Window object created and attached
301  * to the freeglut structure. OpenGL context is created here.
302  */
303 void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, int h, GLboolean gameMode )
304 {
305 #if TARGET_HOST_UNIX_X11
306     XSetWindowAttributes winAttr;
307     XTextProperty textProperty;
308     XSizeHints sizeHints;
309     XWMHints wmHints;
310     unsigned long mask;
311
312     freeglut_assert_ready;
313
314     /*
315      * Here we are upon the stage. Have the visual selected.
316      */
317     window->Window.VisualInfo = fgChooseVisual();
318     assert( window->Window.VisualInfo != NULL );
319
320     /*
321      * Have the windows attributes set
322      *
323      * HINT: the masks should be updated when adding/removing callbacks.
324      *       This might speed up message processing. Is that true?
325      */
326     winAttr.event_mask        = StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
327                                 ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyRelease |
328                                 VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
329                                 PointerMotionMask | ButtonMotionMask;
330     winAttr.background_pixmap = None;
331     winAttr.background_pixel  = 0;
332     winAttr.border_pixel      = 0;
333
334     /*
335      * The color map is required, too
336      */
337     winAttr.colormap = XCreateColormap(
338         fgDisplay.Display, fgDisplay.RootWindow,
339         window->Window.VisualInfo->visual, AllocNone
340     );
341
342     /*
343      * This tells the XCreateWindow() what attributes are we supplying it with
344      */
345     mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
346
347     /*
348      * Have the window created now
349      */
350     window->Window.Handle = XCreateWindow(
351         fgDisplay.Display,
352         window->Parent == NULL ? fgDisplay.RootWindow : window->Parent->Window.Handle,
353         x, y, w, h, 0,
354         window->Window.VisualInfo->depth, InputOutput,
355         window->Window.VisualInfo->visual, mask,
356         &winAttr
357     );
358
359     /*
360      * The GLX context creation, possibly trying the direct context rendering
361      */
362     window->Window.Context = glXCreateContext(
363         fgDisplay.Display, window->Window.VisualInfo,
364         NULL, fgState.ForceDirectContext | fgState.TryDirectContext
365     );
366
367     /*
368      * Make sure the context is direct when the user wants it forced
369      */
370     if( fgState.ForceDirectContext && !glXIsDirect( fgDisplay.Display, window->Window.Context ) )
371         fgError( "unable to force direct context rendering for window '%s'", title );
372
373     /*
374      * Set the new context as the current one. That's all about the window creation.
375      */
376     glXMakeCurrent(
377         fgDisplay.Display,
378         window->Window.Handle,
379         window->Window.Context
380     );
381
382     /*
383      * Assume the new window is visible by default
384      */
385     window->State.Visible = TRUE;
386
387     /*
388      * For the position and size hints -- make sure we are passing valid values
389      */
390     sizeHints.flags = 0;
391
392     if (fgState.Position.Use == TRUE) sizeHints.flags |= USPosition;
393     if (fgState.Size.Use     == TRUE) sizeHints.flags |= USSize;
394
395     /*
396      * Fill in the size hints values now (the x, y, width and height
397      * settings are obsolote, are there any more WMs that support them?)
398      */
399     sizeHints.x      = x; sizeHints.y      = y;
400     sizeHints.width  = w; sizeHints.height = h;
401
402     /*
403      * We can have forced all new windows start in iconified state:
404      */
405     wmHints.flags = StateHint;
406     wmHints.initial_state = (fgState.ForceIconic == FALSE) ? NormalState : IconicState;
407
408     /*
409      * Prepare the window and iconified window names...
410      */
411     XStringListToTextProperty( (char **) &title, 1, &textProperty );
412
413     /*
414      * Set the window's properties now
415      */
416     XSetWMProperties(
417         fgDisplay.Display,
418         window->Window.Handle,
419         &textProperty,
420         &textProperty,
421         0,
422         0,
423         &sizeHints,
424         &wmHints,
425         NULL
426     );
427
428     /*
429      * Make sure we are informed about the window deletion commands
430      */
431     XSetWMProtocols( fgDisplay.Display, window->Window.Handle, &fgDisplay.DeleteWindow, 1 );
432
433     /*
434      * Finally, have the window mapped to our display
435      */
436     XMapWindow( fgDisplay.Display, window->Window.Handle );
437
438     /*
439      * In game mode, move the viewport a bit to hide the decorations.
440      * This code depends on the XFree86 video mode extensions.
441      */
442     if( gameMode == TRUE )
443     {
444         /*
445          * This somehow fixes the glutGet() GLUT_WINDOW_X and GLUT_WINDOW_Y problem...
446          */
447         XMoveWindow( fgDisplay.Display, window->Window.Handle, x, y );
448
449 #       ifdef X_XF86VidModeSetViewPort
450
451         /*
452          * Set the newly created window as the current one...
453          */
454         glutSetWindow( window->ID );
455
456         /*
457          * Move the viewport a bit down and right from top-left corner to hide the decorations
458          */
459         XF86VidModeSetViewPort(
460             fgDisplay.Display,
461             fgDisplay.Screen,
462             glutGet( GLUT_WINDOW_X ),
463             glutGet( GLUT_WINDOW_Y )
464         );
465
466 #       endif
467     }
468
469 #elif TARGET_HOST_WIN32
470
471         WNDCLASS wc;
472         int flags;
473         ATOM atom;
474         HWND hWnd;
475
476     freeglut_assert_ready;
477
478         /*
479          * Grab the window class we have registered on glutInit():
480          */
481         atom = GetClassInfo( fgDisplay.Instance, "FREEGLUT", &wc );
482         assert( atom != 0 );
483
484     if( gameMode == FALSE )
485     {
486         /*
487          * Update the window position and dimensions, taking account of window decorations
488          */
489                 x -= (GetSystemMetrics( SM_CXSIZEFRAME ) - 1); 
490                 y -= (GetSystemMetrics( SM_CYSIZEFRAME ) - 1);
491                 w += (GetSystemMetrics( SM_CXSIZEFRAME ) - 1)*2;
492                 h += (GetSystemMetrics( SM_CYSIZEFRAME ) - 1)*2 + GetSystemMetrics( SM_CYCAPTION );
493
494         /*
495              * Check if the user wants us to use the default position/size
496              */
497             if( fgState.Position.Use == FALSE ) { x = CW_USEDEFAULT; y = CW_USEDEFAULT; }
498             if( fgState.Size    .Use == FALSE ) { w = CW_USEDEFAULT; h = CW_USEDEFAULT; }
499
500             /*
501              * There's a small difference between creating the top, child and game mode windows
502              */
503             flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
504
505             if( window->Parent == NULL )
506                     flags |= WS_OVERLAPPEDWINDOW;
507             else
508                     flags |= WS_CHILD;
509     }
510     else
511     {
512         /*
513          * In game mode, the story is a little bit different...
514          */
515         assert( window->Parent == NULL );
516
517         /*
518          * Set the window creation flags appropriately to make the window entirely visible:
519          */
520         flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
521     }
522
523     /*
524      * Create the window now, passing the freeglut window structure as the parameter
525      */
526         window->Window.Handle = CreateWindow( 
527                 "FREEGLUT",
528         title,
529                 flags,
530         x, y, w, h,
531                 (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
532                 (HMENU) NULL,
533                 fgDisplay.Instance,
534                 (LPVOID) window
535         );
536
537         /*
538      * Make sure window was created
539      */
540         assert( window->Window.Handle != NULL );
541
542     /*
543      * Show and update the main window. Hide the mouse cursor.
544      */
545     ShowWindow( window->Window.Handle, fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW );
546     UpdateWindow( window->Window.Handle );
547     ShowCursor( TRUE );
548
549 #endif
550
551     /*
552      * Set the newly created window as the current one
553      */
554     glutSetWindow( window->ID );
555 }
556
557 /*
558  * Closes a window, destroying the frame and OpenGL context
559  */
560 void fgCloseWindow( SFG_Window* window )
561 {
562     freeglut_assert_ready;
563
564 #if TARGET_HOST_UNIX_X11
565     /*
566      * As easy as kill bunnies with axes. Destroy the context first:
567      */
568     glXDestroyContext( fgDisplay.Display, window->Window.Context );
569
570     /*
571      * Then have the window killed:
572      */
573     XDestroyWindow( fgDisplay.Display, window->Window.Handle );
574
575     /*
576      * Finally, flush the rests down the stream
577      */
578     XFlush( fgDisplay.Display );
579
580 #elif TARGET_HOST_WIN32
581         /*
582          * Send the WM_CLOSE message to the window now
583          */
584         SendMessage( 
585                 window->Window.Handle,
586                 WM_CLOSE,
587                 0,
588                 0
589         );
590
591 #endif
592 }
593
594
595 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
596
597 /*
598  * Creates a new top-level freeglut window
599  */
600 int FGAPIENTRY glutCreateWindow( const char* title )
601 {
602     /*
603      * Create a new window and return it's unique ID number
604      */
605     return( fgCreateWindow( NULL, title, fgState.Position.X, fgState.Position.Y,
606                             fgState.Size.X, fgState.Size.Y, FALSE )->ID );
607 }
608
609 /*
610  * This function creates a sub window.
611  */
612 int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
613 {
614     SFG_Window* window = NULL;
615     SFG_Window* parent = NULL;
616
617     freeglut_assert_ready;
618
619     /*
620      * Find a parent to the newly created window...
621      */
622     parent = fgWindowByID( parentID );
623
624     /*
625      * Fail if the parent has not been found
626      */
627     freeglut_return_val_if_fail( parent != NULL, 0 );
628
629     /*
630      * Create the new window
631      */
632     window = fgCreateWindow( parent, "", x, y, w, h, FALSE );
633
634     /*
635      * Return the new window's ID
636      */
637     return( window->ID );
638 }
639
640 /*
641  * Destroys a window and all of it's subwindows
642  */
643 void FGAPIENTRY glutDestroyWindow( int windowID )
644 {
645     /*
646      * Grab the freeglut window pointer from the structure
647      */
648     SFG_Window* window = fgWindowByID( windowID );
649     freeglut_return_if_fail( window != NULL );
650
651     /*
652      * There is a function that performs all needed steps
653      * defined in freeglut_structure.c. Let's use it:
654      */
655     fgDestroyWindow( window, TRUE );
656 }
657
658 /*
659  * This function selects the current window
660  */
661 void FGAPIENTRY glutSetWindow( int ID )
662 {
663     SFG_Window* window = NULL;
664
665     /*
666      * Make sure we don't get called too early
667      */
668     freeglut_assert_ready;
669
670     /*
671      * Be wise. Be wise. Be wise. Be quick.
672      */
673     if( fgStructure.Window != NULL )
674         if( fgStructure.Window->ID == ID )
675             return;
676
677     /*
678      * Now we are sure there is sense in looking for the window
679      */
680     window = fgWindowByID( ID );
681
682     /*
683      * In the case of an utter failure...
684      */
685     if( window == NULL )
686     {
687         /*
688          * ...issue a warning message and keep rolling on
689          */
690         fgWarning( "glutSetWindow(): window ID %i not found!", ID );
691         return;
692     }
693
694 #if TARGET_HOST_UNIX_X11
695     /*
696          * Make the selected window's GLX context the current one
697      */
698     glXMakeCurrent(
699         fgDisplay.Display,
700         window->Window.Handle,
701         window->Window.Context
702     );
703
704 #elif TARGET_HOST_WIN32
705         /*
706          * Release the previous' context's device context
707          */
708         if( fgStructure.Window != NULL )
709                 ReleaseDC( fgStructure.Window->Window.Handle, fgStructure.Window->Window.Device );
710
711         /*
712          * We will care about releasing the device context later
713          */
714         window->Window.Device = GetDC( window->Window.Handle );
715
716         /*
717          * Set the new current context:
718          */
719         wglMakeCurrent( 
720                 window->Window.Device, 
721                 window->Window.Context 
722         );
723
724 #endif
725
726     /*
727      * Remember that we have changed the current window state
728      */
729     fgStructure.Window = window;
730 }
731
732 /*
733  * This function returns the ID number of the current window, 0 if none exists
734  */
735 int FGAPIENTRY glutGetWindow( void )
736 {
737     freeglut_assert_ready;
738
739     /*
740      * Do we have a current window selected?
741      */
742     if( fgStructure.Window == NULL )
743     {
744         /*
745          * Nope. Return zero to mark the state.
746          */
747         return( 0 );
748     }
749
750     /*
751      * Otherwise, return the ID of the current window
752      */
753     return( fgStructure.Window->ID );
754 }
755
756 /*
757  * This function makes the current window visible
758  */
759 void FGAPIENTRY glutShowWindow( void )
760 {
761     freeglut_assert_ready; freeglut_assert_window;
762
763 #if TARGET_HOST_UNIX_X11
764     /*
765      * Showing the window is done via mapping under X
766      */
767     XMapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
768     XFlush( fgDisplay.Display );
769
770 #elif TARGET_HOST_WIN32
771         /*
772          * Restore the window's originial position and size
773          */
774         ShowWindow( fgStructure.Window->Window.Handle, SW_SHOW );
775
776 #endif
777 }
778
779 /*
780  * This function hides the current window
781  */
782 void FGAPIENTRY glutHideWindow( void )
783 {
784     freeglut_assert_ready; freeglut_assert_window;
785
786 #if TARGET_HOST_UNIX_X11
787     /*
788      * The way we hide a window depends on if we're dealing
789      * with a top-level or children one...
790      */
791     if( fgStructure.Window->Parent == NULL )
792     {
793         /*
794          * This is a top-level window
795          */
796         XWithdrawWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, fgDisplay.Screen );
797     }
798     else
799     {
800         /*
801          * Nope, it's a child window
802          */
803         XUnmapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
804     }
805
806     /*
807      * Flush the X state now
808      */
809     XFlush( fgDisplay.Display );
810
811 #elif TARGET_HOST_WIN32
812         /*
813          * Hide the window
814          */
815         ShowWindow( fgStructure.Window->Window.Handle, SW_HIDE );
816
817 #endif
818 }
819
820 /*
821  * Iconify the current window (top-level windows only)
822  */
823 void FGAPIENTRY glutIconifyWindow( void )
824 {
825     freeglut_assert_ready; freeglut_assert_window;
826
827 #if TARGET_HOST_UNIX_X11
828     /*
829      * Iconify the window and flush the X state
830      */
831     XIconifyWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, fgDisplay.Screen );
832     XFlush( fgDisplay.Display );
833
834 #elif TARGET_HOST_WIN32
835         /*
836          * Minimize the current window (this should be the same as X window iconifying)
837          */
838         ShowWindow( fgStructure.Window->Window.Handle, SW_MINIMIZE );
839
840 #endif
841 }
842
843 /*
844  * Set the current window's title
845  */
846 void FGAPIENTRY glutSetWindowTitle( char* title )
847 {
848         freeglut_assert_ready; freeglut_assert_window;
849
850     /*
851      * Works only for top-level windows
852      */
853     if( fgStructure.Window->Parent != NULL )
854         return;
855
856 #if TARGET_HOST_UNIX_X11
857         {
858                 XTextProperty text;
859
860                 /*
861                  * Prepare the text properties
862                  */
863                 text.value = (unsigned char *) title;
864                 text.encoding = XA_STRING;
865                 text.format = 8;
866                 text.nitems = strlen( title );
867
868                 /*
869                  * Set the title now
870                  */
871                 XSetWMName(
872                         fgDisplay.Display,
873                         fgStructure.Window->Window.Handle,
874                         &text
875                 );
876
877                 /*
878                  * Have the X display state flushed
879                  */
880                 XFlush( fgDisplay.Display );
881         }
882
883 #elif TARGET_HOST_WIN32
884         /*
885          * This seems to be a bit easier under Win32
886          */
887         SetWindowText( fgStructure.Window->Window.Handle, title );
888
889 #endif
890 }
891
892 /*
893  * Set the current window's iconified title
894  */
895 void FGAPIENTRY glutSetIconTitle( char* title )
896 {
897     freeglut_assert_ready; freeglut_assert_window;
898
899     /*
900      * Works only for top-level windows
901      */
902     if( fgStructure.Window->Parent != NULL )
903         return;
904
905 #if TARGET_HOST_UNIX_X11
906         {
907                 XTextProperty text;
908
909                 /*
910                  * Prepare the text properties
911                  */
912                 text.value = (unsigned char *) title;
913                 text.encoding = XA_STRING;
914                 text.format = 8;
915                 text.nitems = strlen( title );
916
917                 /*
918                  * Set the title now
919                  */
920                 XSetWMIconName(
921                         fgDisplay.Display,
922                         fgStructure.Window->Window.Handle,
923                         &text
924                 );
925
926                 /*
927                  * Have the X display state flushed
928                  */
929                 XFlush( fgDisplay.Display );
930         }
931
932 #elif TARGET_HOST_WIN32
933         /*
934          * This seems to be a bit easier under Win32
935          */
936         SetWindowText( fgStructure.Window->Window.Handle, title );
937
938 #endif
939 }
940
941 /*
942  * Change the current window's size
943  */
944 void FGAPIENTRY glutReshapeWindow( int width, int height )
945 {
946     freeglut_assert_ready; freeglut_assert_window;
947
948 #if TARGET_HOST_UNIX_X11
949     /*
950      * Resize the window and flush the X state
951      */
952     XResizeWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, width, height );
953     XFlush( fgDisplay.Display );
954
955 #elif TARGET_HOST_WIN32
956         {
957                 RECT winRect;
958
959                 /*
960                  * First off, grab the current window's position
961                  */
962                 GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
963
964                 /*
965                  * Resize the window, forcing a redraw to happen
966                  */
967                 MoveWindow(
968                         fgStructure.Window->Window.Handle,
969                         winRect.left,
970                         winRect.top,
971                         width,
972                         height,
973                         TRUE
974                 );
975         }
976 #endif
977 }
978
979 /*
980  * Change the current window's position
981  */
982 void FGAPIENTRY glutPositionWindow( int x, int y )
983 {
984     freeglut_assert_ready; freeglut_assert_window;
985
986 #if TARGET_HOST_UNIX_X11
987     /*
988      * Reposition the window and flush the X state
989      */
990     XMoveWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, x, y );
991     XFlush( fgDisplay.Display );
992
993 #elif TARGET_HOST_WIN32
994         {
995                 RECT winRect;
996
997                 /*
998                  * First off, grab the current window's position
999                  */
1000                 GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
1001
1002                 /*
1003                  * Reposition the window, forcing a redraw to happen
1004                  */
1005                 MoveWindow(
1006                         fgStructure.Window->Window.Handle,
1007                         x,
1008                         y,
1009                         winRect.right - winRect.left,
1010                         winRect.bottom - winRect.top,
1011                         TRUE
1012                 );
1013         }
1014
1015 #endif
1016 }
1017
1018 /*
1019  * Lowers the current window (by Z order change)
1020  */
1021 void FGAPIENTRY glutPushWindow( void )
1022 {
1023     freeglut_assert_ready; freeglut_assert_window;
1024
1025 #if TARGET_HOST_UNIX_X11
1026     /*
1027      * Lower the current window
1028      */
1029     XLowerWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
1030
1031 #elif TARGET_HOST_WIN32
1032         /*
1033          * Set the new window's Z position, not affecting the rest of the settings:
1034          */
1035         SetWindowPos(
1036                 fgStructure.Window->Window.Handle,
1037                 HWND_BOTTOM,
1038                 0, 0, 0, 0,
1039                 SWP_NOSIZE | SWP_NOMOVE
1040         );
1041
1042 #endif
1043 }
1044
1045 /*
1046  * Raises the current window (by Z order change)
1047  */
1048 void FGAPIENTRY glutPopWindow( void )
1049 {
1050     freeglut_assert_ready; freeglut_assert_window;
1051
1052 #if TARGET_HOST_UNIX_X11
1053     /*
1054      * Raise the current window
1055      */
1056     XRaiseWindow( fgDisplay.Display, fgStructure.Window->Window.Handle );
1057
1058 #elif TARGET_HOST_WIN32
1059         /*
1060          * Set the new window's Z position, not affecting the rest of the settings:
1061          */
1062         SetWindowPos(
1063                 fgStructure.Window->Window.Handle,
1064                 HWND_TOP,
1065                 0, 0, 0, 0,
1066                 SWP_NOSIZE | SWP_NOMOVE
1067         );
1068
1069 #endif
1070 }
1071
1072 /*
1073  * Resize the current window so that it fits the whole screen
1074  */
1075 void FGAPIENTRY glutFullScreen( void )
1076 {
1077     freeglut_assert_ready; freeglut_assert_window;
1078
1079     /*
1080      * Just have the window repositioned and resized
1081      */
1082     glutPositionWindow( 0, 0 );
1083
1084     glutReshapeWindow(
1085         fgDisplay.ScreenWidth,
1086         fgDisplay.ScreenHeight
1087     );
1088 }
1089
1090 /*** END OF FILE ***/
1091
1092
1093
1094
1095
1096
1097
1098
1099