(99) src/freeglut_window.c:67 Removed #included "mwmborder.c"
+*******************************************************************************************
+* Changes on 10 August 2003
+*******************************************************************************************
+
+(100) GameMode fixes: src/freeglut_gamemode.c src/freeglut_internal.h src/freeglut_window.c
+
+ src/freeglut_gamemode.c:
+ fghRememberState(): remember original XFree86 ViewPort
+ fghRememberState(): remember original pointer position
+ fghRestoreState(): restore original pointer position
+ fghRestoreState(): restore original XFree86 ViewPort
+ fghChangeDisplayMode(): fix glutGameModeGet(GLUT_GAME_MODE_POSSIBLE)
+ fghChangeDisplayMode(): remove superflous attempt to change ViewPort
+ glutEnterGameMode(): move special XMoveWindow() from generic code here
+ glutEnterGameMode(): call XSync() to avoid races with XPointer calls
+ glutEnterGameMode(): call to XWrapPointer() to ensure that the pointer is grabbed
+ glutEnterGameMode(): wait until window is viewable to avoid exit on XSetInputFocus
+ glutEnterGameMode(): move decorations away to fix fullscreen w/ max resolution
+
+ src/freeglut_internal.h:
+ struct tagSFG_Display: add fields for saving viewport and pointer position
+
+ src/freeglut_window.c:
+ fgOpenWindow(): remove obsolete special case for GameModeEnter()
+
*/
# 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:
*/
*/
void fghRestoreState( void )
{
+ /*
+ * Restore the remembered pointer position:
+ */
+ XWarpPointer(
+ fgDisplay.Display, None, fgDisplay.RootWindow, 0, 0, 0, 0,
+ fgDisplay.DisplayPointerX, fgDisplay.DisplayPointerY
+ );
+
#if TARGET_HOST_UNIX_X11
/*
displayModes[ i ]->dotclock == fgDisplay.DisplayModeClock )
{
/*
- * OKi, this is the display mode we have been looking for...
+ * OK, this is the display mode we have been looking for...
*/
XF86VidModeSwitchToMode(
fgDisplay.Display,
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);
+ /*
+ * 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
- if (fgDisplay.DisplayModeValid)
+ /*
+ * This is also used by applcations which check modes by calling
+ * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check:
+ */
+ if (haveToTest || fgDisplay.DisplayModeValid)
{
XF86VidModeModeInfo** displayModes;
int i, displayModesCount;
fgDisplay.Screen,
displayModes[ i ]
);
-
- /*
- * Set the viewport's origin to (0,0) (the game mode window's top-left corner)
- */
- XF86VidModeSetViewPort(
- fgDisplay.Display,
- fgDisplay.Screen,
- 0,
- 0
- );
-
/*
* Return successfull...
*/
#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(
- fgDisplay.Display,
- fgStructure.GameMode->Window.Handle,
- RevertToNone,
- CurrentTime
+ 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
);
/*
- * 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:
*/
- XGrabPointer(
+ 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.
+ */
+ 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
*/