Splitting the X11-specific "freeglut_gamemode.c" code into its own file
authorJohn F. Fay <johnffay@nettally.com>
Sun, 5 Feb 2012 03:16:52 +0000 (03:16 +0000)
committerJohn F. Fay <johnffay@nettally.com>
Sun, 5 Feb 2012 03:16:52 +0000 (03:16 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1053 7f0cb862-5218-0410-a997-914c9d46530a

src/Common/freeglut_gamemode.c
src/mswin/freeglut_gamemode_mswin.c
src/x11/freeglut_gamemode_x11.c

index f69595c..8a923eb 100644 (file)
 extern void fgPlatformRememberState( void );\r
 extern void fgPlatformRestoreState( void );\r
 extern GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest );\r
+extern void fgPlatformEnterGameMode( void );\r
+extern void fgPlatformLeaveGameMode( void );\r
 \r
 \r
-#if TARGET_HOST_POSIX_X11\r
-static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)\r
-{\r
-#ifdef HAVE_X11_EXTENSIONS_XRANDR_H\r
-    int event_base, error_base, ver_major, ver_minor, use_rate;\r
-    XRRScreenConfiguration *xrr_config = 0;\r
-    Status result = -1;\r
-\r
-    /* must check at runtime for the availability of the extension */\r
-    if(!XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {\r
-        return -1;\r
-    }\r
-\r
-    XRRQueryVersion(fgDisplay.pDisplay.Display, &ver_major, &ver_minor);\r
-\r
-    /* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and\r
-     * the user actually cares about it (rate > 0)\r
-     */\r
-    use_rate = ( rate > 0 ) && ( ( ver_major >= 1 ) ||\r
-                                        ( ( ver_major == 1 ) && ( ver_minor >= 1 ) ) );\r
-\r
-    /* this loop is only so that the whole thing will be repeated if someone\r
-     * else changes video mode between our query of the current information and\r
-     * the attempt to change it.\r
-     */\r
-    do {\r
-        XRRScreenSize *ssizes;\r
-        short *rates;\r
-        Rotation rot;\r
-        int i, ssizes_count, rates_count, curr, res_idx = -1;\r
-        Time timestamp, cfg_timestamp;\r
-\r
-        if(xrr_config) {\r
-            XRRFreeScreenConfigInfo(xrr_config);\r
-        }\r
-\r
-        if(!(xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) {\r
-            fgWarning("XRRGetScreenInfo failed");\r
-            break;\r
-        }\r
-        ssizes = XRRConfigSizes(xrr_config, &ssizes_count);\r
-        curr = XRRConfigCurrentConfiguration(xrr_config, &rot);\r
-        timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp);\r
-\r
-        /* if either of xsz or ysz are unspecified, use the current values */\r
-        if(xsz <= 0)\r
-            xsz = fgState.GameModeSize.X = ssizes[curr].width;\r
-        if(ysz <= 0)\r
-            ysz = fgState.GameModeSize.Y = ssizes[curr].height;\r
-\r
-\r
-        if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) {\r
-            /* no need to switch, we're already in the requested resolution */\r
-            res_idx = curr;\r
-        } else {\r
-            for(i=0; i<ssizes_count; i++) {\r
-                if(ssizes[i].width == xsz && ssizes[i].height == ysz) {\r
-                    res_idx = i;\r
-                    break;  /* found it */\r
-                }\r
-            }\r
-        }\r
-        if(res_idx == -1)\r
-            break;  /* no matching resolution */\r
-\r
-#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )\r
-        if(use_rate) {\r
-            rate = fgState.GameModeRefresh;\r
-\r
-            /* for the selected resolution, let's find out if there is\r
-             * a matching refresh rate available.\r
-             */\r
-            rates = XRRConfigRates(xrr_config, res_idx, &rates_count);\r
-\r
-            for(i=0; i<rates_count; i++) {\r
-                if(rates[i] == rate) {\r
-                    break;\r
-                }\r
-            }\r
-            if(i == rates_count) {\r
-                break; /* no matching rate */\r
-            }\r
-        }\r
-#endif\r
-\r
-        if(just_checking) {\r
-            result = 0;\r
-            break;\r
-        }\r
-\r
-#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )\r
-        if(use_rate)\r
-            result = XRRSetScreenConfigAndRate(fgDisplay.pDisplay.Display, xrr_config,\r
-                    fgDisplay.pDisplay.RootWindow, res_idx, rot, rate, timestamp);\r
-        else\r
-#endif\r
-            result = XRRSetScreenConfig(fgDisplay.pDisplay.Display, xrr_config,\r
-                    fgDisplay.pDisplay.RootWindow, res_idx, rot, timestamp);\r
-\r
-    } while(result == RRSetConfigInvalidTime);\r
-\r
-    if(xrr_config) {\r
-        XRRFreeScreenConfigInfo(xrr_config);\r
-    }\r
-\r
-    if(result == 0) {\r
-        return 0;\r
-    }\r
-\r
-#endif  /* HAVE_X11_EXTENSIONS_XRANDR_H */\r
-    return -1;\r
-}\r
-#endif  /* TARGET_HOST_POSIX_X11 */\r
-\r
-#if TARGET_HOST_POSIX_X11\r
-/*\r
- * Remembers the current visual settings, so that\r
- * we can change them and restore later...\r
- */\r
-void fgPlatformRememberState( void )\r
-{\r
-    int event_base, error_base;\r
-\r
-    /*\r
-     * Remember the current pointer location before going fullscreen\r
-     * for restoring it later:\r
-     */\r
-    Window junk_window;\r
-    unsigned int junk_mask;\r
-\r
-    XQueryPointer(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow,\r
-            &junk_window, &junk_window,\r
-            &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY,\r
-            &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, &junk_mask);\r
-\r
-#   ifdef HAVE_X11_EXTENSIONS_XRANDR_H\r
-    if(XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {\r
-        XRRScreenConfiguration *xrr_config;\r
-        XRRScreenSize *ssizes;\r
-        Rotation rot;\r
-        int ssize_count, curr;\r
-\r
-        if((xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) {\r
-            ssizes = XRRConfigSizes(xrr_config, &ssize_count);\r
-            curr = XRRConfigCurrentConfiguration(xrr_config, &rot);\r
-\r
-            fgDisplay.pDisplay.prev_xsz = ssizes[curr].width;\r
-            fgDisplay.pDisplay.prev_ysz = ssizes[curr].height;\r
-            fgDisplay.pDisplay.prev_refresh = -1;\r
-\r
-#       if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )\r
-            if(fgState.GameModeRefresh != -1) {\r
-                fgDisplay.pDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config);\r
-            }\r
-#       endif\r
-\r
-            fgDisplay.pDisplay.prev_size_valid = 1;\r
-\r
-            XRRFreeScreenConfigInfo(xrr_config);\r
-        }\r
-    }\r
-#   endif\r
-\r
-    /*\r
-     * This highly depends on the XFree86 extensions,\r
-     * not approved as X Consortium standards\r
-     */\r
-#   ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
-    if(!XF86VidModeQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {\r
-        return;\r
-    }\r
-\r
-    /*\r
-     * Remember the current ViewPort location of the screen to be able to\r
-     * restore the ViewPort on LeaveGameMode():\r
-     */\r
-    if( !XF86VidModeGetViewPort(\r
-             fgDisplay.pDisplay.Display,\r
-             fgDisplay.pDisplay.Screen,\r
-             &fgDisplay.pDisplay.DisplayViewPortX,\r
-             &fgDisplay.pDisplay.DisplayViewPortY ) )\r
-        fgWarning( "XF86VidModeGetViewPort failed" );\r
-\r
-\r
-    /* Query the current display settings: */\r
-    fgDisplay.pDisplay.DisplayModeValid =\r
-      XF86VidModeGetModeLine(\r
-        fgDisplay.pDisplay.Display,\r
-        fgDisplay.pDisplay.Screen,\r
-        &fgDisplay.pDisplay.DisplayModeClock,\r
-        &fgDisplay.pDisplay.DisplayMode\r
-    );\r
-\r
-    if( !fgDisplay.pDisplay.DisplayModeValid )\r
-        fgWarning( "XF86VidModeGetModeLine failed" );\r
-#   endif\r
-\r
-}\r
-#endif\r
-\r
-#if TARGET_HOST_POSIX_X11\r
-/*\r
- * Restores the previously remembered visual settings\r
- */\r
-void fgPlatformRestoreState( void )\r
-{\r
-    /* Restore the remembered pointer position: */\r
-    XWarpPointer(\r
-        fgDisplay.pDisplay.Display, None, fgDisplay.pDisplay.RootWindow, 0, 0, 0, 0,\r
-        fgDisplay.pDisplay.DisplayPointerX, fgDisplay.pDisplay.DisplayPointerY\r
-    );\r
-\r
-\r
-#   ifdef HAVE_X11_EXTENSIONS_XRANDR_H\r
-    if(fgDisplay.pDisplay.prev_size_valid) {\r
-        if(xrandr_resize(fgDisplay.pDisplay.prev_xsz, fgDisplay.pDisplay.prev_ysz, fgDisplay.pDisplay.prev_refresh, 0) != -1) {\r
-            fgDisplay.pDisplay.prev_size_valid = 0;\r
-#       ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
-            fgDisplay.pDisplay.DisplayModeValid = 0;\r
-#       endif\r
-            return;\r
-        }\r
-    }\r
-#   endif\r
-\r
-\r
-\r
-#   ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
-    /*\r
-     * This highly depends on the XFree86 extensions,\r
-     * not approved as X Consortium standards\r
-     */\r
-\r
-    if( fgDisplay.pDisplay.DisplayModeValid )\r
-    {\r
-        XF86VidModeModeInfo** displayModes;\r
-        int i, displayModesCount;\r
-\r
-        if( !XF86VidModeGetAllModeLines(\r
-                 fgDisplay.pDisplay.Display,\r
-                 fgDisplay.pDisplay.Screen,\r
-                 &displayModesCount,\r
-                 &displayModes ) )\r
-        {\r
-            fgWarning( "XF86VidModeGetAllModeLines failed" );\r
-            return;\r
-        }\r
-\r
-\r
-        /*\r
-         * Check every of the modes looking for one that matches our demands.\r
-         * If we find one, switch to it and restore the remembered viewport.\r
-         */\r
-        for( i = 0; i < displayModesCount; i++ )\r
-        {\r
-            if(displayModes[ i ]->hdisplay == fgDisplay.pDisplay.DisplayMode.hdisplay &&\r
-               displayModes[ i ]->vdisplay == fgDisplay.pDisplay.DisplayMode.vdisplay &&\r
-               displayModes[ i ]->dotclock == fgDisplay.pDisplay.DisplayModeClock )\r
-            {\r
-                if( !XF86VidModeSwitchToMode(\r
-                         fgDisplay.pDisplay.Display,\r
-                         fgDisplay.pDisplay.Screen,\r
-                         displayModes[ i ] ) )\r
-                {\r
-                    fgWarning( "XF86VidModeSwitchToMode failed" );\r
-                    break;\r
-                }\r
-\r
-                if( !XF86VidModeSetViewPort(\r
-                         fgDisplay.pDisplay.Display,\r
-                         fgDisplay.pDisplay.Screen,\r
-                         fgDisplay.pDisplay.DisplayViewPortX,\r
-                         fgDisplay.pDisplay.DisplayViewPortY ) )\r
-                    fgWarning( "XF86VidModeSetViewPort failed" );\r
-\r
-\r
-                /*\r
-                 * For the case this would be the last X11 call the application\r
-                 * calls exit() we've to flush the X11 output queue to have the\r
-                 * commands sent to the X server before the application exits.\r
-                 */\r
-                XFlush( fgDisplay.pDisplay.Display );\r
-\r
-                fgDisplay.pDisplay.DisplayModeValid = 0;\r
-#       ifdef HAVE_X11_EXTENSIONS_XRANDR_H\r
-                fgDisplay.pDisplay.prev_size_valid = 0;\r
-#       endif\r
-\r
-                break;\r
-            }\r
-        }\r
-        XFree( displayModes );\r
-    }\r
-\r
-#   endif\r
-\r
-}\r
-#endif\r
-\r
-#if TARGET_HOST_POSIX_X11\r
-#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
-\r
-/*\r
- * Checks a single display mode settings against user's preferences.\r
- */\r
-static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )\r
-{\r
-    /* The desired values should be stored in fgState structure... */\r
-    return ( width == fgState.GameModeSize.X ) &&\r
-           ( height == fgState.GameModeSize.Y ) &&\r
-           ( depth == fgState.GameModeDepth ) &&\r
-           ( refresh == fgState.GameModeRefresh );\r
-}\r
-\r
-/*\r
- * Checks all display modes settings against user's preferences.\r
- * Returns the mode number found or -1 if none could be found.\r
- */\r
-static int fghCheckDisplayModes( GLboolean exactMatch, int displayModesCount, XF86VidModeModeInfo** displayModes )\r
-{\r
-    int i;\r
-    for( i = 0; i < displayModesCount; i++ )\r
-    {\r
-        /* Compute the displays refresh rate, dotclock comes in kHz. */\r
-        int refresh = ( displayModes[ i ]->dotclock * 1000 ) /\r
-                      ( displayModes[ i ]->htotal * displayModes[ i ]->vtotal );\r
-\r
-        if( fghCheckDisplayMode( displayModes[ i ]->hdisplay,\r
-                                 displayModes[ i ]->vdisplay,\r
-                                 fgState.GameModeDepth,\r
-                                 ( exactMatch ? refresh : fgState.GameModeRefresh ) ) ) {\r
-            if (!exactMatch)\r
-            {\r
-                /* Update the chosen refresh rate, otherwise a\r
-                 * glutGameModeGet(GLUT_GAME_MODE_REFRESH_RATE) would not\r
-                 * return the right values\r
-                 */\r
-                fgState.GameModeRefresh = refresh;\r
-            }\r
-\r
-            return i;\r
-        }\r
-    }\r
-    return -1;\r
-}\r
-\r
-#endif\r
-#endif\r
-\r
-#if TARGET_HOST_POSIX_X11\r
-\r
-/*\r
- * Changes the current display mode to match user's settings\r
- */\r
-GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest )\r
-{\r
-    GLboolean success = GL_FALSE;\r
-    /* first try to use XRandR, then fallback to XF86VidMode */\r
-#   ifdef HAVE_X11_EXTENSIONS_XRANDR_H\r
-    if(xrandr_resize(fgState.GameModeSize.X, fgState.GameModeSize.Y,\r
-                fgState.GameModeRefresh, haveToTest) != -1) {\r
-        return GL_TRUE;\r
-    }\r
-#   endif\r
-\r
-\r
-    /*\r
-     * This highly depends on the XFree86 extensions,\r
-     * not approved as X Consortium standards\r
-     */\r
-#   ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
-\r
-    /*\r
-     * This is also used by applications which check modes by calling\r
-     * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check:\r
-     */\r
-    if( haveToTest || fgDisplay.pDisplay.DisplayModeValid )\r
-    {\r
-        XF86VidModeModeInfo** displayModes;\r
-        int i, displayModesCount;\r
-\r
-        /* If we don't have a valid modeline in the display structure, which\r
-         * can happen if this is called from glutGameModeGet instead of\r
-         * glutEnterGameMode, then we need to query the current mode, to make\r
-         * unspecified settings to default to their current values.\r
-         */\r
-        if(!fgDisplay.pDisplay.DisplayModeValid) {\r
-            if(!XF86VidModeGetModeLine(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen,\r
-                    &fgDisplay.pDisplay.DisplayModeClock, &fgDisplay.pDisplay.DisplayMode)) {\r
-                return success;\r
-            }\r
-        }\r
-\r
-        if (fgState.GameModeSize.X == -1)\r
-        {\r
-            fgState.GameModeSize.X = fgDisplay.pDisplay.DisplayMode.hdisplay;\r
-        }\r
-        if (fgState.GameModeSize.Y == -1)\r
-        {\r
-            fgState.GameModeSize.Y = fgDisplay.pDisplay.DisplayMode.vdisplay;\r
-        }\r
-        if (fgState.GameModeDepth == -1)\r
-        {\r
-            /* can't get color depth from this, nor can we change it, do nothing\r
-             * TODO: get with XGetVisualInfo()? but then how to set?\r
-             */\r
-        }\r
-        if (fgState.GameModeRefresh == -1)\r
-        {\r
-            /* Compute the displays refresh rate, dotclock comes in kHz. */\r
-            int refresh = ( fgDisplay.pDisplay.DisplayModeClock * 1000 ) /\r
-                ( fgDisplay.pDisplay.DisplayMode.htotal * fgDisplay.pDisplay.DisplayMode.vtotal );\r
-\r
-            fgState.GameModeRefresh = refresh;\r
-        }\r
-\r
-        /* query all possible display modes */\r
-        if( !XF86VidModeGetAllModeLines(\r
-                 fgDisplay.pDisplay.Display,\r
-                 fgDisplay.pDisplay.Screen,\r
-                 &displayModesCount,\r
-                 &displayModes ) )\r
-        {\r
-            fgWarning( "XF86VidModeGetAllModeLines failed" );\r
-            return success;\r
-        }\r
-\r
-\r
-        /*\r
-         * Check every of the modes looking for one that matches our demands,\r
-         * ignoring the refresh rate if no exact match could be found.\r
-         */\r
-        i = fghCheckDisplayModes( GL_TRUE, displayModesCount, displayModes );\r
-        if( i < 0 ) {\r
-            i = fghCheckDisplayModes( GL_FALSE, displayModesCount, displayModes );\r
-        }\r
-        success = ( i < 0 ) ? GL_FALSE : GL_TRUE;\r
-\r
-        if( !haveToTest && success ) {\r
-            if( !XF86VidModeSwitchToMode(\r
-                     fgDisplay.pDisplay.Display,\r
-                     fgDisplay.pDisplay.Screen,\r
-                     displayModes[ i ] ) )\r
-                fgWarning( "XF86VidModeSwitchToMode failed" );\r
-        }\r
-\r
-        XFree( displayModes );\r
-    }\r
-\r
-#   endif\r
-\r
-    return success;\r
-}\r
-\r
-#endif\r
-\r
 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */\r
 \r
 /*\r
@@ -570,93 +116,7 @@ int FGAPIENTRY glutEnterGameMode( void )
     fgStructure.GameModeWindow->State.Height = fgState.GameModeSize.Y;\r
     fgStructure.GameModeWindow->State.NeedToResize = GL_TRUE;\r
 \r
-#if TARGET_HOST_POSIX_X11\r
-\r
-    /*\r
-     * Sync needed to avoid a real race, the Xserver must have really created\r
-     * the window before we can grab the pointer into it:\r
-     */\r
-    XSync( fgDisplay.pDisplay.Display, False );\r
-    /*\r
-     * Grab the pointer to confine it into the window after the calls to\r
-     * XWrapPointer() which ensure that the pointer really enters the window.\r
-     *\r
-     * We also need to wait here until XGrabPointer() returns GrabSuccess,\r
-     * otherwise the new window is not viewable yet and if the next function\r
-     * (XSetInputFocus) is called with a not yet viewable window, it will exit\r
-     * the application which we have to aviod, so wait until it's viewable:\r
-     */\r
-    while( GrabSuccess != XGrabPointer(\r
-               fgDisplay.pDisplay.Display, fgStructure.GameModeWindow->Window.Handle,\r
-               TRUE,\r
-               ButtonPressMask | ButtonReleaseMask | ButtonMotionMask\r
-               | PointerMotionMask,\r
-               GrabModeAsync, GrabModeAsync,\r
-               fgStructure.GameModeWindow->Window.Handle, None, CurrentTime) )\r
-        usleep( 100 );\r
-    /*\r
-     * Change input focus to the new window. This will exit the application\r
-     * if the new window is not viewable yet, see the XGrabPointer loop above.\r
-     */\r
-    XSetInputFocus(\r
-        fgDisplay.pDisplay.Display,\r
-        fgStructure.GameModeWindow->Window.Handle,\r
-        RevertToNone,\r
-        CurrentTime\r
-    );\r
-\r
-    /* Move the Pointer to the middle of the fullscreen window */\r
-    XWarpPointer(\r
-        fgDisplay.pDisplay.Display,\r
-        None,\r
-        fgDisplay.pDisplay.RootWindow,\r
-        0, 0, 0, 0,\r
-        fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2\r
-    );\r
-\r
-#   ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
-\r
-    if( fgDisplay.pDisplay.DisplayModeValid )\r
-    {\r
-        int x, y;\r
-        Window child;\r
-\r
-        /* Change to viewport to the window topleft edge: */\r
-        if( !XF86VidModeSetViewPort( fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, 0, 0 ) )\r
-            fgWarning( "XF86VidModeSetViewPort failed" );\r
-\r
-        /*\r
-         * Final window repositioning: It could be avoided using an undecorated\r
-         * window using override_redirect, but this * would possily require\r
-         * more changes and investigation.\r
-         */\r
-\r
-        /* Get the current postion of the drawable area on screen */\r
-        XTranslateCoordinates(\r
-            fgDisplay.pDisplay.Display,\r
-            fgStructure.CurrentWindow->Window.Handle,\r
-            fgDisplay.pDisplay.RootWindow,\r
-            0, 0, &x, &y,\r
-            &child\r
-        );\r
-\r
-        /* Move the decorataions out of the topleft corner of the display */\r
-        XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,\r
-                     -x, -y);\r
-    }\r
-\r
-#endif\r
-\r
-    /* Grab the keyboard, too */\r
-    XGrabKeyboard(\r
-        fgDisplay.pDisplay.Display,\r
-        fgStructure.GameModeWindow->Window.Handle,\r
-        FALSE,\r
-        GrabModeAsync, GrabModeAsync,\r
-        CurrentTime\r
-    );\r
-\r
-#endif\r
+    fgPlatformEnterGameMode();\r
 \r
     return fgStructure.GameModeWindow->ID;\r
 }\r
