X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_gamemode.c;h=abee9c6ce28eb1302ff21c26f88d0cfb6796d93c;hb=67f09037126cd24e4cd3f48ab8e04ed1cce4dfae;hp=d6c6a25642cd13c0c66d4b07c68ff8e0be7ab9af;hpb=646676b8dbf8ab504ac8a275fe9a63a403a3190b;p=freeglut diff --git a/src/freeglut_gamemode.c b/src/freeglut_gamemode.c index d6c6a25..abee9c6 100644 --- a/src/freeglut_gamemode.c +++ b/src/freeglut_gamemode.c @@ -59,16 +59,48 @@ 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: */ - 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 @@ -101,52 +133,71 @@ void fghRestoreState( void ) { #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; ihdisplay == 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; ihdisplay == 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; + } } } @@ -188,52 +239,48 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest ) */ # ifdef X_XF86VidModeGetAllModeLines - XF86VidModeModeInfo** displayModes; - int i, displayModesCount; - /* - * Query for all the display available... + * This is also used by applcations which check modes by calling + * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check: */ - XF86VidModeGetAllModeLines( - fgDisplay.Display, - fgDisplay.Screen, - &displayModesCount, - &displayModes - ); - - /* - * Check every of the modes looking for one that matches our demands - */ - for( i=0; ihdisplay, 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; ihdisplay, 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 ); + } } } @@ -299,7 +346,7 @@ GLboolean fghChangeDisplayMode( GLboolean haveToTest ) mode = displayModes; break; } - + /* * Switch to the next display mode, if any */ @@ -411,7 +458,7 @@ int FGAPIENTRY glutEnterGameMode( void ) */ if( fghChangeDisplayMode( FALSE ) == FALSE ) { - fgWarning( "failed to change screen settings" ); + fgWarning( "failed to change screen settings" ); return( FALSE ); } @@ -424,30 +471,85 @@ 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: */ - 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: */ - 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 */