Putting in the "glutFullScreen" support for Gnome and other X window managers per...
[freeglut] / src / freeglut_state.c
index 84b261e..589f8ff 100644 (file)
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define  G_LOG_DOMAIN  "freeglut-state"
-
-#include "../include/GL/freeglut.h"
+#include <GL/freeglut.h>
 #include "freeglut_internal.h"
 
 /*
  * TODO BEFORE THE STABLE RELEASE:
  *
- *  glutGet()               -- X11 tests passed, but check if all enums handled (what about Win32?)
- *  glutDeviceGet()         -- X11 tests passed, but check if all enums handled (what about Win32?)
+ *  glutGet()               -- X11 tests passed, but check if all enums
+ *                             handled (what about Win32?)
+ *  glutDeviceGet()         -- X11 tests passed, but check if all enums
+ *                             handled (what about Win32?)
  *  glutGetModifiers()      -- OK, but could also remove the limitation
  *  glutLayerGet()          -- what about GLUT_NORMAL_DAMAGED?
  *
 
 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 /*
  * Queries the GL context about some attributes
  */
 static int fghGetConfig( int attribute )
 {
-  int returnValue ;
-
-  /*
-   * Return nothing if there is no current window set
-   */
-  if( fgStructure.Window == NULL )
-    return( 0 );
-
-  /*
-   * glXGetConfig should work fine
-   */
-  glXGetConfig( fgDisplay.Display, fgStructure.Window->Window.VisualInfo, attribute, &returnValue );
+  int returnValue = 0;
+  int result;  /*  Not checked  */
 
+  if( fgStructure.CurrentWindow )
+      result = glXGetFBConfigAttrib( fgDisplay.Display,
+                                     *(fgStructure.CurrentWindow->Window.FBConfig),
+                                     attribute,
+                                     &returnValue );
 
-  /*
-   * Have the query results returned
-   */
-  return ( returnValue ) ;
+  return returnValue;
 }
 #endif
 
+/* Check if the window is in full screen state. */
+static int fghCheckFullScreen(void)
+{
+#if TARGET_HOST_POSIX_X11
+    return fgStructure.CurrentWindow->State.IsFullscreen;
+#else
+    return 0;
+#endif
+}
+
 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
 
 /*
@@ -83,94 +81,135 @@ static int fghGetConfig( int attribute )
  */
 void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
 {
-  freeglut_assert_ready;
-
-  /*
-   * Check what is the caller querying for. In chronological code add order.
-   */
-  switch( eWhat )
-  {
-  case GLUT_INIT_WINDOW_X:          fgState.Position.X          = (GLint)value ;
-                                    break ;
-  case GLUT_INIT_WINDOW_Y:          fgState.Position.Y          = (GLint)value ;
-                                    break ;
-  case GLUT_INIT_WINDOW_WIDTH:      fgState.Size.X              = (GLint)value ;
-                                    break ;
-  case GLUT_INIT_WINDOW_HEIGHT:     fgState.Size.Y              = (GLint)value ;
-                                    break ;
-  case GLUT_INIT_DISPLAY_MODE:      fgState.DisplayMode         = (unsigned int)value ;
-                                    break ;
-
-  case GLUT_ACTION_ON_WINDOW_CLOSE: fgState.ActionOnWindowClose = value ;
-                                    break ;
-
-  case GLUT_RENDERING_CONTEXT:      fgState.UseCurrentContext   = ( value == GLUT_USE_CURRENT_CONTEXT ) ? TRUE : FALSE ;
-                                    break ;
-
-  case GLUT_WINDOW_CURSOR:
-      if( fgStructure.Window != NULL ) fgStructure.Window->State.Cursor = value ;
-      break ;
-
-  default:
-      /*
-       * Just have it reported, so that we can see what needs to be implemented
-       */
-      fgWarning( "glutSetOption(): missing enum handle %i\n", eWhat );
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetOption" );
+
+    /*
+     * XXX In chronological code add order.  (WHY in that order?)
+     */
+    switch( eWhat )
+    {
+    case GLUT_INIT_WINDOW_X:
+        fgState.Position.X = (GLint)value;
+        break;
+
+    case GLUT_INIT_WINDOW_Y:
+        fgState.Position.Y = (GLint)value;
+        break;
+
+    case GLUT_INIT_WINDOW_WIDTH:
+        fgState.Size.X = (GLint)value;
+        break;
+
+    case GLUT_INIT_WINDOW_HEIGHT:
+        fgState.Size.Y = (GLint)value;
+        break;
+
+    case GLUT_INIT_DISPLAY_MODE:
+        fgState.DisplayMode = (unsigned int)value;
+        break;
+
+    case GLUT_ACTION_ON_WINDOW_CLOSE:
+        fgState.ActionOnWindowClose = value;
+        break;
+
+    case GLUT_RENDERING_CONTEXT:
+        fgState.UseCurrentContext =
+            ( value == GLUT_USE_CURRENT_CONTEXT ) ? GL_TRUE : GL_FALSE;
+        break;
+
+    case GLUT_DIRECT_RENDERING:
+        fgState.DirectContext = value;
+        break;
+
+    case GLUT_WINDOW_CURSOR:
+        if( fgStructure.CurrentWindow != NULL )
+            fgStructure.CurrentWindow->State.Cursor = value;
+        break;
+
+    case GLUT_AUX:
+      fgState.AuxiliaryBufferNumber = value;
       break;
-  }
+
+    case GLUT_MULTISAMPLE:
+      fgState.SampleNumber = value;
+      break;
+
+    default:
+        fgWarning( "glutSetOption(): missing enum handle %d", eWhat );
+        break;
+    }
 }
 
