Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/freeglut/src/x11/fg_gamemode_x11.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/freeglut/src/x11/fg_gamemode_x11.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,608 @@ +/* + * fg_gamemode_x11.c + * + * The game mode handling code. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, <olszta@sourceforge.net> + * Copied for Platform code by Evan Felix <karcaw at gmail.com> + * Creation date: Thur Feb 2 2012 + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <GL/freeglut.h> +#include "../fg_internal.h" + +/* we'll try to use XR&R if it's available at compile-time, and at runtime, and the user + * hasn't explicitly disabled it by setting the FREEGLUT_NO_XRANDR env-var. + */ +static int use_xrandr(void) +{ +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H + int event_base, error_base; + if(!XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) { + return 0; + } + if(getenv("FREEGLUT_NO_XRANDR")) { + return 0; + } + return 1; +#else + return 0; /* no compile-time support */ +#endif +} + +/* we'll try to use XF86VidMode if it's available at compile-time, and at runtime, and the + * user hasn't explicitly disabled it by setting the FREEGLUT_NO_XF86VM env-var. + */ +static int use_xf86vm(void) +{ +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + int event_base, error_base; + if(!XF86VidModeQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) { + return 0; + } + if(getenv("FREEGLUT_NO_XF86VM")) { + return 0; + } + return 1; +#else + return 0; /* no compile-time support */ +#endif +} + + +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H +static int xrandr_resize(int xsz, int ysz, int rate, int just_checking) +{ + int ver_major, ver_minor, use_rate; + XRRScreenConfiguration *xrr_config = 0; + Status result = -1; + + /* NOTE: we have already determined that XR&R is available and enabled before calling this */ + + XRRQueryVersion(fgDisplay.pDisplay.Display, &ver_major, &ver_minor); + + /* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and + * the user actually cares about it (rate > 0) + */ + use_rate = ( rate > 0 ) && ( ( ver_major > 1 ) || + ( ( ver_major == 1 ) && ( ver_minor >= 1 ) ) ); + + /* this loop is only so that the whole thing will be repeated if someone + * else changes video mode between our query of the current information and + * the attempt to change it. + */ + do { + XRRScreenSize *ssizes; + short *rates; + Rotation rot; + int i, ssizes_count, rates_count, curr, res_idx = -1; + Time timestamp, cfg_timestamp; + + if(xrr_config) { + XRRFreeScreenConfigInfo(xrr_config); + } + + if(!(xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) { + fgWarning("XRRGetScreenInfo failed"); + break; + } + ssizes = XRRConfigSizes(xrr_config, &ssizes_count); + curr = XRRConfigCurrentConfiguration(xrr_config, &rot); + timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp); + + /* if either of xsz or ysz are unspecified, use the current values */ + if(xsz <= 0) + xsz = fgState.GameModeSize.X = ssizes[curr].width; + if(ysz <= 0) + ysz = fgState.GameModeSize.Y = ssizes[curr].height; + + + if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) { + /* no need to switch, we're already in the requested resolution */ + res_idx = curr; + } else { + for(i=0; i<ssizes_count; i++) { + if(ssizes[i].width == xsz && ssizes[i].height == ysz) { + res_idx = i; + break; /* found it */ + } + } + } + if(res_idx == -1) + break; /* no matching resolution */ + +#if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) + if(use_rate) { + rate = fgState.GameModeRefresh; + + /* for the selected resolution, let's find out if there is + * a matching refresh rate available. + */ + rates = XRRConfigRates(xrr_config, res_idx, &rates_count); + + for(i=0; i<rates_count; i++) { + if(rates[i] == rate) { + break; + } + } + if(i == rates_count) { + break; /* no matching rate */ + } + } +#endif + + if(just_checking) { + result = 0; + break; + } + +#if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) + if(use_rate) + result = XRRSetScreenConfigAndRate(fgDisplay.pDisplay.Display, xrr_config, + fgDisplay.pDisplay.RootWindow, res_idx, rot, rate, timestamp); + else +#endif + result = XRRSetScreenConfig(fgDisplay.pDisplay.Display, xrr_config, + fgDisplay.pDisplay.RootWindow, res_idx, rot, timestamp); + + } while(result == RRSetConfigInvalidTime); + + if(xrr_config) { + XRRFreeScreenConfigInfo(xrr_config); + } + + if(result == 0) { + return 0; + } + + return -1; +} +#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ + +/* + * Remembers the current visual settings, so that + * we can change them and restore later... + */ +void fgPlatformRememberState( void ) +{ + /* + * Remember the current pointer location before going fullscreen + * for restoring it later: + */ + Window junk_window; + unsigned int junk_mask; + + XQueryPointer(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow, + &junk_window, &junk_window, + &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, + &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, &junk_mask); + +# ifdef HAVE_X11_EXTENSIONS_XRANDR_H + if(use_xrandr()) { + XRRScreenConfiguration *xrr_config; + XRRScreenSize *ssizes; + Rotation rot; + int ssize_count, curr; + + if((xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) { + ssizes = XRRConfigSizes(xrr_config, &ssize_count); + curr = XRRConfigCurrentConfiguration(xrr_config, &rot); + + fgDisplay.pDisplay.prev_xsz = ssizes[curr].width; + fgDisplay.pDisplay.prev_ysz = ssizes[curr].height; + fgDisplay.pDisplay.prev_refresh = -1; + +# if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) + if(fgState.GameModeRefresh != -1) { + fgDisplay.pDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config); + } +# endif + + fgDisplay.pDisplay.prev_size_valid = 1; + + XRRFreeScreenConfigInfo(xrr_config); + } + } +# endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ + + /* + * This highly depends on the XFree86 extensions, + * not approved as X Consortium standards + */ +# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + if(use_xf86vm()) { + /* + * Remember the current ViewPort location of the screen to be able to + * restore the ViewPort on LeaveGameMode(): + */ + if( !XF86VidModeGetViewPort( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + &fgDisplay.pDisplay.DisplayViewPortX, + &fgDisplay.pDisplay.DisplayViewPortY ) ) + fgWarning( "XF86VidModeGetViewPort failed" ); + + + /* Query the current display settings: */ + fgDisplay.pDisplay.DisplayModeValid = + XF86VidModeGetModeLine( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + &fgDisplay.pDisplay.DisplayModeClock, + &fgDisplay.pDisplay.DisplayMode + ); + + if( !fgDisplay.pDisplay.DisplayModeValid ) + fgWarning( "XF86VidModeGetModeLine failed" ); + } +# endif + +} + +/* + * Restores the previously remembered visual settings + */ +void fgPlatformRestoreState( void ) +{ + /* Restore the remembered pointer position: */ + XWarpPointer( + fgDisplay.pDisplay.Display, None, fgDisplay.pDisplay.RootWindow, 0, 0, 0, 0, + fgDisplay.pDisplay.DisplayPointerX, fgDisplay.pDisplay.DisplayPointerY + ); + +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H + if(use_xrandr()) { + if(fgDisplay.pDisplay.prev_size_valid) { + if(xrandr_resize(fgDisplay.pDisplay.prev_xsz, fgDisplay.pDisplay.prev_ysz, fgDisplay.pDisplay.prev_refresh, 0) != -1) { + fgDisplay.pDisplay.prev_size_valid = 0; +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + fgDisplay.pDisplay.DisplayModeValid = 0; +#endif + } + } + return; /* don't fall back to XF86VidMode if we have XR&R */ + } +#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ + + + +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + /* + * This highly depends on the XFree86 extensions, + * not approved as X Consortium standards + */ + if(use_xf86vm()) { + + if( fgDisplay.pDisplay.DisplayModeValid ) + { + XF86VidModeModeInfo** displayModes; + int i, displayModesCount; + + if( !XF86VidModeGetAllModeLines( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + &displayModesCount, + &displayModes ) ) + { + fgWarning( "XF86VidModeGetAllModeLines failed" ); + return; + } + + + /* + * Check every of the modes looking for one that matches our demands. + * If we find one, switch to it and restore the remembered viewport. + */ + for( i = 0; i < displayModesCount; i++ ) + { + if(displayModes[ i ]->hdisplay == fgDisplay.pDisplay.DisplayMode.hdisplay && + displayModes[ i ]->vdisplay == fgDisplay.pDisplay.DisplayMode.vdisplay && + displayModes[ i ]->dotclock == fgDisplay.pDisplay.DisplayModeClock ) + { + if( !XF86VidModeSwitchToMode( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + displayModes[ i ] ) ) + { + fgWarning( "XF86VidModeSwitchToMode failed" ); + break; + } + + if( !XF86VidModeSetViewPort( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + fgDisplay.pDisplay.DisplayViewPortX, + fgDisplay.pDisplay.DisplayViewPortY ) ) + fgWarning( "XF86VidModeSetViewPort failed" ); + + + /* + * 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 exits. + */ + XFlush( fgDisplay.pDisplay.Display ); + + fgDisplay.pDisplay.DisplayModeValid = 0; +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H + fgDisplay.pDisplay.prev_size_valid = 0; +#endif + break; + } + } + XFree( displayModes ); + } + } +#endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */ +} + +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + +/* + * Checks a single display mode settings against user's preferences. + */ +static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh ) +{ + /* The desired values should be stored in fgState structure... */ + return ( width == fgState.GameModeSize.X ) && + ( height == fgState.GameModeSize.Y ) && + ( depth == fgState.GameModeDepth ) && + ( refresh == fgState.GameModeRefresh ); +} + +/* + * Checks all display modes settings against user's preferences. + * Returns the mode number found or -1 if none could be found. + */ +static int fghCheckDisplayModes( GLboolean exactMatch, int displayModesCount, XF86VidModeModeInfo** displayModes ) +{ + int i; + for( i = 0; i < displayModesCount; i++ ) + { + /* Compute the displays refresh rate, dotclock comes in kHz. */ + int refresh = ( displayModes[ i ]->dotclock * 1000 ) / + ( displayModes[ i ]->htotal * displayModes[ i ]->vtotal ); + + if( fghCheckDisplayMode( displayModes[ i ]->hdisplay, + displayModes[ i ]->vdisplay, + fgState.GameModeDepth, + ( exactMatch ? refresh : fgState.GameModeRefresh ) ) ) { + if (!exactMatch) + { + /* Update the chosen refresh rate, otherwise a + * glutGameModeGet(GLUT_GAME_MODE_REFRESH_RATE) would not + * return the right values + */ + fgState.GameModeRefresh = refresh; + } + + return i; + } + } + return -1; +} + +#endif + +/* + * Changes the current display mode to match user's settings + */ +GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest ) +{ + GLboolean success = GL_FALSE; +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H + if(use_xrandr()) { + if(xrandr_resize(fgState.GameModeSize.X, fgState.GameModeSize.Y, + fgState.GameModeRefresh, haveToTest) != -1) { + return GL_TRUE; + } + return GL_FALSE; /* don't fall back to XF86VidMode */ + } +#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ + + + /* + * This highly depends on the XFree86 extensions, + * not approved as X Consortium standards + */ +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + if(use_xf86vm()) { + /* + * This is also used by applications which check modes by calling + * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check: + */ + if( haveToTest || fgDisplay.pDisplay.DisplayModeValid ) + { + XF86VidModeModeInfo** displayModes; + int i, displayModesCount; + + /* If we don't have a valid modeline in the display structure, which + * can happen if this is called from glutGameModeGet instead of + * glutEnterGameMode, then we need to query the current mode, to make + * unspecified settings to default to their current values. + */ + if(!fgDisplay.pDisplay.DisplayModeValid) { + if(!XF86VidModeGetModeLine(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, + &fgDisplay.pDisplay.DisplayModeClock, &fgDisplay.pDisplay.DisplayMode)) { + return success; + } + } + + if (fgState.GameModeSize.X == -1) + { + fgState.GameModeSize.X = fgDisplay.pDisplay.DisplayMode.hdisplay; + } + if (fgState.GameModeSize.Y == -1) + { + fgState.GameModeSize.Y = fgDisplay.pDisplay.DisplayMode.vdisplay; + } + if (fgState.GameModeDepth == -1) + { + /* can't get color depth from this, nor can we change it, do nothing + * TODO: get with XGetVisualInfo()? but then how to set? + */ + } + if (fgState.GameModeRefresh == -1) + { + /* Compute the displays refresh rate, dotclock comes in kHz. */ + int refresh = ( fgDisplay.pDisplay.DisplayModeClock * 1000 ) / + ( fgDisplay.pDisplay.DisplayMode.htotal * fgDisplay.pDisplay.DisplayMode.vtotal ); + + fgState.GameModeRefresh = refresh; + } + + /* query all possible display modes */ + if( !XF86VidModeGetAllModeLines( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + &displayModesCount, + &displayModes ) ) + { + fgWarning( "XF86VidModeGetAllModeLines failed" ); + return success; + } + + + /* + * Check every of the modes looking for one that matches our demands, + * ignoring the refresh rate if no exact match could be found. + */ + i = fghCheckDisplayModes( GL_TRUE, displayModesCount, displayModes ); + if( i < 0 ) { + i = fghCheckDisplayModes( GL_FALSE, displayModesCount, displayModes ); + } + success = ( i < 0 ) ? GL_FALSE : GL_TRUE; + + if( !haveToTest && success ) { + if( !XF86VidModeSwitchToMode( + fgDisplay.pDisplay.Display, + fgDisplay.pDisplay.Screen, + displayModes[ i ] ) ) + fgWarning( "XF86VidModeSwitchToMode failed" ); + } + + XFree( displayModes ); + } + } + +#endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */ + + return success; +} + + +void fgPlatformEnterGameMode( void ) +{ + + /* + * 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.pDisplay.Display, False ); + /* + * 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.pDisplay.Display, fgStructure.GameModeWindow->Window.Handle, + TRUE, + ButtonPressMask | ButtonReleaseMask | ButtonMotionMask + | PointerMotionMask, + GrabModeAsync, GrabModeAsync, + fgStructure.GameModeWindow->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.pDisplay.Display, + fgStructure.GameModeWindow->Window.Handle, + RevertToNone, + CurrentTime + ); + + /* Move the Pointer to the middle of the fullscreen window */ + XWarpPointer( + fgDisplay.pDisplay.Display, + None, + fgDisplay.pDisplay.RootWindow, + 0, 0, 0, 0, + fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2 + ); + +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H + if(use_xf86vm()) { + + if( fgDisplay.pDisplay.DisplayModeValid ) + { + int x, y; + Window child; + + /* Change to viewport to the window topleft edge: */ + if( !XF86VidModeSetViewPort( fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, 0, 0 ) ) + fgWarning( "XF86VidModeSetViewPort failed" ); + + /* + * 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 position of the drawable area on screen */ + XTranslateCoordinates( + fgDisplay.pDisplay.Display, + fgStructure.CurrentWindow->Window.Handle, + fgDisplay.pDisplay.RootWindow, + 0, 0, &x, &y, + &child + ); + + /* Move the decorataions out of the topleft corner of the display */ + XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, + -x, -y); + } + } + +#endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */ + + /* Grab the keyboard, too */ + XGrabKeyboard( + fgDisplay.pDisplay.Display, + fgStructure.GameModeWindow->Window.Handle, + FALSE, + GrabModeAsync, GrabModeAsync, + CurrentTime + ); + +} + +void fgPlatformLeaveGameMode( void ) +{ + XUngrabPointer( fgDisplay.pDisplay.Display, CurrentTime ); + XUngrabKeyboard( fgDisplay.pDisplay.Display, CurrentTime ); +} +
