/** * Queries all the available modes in the display configuration. */ RRInfo() : _numSizes(0) { _conf = XRRGetScreenInfo(QX11Info::display(), QX11Info::appRootWindow()); if(!_conf) return; // Not available. // Let's see which modes are available. _sizes = XRRConfigSizes(_conf, &_numSizes); for(int i = 0; i < _numSizes; ++i) { int numRates = 0; short* rates = XRRConfigRates(_conf, i, &numRates); for(int k = 0; k < numRates; k++) { DisplayMode mode; de::zap(mode); mode.width = _sizes[i].width; mode.height = _sizes[i].height; mode.depth = displayDepth; mode.refreshRate = rates[k]; _modes.push_back(mode); } } ::Time prevConfTime; _confTime = XRRConfigTimes(_conf, &prevConfTime); }
/** * This method first resets the current resolution using RandR to wake up * the graphics driver, then sets the resolution requested if it is among * those offered by the driver. */ static void setSize(Display *pDisplay, uint32_t cx, uint32_t cy) { XRRScreenConfiguration *pConfig; XRRScreenSize *pSizes; int cSizes; pConfig = XRRGetScreenInfo(pDisplay, DefaultRootWindow(pDisplay)); /* Reset the current mode */ LogRelFlowFunc(("Setting size %ux%u\n", cx, cy)); if (pConfig) { pSizes = XRRConfigSizes(pConfig, &cSizes); unsigned uDist = UINT32_MAX; int iMode = -1; for (int i = 0; i < cSizes; ++i) { #define VBCL_SQUARE(x) (x) * (x) unsigned uThisDist = VBCL_SQUARE(pSizes[i].width - cx) + VBCL_SQUARE(pSizes[i].height - cy); LogRelFlowFunc(("Found size %dx%d, distance %u\n", pSizes[i].width, pSizes[i].height, uThisDist)); #undef VBCL_SQUARE if (uThisDist < uDist) { uDist = uThisDist; iMode = i; } } if (iMode >= 0) { Time config_timestamp = 0; XRRConfigTimes(pConfig, &config_timestamp); LogRelFlowFunc(("Setting new size %d\n", iMode)); XRRSetScreenConfig(pDisplay, pConfig, DefaultRootWindow(pDisplay), iMode, RR_Rotate_0, config_timestamp); } XRRFreeScreenConfigInfo(pConfig); } }
static int xrandr_resize(int xsz, int ysz, int rate, int just_checking) { #ifdef HAVE_X11_EXTENSIONS_XRANDR_H int event_base, error_base, ver_major, ver_minor, use_rate; XRRScreenConfiguration *xrr_config = 0; Status result = -1; /* must check at runtime for the availability of the extension */ if(!XRRQueryExtension(fgDisplay.Display, &event_base, &error_base)) { return -1; } XRRQueryVersion(fgDisplay.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.Display, fgDisplay.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.Display, xrr_config, fgDisplay.RootWindow, res_idx, rot, rate, timestamp); else #endif result = XRRSetScreenConfig(fgDisplay.Display, xrr_config, fgDisplay.RootWindow, res_idx, rot, timestamp); } while(result == RRSetConfigInvalidTime); if(xrr_config) { XRRFreeScreenConfigInfo(xrr_config); } if(result == 0) { return 0; } #endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ return -1; }