+#if TARGET_HOST_MS_WINDOWS
+/* The following include file is available from SGI but is not standard:
+ *   #include <GL/wglext.h>
+ * So we copy the necessary parts out of it to support the multisampling query
+ */
+#define WGL_SAMPLES_ARB                0x2042
+#endif
+
+
 /*
  * General settings query method
  */
 int FGAPIENTRY glutGet( GLenum eWhat )
 {
-  int returnValue ;
-  GLboolean boolValue ;
-
-  if ( eWhat == GLUT_INIT_STATE )
-    return ( fgState.Time.Set ) ;
+#if TARGET_HOST_MS_WINDOWS
+    int returnValue ;
+    GLboolean boolValue ;
+#endif
 
-    freeglut_assert_ready;
+    int nsamples = 0;
 
-    /*
-     * Check what is the caller querying for. In chronological code add order.
-     */
-    switch( eWhat )
+    switch (eWhat)
     {
+    case GLUT_INIT_STATE:
+        return fgState.Initialised;
+
     case GLUT_ELAPSED_TIME:
-        /*
-         * This is easy and nicely portable, as we are using GLib...
-         */
-        return( fgElapsedTime() );
+        return fgElapsedTime();
+    }
 
-    /*
-     * Following values are stored in fgState and fgDisplay global structures
-     */
-    case GLUT_SCREEN_WIDTH:         return( fgDisplay.ScreenWidth    );
-    case GLUT_SCREEN_HEIGHT:        return( fgDisplay.ScreenHeight   );
-    case GLUT_SCREEN_WIDTH_MM:      return( fgDisplay.ScreenWidthMM  );
-    case GLUT_SCREEN_HEIGHT_MM:     return( fgDisplay.ScreenHeightMM );
-    case GLUT_INIT_WINDOW_X:        return( fgState.Position.X       );
-    case GLUT_INIT_WINDOW_Y:        return( fgState.Position.Y       );
-    case GLUT_INIT_WINDOW_WIDTH:    return( fgState.Size.X           );
-    case GLUT_INIT_WINDOW_HEIGHT:   return( fgState.Size.Y           );
-    case GLUT_INIT_DISPLAY_MODE:    return( fgState.DisplayMode      );
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGet" );
 
+    /* XXX In chronological code add order.  (WHY in that order?) */
+    switch( eWhat )
+    {
+    /* Following values are stored in fgState and fgDisplay global structures */
+    case GLUT_SCREEN_WIDTH:         return fgDisplay.ScreenWidth   ;
+    case GLUT_SCREEN_HEIGHT:        return fgDisplay.ScreenHeight  ;
+    case GLUT_SCREEN_WIDTH_MM:      return fgDisplay.ScreenWidthMM ;
+    case GLUT_SCREEN_HEIGHT_MM:     return fgDisplay.ScreenHeightMM;
+    case GLUT_INIT_WINDOW_X:        return fgState.Position.Use ?
+                                           fgState.Position.X : -1 ;
+    case GLUT_INIT_WINDOW_Y:        return fgState.Position.Use ?
+                                           fgState.Position.Y : -1 ;
+    case GLUT_INIT_WINDOW_WIDTH:    return fgState.Size.Use ?
+                                           fgState.Size.X : -1     ;
+    case GLUT_INIT_WINDOW_HEIGHT:   return fgState.Size.Use ?
+                                           fgState.Size.Y : -1     ;
+    case GLUT_INIT_DISPLAY_MODE:    return fgState.DisplayMode     ;
+    case GLUT_INIT_MAJOR_VERSION:   return fgState.MajorVersion    ;
+    case GLUT_INIT_MINOR_VERSION:   return fgState.MinorVersion    ;
+    case GLUT_INIT_FLAGS:           return fgState.ContextFlags    ;
+    case GLUT_INIT_PROFILE:         return fgState.ContextProfile  ;
+
+#if TARGET_HOST_POSIX_X11
     /*
-     * The window/context specific queries are handled mostly by fghGetConfig().
+     * The window/context specific queries are handled mostly by
+     * fghGetConfig().
      */
     case GLUT_WINDOW_NUM_SAMPLES:
-        /*
-         * Multisampling. Return what I know about multisampling.
-         */
-        return( 0 );
+#ifdef GLX_VERSION_1_3
+        glGetIntegerv(GL_SAMPLES, &nsamples);
+#endif
+        return nsamples;
 
-#if TARGET_HOST_UNIX_X11
     /*
-     * The rest of GLX queries under X are general enough to use a macro to check them
+     * The rest of GLX queries under X are general enough to use a macro to
+     * check them
      */
-#   define GLX_QUERY(a,b) case a: return( fghGetConfig( b ) );
+#   define GLX_QUERY(a,b) case a: return fghGetConfig( b );
 
     GLX_QUERY( GLUT_WINDOW_RGBA,                GLX_RGBA                );
     GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER,        GLX_DOUBLEBUFFER        );
@@ -189,291 +228,345 @@ int FGAPIENTRY glutGet( GLenum eWhat )
 
 #   undef GLX_QUERY
 
-    /*
-     * Colormap size is handled in a bit different way than all the rest
-     */
+    /* Colormap size is handled in a bit different way than all the rest */
     case GLUT_WINDOW_COLORMAP_SIZE:
-        /*
-         * Check for the visual type
-         */
-        if( (fghGetConfig( GLX_RGBA )) || (fgStructure.Window == NULL) )
+        if( (fghGetConfig( GLX_RGBA )) || (fgStructure.CurrentWindow == NULL) )
         {
             /*
              * We've got a RGBA visual, so there is no colormap at all.
              * The other possibility is that we have no current window set.
              */
-            return( 0 );
+            return 0;
         }
+        else
+        {
+          const GLXFBConfig * fbconfig =
+                fgStructure.CurrentWindow->Window.FBConfig;
 
-        /*
-         * Otherwise return the number of entries in the colormap
-         */
-        return( fgStructure.Window->Window.VisualInfo->visual->map_entries );
+          XVisualInfo * visualInfo =
+                glXGetVisualFromFBConfig( fgDisplay.Display, *fbconfig );
+
+          const int result = visualInfo->visual->map_entries;
+
+          XFree(visualInfo);
+
+          return result;
+        }
 
     /*
-     * Those calls are somewhat similiar, as they use XGetWindowAttributes() function
+     * Those calls are somewhat similiar, as they use XGetWindowAttributes()
+     * function
      */
     case GLUT_WINDOW_X:
     case GLUT_WINDOW_Y:
+    case GLUT_WINDOW_BORDER_WIDTH:
+    case GLUT_WINDOW_HEADER_HEIGHT:
+    {
+        int x, y;
+        Window w;
+
+        if( fgStructure.CurrentWindow == NULL )
+            return 0;
+
+        XTranslateCoordinates(
+            fgDisplay.Display,
+            fgStructure.CurrentWindow->Window.Handle,
+            fgDisplay.RootWindow,
+            0, 0, &x, &y, &w);
+
+        switch ( eWhat )
+        {
+        case GLUT_WINDOW_X: return x;
+        case GLUT_WINDOW_Y: return y;
+        }
+
+        if ( w == 0 )
+            return 0;
+        XTranslateCoordinates(
+            fgDisplay.Display,
+            fgStructure.CurrentWindow->Window.Handle,
+            w, 0, 0, &x, &y, &w);
+
+        switch ( eWhat )
+        {
+        case GLUT_WINDOW_BORDER_WIDTH:  return x;
+        case GLUT_WINDOW_HEADER_HEIGHT: return y;
+        }
+    }
+
     case GLUT_WINDOW_WIDTH:
     case GLUT_WINDOW_HEIGHT:
-    case GLUT_WINDOW_BORDER_WIDTH :
-    case GLUT_WINDOW_HEADER_HEIGHT :
     {
         XWindowAttributes winAttributes;
 
-        /*
-         * Return zero if there is no current window set
-         */
-        if( fgStructure.Window == NULL )
-            return( 0 );
-
-        /*
-         * Grab the current window's attributes now
-         */
+        if( fgStructure.CurrentWindow == NULL )
+            return 0;
         XGetWindowAttributes(
             fgDisplay.Display,
-            fgStructure.Window->Window.Handle,
+            fgStructure.CurrentWindow->Window.Handle,
             &winAttributes
         );
-
-        /*
-         * See which window attribute to return
-         */
         switch ( eWhat )
         {
-        case GLUT_WINDOW_X:                return winAttributes.x ;
-        case GLUT_WINDOW_Y:                return winAttributes.y ;
         case GLUT_WINDOW_WIDTH:            return winAttributes.width ;
         case GLUT_WINDOW_HEIGHT:           return winAttributes.height ;
-        case GLUT_WINDOW_BORDER_WIDTH :    return winAttributes.border_width ;
-        case GLUT_WINDOW_HEADER_HEIGHT :   return winAttributes.border_width * 3 ;  /* a kludge for now */
         }
     }
 
-    /*
-     * I do not know yet if there will be a fgChooseVisual() function for Win32
-     */
+    /* I do not know yet if there will be a fgChooseVisual() function for Win32 */
     case GLUT_DISPLAY_MODE_POSSIBLE:
-        /*
-         * Check if the current display mode is possible
-         */
-        return( fgChooseVisual() == NULL ? 0 : 1 );
+    {
+        /*  We should not have to call fgChooseFBConfig again here.  */
+        GLXFBConfig * fbconfig;
+        int isPossible;
 
-    /*
-     * This is system-dependant
-     */
+        fbconfig = fgChooseFBConfig();
+
+        if (fbconfig == NULL)
+        {
+            isPossible = 0;
+        }
+        else
+        {
+            isPossible = 1;
+            XFree(fbconfig);
+        }
+
+        return isPossible;
+    }
+
+    /* This is system-dependant */
     case GLUT_WINDOW_FORMAT_ID:
-        /*
-         * Return the visual ID, if there is a current window naturally:
-         */
-        if( fgStructure.Window == NULL )
-            return( 0 );
+        if( fgStructure.CurrentWindow == NULL )
+            return 0;
 
-        return( fgStructure.Window->Window.VisualInfo->visualid );
+        return fghGetConfig( GLX_VISUAL_ID );
 
-#elif TARGET_HOST_WIN32
+#elif TARGET_HOST_MS_WINDOWS
 
-    /*
-     * Handle the OpenGL inquiries
-     */
+    case GLUT_WINDOW_NUM_SAMPLES:
+      glGetIntegerv(WGL_SAMPLES_ARB, &nsamples);
+      return nsamples;
+
+    /* Handle the OpenGL inquiries */
     case GLUT_WINDOW_RGBA:
-      glGetBooleanv ( GL_RGBA_MODE, &boolValue ) ;         /* True if color buffers store RGBA */
-      returnValue = boolValue ? 1 : 0 ;
-      return ( returnValue ) ;
+#if defined(_WIN32_WCE)
+      boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
+#else
+      glGetBooleanv ( GL_RGBA_MODE, &boolValue );
+      returnValue = boolValue ? 1 : 0;
+#endif
+      return returnValue;
     case GLUT_WINDOW_DOUBLEBUFFER:
-      glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue ) ;      /* True if front and back buffers exist */
-      returnValue = boolValue ? 1 : 0 ;
-      return ( returnValue ) ;
+#if defined(_WIN32_WCE)
+      boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
+#else
+      glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue );
+      returnValue = boolValue ? 1 : 0;
+#endif
+      return returnValue;
     case GLUT_WINDOW_STEREO:
