Fixing bug report #1052151 from October 2004.
[freeglut] / src / freeglut_gamemode.c
index 490d2f6..67159e1 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-gamemode"
-
-#include "../include/GL/freeglut.h"
+#include <GL/freeglut.h>
 #include "freeglut_internal.h"
 
 /*
  * Remembers the current visual settings, so that
  * we can change them and restore later...
  */
-void fghRememberState( void )
+static void fghRememberState( void )
 {
-#if TARGET_HOST_UNIX_X11
+#if TARGET_HOST_POSIX_X11
 
     /*
-     * This highly depends on the XFree86 extensions, not approved as X Consortium standards
+     * This highly depends on the XFree86 extensions,
+     * not approved as X Consortium standards
      */
 #   ifdef X_XF86VidModeGetModeLine
 
@@ -64,33 +59,31 @@ void fghRememberState( void )
      * Remember the current ViewPort location of the screen to be able to
      * restore the ViewPort on LeaveGameMode():
      */
-    XF86VidModeGetViewPort(
-       fgDisplay.Display,
-       fgDisplay.Screen,
-       &fgDisplay.DisplayViewPortX,
-       &fgDisplay.DisplayViewPortY
-    );
+    if( !XF86VidModeGetViewPort(
+             fgDisplay.Display,
+             fgDisplay.Screen,
+             &fgDisplay.DisplayViewPortX,
+             &fgDisplay.DisplayViewPortY ) )
+        fgWarning( "XF86VidModeGetViewPort failed" );
 
     /*
      * Remember the current pointer location before going fullscreen
      * for restoring it later:
      */
     {
-       Window junk_window;
-       unsigned int mask;
-
-       XQueryPointer(
-           fgDisplay.Display, fgDisplay.RootWindow,
-           &junk_window, &junk_window,
-           &fgDisplay.DisplayPointerX, &fgDisplay.DisplayPointerY,
-           &fgDisplay.DisplayPointerX, &fgDisplay.DisplayPointerY, &mask
-       );
+        Window junk_window;
+        unsigned int mask;
+
+        XQueryPointer(
+            fgDisplay.Display, fgDisplay.RootWindow,
+            &junk_window, &junk_window,
+            &fgDisplay.DisplayPointerX, &fgDisplay.DisplayPointerY,
+            &fgDisplay.DisplayPointerX, &fgDisplay.DisplayPointerY, &mask
+        );
     }
 
-    /*
-     * Query the current display settings:
-     */
-    fgDisplay.DisplayModeValid = 
+    /* Query the current display settings: */
+    fgDisplay.DisplayModeValid =
       XF86VidModeGetModeLine(
         fgDisplay.Display,
         fgDisplay.Screen,
@@ -98,30 +91,31 @@ void fghRememberState( void )
         &fgDisplay.DisplayMode
     );
 
-    if (!fgDisplay.DisplayModeValid)
-       fgWarning( "Runtime use of XF86VidModeGetModeLine failed.\n" );
+    if( !fgDisplay.DisplayModeValid )
+            fgWarning( "XF86VidModeGetModeLine failed" );
 
 #   else
-#       warning fghRememberState: missing XFree86 video mode extensions, game mode will not change screen resolution when activated
+    /*
+     * XXX warning fghRememberState: missing XFree86 video mode extensions,
+     * XXX game mode will not change screen resolution when activated
+     */
 #   endif
 
-#elif TARGET_HOST_WIN32
+#elif TARGET_HOST_MS_WINDOWS
 
 /*    DEVMODE devMode; */
 
-    /*
-     * Grab the current desktop settings...
-     */
+    /* Grab the current desktop settings... */
 
 /* hack to get around my stupid cross-gcc headers */
 #define FREEGLUT_ENUM_CURRENT_SETTINGS -1
 
-    EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS, &fgDisplay.DisplayMode );
+    EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS,
+                         &fgDisplay.DisplayMode );
 
