Game mode fixes from Bernhard Kaindl and Eric Espie.
git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@163 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
parent
53988cfb1a
commit
9f2e97a2cc
@ -268,3 +268,28 @@ October 24, 2002:
|
||||
|
||||
(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()
|
||||
|
||||
|
@ -59,6 +59,34 @@ void fghRememberState( void )
|
||||
*/
|
||||
# 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:
|
||||
*/
|
||||
@ -103,6 +131,14 @@ void fghRememberState( void )
|
||||
*/
|
||||
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
|
||||
|
||||
/*
|
||||
@ -135,7 +171,7 @@ void fghRestoreState( void )
|
||||
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,
|
||||
@ -144,11 +180,19 @@ void fghRestoreState( void )
|
||||
);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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);
|
||||
|
||||
@ -195,7 +239,11 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
|
||||
*/
|
||||
# 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;
|
||||
@ -228,17 +276,6 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest )
|
||||
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...
|
||||
*/
|
||||
@ -434,8 +471,45 @@ int FGAPIENTRY glutEnterGameMode( void )
|
||||
|
||||
#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:
|
||||
*/
|
||||
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
|
||||
);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
XSetInputFocus(
|
||||
fgDisplay.Display,
|
||||
@ -444,20 +518,38 @@ int FGAPIENTRY glutEnterGameMode( void )
|
||||
CurrentTime
|
||||
);
|
||||
|
||||
# ifdef X_XF86VidModeSetViewPort
|
||||
|
||||
if (fgDisplay.DisplayModeValid) {
|
||||
int x, y;
|
||||
Window child;
|
||||
|
||||
/*
|
||||
* Confine the mouse pointer to the window's client area
|
||||
* Change to viewport to the window topleft edge:
|
||||
*/
|
||||
XGrabPointer(
|
||||
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.GameMode->Window.Handle,
|
||||
TRUE,
|
||||
ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|PointerMotionMask,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
fgStructure.GameMode->Window.Handle,
|
||||
None,
|
||||
CurrentTime
|
||||
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
|
||||
*/
|
||||
|
@ -269,6 +269,11 @@ struct tagSFG_Display
|
||||
int DisplayModeValid; /* Flag that indicates runtime status*/
|
||||
XF86VidModeModeLine DisplayMode; /* Current screen's display settings */
|
||||
int DisplayModeClock; /* The display mode's refresh rate */
|
||||
int DisplayViewPortX; /* saved X location of the viewport */
|
||||
int DisplayViewPortY; /* saved Y location of the viewport */
|
||||
int DisplayPointerX; /* saved X location of the pointer */
|
||||
int DisplayPointerY; /* saved Y location of the pointer */
|
||||
|
||||
#endif
|
||||
|
||||
#elif TARGET_HOST_WIN32
|
||||
|
@ -565,37 +565,6 @@ void fgOpenWindow( SFG_Window* window, const char* title, int x, int y, int w, i
|
||||
*/
|
||||
XMapWindow( fgDisplay.Display, window->Window.Handle );
|
||||
|
||||
/*
|
||||
* In game mode, move the viewport a bit to hide the decorations.
|
||||
* This code depends on the XFree86 video mode extensions.
|
||||
*/
|
||||
if( gameMode == TRUE )
|
||||
{
|
||||
/*
|
||||
* This somehow fixes the glutGet() GLUT_WINDOW_X and GLUT_WINDOW_Y problem...
|
||||
*/
|
||||
XMoveWindow( fgDisplay.Display, window->Window.Handle, x, y );
|
||||
|
||||
# ifdef X_XF86VidModeSetViewPort
|
||||
|
||||
/*
|
||||
* Set the newly created window as the current one...
|
||||
*/
|
||||
fgSetWindow( window );
|
||||
|
||||
/*
|
||||
* Move the viewport a bit down and right from top-left corner to hide the decorations
|
||||
*/
|
||||
XF86VidModeSetViewPort(
|
||||
fgDisplay.Display,
|
||||
fgDisplay.Screen,
|
||||
glutGet( GLUT_WINDOW_X ),
|
||||
glutGet( GLUT_WINDOW_Y )
|
||||
);
|
||||
|
||||
# endif
|
||||
}
|
||||
|
||||
#elif TARGET_HOST_WIN32
|
||||
|
||||
WNDCLASS wc;
|
||||
|
Reference in New Issue
Block a user