-      glGetBooleanv ( GL_STEREO, &boolValue ) ;            /* True if left and right buffers exist */
-      returnValue = boolValue ? 1 : 0 ;
-      return ( returnValue ) ;
+#if defined(_WIN32_WCE)
+      boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
+#else
+      glGetBooleanv ( GL_STEREO, &boolValue );
+      returnValue = boolValue ? 1 : 0;
+#endif
+      return returnValue;
 
     case GLUT_WINDOW_RED_SIZE:
-      glGetIntegerv ( GL_RED_BITS, &returnValue ) ;          /* Number of bits per red component in color buffers */
-      return ( returnValue ) ;
+      glGetIntegerv ( GL_RED_BITS, &returnValue );
+      return returnValue;
     case GLUT_WINDOW_GREEN_SIZE:
-      glGetIntegerv ( GL_GREEN_BITS, &returnValue ) ;        /* Number of bits per green component in color buffers */
-      return ( returnValue ) ;
+      glGetIntegerv ( GL_GREEN_BITS, &returnValue );
+      return returnValue;
     case GLUT_WINDOW_BLUE_SIZE:
-      glGetIntegerv ( GL_BLUE_BITS, &returnValue ) ;         /* Number of bits per blue component in color buffers */
-      return ( returnValue ) ;
+      glGetIntegerv ( GL_BLUE_BITS, &returnValue );
+      return returnValue;
     case GLUT_WINDOW_ALPHA_SIZE:
