Search code examples
clinuxxlibxrandr

Possible resolutions with multiple displays using Xinerama


I am trying to list all the displays with Xinerama and Xrandr. This is the code that should do it:

int i, j, screenCount, sizeCount, eventBase, errorBase;
char displayName[64];
DIR *dir;
struct dirent *direntry;
XRRScreenSize *sizes;
XRRScreenConfiguration *screenConfig;
XineramaScreenInfo *xineramaInfo;
Display *disp;
Window root;

dir = opendir("/tmp/.X11-unix");
while((direntry = readdir(dir)) != NULL){
    if(direntry->d_name[0] != 'X'){
        continue;
    }
    snprintf(displayName, 64, ":%s", direntry->d_name + 1);
    disp = XOpenDisplay(displayName);
    if(disp != NULL){
        if(XineramaQueryExtension(disp, &eventBase, &errorBase) && XineramaIsActive(disp)){
            xineramaInfo = XineramaQueryScreens(disp, &screenCount);
        }else{
            break;
        }
        printf("Display %s has %d screens\n", displayName, screenCount);
        for(i = 0; i < screenCount; i++){
            root = RootWindow(disp, i);
            screenConfig = XRRGetScreenInfo(disp, root);
            sizes = XRRConfigSizes(screenConfig, &sizeCount);
            for(j = 0; j < sizeCount; j++){
                printf("%d x %d\n", sizes[j].width, sizes[j].height);
            }
        }
        XCloseDisplay(disp);
        XFree(xineramaInfo);
    }
}

But it throws the following error:

Display :0 has 3 screens
1680 x 1050
1600 x 1200
1280 x 1024
1024 x 768
832 x 624
800 x 600
640 x 480
720 x 400
X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  140 (RANDR)
  Minor opcode of failed request:  5 (RRGetScreenInfo)
  Resource id in failed request:  0x18
  Serial number of failed request:  16
  Current serial number in output stream:  16

Is there something wrong with my code or is it not possible to list all the resolutions from all the displays with Xinerama?


Solution

  • After a long look at the source from Xrandr I found the solution:

    bool findResolutions(Display *display)
    {
        int i, j, k, eventBase, errorBase;
        Window root;
        XRRScreenResources *resources;
        XRROutputInfo *outputInfo;
    
        if(!XineramaQueryExtension(display, &eventBase, &errorBase) || !XineramaIsActive(display)){
            printf("Xinerama not supported or active\n");
            return false;
        }
    
        root = RootWindow(display, 0);
        resources = XRRGetScreenResources(display, root);
    
        for(i = 0; i < resources->noutput; i++){
            outputInfo = XRRGetOutputInfo(display, resources, resources->outputs[i]);
            for(j = 0; j < outputInfo->nmode; j++){
                for(k = 0; k < resources->nmode; k++){
                    if(outputInfo->modes[j] == resources->modes[k].id){
                        printf("%dx%d", resources->modes[k].width, resources->modes[k].height);
                        break;
                    }
                }
            }
    
            XRRFreeOutputInfo(outputInfo);
        }
    
        XRRFreeScreenResources(resources);
    
        return true;
    }