X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffreeglut_gamemode.c;h=0813d4136a8859e8a2f8bd9c84ad6dbbccb741eb;hb=1a7b5b7702bcc093a613b02be7af4720f2618c79;hp=de6cbb42ccc69424b87368c9dfaea9c90d134cf4;hpb=d9b5d2cb3d40aedab449b1e7aa7a6f44fc40f4b4;p=freeglut diff --git a/src/freeglut_gamemode.c b/src/freeglut_gamemode.c index de6cbb4..0813d41 100644 --- a/src/freeglut_gamemode.c +++ b/src/freeglut_gamemode.c @@ -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, @@ -143,14 +179,22 @@ void fghRestoreState( void ) 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; } @@ -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,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( - 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 */