-      glGetIntegerv ( GL_ALPHA_BITS, &returnValue ) ;        /* Number of bits per alpha component in color buffers */
-      return ( returnValue ) ;
+      glGetIntegerv ( GL_ALPHA_BITS, &returnValue );
+      return returnValue;
     case GLUT_WINDOW_ACCUM_RED_SIZE:
-      glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue ) ;    /* Number of bits per red component in the accumulation buffer */
-      return ( returnValue ) ;
+#if defined(_WIN32_WCE)
+      returnValue = 0;  /* WinCE doesn't support this feature */
+#else
+      glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue );
+#endif
+      return returnValue;
     case GLUT_WINDOW_ACCUM_GREEN_SIZE:
-      glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue ) ;  /* Number of bits per green component in the accumulation buffer */
-      return ( returnValue ) ;
+#if defined(_WIN32_WCE)
+      returnValue = 0;  /* WinCE doesn't support this feature */
+#else
+      glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue );
+#endif
+      return returnValue;
     case GLUT_WINDOW_ACCUM_BLUE_SIZE:
-      glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue ) ;   /* Number of bits per blue component in the accumulation buffer */
-      return ( returnValue ) ;
+#if defined(_WIN32_WCE)
+      returnValue = 0;  /* WinCE doesn't support this feature */
+#else
+      glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue );
+#endif
+      return returnValue;
     case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
-      glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue ) ;  /* Number of bits per alpha component in the accumulation buffer */
-      return ( returnValue ) ;
+#if defined(_WIN32_WCE)
+      returnValue = 0;  /* WinCE doesn't support this feature */
+#else
+      glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue );
+#endif
+      return returnValue;
     case GLUT_WINDOW_DEPTH_SIZE:
-      glGetIntegerv ( GL_DEPTH_BITS, &returnValue ) ;        /* Number of depth-buffer bitplanes */
-      return ( returnValue ) ;
+      glGetIntegerv ( GL_DEPTH_BITS, &returnValue );
+      return returnValue;
 
     case GLUT_WINDOW_BUFFER_SIZE:
       returnValue = 1 ;                                      /* ????? */
-      return ( returnValue ) ;
+      return returnValue;
     case GLUT_WINDOW_STENCIL_SIZE:
       returnValue = 0 ;                                      /* ????? */
-      return ( returnValue ) ;
+      return returnValue;
 
