Programming OpenGL in Linux: Changing the Screen Resolution

From OpenGL.org
Jump to: navigation, search

Change Screen Resolution?

Some programs- probably games- may require to change the screen resolution, e.g. for performance reasons. The program could ask the user to change the screen resolution- which is, of course, bad style- or use the Xrandr extension (Xrandr stands for X Resize, Rotate and Reflection). There are two ways for using this extension:

Using the xrandr command line tool

First, make yourself familiar with the xrandr command. Calling xrandr without arguments lists all possible resolutions and frequencies. Using xrandr with the -s option selects a screen size from this list. Although this sounds like it is easy to use- which it surely is- note that xrandr is a command line tool. If you want to use it in your application, you have to call it twice: First, to get all possible resolution, directing the output to a temporary file. Then, parse the file to get all possible resolutions. Finally, call xrandr again with a certain resolution.

For those who do not know: Calling any command line tool from an application can be achieved with the system function (defined in stdlib.h). What you have to do could look like this:


#include<stdlib.h>

system("xrandr > resolutions.tmp"); // direct output to 'resolutions.tmp'

//
// retrieve possible resolutions from 'resolutions.tmp'
//

system("xrandr -s resolution_id"); // select a certain screen resolution

Using library functions

If your Linux System is set up properly, there should be a /usr/include/X11 directory (in which you find Xlib.h and other header files) and a subdirectory /usr/include/X11/extensions with Xrandr.h. Furthermore, the libXrandr.so library is needed. The following program shows how to use the Xrandr functions to get all possible screen resolutions and display frequencies:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<X11/Xlib.h>
#include<X11/extensions/Xrandr.h>

Display                 *dpy;
Window                  root;
int                     num_sizes;
XRRScreenSize           *xrrs;
XRRScreenConfiguration  *conf;
short                   possible_frequencies[64][64];
short                   original_rate;
Rotation                original_rotation;
SizeID                  original_size_id;

int main(int argc, char *argv[]){
 //
 //     CONNECT TO X-SERVER, GET ROOT WINDOW ID
 //
 dpy    = XOpenDisplay(NULL);
 root   = RootWindow(dpy, 0);
 //
 //     GET POSSIBLE SCREEN RESOLUTIONS
 //
 xrrs   = XRRSizes(dpy, 0, &num_sizes);
 //
 //     LOOP THROUGH ALL POSSIBLE RESOLUTIONS,
 //     GETTING THE SELECTABLE DISPLAY FREQUENCIES
 //
 for(int i = 0; i < num_sizes; i ++) {
        short   *rates;
        int     num_rates;

        printf("\n\t%2i : %4i x %4i   (%4imm x%4imm ) ", i, xrrs[i].width, xrrs[i].height, xrrs[i].mwidth, xrrs[i].mheight);

        rates = XRRRates(dpy, 0, i, &num_rates);

        for(int j = 0; j < num_rates; j ++) {
                possible_frequencies[i][j] = rates[j];
                printf("%4i ", rates[j]); } }

 printf("\n");
 //
 //     GET CURRENT RESOLUTION AND FREQUENCY
 //
 conf                   = XRRGetScreenInfo(dpy, root);
 original_rate          = XRRConfigCurrentRate(conf);
 original_size_id       = XRRConfigCurrentConfiguration(conf, &original_rotation);

 printf("\n\tCURRENT SIZE ID  : %i\n", original_size_id);
 printf("\tCURRENT ROTATION : %i \n", original_rotation);
 printf("\tCURRENT RATE     : %i Hz\n\n", original_rate);
 //
 //     CHANGE RESOLUTION
 //
 printf("\tCHANGED TO %i x %i PIXELS, %i Hz\n\n", xrrs[1].width, xrrs[1].height, possible_frequencies[1][0]);
 XRRSetScreenConfigAndRate(dpy, conf, root, 1, RR_Rotate_0, possible_frequencies[1][0], CurrentTime);
 //
 //     SLEEP A WHILE
 //
 usleep(6000000);
 //
 //     RESTORE ORIGINAL CONFIGURATION
 //
 printf("\tRESTORING %i x %i PIXELS, %i Hz\n\n", xrrs[original_size_id].width, xrrs[original_size_id].height, original_rate);
 XRRSetScreenConfigAndRate(dpy, conf, root, original_size_id, original_rotation, original_rate, CurrentTime);
 //
 //     EXIT
 //
 XCloseDisplay(dpy); }
//
//      gcc -o Xrandr Xrandr.cc -lX11 -lXrandr -lstdc++
//

The Program, with its comments, should explain itself: First all possible resolutions and frequencies are acquired. Then the original parameters are stored. The resolution is changed for some seconds, and finally, the original resolution is restored.