X11: Let XRandR respect multiple screens (DISPLAY=:0.0 vs :0.1, etc).
authorRyan C. Gordon
Tue, 17 Nov 2015 12:15:35 -0500
changeset 9920183936dd34d5
parent 9919 ac5490d5aefc
child 9921 8865d17947de
X11: Let XRandR respect multiple screens (DISPLAY=:0.0 vs :0.1, etc).
src/video/x11/SDL_x11modes.c
     1.1 --- a/src/video/x11/SDL_x11modes.c	Mon Nov 16 21:20:38 2015 -0800
     1.2 +++ b/src/video/x11/SDL_x11modes.c	Tue Nov 17 12:15:35 2015 -0500
     1.3 @@ -357,16 +357,12 @@
     1.4  int
     1.5  X11_InitModes_XRandR(_THIS)
     1.6  {
     1.7 -    /* In theory, you _could_ have multiple screens (like DISPLAY=:0.0
     1.8 -       and DISPLAY=:0.1) but no XRandR system we care about is like this,
     1.9 -       as all the physical displays would be separate XRandR "outputs" on
    1.10 -       the one X11 virtual "screen". So we don't use ScreenCount() here. */
    1.11 -
    1.12      SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    1.13      Display *dpy = data->display;
    1.14 +    const int screencount = ScreenCount(dpy);
    1.15 +    const int default_screen = DefaultScreen(dpy);
    1.16 +    RROutput primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, default_screen));
    1.17      Atom EDID = X11_XInternAtom(dpy, "EDID", False);
    1.18 -    const int screen = DefaultScreen(dpy);
    1.19 -    RROutput primary;
    1.20      XRRScreenResources *res = NULL;
    1.21      Uint32 pixelformat;
    1.22      XVisualInfo vinfo;
    1.23 @@ -374,120 +370,127 @@
    1.24      int looking_for_primary;
    1.25      int scanline_pad;
    1.26      int output;
    1.27 -    int i, n;
    1.28 -
    1.29 -    if (get_visualinfo(dpy, screen, &vinfo) < 0) {
    1.30 -        return -1;
    1.31 -    }
    1.32 -
    1.33 -    pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
    1.34 -    if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
    1.35 -        return SDL_SetError("Palettized video modes are no longer supported");
    1.36 -    }
    1.37 -
    1.38 -    scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
    1.39 -    pixmapformats = X11_XListPixmapFormats(dpy, &n);
    1.40 -    if (pixmapformats) {
    1.41 -        for (i = 0; i < n; ++i) {
    1.42 -            if (pixmapformats[i].depth == vinfo.depth) {
    1.43 -                scanline_pad = pixmapformats[i].scanline_pad;
    1.44 -                break;
    1.45 -            }
    1.46 -        }
    1.47 -        X11_XFree(pixmapformats);
    1.48 -    }
    1.49 -
    1.50 -    res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
    1.51 -    if (!res) {
    1.52 -        return -1;
    1.53 -    }
    1.54 -
    1.55 -    primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, screen));
    1.56 +    int screen, i, n;
    1.57  
    1.58      for (looking_for_primary = 1; looking_for_primary >= 0; looking_for_primary--) {
    1.59 -        for (output = 0; output < res->noutput; output++) {
    1.60 -            XRROutputInfo *output_info;
    1.61 -            int display_x, display_y;
    1.62 -            unsigned long display_mm_width, display_mm_height;
    1.63 -            SDL_DisplayData *displaydata;
    1.64 -            char display_name[128];
    1.65 -            SDL_DisplayMode mode;
    1.66 -            SDL_DisplayModeData *modedata;
    1.67 -            SDL_VideoDisplay display;
    1.68 -            RRMode modeID;
    1.69 -            RRCrtc output_crtc;
    1.70 -            XRRCrtcInfo *crtc;
    1.71 +        for (screen = 0; screen < screencount; screen++) {
    1.72  
    1.73 -            /* The primary output _should_ always be sorted first, but just in case... */
    1.74 -            if ((looking_for_primary && (res->outputs[output] != primary)) ||
    1.75 -                (!looking_for_primary && (res->outputs[output] == primary))) {
    1.76 +            /* we want the primary output first, and then skipped later. */
    1.77 +            if ((looking_for_primary && (screen != default_screen)) ||
    1.78 +                (!looking_for_primary && (screen == default_screen))) {
    1.79                  continue;
    1.80              }
    1.81  
    1.82 -            output_info = X11_XRRGetOutputInfo(dpy, res, res->outputs[output]);
    1.83 -            if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
    1.84 -                X11_XRRFreeOutputInfo(output_info);
    1.85 +            if (get_visualinfo(dpy, screen, &vinfo) < 0) {
    1.86 +                continue;  /* uh, skip this screen? */
    1.87 +            }
    1.88 +
    1.89 +            pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
    1.90 +            if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
    1.91 +                continue;  /* Palettized video modes are no longer supported */
    1.92 +            }
    1.93 +
    1.94 +            scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
    1.95 +            pixmapformats = X11_XListPixmapFormats(dpy, &n);
    1.96 +            if (pixmapformats) {
    1.97 +                for (i = 0; i < n; ++i) {
    1.98 +                    if (pixmapformats[i].depth == vinfo.depth) {
    1.99 +                        scanline_pad = pixmapformats[i].scanline_pad;
   1.100 +                        break;
   1.101 +                    }
   1.102 +                }
   1.103 +                X11_XFree(pixmapformats);
   1.104 +            }
   1.105 +
   1.106 +            res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
   1.107 +            if (!res) {
   1.108                  continue;
   1.109              }
   1.110  
   1.111 -            SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
   1.112 -            display_mm_width = output_info->mm_width;
   1.113 -            display_mm_height = output_info->mm_height;
   1.114 -            output_crtc = output_info->crtc;
   1.115 -            X11_XRRFreeOutputInfo(output_info);
   1.116 +            for (output = 0; output < res->noutput; output++) {
   1.117 +                XRROutputInfo *output_info;
   1.118 +                int display_x, display_y;
   1.119 +                unsigned long display_mm_width, display_mm_height;
   1.120 +                SDL_DisplayData *displaydata;
   1.121 +                char display_name[128];
   1.122 +                SDL_DisplayMode mode;
   1.123 +                SDL_DisplayModeData *modedata;
   1.124 +                SDL_VideoDisplay display;
   1.125 +                RRMode modeID;
   1.126 +                RRCrtc output_crtc;
   1.127 +                XRRCrtcInfo *crtc;
   1.128  
   1.129 -            crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
   1.130 -            if (!crtc) {
   1.131 -                continue;
   1.132 -            }
   1.133 +                /* The primary output _should_ always be sorted first, but just in case... */
   1.134 +                if ((looking_for_primary && ((screen != default_screen) || (res->outputs[output] != primary))) ||
   1.135 +                    (!looking_for_primary && (screen == default_screen) && (res->outputs[output] == primary))) {
   1.136 +                    continue;
   1.137 +                }
   1.138  
   1.139 -            SDL_zero(mode);
   1.140 -            modeID = crtc->mode;
   1.141 -            mode.w = crtc->width;
   1.142 -            mode.h = crtc->height;
   1.143 -            mode.format = pixelformat;
   1.144 +                output_info = X11_XRRGetOutputInfo(dpy, res, res->outputs[output]);
   1.145 +                if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
   1.146 +                    X11_XRRFreeOutputInfo(output_info);
   1.147 +                    continue;
   1.148 +                }
   1.149  
   1.150 -            display_x = crtc->x;
   1.151 -            display_y = crtc->y;
   1.152 -
   1.153 -            X11_XRRFreeCrtcInfo(crtc);
   1.154 +                SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
   1.155 +                display_mm_width = output_info->mm_width;
   1.156 +                display_mm_height = output_info->mm_height;
   1.157 +                output_crtc = output_info->crtc;
   1.158 +                X11_XRRFreeOutputInfo(output_info);
   1.159  
   1.160 -            displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
   1.161 -            if (!displaydata) {
   1.162 -                return SDL_OutOfMemory();
   1.163 -            }
   1.164 +                crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
   1.165 +                if (!crtc) {
   1.166 +                    continue;
   1.167 +                }
   1.168 +
   1.169 +                SDL_zero(mode);
   1.170 +                modeID = crtc->mode;
   1.171 +                mode.w = crtc->width;
   1.172 +                mode.h = crtc->height;
   1.173 +                mode.format = pixelformat;
   1.174  
   1.175 -            modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
   1.176 -            if (!modedata) {
   1.177 -                SDL_free(displaydata);
   1.178 -                return SDL_OutOfMemory();
   1.179 -            }
   1.180 -            modedata->xrandr_mode = modeID;
   1.181 -            mode.driverdata = modedata;
   1.182 +                display_x = crtc->x;
   1.183 +                display_y = crtc->y;
   1.184 +
   1.185 +                X11_XRRFreeCrtcInfo(crtc);
   1.186 +
   1.187 +                displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
   1.188 +                if (!displaydata) {
   1.189 +                    return SDL_OutOfMemory();
   1.190 +                }
   1.191 +
   1.192 +                modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
   1.193 +                if (!modedata) {
   1.194 +                    SDL_free(displaydata);
   1.195 +                    return SDL_OutOfMemory();
   1.196 +                }
   1.197 +                modedata->xrandr_mode = modeID;
   1.198 +                mode.driverdata = modedata;
   1.199  
   1.200 -            displaydata->screen = screen;
   1.201 -            displaydata->visual = vinfo.visual;
   1.202 -            displaydata->depth = vinfo.depth;
   1.203 -            displaydata->hdpi = ((float) mode.w) * 25.4f / display_mm_width;
   1.204 -            displaydata->vdpi = ((float) mode.h) * 25.4f / display_mm_height;
   1.205 -            displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
   1.206 -            displaydata->scanline_pad = scanline_pad;
   1.207 -            displaydata->x = display_x;
   1.208 -            displaydata->y = display_y;
   1.209 -            displaydata->use_xrandr = 1;
   1.210 -            displaydata->xrandr_output = res->outputs[output];
   1.211 +                displaydata->screen = screen;
   1.212 +                displaydata->visual = vinfo.visual;
   1.213 +                displaydata->depth = vinfo.depth;
   1.214 +                displaydata->hdpi = ((float) mode.w) * 25.4f / display_mm_width;
   1.215 +                displaydata->vdpi = ((float) mode.h) * 25.4f / display_mm_height;
   1.216 +                displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
   1.217 +                displaydata->scanline_pad = scanline_pad;
   1.218 +                displaydata->x = display_x;
   1.219 +                displaydata->y = display_y;
   1.220 +                displaydata->use_xrandr = 1;
   1.221 +                displaydata->xrandr_output = res->outputs[output];
   1.222  
   1.223 -            SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
   1.224 -            SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), res->outputs[output], display_mm_width, display_mm_height);
   1.225 +                SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
   1.226 +                SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), res->outputs[output], display_mm_width, display_mm_height);
   1.227  
   1.228 -            SDL_zero(display);
   1.229 -            if (*display_name) {
   1.230 -                display.name = display_name;
   1.231 +                SDL_zero(display);
   1.232 +                if (*display_name) {
   1.233 +                    display.name = display_name;
   1.234 +                }
   1.235 +                display.desktop_mode = mode;
   1.236 +                display.current_mode = mode;
   1.237 +                display.driverdata = displaydata;
   1.238 +                SDL_AddVideoDisplay(&display);
   1.239              }
   1.240 -            display.desktop_mode = mode;
   1.241 -            display.current_mode = mode;
   1.242 -            display.driverdata = displaydata;
   1.243 -            SDL_AddVideoDisplay(&display);
   1.244          }
   1.245      }
   1.246