-    /*
-     * Window position and size
-     */
     case GLUT_WINDOW_X:
     case GLUT_WINDOW_Y:
     case GLUT_WINDOW_WIDTH:
     case GLUT_WINDOW_HEIGHT:
     {
         /*
-         *  There is considerable confusion about the "right thing to do" concerning window
-         * size and position.  GLUT itself is not consistent between Windows and Linux; since
-         * platform independence is a virtue for "freeglut", we decided to break with GLUT's
-         * behaviour.
-         *  Under Linux, it is apparently not possible to get the window border sizes in order
-         * to subtract them off the window's initial position until some time after the window
-         * has been created.  Therefore we decided on the following behaviour, both under
-         * Windows and under Linux:
-         *  - When you create a window with position (x,y) and size (w,h), the upper left hand
-         *    corner of the outside of the window is at (x,y) and the size of the drawable area
-         *    is (w,h).
-         *  - When you query the size and position of the window--as is happening here for
-         *    Windows--"freeglut" will return the size of the drawable area--the (w,h) that you
-         *    specified when you created the window--and the coordinates of the upper left hand
-         *    corner of the drawable area--which is NOT the (x,y) you specified.
+         *  There is considerable confusion about the "right thing to
+         *  do" concerning window  size and position.  GLUT itself is
+         *  not consistent between Windows and UNIX/X11; since
+         *  platform independence is a virtue for "freeglut", we
+         *  decided to break with GLUT's behaviour.
+         *
+         *  Under UNIX/X11, it is apparently not possible to get the
+         *  window border sizes in order to subtract them off the
+         *  window's initial position until some time after the window
+         *  has been created.  Therefore we decided on the following
+         *  behaviour, both under Windows and under UNIX/X11:
+         *  - When you create a window with position (x,y) and size
+         *    (w,h), the upper left hand corner of the outside of the
+         *    window is at (x,y) and the size of the drawable area  is
+         *    (w,h).
+         *  - When you query the size and position of the window--as
+         *    is happening here for Windows--"freeglut" will return
+         *    the size of the drawable area--the (w,h) that you
+         *    specified when you created the window--and the coordinates
+         *    of the upper left hand corner of the drawable
+         *    area--which is NOT the (x,y) you specified.
          */
 
         RECT winRect;
 
-        /*
-         * Check if there is a window to be queried for dimensions:
-         */
-        freeglut_return_val_if_fail( fgStructure.Window != NULL, 0 );
+        freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
 
         /*
          * We need to call GetWindowRect() first...
          *  (this returns the pixel coordinates of the outside of the window)
          */
-        GetWindowRect( fgStructure.Window->Window.Handle, &winRect );
+        GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
 
-        /*
-         * ...then we've got to correct the results we've just received...
-         */
-        if ( ( fgStructure.GameMode != fgStructure.Window ) && ( fgStructure.Window->Parent == NULL ) )
+        /* ...then we've got to correct the results we've just received... */
+
+#if !defined(_WIN32_WCE)
+        if ( ( fgStructure.GameModeWindow != fgStructure.CurrentWindow ) && ( fgStructure.CurrentWindow->Parent == NULL ) &&
+             ( ! fgStructure.CurrentWindow->IsMenu ) )
         {
           winRect.left   += GetSystemMetrics( SM_CXSIZEFRAME );
           winRect.right  -= GetSystemMetrics( SM_CXSIZEFRAME );
           winRect.top    += GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION );
           winRect.bottom -= GetSystemMetrics( SM_CYSIZEFRAME );
         }
+#endif /* !defined(_WIN32_WCE) */
 
-        /*
-         * ...and finally return the caller the desired value:
-         */
         switch( eWhat )
         {
-        case GLUT_WINDOW_X:      return( winRect.left                 );
-        case GLUT_WINDOW_Y:      return( winRect.top                  );
-        case GLUT_WINDOW_WIDTH:  return( winRect.right - winRect.left );
-        case GLUT_WINDOW_HEIGHT: return( winRect.bottom - winRect.top );
+        case GLUT_WINDOW_X:      return winRect.left                ;
+        case GLUT_WINDOW_Y:      return winRect.top                 ;
+        case GLUT_WINDOW_WIDTH:  return winRect.right - winRect.left;
+        case GLUT_WINDOW_HEIGHT: return winRect.bottom - winRect.top;
         }
     }
     break;
 
     case GLUT_WINDOW_BORDER_WIDTH :
-        return ( GetSystemMetrics( SM_CXSIZEFRAME ) ) ;
+#if defined(_WIN32_WCE)
+        return 0;
+#else
+        return GetSystemMetrics( SM_CXSIZEFRAME );
+#endif /* !defined(_WIN32_WCE) */
 
     case GLUT_WINDOW_HEADER_HEIGHT :
-        return ( GetSystemMetrics( SM_CYCAPTION ) ) ;
+#if defined(_WIN32_WCE)
+        return 0;
+#else
+        return GetSystemMetrics( SM_CYCAPTION );
+#endif /* defined(_WIN32_WCE) */
 
     case GLUT_DISPLAY_MODE_POSSIBLE:
-        /*
-         * Check if the current display mode is possible
-         */
-        return( fgSetupPixelFormat( fgStructure.Window, TRUE, PFD_MAIN_PLANE ) );
+#if defined(_WIN32_WCE)
+        return 0;
+#else
+        return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
+                                    PFD_MAIN_PLANE );
+#endif /* defined(_WIN32_WCE) */
 
-    case GLUT_WINDOW_FORMAT_ID:
-        /*
-         * Return the pixel format of the current window
-         */
-        if( fgStructure.Window != NULL )
-            return( GetPixelFormat( fgStructure.Window->Window.Device ) );
 
-        /*
-         * If the current window does not exist, fail:
-         */
-        return( 0 );
+    case GLUT_WINDOW_FORMAT_ID:
+#if !defined(_WIN32_WCE)
+        if( fgStructure.CurrentWindow != NULL )
+            return GetPixelFormat( fgStructure.CurrentWindow->Window.Device );
+#endif /* defined(_WIN32_WCE) */
+        return 0;
 
 #endif
 
