Rewritten X11 video mode support to directly set requested modes and exactly restore the desktop mode at shutdown.
authorSam Lantinga <slouken@libsdl.org>
Wed, 03 Oct 2012 18:56:29 -0700
changeset 6548fc9e6be24ca9
parent 6547 38bc368a3b87
child 6549 db16b819e1d1
Rewritten X11 video mode support to directly set requested modes and exactly restore the desktop mode at shutdown.
src/video/x11/SDL_x11modes.c
src/video/x11/SDL_x11modes.h
     1.1 --- a/src/video/x11/SDL_x11modes.c	Wed Oct 03 18:54:31 2012 -0700
     1.2 +++ b/src/video/x11/SDL_x11modes.c	Wed Oct 03 18:56:29 2012 -0700
     1.3 @@ -132,129 +132,6 @@
     1.4  
     1.5      return SDL_PIXELFORMAT_UNKNOWN;
     1.6  }
     1.7 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
     1.8 -static SDL_bool CheckXinerama(Display * display, int *major, int *minor);
     1.9 -#endif
    1.10 -
    1.11 -int
    1.12 -X11_InitModes(_THIS)
    1.13 -{
    1.14 -    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    1.15 -    int screen, screencount;
    1.16 -
    1.17 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
    1.18 -    int xinerama_major, xinerama_minor;
    1.19 -    XineramaScreenInfo * xinerama = NULL;
    1.20 -    /* Query Xinerama extention
    1.21 -     * NOTE: This works with Nvidia Twinview correctly, but you need version 302.17 (released on June 2012)
    1.22 -     *       or newer of the Nvidia binary drivers
    1.23 -     */
    1.24 -    if (CheckXinerama(data->display, &xinerama_major, &xinerama_minor)) {
    1.25 -        xinerama = XineramaQueryScreens(data->display, &screencount);
    1.26 -    }
    1.27 -    if (!xinerama) {
    1.28 -        screencount = ScreenCount(data->display);
    1.29 -    }
    1.30 -#else
    1.31 -    screencount = ScreenCount(data->display);
    1.32 -#endif
    1.33 -
    1.34 -    for (screen = 0; screen < screencount; ++screen) {
    1.35 -        XVisualInfo vinfo;
    1.36 -        SDL_VideoDisplay display;
    1.37 -        SDL_DisplayData *displaydata;
    1.38 -        SDL_DisplayMode mode;
    1.39 -        XPixmapFormatValues *pixmapFormats;
    1.40 -        int i, n;
    1.41 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
    1.42 -        if (xinerama) {
    1.43 -            if (get_visualinfo(data->display, 0, &vinfo) < 0) {
    1.44 -                continue;
    1.45 -            }
    1.46 -        }
    1.47 -        else {
    1.48 -            if (get_visualinfo(data->display, screen, &vinfo) < 0) {
    1.49 -                continue;
    1.50 -            }
    1.51 -        }
    1.52 -#else
    1.53 -        if (get_visualinfo(data->display, screen, &vinfo) < 0) {
    1.54 -            continue;
    1.55 -        }
    1.56 -#endif
    1.57 -
    1.58 -        mode.format = X11_GetPixelFormatFromVisualInfo(data->display, &vinfo);
    1.59 -        if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {
    1.60 -            /* We don't support palettized modes now */
    1.61 -            continue;
    1.62 -        }
    1.63 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
    1.64 -        if (xinerama) {
    1.65 -            mode.w = xinerama[screen].width;
    1.66 -            mode.h = xinerama[screen].height;
    1.67 -        }
    1.68 -        else {
    1.69 -            mode.w = DisplayWidth(data->display, screen);
    1.70 -            mode.h = DisplayHeight(data->display, screen);
    1.71 -        }
    1.72 -#else
    1.73 -        mode.w = DisplayWidth(data->display, screen);
    1.74 -        mode.h = DisplayHeight(data->display, screen);
    1.75 -#endif
    1.76 -        mode.refresh_rate = 0;
    1.77 -        mode.driverdata = NULL;
    1.78 -
    1.79 -        displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
    1.80 -        if (!displaydata) {
    1.81 -            continue;
    1.82 -        }
    1.83 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
    1.84 -        /* Most of SDL's calls to X11 are unwaware of Xinerama, and to X11 standard calls, when Xinerama is active,
    1.85 -         * there's only one screen available. So we force the screen number to zero and
    1.86 -         * let Xinerama specific code handle specific functionality using displaydata->xinerama_info
    1.87 -         */
    1.88 -        if (xinerama) {
    1.89 -            displaydata->screen = 0;
    1.90 -            displaydata->use_xinerama = xinerama_major * 100 + xinerama_minor;
    1.91 -            displaydata->xinerama_info = xinerama[screen];
    1.92 -            displaydata->xinerama_screen = screen;
    1.93 -        }
    1.94 -        else displaydata->screen = screen;
    1.95 -#else
    1.96 -        displaydata->screen = screen;
    1.97 -#endif
    1.98 -        displaydata->visual = vinfo.visual;
    1.99 -        displaydata->depth = vinfo.depth;
   1.100 -
   1.101 -        displaydata->scanline_pad = SDL_BYTESPERPIXEL(mode.format) * 8;
   1.102 -        pixmapFormats = XListPixmapFormats(data->display, &n);
   1.103 -        if (pixmapFormats) {
   1.104 -            for (i = 0; i < n; ++i) {
   1.105 -                if (pixmapFormats[i].depth == displaydata->depth) {
   1.106 -                    displaydata->scanline_pad = pixmapFormats[i].scanline_pad;
   1.107 -                    break;
   1.108 -                }
   1.109 -            }
   1.110 -            XFree(pixmapFormats);
   1.111 -        }
   1.112 -
   1.113 -        SDL_zero(display);
   1.114 -        display.desktop_mode = mode;
   1.115 -        display.current_mode = mode;
   1.116 -        display.driverdata = displaydata;
   1.117 -        SDL_AddVideoDisplay(&display);
   1.118 -    }
   1.119 -
   1.120 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.121 -    if (xinerama) XFree(xinerama);
   1.122 -#endif
   1.123 -
   1.124 -    if (_this->num_displays == 0) {
   1.125 -        SDL_SetError("No available displays");
   1.126 -        return -1;
   1.127 -    }
   1.128 -    return 0;
   1.129 -}
   1.130  
   1.131  /* Global for the error handler */
   1.132  int vm_event, vm_error = -1;
   1.133 @@ -296,7 +173,7 @@
   1.134          return SDL_FALSE;
   1.135      }
   1.136  #ifdef X11MODES_DEBUG
   1.137 -    printf("Xinerama available!\n");
   1.138 +    printf("Xinerama available at version %d.%d!\n", *major, *minor);
   1.139  #endif
   1.140      return SDL_TRUE;
   1.141  }
   1.142 @@ -335,7 +212,7 @@
   1.143          return SDL_FALSE;
   1.144      }
   1.145  #ifdef X11MODES_DEBUG
   1.146 -    printf("XRandR available!\n");
   1.147 +    printf("XRandR available at version %d.%d!\n", *major, *minor);
   1.148  #endif
   1.149      return SDL_TRUE;
   1.150  }
   1.151 @@ -343,16 +220,47 @@
   1.152  #define XRANDR_ROTATION_LEFT    (1 << 1)
   1.153  #define XRANDR_ROTATION_RIGHT   (1 << 3)
   1.154  
   1.155 -static void
   1.156 -get_xrandr_mode_size(XRRModeInfo *mode, Rotation rotation, int *w, int *h)
   1.157 +static int
   1.158 +CalculateXRandRRefreshRate(const XRRModeInfo *info)
   1.159 +{
   1.160 +    return (info->hTotal
   1.161 +            && info->vTotal) ? (1000 * info->dotClock / (info->hTotal *
   1.162 +                                                         info->vTotal)) : 0;
   1.163 +}
   1.164 +
   1.165 +static SDL_bool
   1.166 +SetXRandRModeInfo(Display *display, XRRScreenResources *res, XRROutputInfo *output_info,
   1.167 +                  RRMode modeID, SDL_DisplayMode *mode)
   1.168  {
   1.169 -    if (rotation & (XRANDR_ROTATION_LEFT|XRANDR_ROTATION_RIGHT)) {
   1.170 -        *w = mode->height;
   1.171 -        *h = mode->width;
   1.172 -    } else {
   1.173 -        *w = mode->width;
   1.174 -        *h = mode->height;
   1.175 +    int i;
   1.176 +    for (i = 0; i < res->nmode; ++i) {
   1.177 +        if (res->modes[i].id == modeID) {
   1.178 +            XRRCrtcInfo *crtc;
   1.179 +            Rotation rotation = 0;
   1.180 +            const XRRModeInfo *info = &res->modes[i];
   1.181 +
   1.182 +            crtc = XRRGetCrtcInfo(display, res, output_info->crtc);
   1.183 +            if (crtc) {
   1.184 +                rotation = crtc->rotation;
   1.185 +                XRRFreeCrtcInfo(crtc);
   1.186 +            }
   1.187 +
   1.188 +            if (rotation & (XRANDR_ROTATION_LEFT|XRANDR_ROTATION_RIGHT)) {
   1.189 +                mode->w = info->height;
   1.190 +                mode->h = info->width;
   1.191 +            } else {
   1.192 +                mode->w = info->width;
   1.193 +                mode->h = info->height;
   1.194 +            }
   1.195 +            mode->refresh_rate = CalculateXRandRRefreshRate(info);
   1.196 +            ((SDL_DisplayModeData*)mode->driverdata)->xrandr_mode = modeID;
   1.197 +#ifdef X11MODES_DEBUG
   1.198 +            printf("XRandR mode %d: %dx%d@%dHz\n", modeID, mode->w, mode->h, mode->refresh_rate);
   1.199 +#endif
   1.200 +            return SDL_TRUE;
   1.201 +        }
   1.202      }
   1.203 +    return SDL_FALSE;
   1.204  }
   1.205  #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
   1.206  
   1.207 @@ -391,7 +299,7 @@
   1.208          return SDL_FALSE;
   1.209      }
   1.210  #ifdef X11MODES_DEBUG
   1.211 -    printf("XVidMode available!\n");
   1.212 +    printf("XVidMode available at version %d.%d!\n", *major, *minor);
   1.213  #endif
   1.214      return SDL_TRUE;
   1.215  }
   1.216 @@ -423,62 +331,261 @@
   1.217  }
   1.218  
   1.219  static int
   1.220 -calculate_rate(XF86VidModeModeInfo * info)
   1.221 +CalculateXVidModeRefreshRate(const XF86VidModeModeInfo * info)
   1.222  {
   1.223      return (info->htotal
   1.224              && info->vtotal) ? (1000 * info->dotclock / (info->htotal *
   1.225                                                           info->vtotal)) : 0;
   1.226  }
   1.227  
   1.228 -static void
   1.229 -save_mode(Display * display, SDL_DisplayData * data)
   1.230 +SDL_bool
   1.231 +SetXVidModeModeInfo(const XF86VidModeModeInfo *info, SDL_DisplayMode *mode)
   1.232  {
   1.233 -    XF86VidModeGetModeInfo(display, data->screen,
   1.234 -                                    &data->saved_mode);
   1.235 -    XF86VidModeGetViewPort(display, data->screen,
   1.236 -                                    &data->saved_view.x,
   1.237 -                                    &data->saved_view.y);
   1.238 +    mode->w = info->hdisplay;
   1.239 +    mode->h = info->vdisplay;
   1.240 +    mode->refresh_rate = CalculateXVidModeRefreshRate(info);
   1.241 +    ((SDL_DisplayModeData*)mode->driverdata)->vm_mode = *info;
   1.242 +    return SDL_TRUE;
   1.243  }
   1.244 +#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
   1.245  
   1.246 -/*
   1.247 -static void
   1.248 -restore_mode(Display * display, SDL_DisplayData * data)
   1.249 +int
   1.250 +X11_InitModes(_THIS)
   1.251  {
   1.252 -    XF86VidModeModeInfo mode;
   1.253 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   1.254 +    int screen, screencount;
   1.255 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.256 +    int xinerama_major, xinerama_minor;
   1.257 +    int use_xinerama = 0;
   1.258 +    XineramaScreenInfo *xinerama = NULL;
   1.259 +#endif
   1.260 +#if SDL_VIDEO_DRIVER_X11_XRANDR
   1.261 +    int xrandr_major, xrandr_minor;
   1.262 +    int use_xrandr = 0;
   1.263 +    XRRScreenResources *res = NULL;
   1.264 +#endif
   1.265 +#if SDL_VIDEO_DRIVER_X11_XVIDMODE
   1.266 +    int vm_major, vm_minor;
   1.267 +    int use_vidmode = 0;
   1.268 +#endif
   1.269  
   1.270 -    if (XF86VidModeGetModeInfo(display, data->screen, &mode)) {
   1.271 -        if (SDL_memcmp(&mode, &data->saved_mode, sizeof(mode)) != 0) {
   1.272 -            XF86VidModeSwitchToMode(display, data->screen, &data->saved_mode);
   1.273 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.274 +    /* Query Xinerama extention
   1.275 +     * NOTE: This works with Nvidia Twinview correctly, but you need version 302.17 (released on June 2012)
   1.276 +     *       or newer of the Nvidia binary drivers
   1.277 +     */
   1.278 +    if (CheckXinerama(data->display, &xinerama_major, &xinerama_minor)) {
   1.279 +        xinerama = XineramaQueryScreens(data->display, &screencount);
   1.280 +        if (xinerama) {
   1.281 +            use_xinerama = xinerama_major * 100 + xinerama_minor;
   1.282          }
   1.283      }
   1.284 -    if ((data->saved_view.x != 0) || (data->saved_view.y != 0)) {
   1.285 -        XF86VidModeSetViewPort(display, data->screen,
   1.286 -                                        data->saved_view.x,
   1.287 -                                        data->saved_view.y);
   1.288 +    if (!xinerama) {
   1.289 +        screencount = ScreenCount(data->display);
   1.290 +    }
   1.291 +#else
   1.292 +    screencount = ScreenCount(data->display);
   1.293 +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
   1.294 +
   1.295 +#if SDL_VIDEO_DRIVER_X11_XRANDR
   1.296 +    /* require at least XRandR v1.2 */
   1.297 +    if (CheckXRandR(data->display, &xrandr_major, &xrandr_minor) &&
   1.298 +        (xrandr_major >= 2 || (xrandr_major == 1 && xrandr_minor >= 2))) {
   1.299 +        use_xrandr = xrandr_major * 100 + xrandr_minor;
   1.300 +    }
   1.301 +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
   1.302 +
   1.303 +#if SDL_VIDEO_DRIVER_X11_XVIDMODE
   1.304 +    if (CheckVidMode(data->display, &vm_major, &vm_minor)) {
   1.305 +        use_vidmode = vm_major * 100 + vm_minor;
   1.306      }
   1.307 +#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
   1.308 +
   1.309 +    for (screen = 0; screen < screencount; ++screen) {
   1.310 +        XVisualInfo vinfo;
   1.311 +        SDL_VideoDisplay display;
   1.312 +        SDL_DisplayData *displaydata;
   1.313 +        SDL_DisplayMode mode;
   1.314 +        SDL_DisplayModeData *modedata;
   1.315 +        XPixmapFormatValues *pixmapFormats;
   1.316 +        int i, n;
   1.317 +
   1.318 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.319 +        if (xinerama) {
   1.320 +            if (get_visualinfo(data->display, 0, &vinfo) < 0) {
   1.321 +                continue;
   1.322 +            }
   1.323 +        } else {
   1.324 +            if (get_visualinfo(data->display, screen, &vinfo) < 0) {
   1.325 +                continue;
   1.326 +            }
   1.327 +        }
   1.328 +#else
   1.329 +        if (get_visualinfo(data->display, screen, &vinfo) < 0) {
   1.330 +            continue;
   1.331 +        }
   1.332 +#endif
   1.333 +
   1.334 +        displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
   1.335 +        if (!displaydata) {
   1.336 +            continue;
   1.337 +        }
   1.338 +
   1.339 +        mode.format = X11_GetPixelFormatFromVisualInfo(data->display, &vinfo);
   1.340 +        if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {
   1.341 +            /* We don't support palettized modes now */
   1.342 +            SDL_free(displaydata);
   1.343 +            continue;
   1.344 +        }
   1.345 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.346 +        if (xinerama) {
   1.347 +            mode.w = xinerama[screen].width;
   1.348 +            mode.h = xinerama[screen].height;
   1.349 +        } else {
   1.350 +            mode.w = DisplayWidth(data->display, screen);
   1.351 +            mode.h = DisplayHeight(data->display, screen);
   1.352 +        }
   1.353 +#else
   1.354 +        mode.w = DisplayWidth(data->display, screen);
   1.355 +        mode.h = DisplayHeight(data->display, screen);
   1.356 +#endif
   1.357 +        mode.refresh_rate = 0;
   1.358 +
   1.359 +        modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
   1.360 +        if (!modedata) {
   1.361 +            SDL_free(displaydata);
   1.362 +            continue;
   1.363 +        }
   1.364 +        mode.driverdata = modedata;
   1.365 +
   1.366 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.367 +        /* Most of SDL's calls to X11 are unwaware of Xinerama, and to X11 standard calls, when Xinerama is active,
   1.368 +         * there's only one screen available. So we force the screen number to zero and
   1.369 +         * let Xinerama specific code handle specific functionality using displaydata->xinerama_info
   1.370 +         */
   1.371 +        if (use_xinerama) {
   1.372 +            displaydata->screen = 0;
   1.373 +            displaydata->use_xinerama = use_xinerama;
   1.374 +            displaydata->xinerama_info = xinerama[screen];
   1.375 +            displaydata->xinerama_screen = screen;
   1.376 +        }
   1.377 +        else displaydata->screen = screen;
   1.378 +#else
   1.379 +        displaydata->screen = screen;
   1.380 +#endif
   1.381 +        displaydata->visual = vinfo.visual;
   1.382 +        displaydata->depth = vinfo.depth;
   1.383 +
   1.384 +        displaydata->scanline_pad = SDL_BYTESPERPIXEL(mode.format) * 8;
   1.385 +        pixmapFormats = XListPixmapFormats(data->display, &n);
   1.386 +        if (pixmapFormats) {
   1.387 +            for (i = 0; i < n; ++i) {
   1.388 +                if (pixmapFormats[i].depth == displaydata->depth) {
   1.389 +                    displaydata->scanline_pad = pixmapFormats[i].scanline_pad;
   1.390 +                    break;
   1.391 +                }
   1.392 +            }
   1.393 +            XFree(pixmapFormats);
   1.394 +        }
   1.395 +
   1.396 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.397 +        if (use_xinerama) {
   1.398 +            displaydata->x = xinerama[screen].x_org;
   1.399 +            displaydata->y = xinerama[screen].y_org;
   1.400 +        }
   1.401 +        else
   1.402 +#endif
   1.403 +        {
   1.404 +            displaydata->x = 0;
   1.405 +            displaydata->y = 0;
   1.406 +        }
   1.407 +
   1.408 +#if SDL_VIDEO_DRIVER_X11_XRANDR
   1.409 +        if (use_xrandr) {
   1.410 +            res = XRRGetScreenResources(data->display, RootWindow(data->display, displaydata->screen));
   1.411 +        }
   1.412 +        if (res) {
   1.413 +            XRROutputInfo *output_info;
   1.414 +            XRRCrtcInfo *crtc;
   1.415 +            int output;
   1.416 +
   1.417 +            for (output = 0; output < res->noutput; output++) {
   1.418 +                output_info = XRRGetOutputInfo(data->display, res, res->outputs[output]);
   1.419 +                if (!output_info || output_info->connection == RR_Disconnected) {
   1.420 +                    XRRFreeOutputInfo(output_info);
   1.421 +                    continue;
   1.422 +                }
   1.423 +
   1.424 +                /* Is this the output that corresponds to the current screen?
   1.425 +                   We're checking the crtc position, but that may not be a valid test
   1.426 +                   in all cases.  Anybody want to give this some love?
   1.427 +                 */
   1.428 +                crtc = XRRGetCrtcInfo(data->display, res, output_info->crtc);
   1.429 +                if (!crtc || crtc->x != displaydata->x || crtc->y != displaydata->y) {
   1.430 +                    XRRFreeOutputInfo(output_info);
   1.431 +                    XRRFreeCrtcInfo(crtc);
   1.432 +                    continue;
   1.433 +                }
   1.434 +
   1.435 +                displaydata->use_xrandr = use_xrandr;
   1.436 +                displaydata->xrandr_output = res->outputs[output];
   1.437 +                SetXRandRModeInfo(data->display, res, output_info, crtc->mode, &mode);
   1.438 +
   1.439 +                XRRFreeOutputInfo(output_info);
   1.440 +                XRRFreeCrtcInfo(crtc);
   1.441 +                break;
   1.442 +            }
   1.443 +#ifdef X11MODES_DEBUG
   1.444 +            if (output == res->noutput) {
   1.445 +                printf("Couldn't find XRandR CRTC at %d,%d\n", displaydata->x, displaydata->y);
   1.446 +            }
   1.447 +#endif
   1.448 +            XRRFreeScreenResources(res);
   1.449 +        }
   1.450 +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
   1.451 +
   1.452 +#if SDL_VIDEO_DRIVER_X11_XVIDMODE
   1.453 +        if (!displaydata->use_xrandr &&
   1.454 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.455 +            (!displaydata->use_xinerama || displaydata->xinerama_info.screen_number == 0) &&
   1.456 +#endif
   1.457 +            use_vidmode) {
   1.458 +            displaydata->use_vidmode = use_vidmode;
   1.459 +            XF86VidModeGetModeInfo(data->display, screen, &modedata->vm_mode);
   1.460 +        }
   1.461 +#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
   1.462 +
   1.463 +        SDL_zero(display);
   1.464 +        display.desktop_mode = mode;
   1.465 +        display.current_mode = mode;
   1.466 +        display.driverdata = displaydata;
   1.467 +        SDL_AddVideoDisplay(&display);
   1.468 +    }
   1.469 +
   1.470 +#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.471 +    if (xinerama) XFree(xinerama);
   1.472 +#endif
   1.473 +
   1.474 +    if (_this->num_displays == 0) {
   1.475 +        SDL_SetError("No available displays");
   1.476 +        return -1;
   1.477 +    }
   1.478 +    return 0;
   1.479  }
   1.480 -*/
   1.481 -#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
   1.482  
   1.483  void
   1.484  X11_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display)
   1.485  {
   1.486      Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   1.487      SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
   1.488 -#if SDL_VIDEO_DRIVER_X11_XRANDR
   1.489 -    int xrandr_major, xrandr_minor;
   1.490 -    int nsizes, nrates;
   1.491 -    XRRScreenSize *sizes;
   1.492 -    short *rates;
   1.493 -#endif
   1.494  #if SDL_VIDEO_DRIVER_X11_XVIDMODE
   1.495 -    int vm_major, vm_minor;
   1.496      int nmodes;
   1.497      XF86VidModeModeInfo ** modes;
   1.498  #endif
   1.499      int screen_w;
   1.500      int screen_h;
   1.501      SDL_DisplayMode mode;
   1.502 +    SDL_DisplayModeData *modedata;
   1.503  
   1.504      /* Unfortunately X11 requires the window to be created with the correct
   1.505       * visual and depth ahead of time, but the SDL API allows you to create
   1.506 @@ -500,69 +607,51 @@
   1.507              mode.w = screen_w;
   1.508              mode.h = screen_h;
   1.509              mode.refresh_rate = 0;
   1.510 +            modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
   1.511 +            if (modedata) {
   1.512 +                *modedata = *(SDL_DisplayModeData *)sdl_display->desktop_mode.driverdata;
   1.513 +            }
   1.514 +            mode.driverdata = modedata;
   1.515              SDL_AddDisplayMode(sdl_display, &mode);
   1.516          }
   1.517 -
   1.518 -        /* Add the head xinerama mode */
   1.519 -        mode.w = data->xinerama_info.width;
   1.520 -        mode.h = data->xinerama_info.height;
   1.521 -        mode.refresh_rate = 0;
   1.522 -        SDL_AddDisplayMode(sdl_display, &mode);
   1.523      }
   1.524  #endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
   1.525  
   1.526  #if SDL_VIDEO_DRIVER_X11_XRANDR
   1.527 -    /* XRandR */
   1.528 -    /* require at least XRandR v1.0 (arbitrary) */
   1.529 -    if (CheckXRandR(display, &xrandr_major, &xrandr_minor)
   1.530 -        && xrandr_major >= 1) {
   1.531 -#ifdef X11MODES_DEBUG
   1.532 -        fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n",
   1.533 -                xrandr_major, xrandr_minor);
   1.534 -#endif
   1.535 +    if (data->use_xrandr) {
   1.536 +        XRRScreenResources *res;
   1.537  
   1.538 -        /* save the screen configuration since we must reference it
   1.539 -           each time we toggle modes.
   1.540 -         */
   1.541 -        data->screen_config =
   1.542 -            XRRGetScreenInfo(display, RootWindow(display, data->screen));
   1.543 +        res = XRRGetScreenResources (display, RootWindow(display, data->screen));
   1.544 +        if (res) {
   1.545 +            SDL_DisplayModeData *modedata;
   1.546 +            XRROutputInfo *output_info;
   1.547 +            int i;
   1.548  
   1.549 -        /* retrieve the list of resolution */
   1.550 -        sizes = XRRConfigSizes(data->screen_config, &nsizes);
   1.551 -        if (nsizes > 0) {
   1.552 -            int i, j;
   1.553 -            for (i = 0; i < nsizes; i++) {
   1.554 -                mode.w = sizes[i].width;
   1.555 -                mode.h = sizes[i].height;
   1.556 +            output_info = XRRGetOutputInfo(display, res, data->xrandr_output);
   1.557 +            if (output_info && output_info->connection != RR_Disconnected) {
   1.558 +                for (i = 0; i < output_info->nmode; ++i) {
   1.559 +                    modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
   1.560 +                    if (!modedata) {
   1.561 +                        continue;
   1.562 +                    }
   1.563 +                    mode.driverdata = modedata;
   1.564  
   1.565 -                rates = XRRConfigRates(data->screen_config, i, &nrates);
   1.566 -                for (j = 0; j < nrates; ++j) {
   1.567 -                    mode.refresh_rate = rates[j];
   1.568 -#ifdef X11MODES_DEBUG
   1.569 -                    fprintf(stderr,
   1.570 -                            "XRANDR: mode = %4d[%d], w = %4d, h = %4d, rate = %4d\n",
   1.571 -                            i, j, mode.w, mode.h, mode.refresh_rate);
   1.572 -#endif
   1.573 -                    SDL_AddDisplayMode(sdl_display, &mode);
   1.574 +                    if (SetXRandRModeInfo(display, res, output_info, output_info->modes[i], &mode)) {
   1.575 +                        SDL_AddDisplayMode(sdl_display, &mode);
   1.576 +                    } else {
   1.577 +                        SDL_free(modedata);
   1.578 +                    }
   1.579                  }
   1.580              }
   1.581 -
   1.582 -            data->use_xrandr = xrandr_major * 100 + xrandr_minor;
   1.583 -            data->saved_size =
   1.584 -                XRRConfigCurrentConfiguration(data->screen_config,
   1.585 -                                              &data->saved_rotation);
   1.586 -            data->saved_rate = XRRConfigCurrentRate(data->screen_config);
   1.587 +            XRRFreeOutputInfo(output_info);
   1.588 +            XRRFreeScreenResources(res);
   1.589          }
   1.590 +        return;
   1.591      }
   1.592  #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
   1.593  
   1.594  #if SDL_VIDEO_DRIVER_X11_XVIDMODE
   1.595 -    /* XVidMode */
   1.596 -    if (!data->use_xrandr &&
   1.597 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.598 -        (!data->use_xinerama || data->xinerama_info.screen_number == 0) &&
   1.599 -#endif
   1.600 -        CheckVidMode(display, &vm_major, &vm_minor) &&
   1.601 +    if (data->use_vidmode &&
   1.602          XF86VidModeGetAllModeLines(display, data->screen, &nmodes, &modes)) {
   1.603          int i;
   1.604  
   1.605 @@ -571,332 +660,37 @@
   1.606          for (i = 0; i < nmodes; ++i) {
   1.607              printf("Mode %d: %d x %d @ %d\n", i,
   1.608                     modes[i]->hdisplay, modes[i]->vdisplay,
   1.609 -                   calculate_rate(modes[i]));
   1.610 +                   CalculateXVidModeRefreshRate(modes[i]));
   1.611          }
   1.612  #endif
   1.613          for (i = 0; i < nmodes; ++i) {
   1.614 -            mode.w = modes[i]->hdisplay;
   1.615 -            mode.h = modes[i]->vdisplay;
   1.616 -            mode.refresh_rate = calculate_rate(modes[i]);
   1.617 -            SDL_AddDisplayMode(sdl_display, &mode);
   1.618 +            modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
   1.619 +            if (!modedata) {
   1.620 +                continue;
   1.621 +            }
   1.622 +            mode.driverdata = modedata;
   1.623 +
   1.624 +            if (SetXVidModeModeInfo(modes[i], &mode)) {
   1.625 +                SDL_AddDisplayMode(sdl_display, &mode);
   1.626 +            } else {
   1.627 +                SDL_free(modedata);
   1.628 +            }
   1.629          }
   1.630          XFree(modes);
   1.631 -
   1.632 -        data->use_vidmode = vm_major * 100 + vm_minor;
   1.633 -        save_mode(display, data);
   1.634 +        return;
   1.635      }
   1.636  #endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
   1.637  
   1.638      if (!data->use_xrandr && !data->use_vidmode) {
   1.639 -        mode.w = screen_w;
   1.640 -        mode.h = screen_h;
   1.641 -        mode.refresh_rate = 0;
   1.642 +        /* Add the desktop mode */
   1.643 +        mode = sdl_display->desktop_mode;
   1.644 +        modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
   1.645 +        if (modedata) {
   1.646 +            *modedata = *(SDL_DisplayModeData *)sdl_display->desktop_mode.driverdata;
   1.647 +        }
   1.648 +        mode.driverdata = modedata;
   1.649          SDL_AddDisplayMode(sdl_display, &mode);
   1.650      }
   1.651 -#ifdef X11MODES_DEBUG
   1.652 -    if (data->use_xinerama) {
   1.653 -        printf("Xinerama is enabled\n");
   1.654 -    }
   1.655 -
   1.656 -    if (data->use_xrandr) {
   1.657 -        printf("XRandR is enabled\n");
   1.658 -    }
   1.659 -
   1.660 -    if (data->use_vidmode) {
   1.661 -        printf("VidMode is enabled\n");
   1.662 -    }
   1.663 -#endif /* X11MODES_DEBUG */
   1.664 -}
   1.665 -
   1.666 -static void
   1.667 -get_real_resolution(Display * display, SDL_DisplayData * data, int *w, int *h,
   1.668 -                    int *rate)
   1.669 -{
   1.670 -#if SDL_VIDEO_DRIVER_X11_XRANDR
   1.671 -    if (data->use_xrandr) {
   1.672 -        int nsizes;
   1.673 -        XRRScreenSize *sizes;
   1.674 -
   1.675 -        sizes = XRRConfigSizes(data->screen_config, &nsizes);
   1.676 -        if (nsizes > 0) {
   1.677 -            int cur_size;
   1.678 -            Rotation cur_rotation;
   1.679 -
   1.680 -            cur_size =
   1.681 -                XRRConfigCurrentConfiguration(data->screen_config,
   1.682 -                                              &cur_rotation);
   1.683 -            *w = sizes[cur_size].width;
   1.684 -            *h = sizes[cur_size].height;
   1.685 -            *rate = XRRConfigCurrentRate(data->screen_config);
   1.686 -#ifdef X11MODES_DEBUG
   1.687 -            fprintf(stderr,
   1.688 -                    "XRANDR: get_real_resolution: w = %d, h = %d, rate = %d\n",
   1.689 -                    *w, *h, *rate);
   1.690 -#endif
   1.691 -            return;
   1.692 -        }
   1.693 -    }
   1.694 -#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
   1.695 -
   1.696 -#if SDL_VIDEO_DRIVER_X11_XVIDMODE
   1.697 -    if (data->use_vidmode) {
   1.698 -        XF86VidModeModeInfo mode;
   1.699 -
   1.700 -        if (XF86VidModeGetModeInfo(display, data->screen, &mode)) {
   1.701 -            *w = mode.hdisplay;
   1.702 -            *h = mode.vdisplay;
   1.703 -            *rate = calculate_rate(&mode);
   1.704 -            return;
   1.705 -        }
   1.706 -    }
   1.707 -#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
   1.708 -
   1.709 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.710 -    if (data->use_xinerama) {
   1.711 -        int screencount;
   1.712 -        XineramaScreenInfo *xinerama;
   1.713 -
   1.714 -        /* Update the current screen layout information */
   1.715 -        xinerama = XineramaQueryScreens(display, &screencount);
   1.716 -        if (xinerama && data->xinerama_screen < screencount) {
   1.717 -            data->xinerama_info = xinerama[data->xinerama_screen];
   1.718 -        }
   1.719 -        if (xinerama) XFree(xinerama);
   1.720 -
   1.721 -        *w = data->xinerama_info.width;
   1.722 -        *h = data->xinerama_info.height;
   1.723 -        *rate = 0;
   1.724 -        return;
   1.725 -    }
   1.726 -#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
   1.727 -
   1.728 -    *w = DisplayWidth(display, data->screen);
   1.729 -    *h = DisplayHeight(display, data->screen);
   1.730 -    *rate = 0;
   1.731 -}
   1.732 -
   1.733 -static void
   1.734 -set_best_resolution(Display * display, SDL_DisplayData * data, int w, int h,
   1.735 -                    int rate)
   1.736 -{
   1.737 -    int real_w, real_h, real_rate;
   1.738 -
   1.739 -    /* check current mode so we can avoid uneccessary mode changes */
   1.740 -    get_real_resolution(display, data, &real_w, &real_h, &real_rate);
   1.741 -
   1.742 -    if (w == real_w && h == real_h && (!rate || !real_rate || rate == real_rate)) {
   1.743 -        return;
   1.744 -    }
   1.745 -
   1.746 -#if SDL_VIDEO_DRIVER_X11_XRANDR
   1.747 -    if (data->use_xrandr) {
   1.748 -#ifdef X11MODES_DEBUG
   1.749 -        fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n",
   1.750 -                w, h);
   1.751 -#endif
   1.752 -        int i, nsizes, nrates;
   1.753 -        int best;
   1.754 -        int best_rate;
   1.755 -        XRRScreenSize *sizes;
   1.756 -        short *rates;
   1.757 -
   1.758 -#if SDL_VIDEO_DRIVER_X11_XINERAMA
   1.759 -        if (data->use_xrandr >= 102 && data->use_xinerama) {
   1.760 -            /* See http://cgit.freedesktop.org/xorg/app/xrandr/tree/xrandr.c for the rationale behind this */
   1.761 -            /* Note by Gabriel: the refresh rate is ignored in this code, and seeing that both xrandr
   1.762 -             * and nvidia-settings don't provide a way to set it when Xinerama is enabled, it may not be possible to set it */
   1.763 -            int screencount;
   1.764 -            XineramaScreenInfo * xinerama = NULL;
   1.765 -            XRRScreenResources  *res;
   1.766 -
   1.767 -            /* Update the current screen layout information */
   1.768 -            xinerama = XineramaQueryScreens(display, &screencount);
   1.769 -            if (xinerama && data->xinerama_screen < screencount) {
   1.770 -                data->xinerama_info = xinerama[data->xinerama_screen];
   1.771 -            }
   1.772 -            if (xinerama) XFree(xinerama);
   1.773 -
   1.774 -            res = XRRGetScreenResources (display, RootWindow(display, data->screen));
   1.775 -            if (res) {
   1.776 -                XRROutputInfo *output_info = NULL;
   1.777 -                XRRCrtcInfo *crtc = NULL;
   1.778 -                XRRModeInfo *mode_info, *best_mode_info = NULL;
   1.779 -                int mode_index = 0, output_mode_index = 0, output;
   1.780 -                int mode_w, mode_h, best_w = 0, best_h = 0;
   1.781 -
   1.782 -                for ( output = 0; output < res->noutput; output++) {
   1.783 -                    output_info = XRRGetOutputInfo (display, res, res->outputs[output]);
   1.784 -                    if (!output_info || !output_info->crtc) {
   1.785 -                        XRRFreeOutputInfo(output_info);
   1.786 -                        continue;
   1.787 -                    }
   1.788 -
   1.789 -                    crtc = XRRGetCrtcInfo (display, res, output_info->crtc);
   1.790 -                    if (!crtc || data->xinerama_info.x_org != crtc->x || data->xinerama_info.y_org != crtc->y) {
   1.791 -                        XRRFreeCrtcInfo(crtc);
   1.792 -                        continue;
   1.793 -                    }
   1.794 -
   1.795 -                    /* The CRT offset matches the Xinerama mode, let's hope it's the right one! */
   1.796 -#ifdef X11MODES_DEBUG
   1.797 -                    fprintf(stderr, "XRANDR: set_best_resolution, matched Xinerama screen %d to CRT %ld at %d,%d\n",
   1.798 -                        data->xinerama_info.screen_number, output_info->crtc, crtc->x, crtc->y);
   1.799 -#endif
   1.800 -                    /* Find out the best mode we can use */
   1.801 -                    for (mode_index = 0; mode_index < res->nmode; mode_index++) {
   1.802 -                        mode_info = &res->modes[mode_index];
   1.803 -                        get_xrandr_mode_size(mode_info, crtc->rotation, &mode_w, &mode_h);
   1.804 -                        if (mode_w >= w && mode_h >= h) {
   1.805 -                            /* This may be a useful mode, check out if it belongs to the correct output */
   1.806 -#ifdef X11MODES_DEBUG
   1.807 -                            fprintf(stderr, "Evaluating valid mode %d, w: %d, h: %d\n", mode_index, mode_info->width, mode_info->height);
   1.808 -#endif
   1.809 -                            for ( output_mode_index = 0; output_mode_index < output_info->nmode; output_mode_index++) {
   1.810 -                                if (output_info->modes[output_mode_index] == mode_info->id) {
   1.811 -                                    break;
   1.812 -                                }
   1.813 -                            }
   1.814 -                            if (output_mode_index < output_info->nmode) {
   1.815 -#ifdef X11MODES_DEBUG
   1.816 -                                fprintf(stderr, "Mode belongs to the desired output %d w: %d, h: %d, rotation: %x\n", mode_index, mode_info->width, mode_info->height, crtc->rotation);
   1.817 -#endif
   1.818 -                                /* We have a mode that belongs to the right output and that can contain the w,h required, see if it's smaller than the current one */
   1.819 -                                if ( !best_mode_info || mode_w < best_w || (mode_w == best_w && mode_h < best_h) ) {
   1.820 -                                    best_mode_info = mode_info;
   1.821 -                                    best_w = mode_w;
   1.822 -                                    best_h = mode_h;
   1.823 -                                }
   1.824 -                            }
   1.825 -#ifdef X11MODES_DEBUG
   1.826 -                            else {
   1.827 -                                fprintf(stderr, "Discarding mode because it does not belong to the desired output %d, w: %d, h: %d, rotation: %d\n", mode_index, mode_info->width, mode_info->height, crtc->rotation);
   1.828 -                            }
   1.829 -#endif
   1.830 -                        }
   1.831 -                    }
   1.832 -
   1.833 -                    if (best_mode_info) {
   1.834 -#ifdef X11MODES_DEBUG
   1.835 -                            fprintf(stderr, "XRANDR: set_best_resolution, setting mode w = %d, h = %d on output: %d, CRT with offsets: %d,%d for Xinerama screen: %d\n",
   1.836 -                                    best_mode_info->width, best_mode_info->height, output, crtc->x, crtc->y, data->xinerama_info.screen_number);
   1.837 -#endif
   1.838 -                        XGrabServer (display);
   1.839 -                        XRRSetCrtcConfig (display, res, output_info->crtc, CurrentTime,
   1.840 -                          crtc->x, crtc->y, best_mode_info->id, crtc->rotation,
   1.841 -                          &res->outputs[output], 1);
   1.842 -                        /* TODO: Handle screen rotations, should we call XRRSetCrtcTransform if Xrandr >=1.3 ? */
   1.843 -                        XUngrabServer (display);
   1.844 -                    } else {
   1.845 -                        /* If we reach here, we have found the right screen but no valid best mode */
   1.846 -                        SDL_SetError("The selected screen can't support a resolution of the size desired");
   1.847 -                    }
   1.848 -                    XRRFreeCrtcInfo(crtc);
   1.849 -                    XRRFreeOutputInfo(output_info);
   1.850 -                    break;
   1.851 -                }
   1.852 -                XRRFreeScreenResources(res);
   1.853 -            }
   1.854 -        }
   1.855 -        else
   1.856 -#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
   1.857 -        {
   1.858 -            /* Use older xrandr functions that don't play along very nicely with multi monitors setups */
   1.859 -            /* find the smallest resolution that is at least as big as the user requested */
   1.860 -            best = -1;
   1.861 -            sizes = XRRConfigSizes(data->screen_config, &nsizes);
   1.862 -            for (i = 0; i < nsizes; ++i) {
   1.863 -                if (sizes[i].width < w || sizes[i].height < h) {
   1.864 -                    continue;
   1.865 -                }
   1.866 -                if (sizes[i].width == w && sizes[i].height == h) {
   1.867 -                    best = i;
   1.868 -                    break;
   1.869 -                }
   1.870 -                if (best == -1 ||
   1.871 -                    (sizes[i].width < sizes[best].width) ||
   1.872 -                    (sizes[i].width == sizes[best].width
   1.873 -                     && sizes[i].height < sizes[best].height)) {
   1.874 -                    best = i;
   1.875 -                }
   1.876 -            }
   1.877 -
   1.878 -            if (best >= 0) {
   1.879 -                best_rate = 0;
   1.880 -                rates = XRRConfigRates(data->screen_config, best, &nrates);
   1.881 -                for (i = 0; i < nrates; ++i) {
   1.882 -                    if (rates[i] == rate) {
   1.883 -                        best_rate = rate;
   1.884 -                        break;
   1.885 -                    }
   1.886 -                    if (!rate) {
   1.887 -                        /* Higher is better, right? */
   1.888 -                        if (rates[i] > best_rate) {
   1.889 -                            best_rate = rates[i];
   1.890 -                        }
   1.891 -                    } else {
   1.892 -                        if (SDL_abs(rates[i] - rate) < SDL_abs(best_rate - rate)) {
   1.893 -                            best_rate = rates[i];
   1.894 -                        }
   1.895 -                    }
   1.896 -                }
   1.897 -                XRRSetScreenConfigAndRate(display, data->screen_config,
   1.898 -                                          RootWindow(display, data->screen), best,
   1.899 -                                          data->saved_rotation, best_rate,
   1.900 -                                          CurrentTime);
   1.901 -            }
   1.902 -        }
   1.903 -        return;
   1.904 -    }
   1.905 -#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
   1.906 -
   1.907 -#if SDL_VIDEO_DRIVER_X11_XVIDMODE
   1.908 -    if (data->use_vidmode) {
   1.909 -        XF86VidModeModeInfo ** modes;
   1.910 -        int i, nmodes;
   1.911 -        int best;
   1.912 -
   1.913 -        if (XF86VidModeGetAllModeLines(display, data->screen, &nmodes, &modes)) {
   1.914 -            best = -1;
   1.915 -            for (i = 0; i < nmodes; ++i) {
   1.916 -                if (modes[i]->hdisplay < w || modes[i]->vdisplay < h) {
   1.917 -                    continue;
   1.918 -                }
   1.919 -                if (best == -1 ||
   1.920 -                    (modes[i]->hdisplay < modes[best]->hdisplay) ||
   1.921 -                    (modes[i]->hdisplay == modes[best]->hdisplay
   1.922 -                     && modes[i]->vdisplay < modes[best]->vdisplay)) {
   1.923 -                    best = i;
   1.924 -                    continue;
   1.925 -                }
   1.926 -                if ((modes[i]->hdisplay == modes[best]->hdisplay) &&
   1.927 -                    (modes[i]->vdisplay == modes[best]->vdisplay)) {
   1.928 -                    if (!rate) {
   1.929 -                        /* Higher is better, right? */
   1.930 -                        if (calculate_rate(modes[i]) >
   1.931 -                            calculate_rate(modes[best])) {
   1.932 -                            best = i;
   1.933 -                        }
   1.934 -                    } else {
   1.935 -                        if (SDL_abs(calculate_rate(modes[i]) - rate) <
   1.936 -                            SDL_abs(calculate_rate(modes[best]) - rate)) {
   1.937 -                            best = i;
   1.938 -                        }
   1.939 -                    }
   1.940 -                }
   1.941 -            }
   1.942 -            if (best >= 0) {
   1.943 -#ifdef X11MODES_DEBUG
   1.944 -                printf("Best Mode %d: %d x %d @ %d\n", best,
   1.945 -                       modes[best]->hdisplay, modes[best]->vdisplay,
   1.946 -                       calculate_rate(modes[best]));
   1.947 -#endif
   1.948 -                XF86VidModeSwitchToMode(display, data->screen, modes[best]);
   1.949 -            }
   1.950 -            XFree(modes);
   1.951 -        }
   1.952 -        return;
   1.953 -    }
   1.954 -#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
   1.955  }
   1.956  
   1.957  int
   1.958 @@ -904,8 +698,57 @@
   1.959  {
   1.960      Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   1.961      SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
   1.962 +    SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata;
   1.963  
   1.964 -    set_best_resolution(display, data, mode->w, mode->h, mode->refresh_rate);
   1.965 +#if SDL_VIDEO_DRIVER_X11_XRANDR
   1.966 +    if (data->use_xrandr) {
   1.967 +        XRRScreenResources *res;
   1.968 +        XRROutputInfo *output_info;
   1.969 +        XRRCrtcInfo *crtc;
   1.970 +        Status status;
   1.971 +
   1.972 +        res = XRRGetScreenResources (display, RootWindow(display, data->screen));
   1.973 +        if (!res) {
   1.974 +            SDL_SetError("Couldn't get XRandR screen resources");
   1.975 +            return -1;
   1.976 +        }
   1.977 +
   1.978 +        output_info = XRRGetOutputInfo(display, res, data->xrandr_output);
   1.979 +        if (!output_info || output_info->connection == RR_Disconnected) {
   1.980 +            SDL_SetError("Couldn't get XRandR output info");
   1.981 +            XRRFreeScreenResources(res);
   1.982 +            return -1;
   1.983 +        }
   1.984 +
   1.985 +        crtc = XRRGetCrtcInfo(display, res, output_info->crtc);
   1.986 +        if (!crtc) {
   1.987 +            SDL_SetError("Couldn't get XRandR crtc info");
   1.988 +            XRRFreeOutputInfo(output_info);
   1.989 +            XRRFreeScreenResources(res);
   1.990 +            return -1;
   1.991 +        }
   1.992 +
   1.993 +        status = XRRSetCrtcConfig (display, res, output_info->crtc, CurrentTime,
   1.994 +          crtc->x, crtc->y, modedata->xrandr_mode, crtc->rotation,
   1.995 +          &data->xrandr_output, 1);
   1.996 +
   1.997 +        XRRFreeCrtcInfo(crtc);
   1.998 +        XRRFreeOutputInfo(output_info);
   1.999 +        XRRFreeScreenResources(res);
  1.1000 +
  1.1001 +        if (status != Success) {
  1.1002 +            SDL_SetError("XRRSetCrtcConfig failed");
  1.1003 +            return -1;
  1.1004 +        }
  1.1005 +    }
  1.1006 +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
  1.1007 +
  1.1008 +#if SDL_VIDEO_DRIVER_X11_XVIDMODE
  1.1009 +    if (data->use_vidmode) {
  1.1010 +        XF86VidModeSwitchToMode(display, data->screen, &modedata->vm_mode);
  1.1011 +    }
  1.1012 +#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
  1.1013 +
  1.1014      return 0;
  1.1015  }
  1.1016  
  1.1017 @@ -919,18 +762,23 @@
  1.1018  {
  1.1019      Display *display = ((SDL_VideoData *) _this->driverdata)->display;
  1.1020      SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
  1.1021 -    int real_rate;
  1.1022  
  1.1023 -    rect->x = 0;
  1.1024 -    rect->y = 0;
  1.1025 -    get_real_resolution(display, data, &rect->w, &rect->h, &real_rate);
  1.1026 +    rect->x = data->x;
  1.1027 +    rect->y = data->y;
  1.1028 +    rect->w = sdl_display->current_mode.w;
  1.1029 +    rect->h = sdl_display->current_mode.h;
  1.1030  
  1.1031  #if SDL_VIDEO_DRIVER_X11_XINERAMA
  1.1032 +    /* Get the real current bounds of the display */
  1.1033      if (data->use_xinerama) {
  1.1034 -        rect->x = data->xinerama_info.x_org;
  1.1035 -        rect->y = data->xinerama_info.y_org;
  1.1036 +        int screencount;
  1.1037 +        XineramaScreenInfo *xinerama = XineramaQueryScreens(display, &screencount);
  1.1038 +        if (xinerama) {
  1.1039 +            rect->x = xinerama[data->xinerama_screen].x_org;
  1.1040 +            rect->y = xinerama[data->xinerama_screen].y_org;
  1.1041 +        }
  1.1042      }
  1.1043 -#endif
  1.1044 +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
  1.1045      return 0;
  1.1046  }
  1.1047  
     2.1 --- a/src/video/x11/SDL_x11modes.h	Wed Oct 03 18:54:31 2012 -0700
     2.2 +++ b/src/video/x11/SDL_x11modes.h	Wed Oct 03 18:56:29 2012 -0700
     2.3 @@ -29,6 +29,8 @@
     2.4      Visual *visual;
     2.5      int depth;
     2.6      int scanline_pad;
     2.7 +    int x;
     2.8 +    int y;
     2.9  
    2.10      int use_xinerama;
    2.11      int use_xrandr;
    2.12 @@ -38,22 +40,25 @@
    2.13      XineramaScreenInfo xinerama_info;
    2.14      int xinerama_screen;
    2.15  #endif
    2.16 +
    2.17  #if SDL_VIDEO_DRIVER_X11_XRANDR
    2.18 -    XRRScreenConfiguration *screen_config;
    2.19 -    int saved_size;
    2.20 -    Rotation saved_rotation;
    2.21 -    short saved_rate;
    2.22 -#endif
    2.23 -#if SDL_VIDEO_DRIVER_X11_XVIDMODE
    2.24 -    XF86VidModeModeInfo saved_mode;
    2.25 -    struct
    2.26 -    {
    2.27 -        int x, y;
    2.28 -    } saved_view;
    2.29 +    RROutput xrandr_output;
    2.30  #endif
    2.31  
    2.32  } SDL_DisplayData;
    2.33  
    2.34 +typedef struct
    2.35 +{
    2.36 +#if SDL_VIDEO_DRIVER_X11_XRANDR
    2.37 +    RRMode xrandr_mode;
    2.38 +#endif
    2.39 +
    2.40 +#if SDL_VIDEO_DRIVER_X11_XVIDMODE
    2.41 +    XF86VidModeModeInfo vm_mode;
    2.42 +#endif
    2.43 +
    2.44 +} SDL_DisplayModeData;
    2.45 +
    2.46  extern int X11_InitModes(_THIS);
    2.47  extern void X11_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
    2.48  extern int X11_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);