#include "config.h"
#endif
-#define G_LOG_DOMAIN "freeglut-gamemode"
-
#include "../include/GL/freeglut.h"
#include "freeglut_internal.h"
*/
# ifdef X_XF86VidModeGetModeLine
+
+ /*
+ * 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
+ );
+
+ /*
+ * 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
+ );
+ }
+
/*
* Query the current display settings:
*/
- XF86VidModeGetModeLine(
+ fgDisplay.DisplayModeValid =
+ XF86VidModeGetModeLine(
fgDisplay.Display,
fgDisplay.Screen,
&fgDisplay.DisplayModeClock,
&fgDisplay.DisplayMode
);
+ if (!fgDisplay.DisplayModeValid)
+ fgWarning( "Runtime use of XF86VidModeGetModeLine failed.\n" );
+
# else
# warning fghRememberState: missing XFree86 video mode extensions, game mode will not change screen resolution when activated
# endif
{
#if TARGET_HOST_UNIX_X11
- /*
- * This highly depends on the XFree86 extensions, not approved as X Consortium standards
- */
# ifdef X_XF86VidModeGetAllModeLines
-
- XF86VidModeModeInfo** displayModes;
- int i, displayModesCount;
-
/*
- * Query for all the display available...
+ * Restore the remembered pointer position:
*/
- XF86VidModeGetAllModeLines(
- fgDisplay.Display,
- fgDisplay.Screen,
- &displayModesCount,
- &displayModes
+ XWarpPointer(
+ fgDisplay.Display, None, fgDisplay.RootWindow, 0, 0, 0, 0,
+ fgDisplay.DisplayPointerX, fgDisplay.DisplayPointerY
);
/*
- * Check every of the modes looking for one that matches our demands
+ * This highly depends on the XFree86 extensions, not approved as X Consortium standards
*/
- for( i=0; i<displayModesCount; i++ )
+
+ if (fgDisplay.DisplayModeValid)
{
- if( displayModes[ i ]->hdisplay == fgDisplay.DisplayMode.hdisplay &&
- displayModes[ i ]->vdisplay == fgDisplay.DisplayMode.vdisplay &&
- displayModes[ i ]->dotclock == fgDisplay.DisplayModeClock )
+ XF86VidModeModeInfo** displayModes;
+ int i, displayModesCount;
+
+ /*
+ * Query for all the display available...
+ */
+ XF86VidModeGetAllModeLines(
+ fgDisplay.Display,
+ fgDisplay.Screen,
+ &displayModesCount,
+ &displayModes
+ );
+
+ /*
+ * Check every of the modes looking for one that matches our demands
+ */
+ for( i=0; i<displayModesCount; i++ )
{
- /*
- * OKi, this is the display mode we have been looking for...
- */
- XF86VidModeSwitchToMode(
- fgDisplay.Display,
- fgDisplay.Screen,
- displayModes[ i ]
- );
-
- /*
- * In case this will be the last X11 call we do before exit,
- * we've to flush the X11 output queue to be sure the command
- * is really brought onto it's way to the X server.
- * The application should not do this because it
- * would not be platform independent then.
- */
- XFlush(fgDisplay.Display);
-
- return;
+ if( displayModes[ i ]->hdisplay == fgDisplay.DisplayMode.hdisplay &&
+ displayModes[ i ]->vdisplay == fgDisplay.DisplayMode.vdisplay &&
+ displayModes[ i ]->dotclock == fgDisplay.DisplayModeClock )
+ {
+ /*
+ * OK, this is the display mode we have been looking for...
+ */
+ 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;
+ }
}
}
*/
# ifdef X_XF86VidModeGetAllModeLines
- XF86VidModeModeInfo** displayModes;
- int i, displayModesCount;
-
- /*
- * Query for all the display available...
- */
- XF86VidModeGetAllModeLines(
- fgDisplay.Display,
- fgDisplay.Screen,
- &displayModesCount,
- &displayModes
- );
-
/*
- * Check every of the modes looking for one that matches our demands
+ * This is also used by applcations which check modes by calling
+ * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check:
*/
- for( i=0; i<displayModesCount; i++ )
+ if (haveToTest || fgDisplay.DisplayModeValid)
{
- 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 ]
- );
+ XF86VidModeModeInfo** displayModes;
+ int i, displayModesCount;
- /*
- * Set the viewport's origin to (0,0) (the game mode window's top-left corner)
- */
- XF86VidModeSetViewPort(
- fgDisplay.Display,
- fgDisplay.Screen,
- 0,
- 0
- );
+ /*
+ * Query for all the display available...
+ */
+ XF86VidModeGetAllModeLines(
+ fgDisplay.Display,
+ fgDisplay.Screen,
+ &displayModesCount,
+ &displayModes
+ );
- /*
- * Return successfull...
- */
- return( TRUE );
+ /*
+ * Check every of the modes looking for one that matches our demands
+ */
+ 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 );
+ }
}
}
mode = displayModes;
break;
}
-
+
/*
* Switch to the next display mode, if any
*/
*/
if( fghChangeDisplayMode( FALSE ) == FALSE )
{
- fgWarning( "failed to change screen settings" );
+ fgWarning( "failed to change screen settings" );
return( FALSE );
}
#if TARGET_HOST_UNIX_X11
+ /* Move the window up to the topleft corner */
+ XMoveWindow(fgDisplay.Display, fgStructure.Window->Window.Handle, 0, 0);
+
/*
- * Move the mouse pointer over the game mode window
+ * Sync needed to avoid a real race, the Xserver must have really created
+ * the window before we can grab the pointer into it:
*/
- XSetInputFocus(
+ XSync(fgDisplay.Display, False);
+
+ /* Move the Pointer to the middle of the fullscreen window */
+ XWarpPointer(
fgDisplay.Display,
- fgStructure.GameMode->Window.Handle,
- RevertToNone,
- CurrentTime
+ None,
+ fgDisplay.RootWindow,
+ 0, 0, 0, 0,
+ fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2
);
/*
- * Confine the mouse pointer to the window's client area
+ * Grab the pointer to confine it into the window after the calls to
+ * XWrapPointer() which ensure that the pointer really enters the window.
+ *
+ * We also need to wait here until XGrabPointer() returns GrabSuccess,
+ * otherwise the new window is not viewable yet and if the next function
+ * (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);
+ }
+
+ /*
+ * Change input focus to the new window. This will exit the application
+ * if the new window is not viewable yet, see the XGrabPointer loop above.
*/
- XGrabPointer(
+ XSetInputFocus(
fgDisplay.Display,
fgStructure.GameMode->Window.Handle,
- TRUE,
- ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|PointerMotionMask,
- GrabModeAsync, GrabModeAsync,
- fgStructure.GameMode->Window.Handle,
- None,
+ RevertToNone,
CurrentTime
);
+# ifdef X_XF86VidModeSetViewPort
+
+ if (fgDisplay.DisplayModeValid) {
+ int x, y;
+ Window child;
+
+ /*
+ * Change to viewport to the window topleft edge:
+ */
+ XF86VidModeSetViewPort(fgDisplay.Display, fgDisplay.Screen, 0, 0);
+
+ /*
+ * 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);
+ }
+
+#endif
+
/*
* Grab the keyboard, too
*/