@@ -673,12 +133,7 @@ void FGAPIENTRY glutLeaveGameMode( void )
     fgAddToWindowDestroyList( fgStructure.GameModeWindow );\r
     fgStructure.GameModeWindow = NULL;\r
 \r
-#if TARGET_HOST_POSIX_X11\r
-\r
-    XUngrabPointer( fgDisplay.pDisplay.Display, CurrentTime );\r
-    XUngrabKeyboard( fgDisplay.pDisplay.Display, CurrentTime );\r
-\r
-#endif\r
+    fgPlatformLeaveGameMode();\r
 \r
     fgPlatformRestoreState();\r
 }\r
index 3f23a7b..510c0f6 100644 (file)
@@ -147,3 +147,11 @@ GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest )
     return success;\r
 }\r
 \r
+void fgPlatformEnterGameMode( void ) \r
+{\r
+}\r
+\r
+void fgPlatformLeaveGameMode( void ) \r
+{\r
+}\r
+\r
index e69de29..409a621 100644 (file)
@@ -0,0 +1,571 @@
+/*\r
+ * freeglut_gamemode_x11.c\r
+ *\r
+ * The game mode handling code.\r
+ *\r
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.\r
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>\r
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>\r
+ * Creation date: Thur Feb 2 2012\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a\r
+ * copy of this software and associated documentation files (the "Software"),\r
+ * to deal in the Software without restriction, including without limitation\r
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+ * and/or sell copies of the Software, and to permit persons to whom the\r
+ * Software is furnished to do so, subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included\r
+ * in all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ */\r
+\r
+#include <GL/freeglut.h>\r
+#include "freeglut_internal.h"\r
+\r
+static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)\r
+{\r
+#ifdef HAVE_X11_EXTENSIONS_XRANDR_H\r
+    int event_base, error_base, ver_major, ver_minor, use_rate;\r
+    XRRScreenConfiguration *xrr_config = 0;\r
+    Status result = -1;\r
+\r
+    /* must check at runtime for the availability of the extension */\r
+    if(!XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {\r
+        return -1;\r
+    }\r
+\r
+    XRRQueryVersion(fgDisplay.pDisplay.Display, &ver_major, &ver_minor);\r
+\r
+    /* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and\r
+     * the user actually cares about it (rate > 0)\r
+     */\r
+    use_rate = ( rate > 0 ) && ( ( ver_major >= 1 ) ||\r
+                                        ( ( ver_major == 1 ) && ( ver_minor >= 1 ) ) );\r
+\r
+    /* this loop is only so that the whole thing will be repeated if someone\r
+     * else changes video mode between our query of the current information and\r
+     * the attempt to change it.\r
+     */\r
+    do {\r
+        XRRScreenSize *ssizes;\r
+        short *rates;\r
+        Rotation rot;\r
+        int i, ssizes_count, rates_count, curr, res_idx = -1;\r
+        Time timestamp, cfg_timestamp;\r
+\r
+        if(xrr_config) {\r
+            XRRFreeScreenConfigInfo(xrr_config);\r
+        }\r
+\r
+        if(!(xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) {\r
+            fgWarning("XRRGetScreenInfo failed");\r
+            break;\r
+        }\r
+        ssizes = XRRConfigSizes(xrr_config, &ssizes_count);\r
+        curr = XRRConfigCurrentConfiguration(xrr_config, &rot);\r
+        timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp);\r
+\r
+        /* if either of xsz or ysz are unspecified, use the current values */\r
+        if(xsz <= 0)\r
+            xsz = fgState.GameModeSize.X = ssizes[curr].width;\r
+        if(ysz <= 0)\r
+            ysz = fgState.GameModeSize.Y = ssizes[curr].height;\r
+\r
+\r
+        if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) {\r
+            /* no need to switch, we're already in the requested resolution */\r
+            res_idx = curr;\r
+        } else {\r
+            for(i=0; i<ssizes_count; i++) {\r
+                if(ssizes[i].width == xsz && ssizes[i].height == ysz) {\r
+                    res_idx = i;\r
+                    break;  /* found it */\r
+                }\r
+            }\r
+        }\r
+        if(res_idx == -1)\r
+            break;  /* no matching resolution */\r
+\r
+#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )\r
+        if(use_rate) {\r
+            rate = fgState.GameModeRefresh;\r
+\r
+            /* for the selected resolution, let's find out if there is\r
+             * a matching refresh rate available.\r
+             */\r
+            rates = XRRConfigRates(xrr_config, res_idx, &rates_count);\r
+\r
+            for(i=0; i<rates_count; i++) {\r
+                if(rates[i] == rate) {\r
+                    break;\r
+                }\r
+            }\r
+            if(i == rates_count) {\r
+                break; /* no matching rate */\r
+            }\r
+        }\r
+#endif\r
+\r
+        if(just_checking) {\r
+            result = 0;\r
+            break;\r
+        }\r
+\r
+#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )\r
+        if(use_rate)\r
+            result = XRRSetScreenConfigAndRate(fgDisplay.pDisplay.Display, xrr_config,\r
+                    fgDisplay.pDisplay.RootWindow, res_idx, rot, rate, timestamp);\r
+        else\r
+#endif\r
+            result = XRRSetScreenConfig(fgDisplay.pDisplay.Display, xrr_config,\r
+                    fgDisplay.pDisplay.RootWindow, res_idx, rot, timestamp);\r
+\r
+    } while(result == RRSetConfigInvalidTime);\r
+\r
+    if(xrr_config) {\r
+        XRRFreeScreenConfigInfo(xrr_config);\r
+    }\r
+\r
+    if(result == 0) {\r
+        return 0;\r
+    }\r
+\r
+#endif  /* HAVE_X11_EXTENSIONS_XRANDR_H */\r
+    return -1;\r
+}\r
+\r
+/*\r
+ * Remembers the current visual settings, so that\r
+ * we can change them and restore later...\r
+ */\r
+void fgPlatformRememberState( void )\r
+{\r
+    int event_base, error_base;\r
+\r
+    /*\r
+     * Remember the current pointer location before going fullscreen\r
+     * for restoring it later:\r
+     */\r
+    Window junk_window;\r
+    unsigned int junk_mask;\r
+\r
+    XQueryPointer(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow,\r
+            &junk_window, &junk_window,\r
+            &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY,\r
+            &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, &junk_mask);\r
+\r
+#   ifdef HAVE_X11_EXTENSIONS_XRANDR_H\r
+    if(XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {\r
+        XRRScreenConfiguration *xrr_config;\r
+        XRRScreenSize *ssizes;\r
+        Rotation rot;\r
+        int ssize_count, curr;\r
+\r
+        if((xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) {\r
+            ssizes = XRRConfigSizes(xrr_config, &ssize_count);\r
+            curr = XRRConfigCurrentConfiguration(xrr_config, &rot);\r
+\r
+            fgDisplay.pDisplay.prev_xsz = ssizes[curr].width;\r
+            fgDisplay.pDisplay.prev_ysz = ssizes[curr].height;\r
+            fgDisplay.pDisplay.prev_refresh = -1;\r
+\r
+#       if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )\r
+            if(fgState.GameModeRefresh != -1) {\r
+                fgDisplay.pDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config);\r
+            }\r
+#       endif\r
+\r
+            fgDisplay.pDisplay.prev_size_valid = 1;\r
+\r
+            XRRFreeScreenConfigInfo(xrr_config);\r
+        }\r
+    }\r
+#   endif\r
+\r
+    /*\r
+     * This highly depends on the XFree86 extensions,\r
+     * not approved as X Consortium standards\r
+     */\r
+#   ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
+    if(!XF86VidModeQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {\r
+        return;\r
+    }\r
+\r
+    /*\r
+     * Remember the current ViewPort location of the screen to be able to\r
+     * restore the ViewPort on LeaveGameMode():\r
+     */\r
+    if( !XF86VidModeGetViewPort(\r
+             fgDisplay.pDisplay.Display,\r
+             fgDisplay.pDisplay.Screen,\r
+             &fgDisplay.pDisplay.DisplayViewPortX,\r
+             &fgDisplay.pDisplay.DisplayViewPortY ) )\r
+        fgWarning( "XF86VidModeGetViewPort failed" );\r
+\r
+\r
+    /* Query the current display settings: */\r
+    fgDisplay.pDisplay.DisplayModeValid =\r
+      XF86VidModeGetModeLine(\r
+        fgDisplay.pDisplay.Display,\r
+        fgDisplay.pDisplay.Screen,\r
+        &fgDisplay.pDisplay.DisplayModeClock,\r
+        &fgDisplay.pDisplay.DisplayMode\r
+    );\r
+\r
+    if( !fgDisplay.pDisplay.DisplayModeValid )\r
+        fgWarning( "XF86VidModeGetModeLine failed" );\r
+#   endif\r
+\r
+}\r
+\r
+/*\r
+ * Restores the previously remembered visual settings\r
+ */\r
+void fgPlatformRestoreState( void )\r
+{\r
+    /* Restore the remembered pointer position: */\r
+    XWarpPointer(\r
+        fgDisplay.pDisplay.Display, None, fgDisplay.pDisplay.RootWindow, 0, 0, 0, 0,\r
+        fgDisplay.pDisplay.DisplayPointerX, fgDisplay.pDisplay.DisplayPointerY\r
+    );\r
+\r
+\r
+#   ifdef HAVE_X11_EXTENSIONS_XRANDR_H\r
+    if(fgDisplay.pDisplay.prev_size_valid) {\r
+        if(xrandr_resize(fgDisplay.pDisplay.prev_xsz, fgDisplay.pDisplay.prev_ysz, fgDisplay.pDisplay.prev_refresh, 0) != -1) {\r
+            fgDisplay.pDisplay.prev_size_valid = 0;\r
+#       ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
+            fgDisplay.pDisplay.DisplayModeValid = 0;\r
+#       endif\r
+            return;\r
+        }\r
+    }\r
+#   endif\r
+\r
+\r
+\r
+#   ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
+    /*\r
+     * This highly depends on the XFree86 extensions,\r
+     * not approved as X Consortium standards\r
+     */\r
+\r
+    if( fgDisplay.pDisplay.DisplayModeValid )\r
+    {\r
+        XF86VidModeModeInfo** displayModes;\r
+        int i, displayModesCount;\r
+\r
+        if( !XF86VidModeGetAllModeLines(\r
+                 fgDisplay.pDisplay.Display,\r
+                 fgDisplay.pDisplay.Screen,\r
+                 &displayModesCount,\r
+                 &displayModes ) )\r
+        {\r
+            fgWarning( "XF86VidModeGetAllModeLines failed" );\r
+            return;\r
+        }\r
+\r
+\r
+        /*\r
+         * Check every of the modes looking for one that matches our demands.\r
+         * If we find one, switch to it and restore the remembered viewport.\r
+         */\r
+        for( i = 0; i < displayModesCount; i++ )\r
+        {\r
+            if(displayModes[ i ]->hdisplay == fgDisplay.pDisplay.DisplayMode.hdisplay &&\r
+               displayModes[ i ]->vdisplay == fgDisplay.pDisplay.DisplayMode.vdisplay &&\r
+               displayModes[ i ]->dotclock == fgDisplay.pDisplay.DisplayModeClock )\r
+            {\r
+                if( !XF86VidModeSwitchToMode(\r
+                         fgDisplay.pDisplay.Display,\r
+                         fgDisplay.pDisplay.Screen,\r
+                         displayModes[ i ] ) )\r
+                {\r
+                    fgWarning( "XF86VidModeSwitchToMode failed" );\r
+                    break;\r
+                }\r
+\r
+                if( !XF86VidModeSetViewPort(\r
+                         fgDisplay.pDisplay.Display,\r
+                         fgDisplay.pDisplay.Screen,\r
+                         fgDisplay.pDisplay.DisplayViewPortX,\r
+                         fgDisplay.pDisplay.DisplayViewPortY ) )\r
+                    fgWarning( "XF86VidModeSetViewPort failed" );\r
+\r
+\r
+                /*\r
+                 * For the case this would be the last X11 call the application\r
+                 * calls exit() we've to flush the X11 output queue to have the\r
+                 * commands sent to the X server before the application exits.\r
+                 */\r
+                XFlush( fgDisplay.pDisplay.Display );\r
+\r
+                fgDisplay.pDisplay.DisplayModeValid = 0;\r
+#       ifdef HAVE_X11_EXTENSIONS_XRANDR_H\r
+                fgDisplay.pDisplay.prev_size_valid = 0;\r
+#       endif\r
+\r
+                break;\r
+            }\r
+        }\r
+        XFree( displayModes );\r
+    }\r
+\r
+#   endif\r
+\r
+}\r
+\r
+#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
+\r
+/*\r
+ * Checks a single display mode settings against user's preferences.\r
+ */\r
+static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )\r
+{\r
+    /* The desired values should be stored in fgState structure... */\r
+    return ( width == fgState.GameModeSize.X ) &&\r
+           ( height == fgState.GameModeSize.Y ) &&\r
+           ( depth == fgState.GameModeDepth ) &&\r
+           ( refresh == fgState.GameModeRefresh );\r
+}\r
+\r
+/*\r
+ * Checks all display modes settings against user's preferences.\r
+ * Returns the mode number found or -1 if none could be found.\r
+ */\r
+static int fghCheckDisplayModes( GLboolean exactMatch, int displayModesCount, XF86VidModeModeInfo** displayModes )\r
+{\r
+    int i;\r
+    for( i = 0; i < displayModesCount; i++ )\r
+    {\r
+        /* Compute the displays refresh rate, dotclock comes in kHz. */\r
+        int refresh = ( displayModes[ i ]->dotclock * 1000 ) /\r
+                      ( displayModes[ i ]->htotal * displayModes[ i ]->vtotal );\r
+\r
+        if( fghCheckDisplayMode( displayModes[ i ]->hdisplay,\r
+                                 displayModes[ i ]->vdisplay,\r
+                                 fgState.GameModeDepth,\r
+                                 ( exactMatch ? refresh : fgState.GameModeRefresh ) ) ) {\r
+            if (!exactMatch)\r
+            {\r
+                /* Update the chosen refresh rate, otherwise a\r
+                 * glutGameModeGet(GLUT_GAME_MODE_REFRESH_RATE) would not\r
+                 * return the right values\r
+                 */\r
+                fgState.GameModeRefresh = refresh;\r
+            }\r
+\r
+            return i;\r
+        }\r
+    }\r
+    return -1;\r
+}\r
+\r
+#endif\r
+\r
+/*\r
+ * Changes the current display mode to match user's settings\r
+ */\r
+GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest )\r
+{\r
+    GLboolean success = GL_FALSE;\r
+    /* first try to use XRandR, then fallback to XF86VidMode */\r
+#   ifdef HAVE_X11_EXTENSIONS_XRANDR_H\r
+    if(xrandr_resize(fgState.GameModeSize.X, fgState.GameModeSize.Y,\r
+                fgState.GameModeRefresh, haveToTest) != -1) {\r
+        return GL_TRUE;\r
+    }\r
+#   endif\r
+\r
+\r
+    /*\r
+     * This highly depends on the XFree86 extensions,\r
+     * not approved as X Consortium standards\r
+     */\r
+#   ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
+\r
+    /*\r
+     * This is also used by applications which check modes by calling\r
+     * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check:\r
+     */\r
+    if( haveToTest || fgDisplay.pDisplay.DisplayModeValid )\r
+    {\r
+        XF86VidModeModeInfo** displayModes;\r
+        int i, displayModesCount;\r
+\r
+        /* If we don't have a valid modeline in the display structure, which\r
+         * can happen if this is called from glutGameModeGet instead of\r
+         * glutEnterGameMode, then we need to query the current mode, to make\r
+         * unspecified settings to default to their current values.\r
+         */\r
+        if(!fgDisplay.pDisplay.DisplayModeValid) {\r
+            if(!XF86VidModeGetModeLine(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen,\r
+                    &fgDisplay.pDisplay.DisplayModeClock, &fgDisplay.pDisplay.DisplayMode)) {\r
+                return success;\r
+            }\r
+        }\r
+\r
+        if (fgState.GameModeSize.X == -1)\r
+        {\r
+            fgState.GameModeSize.X = fgDisplay.pDisplay.DisplayMode.hdisplay;\r
+        }\r
+        if (fgState.GameModeSize.Y == -1)\r
+        {\r
+            fgState.GameModeSize.Y = fgDisplay.pDisplay.DisplayMode.vdisplay;\r
+        }\r
+        if (fgState.GameModeDepth == -1)\r
+        {\r
+            /* can't get color depth from this, nor can we change it, do nothing\r
+             * TODO: get with XGetVisualInfo()? but then how to set?\r
+             */\r
+        }\r
+        if (fgState.GameModeRefresh == -1)\r
+        {\r
+            /* Compute the displays refresh rate, dotclock comes in kHz. */\r
+            int refresh = ( fgDisplay.pDisplay.DisplayModeClock * 1000 ) /\r
+                ( fgDisplay.pDisplay.DisplayMode.htotal * fgDisplay.pDisplay.DisplayMode.vtotal );\r
+\r
+            fgState.GameModeRefresh = refresh;\r
+        }\r
+\r
+        /* query all possible display modes */\r
+        if( !XF86VidModeGetAllModeLines(\r
+                 fgDisplay.pDisplay.Display,\r
+                 fgDisplay.pDisplay.Screen,\r
+                 &displayModesCount,\r
+                 &displayModes ) )\r
+        {\r
+            fgWarning( "XF86VidModeGetAllModeLines failed" );\r
+            return success;\r
+        }\r
+\r
+\r
+        /*\r
+         * Check every of the modes looking for one that matches our demands,\r
+         * ignoring the refresh rate if no exact match could be found.\r
+         */\r
+        i = fghCheckDisplayModes( GL_TRUE, displayModesCount, displayModes );\r
+        if( i < 0 ) {\r
+            i = fghCheckDisplayModes( GL_FALSE, displayModesCount, displayModes );\r
+        }\r
+        success = ( i < 0 ) ? GL_FALSE : GL_TRUE;\r
+\r
+        if( !haveToTest && success ) {\r
+            if( !XF86VidModeSwitchToMode(\r
+                     fgDisplay.pDisplay.Display,\r
+                     fgDisplay.pDisplay.Screen,\r
+                     displayModes[ i ] ) )\r
+                fgWarning( "XF86VidModeSwitchToMode failed" );\r
+        }\r
+\r
+        XFree( displayModes );\r
+    }\r
+\r
+#   endif\r
+\r
+    return success;\r
+}\r
+\r
+\r
+void fgPlatformEnterGameMode( void ) \r
+{\r
+\r
+    /*\r
+     * Sync needed to avoid a real race, the Xserver must have really created\r
+     * the window before we can grab the pointer into it:\r
+     */\r
+    XSync( fgDisplay.pDisplay.Display, False );\r
+    /*\r
+     * Grab the pointer to confine it into the window after the calls to\r
+     * XWrapPointer() which ensure that the pointer really enters the window.\r
+     *\r
+     * We also need to wait here until XGrabPointer() returns GrabSuccess,\r
+     * otherwise the new window is not viewable yet and if the next function\r
+     * (XSetInputFocus) is called with a not yet viewable window, it will exit\r
+     * the application which we have to aviod, so wait until it's viewable:\r
+     */\r
+    while( GrabSuccess != XGrabPointer(\r
+               fgDisplay.pDisplay.Display, fgStructure.GameModeWindow->Window.Handle,\r
+               TRUE,\r
+               ButtonPressMask | ButtonReleaseMask | ButtonMotionMask\r
+               | PointerMotionMask,\r
+               GrabModeAsync, GrabModeAsync,\r
+               fgStructure.GameModeWindow->Window.Handle, None, CurrentTime) )\r
+        usleep( 100 );\r
+    /*\r
+     * Change input focus to the new window. This will exit the application\r
+     * if the new window is not viewable yet, see the XGrabPointer loop above.\r
+     */\r
+    XSetInputFocus(\r
+        fgDisplay.pDisplay.Display,\r
+        fgStructure.GameModeWindow->Window.Handle,\r
+        RevertToNone,\r
+        CurrentTime\r
+    );\r
+\r
+    /* Move the Pointer to the middle of the fullscreen window */\r
+    XWarpPointer(\r
+        fgDisplay.pDisplay.Display,\r
+        None,\r
+        fgDisplay.pDisplay.RootWindow,\r
+        0, 0, 0, 0,\r
+        fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2\r
+    );\r
+\r
+#   ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H\r
+\r
+    if( fgDisplay.pDisplay.DisplayModeValid )\r
+    {\r
+        int x, y;\r
+        Window child;\r
+\r
+        /* Change to viewport to the window topleft edge: */\r
+        if( !XF86VidModeSetViewPort( fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, 0, 0 ) )\r
+            fgWarning( "XF86VidModeSetViewPort failed" );\r
+\r
+        /*\r
+         * Final window repositioning: It could be avoided using an undecorated\r
+         * window using override_redirect, but this * would possily require\r
+         * more changes and investigation.\r
+         */\r
+\r
+        /* Get the current postion of the drawable area on screen */\r
+        XTranslateCoordinates(\r
+            fgDisplay.pDisplay.Display,\r
+            fgStructure.CurrentWindow->Window.Handle,\r
+            fgDisplay.pDisplay.RootWindow,\r
+            0, 0, &x, &y,\r
+            &child\r
+        );\r
+\r
+        /* Move the decorataions out of the topleft corner of the display */\r
+        XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,\r
+                     -x, -y);\r
+    }\r
+\r
+#endif\r
+\r
+    /* Grab the keyboard, too */\r
+    XGrabKeyboard(\r
+        fgDisplay.pDisplay.Display,\r
+        fgStructure.GameModeWindow->Window.Handle,\r
+        FALSE,\r
+        GrabModeAsync, GrabModeAsync,\r
+        CurrentTime\r
+    );\r
+\r
+}\r
+\r
+void fgPlatformLeaveGameMode( void ) \r
+{\r
+    XUngrabPointer( fgDisplay.pDisplay.Display, CurrentTime );\r
+    XUngrabKeyboard( fgDisplay.pDisplay.Display, CurrentTime );\r
+}\r
+\r