-    /*
-     * The window structure queries
-     */
+    /* The window structure queries */
     case GLUT_WINDOW_PARENT:
-        /*
-         * Return the ID number of current window's parent, if any
-         */
-        if( fgStructure.Window         == NULL ) return( 0 );
-        if( fgStructure.Window->Parent == NULL ) return( 0 );
-
-        return( fgStructure.Window->Parent->ID );
+        if( fgStructure.CurrentWindow         == NULL ) return 0;
+        if( fgStructure.CurrentWindow->Parent == NULL ) return 0;
+        return fgStructure.CurrentWindow->Parent->ID;
 
     case GLUT_WINDOW_NUM_CHILDREN:
-        /*
-         * Return the number of children attached to the current window
-         */
-        if( fgStructure.Window == NULL )
-            return( 0 );
-
-        return( fgListLength( &fgStructure.Window->Children ) );
+        if( fgStructure.CurrentWindow == NULL )
+            return 0;
+        return fgListLength( &fgStructure.CurrentWindow->Children );
 
     case GLUT_WINDOW_CURSOR:
-        /*
-         * Return the currently selected window cursor
-         */
-        if( fgStructure.Window == NULL )
-            return( 0 );
-
-        return( fgStructure.Window->State.Cursor );
+        if( fgStructure.CurrentWindow == NULL )
+            return 0;
+        return fgStructure.CurrentWindow->State.Cursor;
 
     case GLUT_MENU_NUM_ITEMS:
-        /*
-         * Return the number of menu entries in the current menu
-         */
-        if( fgStructure.Menu == NULL )
-            return( 0 );
-
-        return( fgListLength( &fgStructure.Menu->Entries ) );
+        if( fgStructure.CurrentMenu == NULL )
+            return 0;
+        return fgListLength( &fgStructure.CurrentMenu->Entries );
 
     case GLUT_ACTION_ON_WINDOW_CLOSE:
-        return fgState.ActionOnWindowClose ;
+        return fgState.ActionOnWindowClose;
 
     case GLUT_VERSION :
-        return VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_PATCH ;
+        return VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_PATCH;
 
     case GLUT_RENDERING_CONTEXT:
-        return ( fgState.UseCurrentContext ? GLUT_USE_CURRENT_CONTEXT : GLUT_CREATE_NEW_CONTEXT ) ;
+        return fgState.UseCurrentContext ? GLUT_USE_CURRENT_CONTEXT
+                                         : GLUT_CREATE_NEW_CONTEXT;
+
+    case GLUT_DIRECT_RENDERING:
+        return fgState.DirectContext;
+
+    case GLUT_FULL_SCREEN:
+        return fghCheckFullScreen();
+
+    case GLUT_AUX:
+      return fgState.AuxiliaryBufferNumber;
+
+    case GLUT_MULTISAMPLE:
+      return fgState.SampleNumber;
 
     default:
-        /*
-         * Just have it reported, so that we can see what needs to be implemented
-         */
-        fgWarning( "glutGet(): missing enum handle %i\n", eWhat );
+        fgWarning( "glutGet(): missing enum handle %d", eWhat );
         break;
     }