-    /*
-     * Make sure we will be restoring all settings needed
-     */
-    fgDisplay.DisplayMode.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+    /* Make sure we will be restoring all settings needed */
+    fgDisplay.DisplayMode.dmFields |=
+        DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
 
 #endif
 }
@@ -129,112 +123,145 @@ void fghRememberState( void )
 /*
  * Restores the previously remembered visual settings
  */
-void fghRestoreState( void )
+static void fghRestoreState( void )
 {
-#if TARGET_HOST_UNIX_X11
-    /*
-     * Restore the remembered pointer position:
-     */
+#if TARGET_HOST_POSIX_X11
+
+#   ifdef X_XF86VidModeGetAllModeLines
+    /* Restore the remembered pointer position: */
     XWarpPointer(
-       fgDisplay.Display, None, fgDisplay.RootWindow, 0, 0, 0, 0,
-       fgDisplay.DisplayPointerX, fgDisplay.DisplayPointerY
+        fgDisplay.Display, None, fgDisplay.RootWindow, 0, 0, 0, 0,
+        fgDisplay.DisplayPointerX, fgDisplay.DisplayPointerY
     );
 
     /*
-     * This highly depends on the XFree86 extensions, not approved as X Consortium standards
+     * This highly depends on the XFree86 extensions,
+     * not approved as X Consortium standards
      */
-#   ifdef X_XF86VidModeGetAllModeLines
 
-    if (fgDisplay.DisplayModeValid)
+    if( fgDisplay.DisplayModeValid )
     {
         XF86VidModeModeInfo** displayModes;
         int i, displayModesCount;
 
-        /*
-         * Query for all the display available...
-         */
-        XF86VidModeGetAllModeLines(
-            fgDisplay.Display,
-            fgDisplay.Screen,
-            &displayModesCount,
-            &displayModes
-        );
+        if( !XF86VidModeGetAllModeLines(
+                 fgDisplay.Display,
+                 fgDisplay.Screen,
+                 &displayModesCount,
+                 &displayModes ) )
+        {
+            fgWarning( "XF86VidModeGetAllModeLines failed" );
+            return;
+        }
+
 
         /*
-         * Check every of the modes looking for one that matches our demands
+         * Check every of the modes looking for one that matches our demands.
+         * If we find one, switch to it and restore the remembered viewport.
          */
-        for( i=0; i<displayModesCount; i++ )
+        for( i = 0; i < displayModesCount; i++ )
         {
-            if( displayModes[ i ]->hdisplay == fgDisplay.DisplayMode.hdisplay &&
-                displayModes[ i ]->vdisplay == fgDisplay.DisplayMode.vdisplay &&
-                displayModes[ i ]->dotclock == fgDisplay.DisplayModeClock )
+            if(displayModes[ i ]->hdisplay == fgDisplay.DisplayMode.hdisplay &&
+               displayModes[ i ]->vdisplay == fgDisplay.DisplayMode.vdisplay &&
+               displayModes[ i ]->dotclock == fgDisplay.DisplayModeClock )
             {
+                if( !XF86VidModeSwitchToMode(
+                         fgDisplay.Display,
+                         fgDisplay.Screen,
+                         displayModes[ i ] ) )
+                {
+                    fgWarning( "XF86VidModeSwitchToMode failed" );
+                    break;
+                }
+
+                if( !XF86VidModeSetViewPort(
+                         fgDisplay.Display,
+                         fgDisplay.Screen,
+                         fgDisplay.DisplayViewPortX,
+                         fgDisplay.DisplayViewPortY ) )
+                    fgWarning( "XF86VidModeSetViewPort failed" );
+
+
                 /*
-                 * OK, this is the display mode we have been looking for...
+                 * For the case this would be the last X11 call the application
+                 * calls exit() we've to flush the X11 output queue to have the
+                 * commands sent to the X server before the application exits.
                  */
-                XF86VidModeSwitchToMode(
-                    fgDisplay.Display,
-                    fgDisplay.Screen,
-                    displayModes[ i ]
-                );
-
-               /*
-                * Now we can restore the remembered ViewPort:
-                */
-               XF86VidModeSetViewPort(
-                    fgDisplay.Display,
-                    fgDisplay.Screen,
-                    fgDisplay.DisplayViewPortX,
-                    fgDisplay.DisplayViewPortY
-               );
-
-               /*
-                * For the case this would be the last X11 call the application
-                * calls exit() we've to flush the X11 output queue to have the
-                * commands sent to the X server before the application exists.
-                */
-               XFlush(fgDisplay.Display);
-
-                return;
+                XFlush( fgDisplay.Display );
+
+                break;
             }
         }
+        XFree( displayModes );
     }
 
 #   else
-#       warning fghRestoreState: missing XFree86 video mode extensions, game mode will not change screen resolution when activated
+    /*
+     * XXX warning fghRestoreState: missing XFree86 video mode extensions,
+     * XXX game mode will not change screen resolution when activated
+     */
 #   endif
 
-#elif TARGET_HOST_WIN32
+#elif TARGET_HOST_MS_WINDOWS
 
-    /*
-     * Restore the previously rememebered desktop display settings
-     */
+    /* Restore the previously rememebered desktop display settings */
     ChangeDisplaySettings( &fgDisplay.DisplayMode, 0 );
 
 #endif
 }
 
