X11 only: Free XVisualInfo structures when they are not needed
[freeglut] / src / freeglut_state.c
1 /*
2  * freeglut_state.c
3  *
4  * Freeglut state query 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: Thu Dec 16 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 #include <GL/freeglut.h>
29 #include "freeglut_internal.h"
30
31 /*
32  * TODO BEFORE THE STABLE RELEASE:
33  *
34  *  glutGet()               -- X11 tests passed, but check if all enums
35  *                             handled (what about Win32?)
36  *  glutDeviceGet()         -- X11 tests passed, but check if all enums
37  *                             handled (what about Win32?)
38  *  glutGetModifiers()      -- OK, but could also remove the limitation
39  *  glutLayerGet()          -- what about GLUT_NORMAL_DAMAGED?
40  *
41  * The fail-on-call policy will help adding the most needed things imho.
42  */
43
44 /* -- LOCAL DEFINITIONS ---------------------------------------------------- */
45
46 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
47
48 #if TARGET_HOST_UNIX_X11
49 /*
50  * Queries the GL context about some attributes
51  */
52 static int fghGetConfig( int attribute )
53 {
54   int returnValue = 0;
55
56   if( fgStructure.CurrentWindow )
57       glXGetConfig( fgDisplay.Display, fgStructure.CurrentWindow->Window.VisualInfo,
58                     attribute, &returnValue );
59
60   return returnValue;
61 }
62 #endif
63
64 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
65
66 /*
67  * General settings assignment method
68  */
69 void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
70 {
71     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetOption" );
72
73     /*
74      * XXX In chronological code add order.  (WHY in that order?)
75      */
76     switch( eWhat )
77     {
78     case GLUT_INIT_WINDOW_X:
79         fgState.Position.X = (GLint)value;
80         break;
81
82     case GLUT_INIT_WINDOW_Y:
83         fgState.Position.Y = (GLint)value;
84         break;
85
86     case GLUT_INIT_WINDOW_WIDTH:
87         fgState.Size.X = (GLint)value;
88         break;
89
90     case GLUT_INIT_WINDOW_HEIGHT:
91         fgState.Size.Y = (GLint)value;
92         break;
93
94     case GLUT_INIT_DISPLAY_MODE:
95         fgState.DisplayMode = (unsigned int)value;
96         break;
97
98     case GLUT_ACTION_ON_WINDOW_CLOSE:
99         fgState.ActionOnWindowClose = value;
100         break;
101
102     case GLUT_RENDERING_CONTEXT:
103         fgState.UseCurrentContext =
104             ( value == GLUT_USE_CURRENT_CONTEXT ) ? GL_TRUE : GL_FALSE;
105         break;
106
107     case GLUT_DIRECT_RENDERING:
108         fgState.DirectContext = value;
109         break;
110
111     case GLUT_WINDOW_CURSOR:
112         if( fgStructure.CurrentWindow != NULL )
113             fgStructure.CurrentWindow->State.Cursor = value;
114         break;
115
116     default:
117         fgWarning( "glutSetOption(): missing enum handle %d", eWhat );
118         break;
119     }
120 }
121
122 /*
123  * General settings query method
124  */
125 int FGAPIENTRY glutGet( GLenum eWhat )
126 {
127 #if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
128     int returnValue ;
129     GLboolean boolValue ;
130 #endif
131
132     switch (eWhat)
133     {
134     case GLUT_INIT_STATE:
135         return fgState.Initialised;
136
137     case GLUT_ELAPSED_TIME:
138         return fgElapsedTime();
139     }
140
141     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGet" );
142
143     /* XXX In chronological code add order.  (WHY in that order?) */
144     switch( eWhat )
145     {
146     /* Following values are stored in fgState and fgDisplay global structures */
147     case GLUT_SCREEN_WIDTH:         return fgDisplay.ScreenWidth   ;
148     case GLUT_SCREEN_HEIGHT:        return fgDisplay.ScreenHeight  ;
149     case GLUT_SCREEN_WIDTH_MM:      return fgDisplay.ScreenWidthMM ;
150     case GLUT_SCREEN_HEIGHT_MM:     return fgDisplay.ScreenHeightMM;
151     case GLUT_INIT_WINDOW_X:        return fgState.Position.X      ;
152     case GLUT_INIT_WINDOW_Y:        return fgState.Position.Y      ;
153     case GLUT_INIT_WINDOW_WIDTH:    return fgState.Size.X          ;
154     case GLUT_INIT_WINDOW_HEIGHT:   return fgState.Size.Y          ;
155     case GLUT_INIT_DISPLAY_MODE:    return fgState.DisplayMode     ;
156
157     /*
158      * The window/context specific queries are handled mostly by
159      * fghGetConfig().
160      */
161     case GLUT_WINDOW_NUM_SAMPLES:
162         /* XXX Multisampling. Return what I know about multisampling. */
163         return 0;
164
165 #if TARGET_HOST_UNIX_X11
166     /*
167      * The rest of GLX queries under X are general enough to use a macro to
168      * check them
169      */
170 #   define GLX_QUERY(a,b) case a: return fghGetConfig( b );
171
172     GLX_QUERY( GLUT_WINDOW_RGBA,                GLX_RGBA                );
173     GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER,        GLX_DOUBLEBUFFER        );
174     GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE,         GLX_BUFFER_SIZE         );
175     GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE,        GLX_STENCIL_SIZE        );
176     GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE,          GLX_DEPTH_SIZE          );
177     GLX_QUERY( GLUT_WINDOW_RED_SIZE,            GLX_RED_SIZE            );
178     GLX_QUERY( GLUT_WINDOW_GREEN_SIZE,          GLX_GREEN_SIZE          );
179     GLX_QUERY( GLUT_WINDOW_BLUE_SIZE,           GLX_BLUE_SIZE           );
180     GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE,          GLX_ALPHA_SIZE          );
181     GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE,      GLX_ACCUM_RED_SIZE      );
182     GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE,    GLX_ACCUM_GREEN_SIZE    );
183     GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE,     GLX_ACCUM_BLUE_SIZE     );
184     GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE,    GLX_ACCUM_ALPHA_SIZE    );
185     GLX_QUERY( GLUT_WINDOW_STEREO,              GLX_STEREO              );
186
187 #   undef GLX_QUERY
188
189     /* Colormap size is handled in a bit different way than all the rest */
190     case GLUT_WINDOW_COLORMAP_SIZE:
191         if( (fghGetConfig( GLX_RGBA )) || (fgStructure.CurrentWindow == NULL) )
192         {
193             /*
194              * We've got a RGBA visual, so there is no colormap at all.
195              * The other possibility is that we have no current window set.
196              */
197             return 0;
198         }
199         return fgStructure.CurrentWindow->Window.VisualInfo->visual->map_entries;
200
201     /*
202      * Those calls are somewhat similiar, as they use XGetWindowAttributes()
203      * function
204      */
205     case GLUT_WINDOW_X:
206     case GLUT_WINDOW_Y:
207     case GLUT_WINDOW_BORDER_WIDTH:
208     case GLUT_WINDOW_HEADER_HEIGHT:
209     {
210         int x, y;
211         Window w;
212
213         if( fgStructure.CurrentWindow == NULL )
214             return 0;
215
216         XTranslateCoordinates(
217             fgDisplay.Display,
218             fgStructure.CurrentWindow->Window.Handle,
219             fgDisplay.RootWindow,
220             0, 0, &x, &y, &w);
221
222         switch ( eWhat )
223         {
224         case GLUT_WINDOW_X: return x;
225         case GLUT_WINDOW_Y: return y;
226         }
227
228         if ( w == 0 )
229             return 0;
230         XTranslateCoordinates(
231             fgDisplay.Display,
232             fgStructure.CurrentWindow->Window.Handle,
233             w, 0, 0, &x, &y, &w);
234
235         switch ( eWhat )
236         {
237         case GLUT_WINDOW_BORDER_WIDTH:  return x;
238         case GLUT_WINDOW_HEADER_HEIGHT: return y;
239         }
240     }
241
242     case GLUT_WINDOW_WIDTH:
243     case GLUT_WINDOW_HEIGHT:
244     {
245         XWindowAttributes winAttributes;
246
247         if( fgStructure.CurrentWindow == NULL )
248             return 0;
249         XGetWindowAttributes(
250             fgDisplay.Display,
251             fgStructure.CurrentWindow->Window.Handle,
252             &winAttributes
253         );
254         switch ( eWhat )
255         {
256         case GLUT_WINDOW_WIDTH:            return winAttributes.width ;
257         case GLUT_WINDOW_HEIGHT:           return winAttributes.height ;
258         }
259     }
260
261     /* I do not know yet if there will be a fgChooseVisual() function for Win32 */
262     case GLUT_DISPLAY_MODE_POSSIBLE:
263     {
264         XVisualInfo* visualInfo = fgChooseVisual();
265         if ( visualInfo == NULL ) {
266             return 0;
267         } else {
268             XFree( visualInfo );
269             return 1;
270         }
271     }
272
273     /* This is system-dependant */
274     case GLUT_WINDOW_FORMAT_ID:
275         if( fgStructure.CurrentWindow == NULL )
276             return 0;
277
278         return fgStructure.CurrentWindow->Window.VisualInfo->visualid;
279
280 #elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
281
282     /* Handle the OpenGL inquiries */
283     case GLUT_WINDOW_RGBA:
284       glGetBooleanv ( GL_RGBA_MODE, &boolValue );
285       returnValue = boolValue ? 1 : 0;
286       return returnValue;
287     case GLUT_WINDOW_DOUBLEBUFFER:
288       glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue );
289       returnValue = boolValue ? 1 : 0;
290       return returnValue;
291     case GLUT_WINDOW_STEREO:
292       glGetBooleanv ( GL_STEREO, &boolValue );
293       returnValue = boolValue ? 1 : 0;
294       return returnValue;
295
296     case GLUT_WINDOW_RED_SIZE:
297       glGetIntegerv ( GL_RED_BITS, &returnValue );
298       return returnValue;
299     case GLUT_WINDOW_GREEN_SIZE:
300       glGetIntegerv ( GL_GREEN_BITS, &returnValue );
301       return returnValue;
302     case GLUT_WINDOW_BLUE_SIZE:
303       glGetIntegerv ( GL_BLUE_BITS, &returnValue );
304       return returnValue;
305     case GLUT_WINDOW_ALPHA_SIZE:
306       glGetIntegerv ( GL_ALPHA_BITS, &returnValue );
307       return returnValue;
308     case GLUT_WINDOW_ACCUM_RED_SIZE:
309       glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue );
310       return returnValue;
311     case GLUT_WINDOW_ACCUM_GREEN_SIZE:
312       glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue );
313       return returnValue;
314     case GLUT_WINDOW_ACCUM_BLUE_SIZE:
315       glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue );
316       return returnValue;
317     case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
318       glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue );
319       return returnValue;
320     case GLUT_WINDOW_DEPTH_SIZE:
321       glGetIntegerv ( GL_DEPTH_BITS, &returnValue );
322       return returnValue;
323
324     case GLUT_WINDOW_BUFFER_SIZE:
325       returnValue = 1 ;                                      /* ????? */
326       return returnValue;
327     case GLUT_WINDOW_STENCIL_SIZE:
328       returnValue = 0 ;                                      /* ????? */
329       return returnValue;
330
331     case GLUT_WINDOW_X:
332     case GLUT_WINDOW_Y:
333     case GLUT_WINDOW_WIDTH:
334     case GLUT_WINDOW_HEIGHT:
335     {
336         /*
337          *  There is considerable confusion about the "right thing to
338          *  do" concerning window  size and position.  GLUT itself is
339          *  not consistent between Windows and UNIX/X11; since
340          *  platform independence is a virtue for "freeglut", we
341          *  decided to break with GLUT's behaviour.
342          *
343          *  Under UNIX/X11, it is apparently not possible to get the
344          *  window border sizes in order to subtract them off the
345          *  window's initial position until some time after the window
346          *  has been created.  Therefore we decided on the following
347          *  behaviour, both under Windows and under UNIX/X11:
348          *  - When you create a window with position (x,y) and size
349          *    (w,h), the upper left hand corner of the outside of the
350          *    window is at (x,y) and the size of the drawable area  is
351          *    (w,h).
352          *  - When you query the size and position of the window--as
353          *    is happening here for Windows--"freeglut" will return
354          *    the size of the drawable area--the (w,h) that you
355          *    specified when you created the window--and the coordinates
356          *    of the upper left hand corner of the drawable
357          *    area--which is NOT the (x,y) you specified.
358          */
359
360         RECT winRect;
361
362         freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
363
364         /*
365          * We need to call GetWindowRect() first...
366          *  (this returns the pixel coordinates of the outside of the window)
367          */
368         GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
369
370         /* ...then we've got to correct the results we've just received... */
371
372 #if !TARGET_HOST_WINCE
373         if ( ( fgStructure.GameMode != fgStructure.CurrentWindow ) && ( fgStructure.CurrentWindow->Parent == NULL ) &&
374              ( ! fgStructure.CurrentWindow->IsMenu ) )
375         {
376           winRect.left   += GetSystemMetrics( SM_CXSIZEFRAME );
377           winRect.right  -= GetSystemMetrics( SM_CXSIZEFRAME );
378           winRect.top    += GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION );
379           winRect.bottom -= GetSystemMetrics( SM_CYSIZEFRAME );
380         }
381 #endif /* !TARGET_HOST_WINCE */
382
383         switch( eWhat )
384         {
385         case GLUT_WINDOW_X:      return winRect.left                ;
386         case GLUT_WINDOW_Y:      return winRect.top                 ;
387         case GLUT_WINDOW_WIDTH:  return winRect.right - winRect.left;
388         case GLUT_WINDOW_HEIGHT: return winRect.bottom - winRect.top;
389         }
390     }
391     break;
392
393     case GLUT_WINDOW_BORDER_WIDTH :
394 #if TARGET_HOST_WINCE
395         return 0;
396 #else
397         return GetSystemMetrics( SM_CXSIZEFRAME );
398 #endif /* !TARGET_HOST_WINCE */
399
400     case GLUT_WINDOW_HEADER_HEIGHT :
401 #if TARGET_HOST_WINCE
402         return 0;
403 #else
404         return GetSystemMetrics( SM_CYCAPTION );
405 #endif /* TARGET_HOST_WINCE */
406
407     case GLUT_DISPLAY_MODE_POSSIBLE:
408 #if TARGET_HOST_WINCE
409         return GL_FALSE;
410 #else
411         return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
412                                     PFD_MAIN_PLANE );
413 #endif /* TARGET_HOST_WINCE */
414
415
416     case GLUT_WINDOW_FORMAT_ID:
417 #if !TARGET_HOST_WINCE
418         if( fgStructure.CurrentWindow != NULL )
419             return GetPixelFormat( fgStructure.CurrentWindow->Window.Device );
420 #endif /* TARGET_HOST_WINCE */
421         return 0;
422
423 #endif
424
425     /* The window structure queries */
426     case GLUT_WINDOW_PARENT:
427         if( fgStructure.CurrentWindow         == NULL ) return 0;
428         if( fgStructure.CurrentWindow->Parent == NULL ) return 0;
429         return fgStructure.CurrentWindow->Parent->ID;
430
431     case GLUT_WINDOW_NUM_CHILDREN:
432         if( fgStructure.CurrentWindow == NULL )
433             return 0;
434         return fgListLength( &fgStructure.CurrentWindow->Children );
435
436     case GLUT_WINDOW_CURSOR:
437         if( fgStructure.CurrentWindow == NULL )
438             return 0;
439         return fgStructure.CurrentWindow->State.Cursor;
440
441     case GLUT_MENU_NUM_ITEMS:
442         if( fgStructure.CurrentMenu == NULL )
443             return 0;
444         return fgListLength( &fgStructure.CurrentMenu->Entries );
445
446     case GLUT_ACTION_ON_WINDOW_CLOSE:
447         return fgState.ActionOnWindowClose;
448
449     case GLUT_VERSION :
450         return VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_PATCH;
451
452     case GLUT_RENDERING_CONTEXT:
453         return fgState.UseCurrentContext ? GLUT_USE_CURRENT_CONTEXT
454                                          : GLUT_CREATE_NEW_CONTEXT;
455
456     case GLUT_DIRECT_RENDERING:
457         return fgState.DirectContext;
458         break;
459
460     default:
461         fgWarning( "glutGet(): missing enum handle %d", eWhat );
462         break;
463     }
464     return -1;
465 }
466
467 /*
468  * Returns various device information.
469  */
470 int FGAPIENTRY glutDeviceGet( GLenum eWhat )
471 {
472     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDeviceGet" );
473
474     /* XXX WARNING: we are mostly lying in this function. */
475     switch( eWhat )
476     {
477     case GLUT_HAS_KEYBOARD:
478         /*
479          * We always have a keyboard present on PC machines...
480          *
481          * XXX I think that some of my PCs will boot without a keyboard.
482          * XXX Also, who says that we are running on a PC?  UNIX/X11
483          * XXX is much more generic, and X11 can go over a network.
484          * XXX Though in actuality, we can probably assume BOTH a
485          * XXX mouse and keyboard for most/all of our users.
486          */
487         return TRUE ;
488
489 #if TARGET_HOST_UNIX_X11
490
491     case GLUT_HAS_MOUSE:
492         return TRUE ;
493
494     case GLUT_NUM_MOUSE_BUTTONS:
495         /*
496          * Return the number of mouse buttons available. This is a big guess.
497          *
498          * XXX We can probe /var/run/dmesg.boot which is world-readable.
499          * XXX This would be somewhat system-dependant, but is doable.
500          * XXX E.g., on NetBSD, my USB mouse registers:
501          * XXX   ums0 at uhidev0: 3 buttons and Z dir.
502          * XXX We can also probe /var/log/XFree86\..*\.log to get
503          * XXX lines such as:
504          * XXX   (**) Option "Buttons" "5"
505          * XXX   (**) Option "ZAxisMapping" "4 5"
506          * XXX   (**) Mouse0: ZAxisMapping: buttons 4 and 5
507          * XXX   (**) Mouse0: Buttons: 5
508          * XXX ...which tells us even more, and is a bit less
509          * XXX system-dependant.  (Other than MS-WINDOWS, all
510          * XXX target hosts with actual users are probably running
511          * XXX XFree86...)  It is at least worth taking a look at
512          * XXX this file.
513          */
514         return 3 ;
515
516 #elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
517
518     case GLUT_HAS_MOUSE:
519         /*
520          * The Windows can be booted without a mouse.
521          * It would be nice to have this reported.
522          */
523         return GetSystemMetrics( SM_MOUSEPRESENT );
524
525     case GLUT_NUM_MOUSE_BUTTONS:
526         /* We are much more fortunate under Win32 about this... */
527 #if TARGET_HOST_WINCE
528         return 1;
529 #else
530         return GetSystemMetrics( SM_CMOUSEBUTTONS );
531 #endif /* TARGET_HOST_WINCE */
532
533 #endif
534
535     case GLUT_HAS_JOYSTICK:
536         return fgJoystickDetect ();
537
538     case GLUT_OWNS_JOYSTICK:
539         return fgState.JoysticksInitialised;
540
541     case GLUT_JOYSTICK_POLL_RATE:
542         return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.JoystickPollRate : 0;
543
544     /* XXX The following two are only for Joystick 0 but this is an improvement */
545     case GLUT_JOYSTICK_BUTTONS:
546         return glutJoystickGetNumButtons ( 0 );
547
548     case GLUT_JOYSTICK_AXES:
549         return glutJoystickGetNumAxes ( 0 );
550
551     case GLUT_HAS_DIAL_AND_BUTTON_BOX:
552         return fgInputDeviceDetect ();
553
554     case GLUT_NUM_DIALS:
555         if ( fgState.InputDevsInitialised ) return 8;
556         return 0;
557  
558     case GLUT_NUM_BUTTON_BOX_BUTTONS:
559         return 0;
560
561     case GLUT_HAS_SPACEBALL:
562     case GLUT_HAS_TABLET:
563         return FALSE;
564
565     case GLUT_NUM_SPACEBALL_BUTTONS:
566     case GLUT_NUM_TABLET_BUTTONS:
567         return 0;
568
569     case GLUT_DEVICE_IGNORE_KEY_REPEAT:
570         return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.IgnoreKeyRepeat : 0;
571
572     case GLUT_DEVICE_KEY_REPEAT:
573         return fgState.KeyRepeat;
574
575     default:
576         fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
577         break;
578     }
579
580     /* And now -- the failure. */
581     return -1;
582 }
583
584 /*
585  * This should return the current state of ALT, SHIFT and CTRL keys.
586  */
587 int FGAPIENTRY glutGetModifiers( void )
588 {
589     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetModifiers" );
590     if( fgState.Modifiers == INVALID_MODIFIERS )
591     {
592         fgWarning( "glutGetModifiers() called outside an input callback" );
593         return 0;
594     }
595
596     return fgState.Modifiers;
597 }
598
599 /*
600  * Return the state of the GLUT API overlay subsystem. A misery ;-)
601  */
602 int FGAPIENTRY glutLayerGet( GLenum eWhat )
603 {
604     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLayerGet" );
605
606     /*
607      * This is easy as layers are not implemented ;-)
608      *
609      * XXX Can we merge the UNIX/X11 and WIN32 sections?  Or
610      * XXX is overlay support planned?
611      */
612     switch( eWhat )
613     {
614
615 #if TARGET_HOST_UNIX_X11
616
617     case GLUT_OVERLAY_POSSIBLE:
618         return FALSE;
619
620     case GLUT_LAYER_IN_USE:
621         return GLUT_NORMAL;
622
623     case GLUT_HAS_OVERLAY:
624         return FALSE;
625
626     case GLUT_TRANSPARENT_INDEX:
627         /*
628          * Return just anything, which is always defined as zero
629          *
630          * XXX HUH?
631          */
632         return 0;
633
634     case GLUT_NORMAL_DAMAGED:
635         /* XXX Actually I do not know. Maybe. */
636         return FALSE;
637
638     case GLUT_OVERLAY_DAMAGED:
639         return -1;
640
641 #elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
642
643     case GLUT_OVERLAY_POSSIBLE:
644 /*      return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
645                                    PFD_OVERLAY_PLANE ); */
646       return FALSE ;
647
648     case GLUT_LAYER_IN_USE:
649         return GLUT_NORMAL;
650
651     case GLUT_HAS_OVERLAY:
652         return FALSE;
653
654     case GLUT_TRANSPARENT_INDEX:
655         /*
656          * Return just anything, which is always defined as zero
657          *
658          * XXX HUH?
659          */
660         return 0;
661
662     case GLUT_NORMAL_DAMAGED:
663         /* XXX Actually I do not know. Maybe. */
664         return FALSE;
665
666     case GLUT_OVERLAY_DAMAGED:
667         return -1;
668 #endif
669
670     default:
671         fgWarning( "glutLayerGet(): missing enum handle %d", eWhat );
672         break;
673     }
674
675     /* And fail. That's good. Programs do love failing. */
676     return -1;
677 }
678
679 /*** END OF FILE ***/