-
-    /*
-     * If nothing happens, then we are in deep trouble...
-     */
-    return( -1 );
+    return -1;
 }
 
 /*
@@ -481,102 +574,117 @@ int FGAPIENTRY glutGet( GLenum eWhat )
  */
 int FGAPIENTRY glutDeviceGet( GLenum eWhat )
 {
-    freeglut_assert_ready;
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDeviceGet" );
 
-    /*
-     * See why are we bothered...
-     *
-     * WARNING: we are mostly lying in this function.
-     */
+    /* XXX WARNING: we are mostly lying in this function. */
     switch( eWhat )
     {
     case GLUT_HAS_KEYBOARD:
         /*
-         * We always have a keyboard present on PC machines...
-         */
-        return( TRUE );
+         * Win32 is assumed a keyboard, and this cannot be queried,
+         * except for WindowsCE.
+         *
+         * X11 has a core keyboard by definition, although it can
+         * be present as a virtual/dummy keyboard. For now, there
+         * is no reliable way to tell if a real keyboard is present.
+         */
+#if defined(_WIN32_CE)
+        return ( GetKeyboardStatus() & KBDI_KEYBOARD_PRESENT ) ? 1 : 0;
+#   if FREEGLUT_LIB_PRAGMAS
+#       pragma comment (lib,"Kbdui.lib")
+#   endif
+
+#else
+        return 1;
+#endif
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 
+    /* X11 has a mouse by definition */
     case GLUT_HAS_MOUSE:
-        /*
-         * Hey, my Atari 65XE hasn't had a mouse!
-         */
-        return( TRUE );
+        return 1 ;
 
     case GLUT_NUM_MOUSE_BUTTONS:
-        /*
-         * Return the number of mouse buttons available. This is a big guess.
+        /* We should be able to pass NULL when the last argument is zero,
+         * but at least one X server has a bug where this causes a segfault.
+         *
+         * In XFree86/Xorg servers, a mouse wheel is seen as two buttons
+         * rather than an Axis; "freeglut_main.c" expects this when
+         * checking for a wheel event.
          */
-        return( 3 );
+        {
+            unsigned char map;
+            int nbuttons = XGetPointerMapping(fgDisplay.Display, &map,0);
+            return nbuttons;
+        }
 
-#elif TARGET_HOST_WIN32
+#elif TARGET_HOST_MS_WINDOWS
 
     case GLUT_HAS_MOUSE:
         /*
-         * The Windows can be booted without a mouse. 
-         * It would be nice to have this reported.
+         * MS Windows can be booted without a mouse.
          */
-        return( GetSystemMetrics( SM_MOUSEPRESENT ) );
+        return GetSystemMetrics( SM_MOUSEPRESENT );
 
     case GLUT_NUM_MOUSE_BUTTONS:
-        /*
-         * We are much more fortunate under Win32 about this...
-         */
-        return( GetSystemMetrics( SM_CMOUSEBUTTONS ) );
-
+#  if defined(_WIN32_WCE)
+        return 1;
+#  else
+        return GetSystemMetrics( SM_CMOUSEBUTTONS );
+#  endif
 #endif
 
-    case GLUT_JOYSTICK_POLL_RATE:
     case GLUT_HAS_JOYSTICK:
+        return fgJoystickDetect ();
+
+    case GLUT_OWNS_JOYSTICK:
+        return fgState.JoysticksInitialised;
+
+    case GLUT_JOYSTICK_POLL_RATE:
+        return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.JoystickPollRate : 0;
+
+    /* XXX The following two are only for Joystick 0 but this is an improvement */
     case GLUT_JOYSTICK_BUTTONS:
+        return glutJoystickGetNumButtons ( 0 );
+
     case GLUT_JOYSTICK_AXES:
-        /*
-         * WARNING: THIS IS A BIG LIE!
-         */
-        return( 0 );
+        return glutJoystickGetNumAxes ( 0 );
 
-    case GLUT_HAS_SPACEBALL:
     case GLUT_HAS_DIAL_AND_BUTTON_BOX:
+        return fgInputDeviceDetect ();
+
+    case GLUT_NUM_DIALS:
+        if ( fgState.InputDevsInitialised ) return 8;
+        return 0;
+    case GLUT_NUM_BUTTON_BOX_BUTTONS:
+        return 0;
+
+    case GLUT_HAS_SPACEBALL:
+        return fgHasSpaceball();
+
     case GLUT_HAS_TABLET:
-        /*
-         * Sounds cool. And unuseful.
-         */
-        return( FALSE );
+        return 0;
 
     case GLUT_NUM_SPACEBALL_BUTTONS:
-    case GLUT_NUM_BUTTON_BOX_BUTTONS:
-    case GLUT_NUM_DIALS:
+        return fgSpaceballNumButtons();
+
     case GLUT_NUM_TABLET_BUTTONS:
-        /*
-         * Zero is not the answer. Zero is the question. Continuum is the answer.
-         */
-        return( 0 );
+        return 0;
 
     case GLUT_DEVICE_IGNORE_KEY_REPEAT:
-        /*
-         * Return what we think about the key auto repeat settings
-         */
-        return( fgState.IgnoreKeyRepeat );
+        return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.IgnoreKeyRepeat : 0;
 
     case GLUT_DEVICE_KEY_REPEAT:
-        /*
-         * WARNING: THIS IS A BIG LIE!
-         */
-        return( GLUT_KEY_REPEAT_DEFAULT );
+        return fgState.KeyRepeat;
 
     default:
-        /*
-         * Complain.
-         */
-        fgWarning( "glutDeviceGet(): missing enum handle %i\n", eWhat );
+        fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
         break;
     }
 
-    /*
-     * And now -- the failure.
-     */
-    return( -1 );
+    /* And now -- the failure. */
+    return -1;
 }
 
 /*
@@ -584,22 +692,14 @@ int FGAPIENTRY glutDeviceGet( GLenum eWhat )
  */
 int FGAPIENTRY glutGetModifiers( void )
 {
-    /*
-     * Fail if there is no current window or called outside an input callback
-     */
-    if( fgStructure.Window == NULL )
-        return( 0 );
-
-    if( fgStructure.Window->State.Modifiers == 0xffffffff )
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetModifiers" );
+    if( fgState.Modifiers == INVALID_MODIFIERS )
     {
         fgWarning( "glutGetModifiers() called outside an input callback" );
-        return( 0 );
+        return 0;
     }
 
-    /*
-     * Return the current modifiers state otherwise
-     */
-    return( fgStructure.Window->State.Modifiers );
+    return fgState.Modifiers;
 }
 
 /*
@@ -607,103 +707,189 @@ int FGAPIENTRY glutGetModifiers( void )
  */
 int FGAPIENTRY glutLayerGet( GLenum eWhat )
 {
-    freeglut_assert_ready;
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLayerGet" );
 
     /*
      * This is easy as layers are not implemented ;-)
+     *
+     * XXX Can we merge the UNIX/X11 and WIN32 sections?  Or
+     * XXX is overlay support planned?
      */
     switch( eWhat )
     {
 
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 
     case GLUT_OVERLAY_POSSIBLE:
-        /*
-         * Nope, overlays are not possible.
-         */
-        return( FALSE );
+        return 0;
 
     case GLUT_LAYER_IN_USE:
-        /*
-         * The normal plane is always in use
-         */
-        return( GLUT_NORMAL );
+        return GLUT_NORMAL;
 
     case GLUT_HAS_OVERLAY:
-        /*
-         * No window is allowed to have an overlay
-         */
-        return( FALSE );
+        return 0;
 
     case GLUT_TRANSPARENT_INDEX:
         /*
          * Return just anything, which is always defined as zero
+         *
+         * XXX HUH?
          */
-        return( 0 );
+        return 0;
 
     case GLUT_NORMAL_DAMAGED:
-        /*
-         * Actually I do not know. Maybe.
-         */
-        return( FALSE );
+        /* XXX Actually I do not know. Maybe. */
+        return 0;
 
     case GLUT_OVERLAY_DAMAGED:
-        /*
-         * Return minus one to mark that no layer is in use
-         */
-        return( -1 );
+        return -1;
 
-#elif TARGET_HOST_WIN32
+#elif TARGET_HOST_MS_WINDOWS
 
     case GLUT_OVERLAY_POSSIBLE:
-        /*
-         * Check if an overlay display mode is possible
-         */
-        return( fgSetupPixelFormat( fgStructure.Window, TRUE, PFD_OVERLAY_PLANE ) );
+/*      return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
+                                   PFD_OVERLAY_PLANE ); */
+      return 0 ;
 
     case GLUT_LAYER_IN_USE:
-        /*
-         * The normal plane is always in use
-         */
-        return( GLUT_NORMAL );
+        return GLUT_NORMAL;
 
     case GLUT_HAS_OVERLAY:
-        /*
-         * No window is allowed to have an overlay
-         */
-        return( FALSE );
+        return 0;
 
     case GLUT_TRANSPARENT_INDEX:
         /*
          * Return just anything, which is always defined as zero
+         *
+         * XXX HUH?
          */
-        return( 0 );
+        return 0;
 
     case GLUT_NORMAL_DAMAGED:
-        /*
-         * Actually I do not know. Maybe.
-         */
-        return( FALSE );
+        /* XXX Actually I do not know. Maybe. */
+        return 0;
 
     case GLUT_OVERLAY_DAMAGED:
-        /*
-         * Return minus one to mark that no layer is in use
-         */
-        return( -1 );
+        return -1;
 #endif
 
     default:
-        /*
-         * Complain to the user about the obvious bug
-         */
-        fgWarning( "glutLayerGet(): missing enum handle %i\n", eWhat );
+        fgWarning( "glutLayerGet(): missing enum handle %d", eWhat );
         break;
     }
 
-    /*
-     * And fail. That's good. Programs do love failing.
-     */
-    return( -1 );
+    /* And fail. That's good. Programs do love failing. */
+    return -1;
+}
+
+int * FGAPIENTRY glutGetModeValues(GLenum eWhat, int * size)
+{
+  int * array;
+
+#if TARGET_HOST_POSIX_X11
+  int attributes[9];
+  GLXFBConfig * fbconfigArray;  /*  Array of FBConfigs  */
+  int fbconfigArraySize;        /*  Number of FBConfigs in the array  */
+  int attribute_name = 0;
+#endif
+
+  FREEGLUT_EXIT_IF_NOT_INITIALISED("glutGetModeValues");
+
+  array = NULL;
+  *size = 0;
+
+  switch (eWhat)
+    {
+#if TARGET_HOST_POSIX_X11
+    case GLUT_AUX:
+    case GLUT_MULTISAMPLE:
+
+      attributes[0] = GLX_BUFFER_SIZE;
+      attributes[1] = GLX_DONT_CARE;
+
+      switch (eWhat)
+        {
+        case GLUT_AUX:
+          /*
+            FBConfigs are now sorted by increasing number of auxiliary
+            buffers.  We want at least one buffer.
+          */
+          attributes[2] = GLX_AUX_BUFFERS;
+          attributes[3] = 1;
+          attributes[4] = None;
+
+          attribute_name = GLX_AUX_BUFFERS;
+
+          break;
+
+
+        case GLUT_MULTISAMPLE:
+          attributes[2] = GLX_AUX_BUFFERS;
+          attributes[3] = GLX_DONT_CARE;
+          attributes[4] = GLX_SAMPLE_BUFFERS;
+          attributes[5] = 1;
+          /*
+            FBConfigs are now sorted by increasing number of samples per
+            pixel.  We want at least one sample.
+          */
+          attributes[6] = GLX_SAMPLES;
+          attributes[7] = 1;
+          attributes[8] = None;
+
+          attribute_name = GLX_SAMPLES;
+
+          break;
+        }
+
+      fbconfigArray = glXChooseFBConfig(fgDisplay.Display,
+                                        fgDisplay.Screen,
+                                        attributes,
+                                        &fbconfigArraySize);
+
+      if (fbconfigArray != NULL)
+        {
+          int * temp_array;
+          int result;   /*  Returned by glXGetFBConfigAttrib. Not checked.  */
+          int previous_value;
+          int i;
+
+          temp_array = malloc(sizeof(int) * fbconfigArraySize);
+          previous_value = 0;
+
+          for (i = 0; i < fbconfigArraySize; i++)
+            {
+              int value;
+
+              result = glXGetFBConfigAttrib(fgDisplay.Display,
+                                            fbconfigArray[i],
+                                            attribute_name,
+                                            &value);
+              if (value > previous_value)
+                {
+                  temp_array[*size] = value;
+                  previous_value = value;
+                  (*size)++;
+                }
+            }
+
+          array = malloc(sizeof(int) * (*size));
+          for (i = 0; i < *size; i++)
+            {
+              array[i] = temp_array[i];
+            }
+
+          free(temp_array);
+          XFree(fbconfigArray);
+        }
+
+      break;
+#endif      
+
+    default:
+      break;
+    }
+
+  return array;
 }
 
 /*** END OF FILE ***/