+#if TARGET_HOST_POSIX_X11
+#ifdef X_XF86VidModeGetAllModeLines
+
 /*
- * Checks the display mode settings against user's preferences
+ * Checks a single display mode settings against user's preferences.
  */
-GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )
+static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )
 {
-    /*
-     * The desired values should be stored in fgState structure...
-     */
-    return( (width == fgState.GameModeSize.X) && (height == fgState.GameModeSize.Y) &&
-            (depth == fgState.GameModeDepth)  && (refresh == fgState.GameModeRefresh) );
+    /* The desired values should be stored in fgState structure... */
+    return ( width == fgState.GameModeSize.X ) &&
+           ( height == fgState.GameModeSize.Y ) &&
+           ( depth == fgState.GameModeDepth ) &&
+           ( refresh == fgState.GameModeRefresh );
 }
 
 /*
+ * Checks all display modes settings against user's preferences.
+ * Returns the mode number found or -1 if none could be found.
+ */
+static int fghCheckDisplayModes( GLboolean exactMatch, int displayModesCount, XF86VidModeModeInfo** displayModes )
+{
+    int i;
+    for( i = 0; i < displayModesCount; i++ )
+    {
+        /* Compute the displays refresh rate, dotclock comes in kHz. */
+        int refresh = ( displayModes[ i ]->dotclock * 1000 ) /
+                      ( displayModes[ i ]->htotal * displayModes[ i ]->vtotal );
+
+        if( fghCheckDisplayMode( displayModes[ i ]->hdisplay,
+                                 displayModes[ i ]->vdisplay,
+                                 fgState.GameModeDepth,
+                                 ( exactMatch ? refresh : fgState.GameModeRefresh ) ) ) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+#endif
+#endif
+
+/*
  * Changes the current display mode to match user's settings
  */
-GLboolean fghChangeDisplayMode( GLboolean haveToTest )
+static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
 {
-#if TARGET_HOST_UNIX_X11
+    GLboolean success = GL_FALSE;
+#if TARGET_HOST_POSIX_X11
 
     /*
-     * This highly depends on the XFree86 extensions, not approved as X Consortium standards
+     * This highly depends on the XFree86 extensions,
+     * not approved as X Consortium standards
      */
 #   ifdef X_XF86VidModeGetAllModeLines
 
@@ -242,157 +269,107 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
      * This is also used by applcations which check modes by calling
      * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check:
      */
-    if (haveToTest || fgDisplay.DisplayModeValid)
+    if( haveToTest || fgDisplay.DisplayModeValid )
     {
         XF86VidModeModeInfo** displayModes;
         int i, displayModesCount;
 
-        /*
-         * Query for all the display available...
-         */
-        XF86VidModeGetAllModeLines(
-            fgDisplay.Display,
-            fgDisplay.Screen,
-            &displayModesCount,
-            &displayModes
-        );
+        if( !XF86VidModeGetAllModeLines(
+                 fgDisplay.Display,
+                 fgDisplay.Screen,
+                 &displayModesCount,
+                 &displayModes ) )
+        {
+            fgWarning( "XF86VidModeGetAllModeLines failed" );
+            return success;
+        }
+
 
         /*
-         * Check every of the modes looking for one that matches our demands
+         * Check every of the modes looking for one that matches our demands,
+         * ignoring the refresh rate if no exact match could be found.
          */
-        for( i=0; i<displayModesCount; i++ )
-        {
-            if( fghCheckDisplayMode( displayModes[ i ]->hdisplay, displayModes[ i ]->vdisplay,
-                                     fgState.GameModeDepth, fgState.GameModeRefresh ) )
-            {
-                   if( haveToTest )
-                               return( TRUE );
-                /*
-                 * OKi, this is the display mode we have been looking for...
-                 */
-                XF86VidModeSwitchToMode(
-                    fgDisplay.Display,
-                    fgDisplay.Screen,
-                    displayModes[ i ]
-                );
-                /*
-                 * Return successfull...
-                 */
-                return( TRUE );
-            }
+        i = fghCheckDisplayModes( GL_TRUE, displayModesCount, displayModes );
+        if( i < 0 ) {
+            i = fghCheckDisplayModes( GL_FALSE, displayModesCount, displayModes );
+        }
+        success = ( i < 0 ) ? GL_FALSE : GL_TRUE;
+
+        if( !haveToTest && success ) {
+            if( !XF86VidModeSwitchToMode(
+                     fgDisplay.Display,
+                     fgDisplay.Screen,
+                     displayModes[ i ] ) )
+                fgWarning( "XF86VidModeSwitchToMode failed" );
         }
+
+        XFree( displayModes );
     }
 
+#   else
+
     /*
-     * Something must have went wrong
+     * XXX warning fghChangeDisplayMode: missing XFree86 video mode extensions,
+     * XXX game mode will not change screen resolution when activated
      */
-    return( FALSE );
+    success = GL_TRUE;
 
-#   else
-#       warning fghChangeDisplayMode: missing XFree86 video mode extensions, game mode will not change screen resolution when activated
 #   endif
 
-#elif TARGET_HOST_WIN32
+#elif TARGET_HOST_MS_WINDOWS
 
-    unsigned int    displayModes = 0, mode = 0xffffffff;
-    GLboolean success = FALSE;
-/*    HDC      desktopDC; */
     DEVMODE  devMode;
+    char *fggmstr = NULL;
 
-    /*
-     * Enumerate the available display modes
-     * Try to get a complete match
-     */
-    while( EnumDisplaySettings( NULL, displayModes, &devMode ) == TRUE )
-    {
-        /*
-         * Does the enumerated display mode match the user's preferences?
-         */
-        if( fghCheckDisplayMode( devMode.dmPelsWidth,  devMode.dmPelsHeight,
-                                 devMode.dmBitsPerPel, devMode.dmDisplayFrequency ) )
-        {
-            /*
-             * OKi, we've found a matching display mode, remember its number and break
-             */
-            mode = displayModes;
-            break;
-        }
+    success = GL_FALSE;
 
-        /*
-         * Switch to the next display mode, if any
-         */
-        displayModes++;
-    }
+    EnumDisplaySettings( NULL, -1, &devMode ); 
+    devMode.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
 
-    if ( mode == 0xffffffff )
-    {
-      /* then try without Display Frequency */
-      displayModes = 0;
-
-      /*
-       * Enumerate the available display modes
-       */
-      while( EnumDisplaySettings( NULL, displayModes, &devMode ) == TRUE )
-      {
-        /* then try without Display Frequency */
-
-        if( fghCheckDisplayMode( devMode.dmPelsWidth,  devMode.dmPelsHeight,
-                                 devMode.dmBitsPerPel, fgState.GameModeRefresh))
-        {
-          /*
-           * OKi, we've found a matching display mode, remember its number and break
-           */
-          mode = displayModes;
-          break;
-        }
-       
-        /*
-         * Switch to the next display mode, if any
-         */
-        displayModes++;
-      }
-    }
+    devMode.dmPelsWidth  = fgState.GameModeSize.X;
+    devMode.dmPelsHeight = fgState.GameModeSize.Y;
+    devMode.dmBitsPerPel = fgState.GameModeDepth;
+    devMode.dmDisplayFrequency = fgState.GameModeRefresh;
+    devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
 
-    /*
-     * Did we find a matching display mode?
-     */
-    if( mode != 0xffffffff )
+    switch ( ChangeDisplaySettingsEx(NULL, &devMode, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) )
     {
-        int retVal = DISP_CHANGE_SUCCESSFUL;
-
-        /*
-         * Mark the values we want to modify in the display change call
-         */
-        devMode.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
-
-        /*
-         * Change the current display mode (possibly in test mode only)
-         */
-        retVal = ChangeDisplaySettings( &devMode, haveToTest ? CDS_TEST : 0 );
-
-        /*
-         * I don't know if it's really needed, but looks nice:
-         */
-        success = (retVal == DISP_CHANGE_SUCCESSFUL) || (retVal == DISP_CHANGE_NOTUPDATED);
-
-        /*
-         * If it was not a test, remember the current screen settings
-         */
-        if( !haveToTest && success )
-        {
-            fgState.GameModeSize.X  = devMode.dmPelsWidth;
-            fgState.GameModeSize.Y  = devMode.dmPelsHeight;
-            fgState.GameModeDepth   = devMode.dmBitsPerPel;
-            fgState.GameModeRefresh = devMode.dmDisplayFrequency;
-        }
+    case DISP_CHANGE_SUCCESSFUL:
+        success = GL_TRUE;
+
+        /* update vars in case if windows switched to proper mode */
+        EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS, &devMode );
+        fgState.GameModeSize.X  = devMode.dmPelsWidth;        
+        fgState.GameModeSize.Y  = devMode.dmPelsHeight;
+        fgState.GameModeDepth   = devMode.dmBitsPerPel;
+        fgState.GameModeRefresh = devMode.dmDisplayFrequency;
+               break;
+    case DISP_CHANGE_RESTART:
+        fggmstr = "The computer must be restarted for the graphics mode to work.";
+        break;
+    case DISP_CHANGE_BADFLAGS:
+        fggmstr = "An invalid set of flags was passed in.";
+        break;
+    case DISP_CHANGE_BADPARAM:
+        fggmstr = "An invalid parameter was passed in. This can include an invalid flag or combination of flags.";
+        break;
+    case DISP_CHANGE_FAILED:
+        fggmstr = "The display driver failed the specified graphics mode.";
+        break;
+    case DISP_CHANGE_BADMODE:
+        fggmstr = "The graphics mode is not supported.";
+        break;
+    default:
+        fggmstr = "Unknown error in graphics mode???"; /* dunno if it is possible,MSDN does not mention any other error */
+        break;
     }
 
-    /*
-     * Otherwise we must have failed somewhere
-     */
-    return( success );
-
+    if ( !success )
+        fgWarning(fggmstr); /* I'd rather get info whats going on in my program than wonder about */
+                            /* magic happenings behind my back, its lib for devels at last ;) */
 #endif
+
+    return success;
 }
 
 
@@ -405,24 +382,28 @@ void FGAPIENTRY glutGameModeString( const char* string )
 {
     int width = 640, height = 480, depth = 16, refresh = 72;
 
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGameModeString" );
+
     /*
      * This one seems a bit easier than glutInitDisplayString. The bad thing
      * about it that I was unable to find the game mode string definition, so
      * that I assumed it is: "[width]x[height]:[depth]@[refresh rate]", which
      * appears in all GLUT game mode programs I have seen to date.
      */
-    if( sscanf( string, "%ix%i:%i@%i", &width, &height, &depth, &refresh ) != 4 )
+    if( sscanf( string, "%ix%i:%i@%i", &width, &height, &depth, &refresh ) !=
+        4 )
         if( sscanf( string, "%ix%i:%i", &width, &height, &depth ) != 3 )
             if( sscanf( string, "%ix%i@%i", &width, &height, &refresh ) != 3 )
                 if( sscanf( string, "%ix%i", &width, &height ) != 2 )
                     if( sscanf( string, ":%i@%i", &depth, &refresh ) != 2 )
                         if( sscanf( string, ":%i", &depth ) != 1 )
                             if( sscanf( string, "@%i", &refresh ) != 1 )
-                                fgWarning( "unable to parse game mode string `%s'", string );
+                                fgWarning(
+                                    "unable to parse game mode string `%s'",
+                                    string
+                                );
 
-    /*
-     * Hopefully it worked, and if not, we still have the default values
-     */
+    /* Hopefully it worked, and if not, we still have the default values */
     fgState.GameModeSize.X  = width;
     fgState.GameModeSize.Y  = height;
     fgState.GameModeDepth   = depth;
@@ -434,59 +415,36 @@ void FGAPIENTRY glutGameModeString( const char* string )
  */
 int FGAPIENTRY glutEnterGameMode( void )
 {
-    /*
-     * Check if a game mode window already exists...
-     */
-    if( fgStructure.GameMode != NULL )
-    {
-        /*
-         * ...if so, delete it before proceeding...
-         */
-        fgAddToWindowDestroyList( fgStructure.GameMode, TRUE );
-    }
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEnterGameMode" );
+
+    if( fgStructure.GameModeWindow )
+        fgAddToWindowDestroyList( fgStructure.GameModeWindow );
     else
-    {
-        /*
-         * ...otherwise remember the current resolution, etc.
-         */
-        fghRememberState();
-    }
+        fghRememberState( );
 
-    /*
-     * We are ready to change the current screen's resolution now
-     */
-    if( fghChangeDisplayMode( FALSE ) == FALSE )
+    if( ! fghChangeDisplayMode( GL_FALSE ) )
     {
-             fgWarning( "failed to change screen settings" );
-        return( FALSE );
+        fgWarning( "failed to change screen settings" );
+        return 0;
     }
 
-    /*
-     * Finally, have the game mode window created
-     */
-    fgStructure.GameMode = fgCreateWindow( 
-        NULL, "FREEGLUT", 0, 0, fgState.GameModeSize.X, fgState.GameModeSize.Y, TRUE 
+    fgStructure.GameModeWindow = fgCreateWindow(
+        NULL, "FREEGLUT", GL_TRUE, 0, 0,
+        GL_TRUE, fgState.GameModeSize.X, fgState.GameModeSize.Y,
+        GL_TRUE, GL_FALSE
     );
 
-#if TARGET_HOST_UNIX_X11
+    fgStructure.GameModeWindow->State.Width  = fgState.GameModeSize.X;
+    fgStructure.GameModeWindow->State.Height = fgState.GameModeSize.Y;
+    fgStructure.GameModeWindow->State.NeedToResize = GL_TRUE;
 
-    /* Move the window up to the topleft corner */
-    XMoveWindow(fgDisplay.Display, fgStructure.Window->Window.Handle, 0, 0);
+#if TARGET_HOST_POSIX_X11
 
     /*
      * Sync needed to avoid a real race, the Xserver must have really created
      * the window before we can grab the pointer into it:
      */
-    XSync(fgDisplay.Display, False);
-
-    /* Move the Pointer to the middle of the fullscreen window */
-    XWarpPointer(
-       fgDisplay.Display,
-       None, 
-       fgDisplay.RootWindow,
-       0, 0, 0, 0,
-       fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2
-    );
+    XSync( fgDisplay.Display, False );
 
     /*
      * Grab the pointer to confine it into the window after the calls to
@@ -497,14 +455,14 @@ int FGAPIENTRY glutEnterGameMode( void )
      * (XSetInputFocus) is called with a not yet viewable window, it will exit
      * the application which we have to aviod, so wait until it's viewable:
      */
-    while (GrabSuccess =! XGrabPointer(
-           fgDisplay.Display, fgStructure.GameMode->Window.Handle,
-           TRUE, ButtonPressMask|ButtonReleaseMask|ButtonMotionMask
-               |PointerMotionMask,
-           GrabModeAsync, GrabModeAsync,
-           fgStructure.GameMode->Window.Handle, None, CurrentTime)) {
-       usleep (100);
-    }
+    while( GrabSuccess != XGrabPointer(
+               fgDisplay.Display, fgStructure.GameModeWindow->Window.Handle,
+               TRUE,
+               ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
+               | PointerMotionMask,
+               GrabModeAsync, GrabModeAsync,
+               fgStructure.GameModeWindow->Window.Handle, None, CurrentTime) )
+        usleep( 100 );
 
     /*
      * Change input focus to the new window. This will exit the application
@@ -512,49 +470,57 @@ int FGAPIENTRY glutEnterGameMode( void )
      */
     XSetInputFocus(
         fgDisplay.Display,
-        fgStructure.GameMode->Window.Handle,
+        fgStructure.GameModeWindow->Window.Handle,
         RevertToNone,
         CurrentTime
     );
 
+    /* Move the Pointer to the middle of the fullscreen window */
+    XWarpPointer(
+        fgDisplay.Display,
+        None,
+        fgDisplay.RootWindow,
+        0, 0, 0, 0,
+        fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2
+    );
+
 #   ifdef X_XF86VidModeSetViewPort
 
-    if (fgDisplay.DisplayModeValid) {
-       int x, y;
-       Window child;
+    if( fgDisplay.DisplayModeValid )
+    {
+        int x, y;
+        Window child;
 
-       /*
-        * Change to viewport to the window topleft edge:
-        */
-       XF86VidModeSetViewPort(fgDisplay.Display, fgDisplay.Screen, 0, 0);
+        /* Change to viewport to the window topleft edge: */
+        if( !XF86VidModeSetViewPort( fgDisplay.Display, fgDisplay.Screen, 0, 0 ) )
+            fgWarning( "XF86VidModeSetViewPort failed" );
 
-       /*
-        * Final window repositioning: It could be avoided using an undecorated
-        * window using override_redirect, but this * would possily require more
-        * changes and investigation.
-        */
+        /*
+         * Final window repositioning: It could be avoided using an undecorated
+         * window using override_redirect, but this * would possily require
+         * more changes and investigation.
+         */
 
         /* Get the current postion of the drawable area on screen */
-       XTranslateCoordinates(
-           fgDisplay.Display,
-           fgStructure.Window->Window.Handle,
-           fgDisplay.RootWindow,
-           0, 0, &x, &y,
-           &child
-       );
-
-       /* Move the decorataions out of the topleft corner of the display */
-       XMoveWindow(fgDisplay.Display, fgStructure.Window->Window.Handle, -x, -y);
+        XTranslateCoordinates(
+            fgDisplay.Display,
+            fgStructure.CurrentWindow->Window.Handle,
+            fgDisplay.RootWindow,
+            0, 0, &x, &y,
+            &child
+        );
+
+        /* Move the decorataions out of the topleft corner of the display */
+        XMoveWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
+                     -x, -y);
     }
 
 #endif
 
-    /*
-     * Grab the keyboard, too
-     */
+    /* Grab the keyboard, too */
     XGrabKeyboard(
         fgDisplay.Display,
-        fgStructure.GameMode->Window.Handle,
+        fgStructure.GameModeWindow->Window.Handle,
         FALSE,
         GrabModeAsync, GrabModeAsync,
         CurrentTime
@@ -562,10 +528,7 @@ int FGAPIENTRY glutEnterGameMode( void )
 
 #endif
 
-    /*
-     * Return successfull
-     */
-    return( TRUE );
+    return fgStructure.GameModeWindow->ID;
 }
 
 /*
@@ -573,26 +536,20 @@ int FGAPIENTRY glutEnterGameMode( void )
  */
 void FGAPIENTRY glutLeaveGameMode( void )
 {
-    freeglut_return_if_fail( fgStructure.GameMode != NULL );
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLeaveGameMode" );
 
-    /*
-     * First of all, have the game mode window destroyed
-     */
-    fgAddToWindowDestroyList( fgStructure.GameMode, TRUE );
+    freeglut_return_if_fail( fgStructure.GameModeWindow );
 
-#if TARGET_HOST_UNIX_X11
+    fgAddToWindowDestroyList( fgStructure.GameModeWindow );
+    fgStructure.GameModeWindow = NULL;
+
+#if TARGET_HOST_POSIX_X11
 
-    /*
-     * Ungrab the mouse and keyboard
-     */
     XUngrabPointer( fgDisplay.Display, CurrentTime );
     XUngrabKeyboard( fgDisplay.Display, CurrentTime );
 
 #endif
 
-    /*
-     * Then, have the desktop visual settings restored
-     */
     fghRestoreState();
 }
 
@@ -601,59 +558,37 @@ void FGAPIENTRY glutLeaveGameMode( void )
  */
 int FGAPIENTRY glutGameModeGet( GLenum eWhat )
 {
-    /*
-     * See why are we bothered
-     */
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGameModeGet" );
+
     switch( eWhat )
     {
     case GLUT_GAME_MODE_ACTIVE:
-        /*
-         * Check if the game mode is currently active
-         */
-        return( fgStructure.GameMode != NULL );
+        return !!fgStructure.GameModeWindow;
 
     case GLUT_GAME_MODE_POSSIBLE:
-        /*
-         * Check if the current game mode settings are valid
-         */
-        return( fghChangeDisplayMode( TRUE ) );
+        return fghChangeDisplayMode( GL_TRUE );
 
     case GLUT_GAME_MODE_WIDTH:
-        /*
-         * The game mode screen width
-         */
-        return( fgState.GameModeSize.X );
+        return fgState.GameModeSize.X;
 
     case GLUT_GAME_MODE_HEIGHT:
-        /*
-         * The game mode screen height
-         */
-        return( fgState.GameModeSize.Y );
+        return fgState.GameModeSize.Y;
 
     case GLUT_GAME_MODE_PIXEL_DEPTH:
-        /*
-         * The game mode pixel depth
-         */
-        return( fgState.GameModeDepth );
+        return fgState.GameModeDepth;
 
     case GLUT_GAME_MODE_REFRESH_RATE:
-        /*
-         * The game mode refresh rate
-         */
-        return( fgState.GameModeRefresh );
+        return fgState.GameModeRefresh;
 
     case GLUT_GAME_MODE_DISPLAY_CHANGED:
         /*
          * This is true if the game mode has been activated successfully..
          */
-        return( fgStructure.GameMode != NULL );
+        return !!fgStructure.GameModeWindow;
     }
 
-    return( -1 );
+    fgWarning( "Unknown gamemode get: %d", eWhat );
+    return -1;
 }
 
 /*** END OF FILE ***/
-
-
-
-