src/video/x11/SDL_x11modes.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 07 Aug 2015 00:59:31 -0400
changeset 9832 5fa8cf552d05
parent 9815 1db11af8159e
child 9834 d3fa6d0d3793
permissions -rw-r--r--
X11: Fixed a memory leak when adding duplicate display modes.
slouken@1950
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9619
     3
  Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
slouken@1950
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1950
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1950
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1950
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@1950
    22
slouken@5481
    23
#if SDL_VIDEO_DRIVER_X11
slouken@5481
    24
slouken@6472
    25
#include "SDL_hints.h"
slouken@1950
    26
#include "SDL_x11video.h"
icculus@9319
    27
#include "SDL_timer.h"
slouken@6796
    28
#include "edid.h"
slouken@1950
    29
gabomdq@7678
    30
/* #define X11MODES_DEBUG */
slouken@6558
    31
slouken@6559
    32
/* I'm becoming more and more convinced that the application should never
slouken@6559
    33
 * use XRandR, and it's the window manager's responsibility to track and
slouken@6559
    34
 * manage display modes for fullscreen windows.  Right now XRandR is completely
slouken@6559
    35
 * broken with respect to window manager behavior on every window manager that
slouken@6559
    36
 * I can find.  For example, on Unity 3D if you show a fullscreen window while
slouken@6559
    37
 * the resolution is changing (within ~250 ms) your window will retain the
slouken@6559
    38
 * fullscreen state hint but be decorated and windowed.
slouken@6796
    39
 *
slouken@6796
    40
 * However, many people swear by it, so let them swear at it. :)
slouken@6558
    41
*/
gabomdq@7678
    42
/* #define XRANDR_DISABLED_BY_DEFAULT */
slouken@6558
    43
slouken@1950
    44
slouken@1950
    45
static int
slouken@1950
    46
get_visualinfo(Display * display, int screen, XVisualInfo * vinfo)
slouken@1950
    47
{
slouken@1950
    48
    const char *visual_id = SDL_getenv("SDL_VIDEO_X11_VISUALID");
slouken@1950
    49
    int depth;
slouken@1950
    50
slouken@1950
    51
    /* Look for an exact visual, if requested */
slouken@1950
    52
    if (visual_id) {
slouken@3697
    53
        XVisualInfo *vi, template;
slouken@3697
    54
        int nvis;
slouken@1950
    55
slouken@1950
    56
        SDL_zero(template);
slouken@1950
    57
        template.visualid = SDL_strtol(visual_id, NULL, 0);
icculus@7827
    58
        vi = X11_XGetVisualInfo(display, VisualIDMask, &template, &nvis);
slouken@1950
    59
        if (vi) {
slouken@1950
    60
            *vinfo = *vi;
icculus@7827
    61
            X11_XFree(vi);
slouken@1950
    62
            return 0;
slouken@1950
    63
        }
slouken@1950
    64
    }
slouken@3697
    65
slouken@1950
    66
    depth = DefaultDepth(display, screen);
slouken@5466
    67
    if ((X11_UseDirectColorVisuals() &&
icculus@7827
    68
         X11_XMatchVisualInfo(display, screen, depth, DirectColor, vinfo)) ||
icculus@7827
    69
        X11_XMatchVisualInfo(display, screen, depth, TrueColor, vinfo) ||
icculus@7827
    70
        X11_XMatchVisualInfo(display, screen, depth, PseudoColor, vinfo) ||
icculus@7827
    71
        X11_XMatchVisualInfo(display, screen, depth, StaticColor, vinfo)) {
slouken@1950
    72
        return 0;
slouken@1950
    73
    }
slouken@1950
    74
    return -1;
slouken@1950
    75
}
slouken@1950
    76
slouken@5182
    77
int
slouken@5182
    78
X11_GetVisualInfoFromVisual(Display * display, Visual * visual, XVisualInfo * vinfo)
slouken@5182
    79
{
slouken@5182
    80
    XVisualInfo *vi;
slouken@5182
    81
    int nvis;
slouken@5182
    82
icculus@7827
    83
    vinfo->visualid = X11_XVisualIDFromVisual(visual);
icculus@7827
    84
    vi = X11_XGetVisualInfo(display, VisualIDMask, vinfo, &nvis);
slouken@5182
    85
    if (vi) {
slouken@5182
    86
        *vinfo = *vi;
icculus@7827
    87
        X11_XFree(vi);
slouken@5182
    88
        return 0;
slouken@5182
    89
    }
slouken@5182
    90
    return -1;
slouken@5182
    91
}
slouken@5182
    92
slouken@5182
    93
Uint32
slouken@2874
    94
X11_GetPixelFormatFromVisualInfo(Display * display, XVisualInfo * vinfo)
slouken@2870
    95
{
slouken@2870
    96
    if (vinfo->class == DirectColor || vinfo->class == TrueColor) {
slouken@2870
    97
        int bpp;
slouken@2870
    98
        Uint32 Rmask, Gmask, Bmask, Amask;
slouken@2870
    99
slouken@2870
   100
        Rmask = vinfo->visual->red_mask;
slouken@2870
   101
        Gmask = vinfo->visual->green_mask;
slouken@2870
   102
        Bmask = vinfo->visual->blue_mask;
slouken@2870
   103
        if (vinfo->depth == 32) {
slouken@2870
   104
            Amask = (0xFFFFFFFF & ~(Rmask | Gmask | Bmask));
slouken@2870
   105
        } else {
slouken@2870
   106
            Amask = 0;
slouken@2870
   107
        }
slouken@2870
   108
slouken@2870
   109
        bpp = vinfo->depth;
slouken@2870
   110
        if (bpp == 24) {
slouken@2870
   111
            int i, n;
icculus@7827
   112
            XPixmapFormatValues *p = X11_XListPixmapFormats(display, &n);
slouken@2870
   113
            if (p) {
slouken@2870
   114
                for (i = 0; i < n; ++i) {
slouken@2870
   115
                    if (p[i].depth == 24) {
slouken@2870
   116
                        bpp = p[i].bits_per_pixel;
slouken@2870
   117
                        break;
slouken@2870
   118
                    }
slouken@2870
   119
                }
icculus@7827
   120
                X11_XFree(p);
slouken@2870
   121
            }
slouken@2870
   122
        }
slouken@2870
   123
slouken@2870
   124
        return SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
slouken@2870
   125
    }
slouken@2870
   126
slouken@2870
   127
    if (vinfo->class == PseudoColor || vinfo->class == StaticColor) {
slouken@2870
   128
        switch (vinfo->depth) {
slouken@2870
   129
        case 8:
slouken@2870
   130
            return SDL_PIXELTYPE_INDEX8;
slouken@2870
   131
        case 4:
slouken@2870
   132
            if (BitmapBitOrder(display) == LSBFirst) {
slouken@2870
   133
                return SDL_PIXELFORMAT_INDEX4LSB;
slouken@2870
   134
            } else {
slouken@2870
   135
                return SDL_PIXELFORMAT_INDEX4MSB;
slouken@2870
   136
            }
slouken@2870
   137
            break;
slouken@2870
   138
        case 1:
slouken@2870
   139
            if (BitmapBitOrder(display) == LSBFirst) {
slouken@2870
   140
                return SDL_PIXELFORMAT_INDEX1LSB;
slouken@2870
   141
            } else {
slouken@2870
   142
                return SDL_PIXELFORMAT_INDEX1MSB;
slouken@2870
   143
            }
slouken@2870
   144
            break;
slouken@2870
   145
        }
slouken@2870
   146
    }
slouken@2870
   147
slouken@2870
   148
    return SDL_PIXELFORMAT_UNKNOWN;
slouken@2870
   149
}
slouken@1950
   150
slouken@2873
   151
/* Global for the error handler */
slouken@2873
   152
int vm_event, vm_error = -1;
slouken@2873
   153
slouken@2873
   154
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@2873
   155
static SDL_bool
slouken@2874
   156
CheckXinerama(Display * display, int *major, int *minor)
slouken@2873
   157
{
icculus@6027
   158
    int event_base = 0;
icculus@6027
   159
    int error_base = 0;
slouken@2873
   160
    const char *env;
slouken@2873
   161
slouken@2873
   162
    /* Default the extension not available */
slouken@2873
   163
    *major = *minor = 0;
slouken@2873
   164
slouken@2873
   165
    /* Allow environment override */
slouken@6472
   166
    env = SDL_GetHint(SDL_HINT_VIDEO_X11_XINERAMA);
slouken@2873
   167
    if (env && !SDL_atoi(env)) {
slouken@6468
   168
#ifdef X11MODES_DEBUG
slouken@6472
   169
        printf("Xinerama disabled due to hint\n");
slouken@6468
   170
#endif
slouken@2873
   171
        return SDL_FALSE;
slouken@2873
   172
    }
slouken@2873
   173
slouken@5408
   174
    if (!SDL_X11_HAVE_XINERAMA) {
slouken@6468
   175
#ifdef X11MODES_DEBUG
slouken@6468
   176
        printf("Xinerama support not available\n");
slouken@6468
   177
#endif
slouken@5408
   178
        return SDL_FALSE;
slouken@5408
   179
    }
slouken@5408
   180
slouken@2873
   181
    /* Query the extension version */
icculus@7827
   182
    if (!X11_XineramaQueryExtension(display, &event_base, &error_base) ||
icculus@7827
   183
        !X11_XineramaQueryVersion(display, major, minor) ||
icculus@7827
   184
        !X11_XineramaIsActive(display)) {
slouken@6468
   185
#ifdef X11MODES_DEBUG
slouken@6468
   186
        printf("Xinerama not active on the display\n");
slouken@6468
   187
#endif
slouken@2873
   188
        return SDL_FALSE;
slouken@2873
   189
    }
slouken@6468
   190
#ifdef X11MODES_DEBUG
slouken@6548
   191
    printf("Xinerama available at version %d.%d!\n", *major, *minor);
slouken@6468
   192
#endif
slouken@2873
   193
    return SDL_TRUE;
slouken@2873
   194
}
icculus@9789
   195
icculus@9789
   196
/* !!! FIXME: remove this later. */
icculus@9789
   197
/* we have a weird bug where XineramaQueryScreens() throws an X error, so this
icculus@9789
   198
   is here to help track it down (and not crash, too!). */
icculus@9789
   199
static SDL_bool xinerama_triggered_error = SDL_FALSE;
icculus@9789
   200
static int
icculus@9789
   201
X11_XineramaFailed(Display * d, XErrorEvent * e)
icculus@9789
   202
{
icculus@9789
   203
    xinerama_triggered_error = SDL_TRUE;
icculus@9789
   204
    fprintf(stderr, "XINERAMA X ERROR: type=%d serial=%lu err=%u req=%u minor=%u\n",
icculus@9789
   205
            e->type, e->serial, (unsigned int) e->error_code,
icculus@9789
   206
            (unsigned int) e->request_code, (unsigned int) e->minor_code);
icculus@9789
   207
    fflush(stderr);
icculus@9789
   208
    return 0;
icculus@9789
   209
}
slouken@2873
   210
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
slouken@2873
   211
slouken@2873
   212
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@2873
   213
static SDL_bool
slouken@2874
   214
CheckXRandR(Display * display, int *major, int *minor)
slouken@2873
   215
{
slouken@2873
   216
    const char *env;
slouken@2873
   217
slouken@2873
   218
    /* Default the extension not available */
slouken@2873
   219
    *major = *minor = 0;
slouken@2873
   220
slouken@2873
   221
    /* Allow environment override */
slouken@6472
   222
    env = SDL_GetHint(SDL_HINT_VIDEO_X11_XRANDR);
slouken@6558
   223
#ifdef XRANDR_DISABLED_BY_DEFAULT
slouken@6558
   224
    if (!env || !SDL_atoi(env)) {
slouken@6558
   225
#ifdef X11MODES_DEBUG
slouken@6558
   226
        printf("XRandR disabled by default due to window manager issues\n");
slouken@6558
   227
#endif
slouken@6558
   228
        return SDL_FALSE;
slouken@6558
   229
    }
slouken@6558
   230
#else
slouken@2873
   231
    if (env && !SDL_atoi(env)) {
slouken@6468
   232
#ifdef X11MODES_DEBUG
slouken@6472
   233
        printf("XRandR disabled due to hint\n");
slouken@6468
   234
#endif
slouken@2873
   235
        return SDL_FALSE;
slouken@2873
   236
    }
slouken@6558
   237
#endif /* XRANDR_ENABLED_BY_DEFAULT */
slouken@2873
   238
slouken@2873
   239
    if (!SDL_X11_HAVE_XRANDR) {
slouken@6468
   240
#ifdef X11MODES_DEBUG
slouken@6468
   241
        printf("XRandR support not available\n");
slouken@6468
   242
#endif
slouken@2873
   243
        return SDL_FALSE;
slouken@2873
   244
    }
slouken@2873
   245
slouken@2873
   246
    /* Query the extension version */
icculus@7827
   247
    if (!X11_XRRQueryVersion(display, major, minor)) {
slouken@6468
   248
#ifdef X11MODES_DEBUG
slouken@6468
   249
        printf("XRandR not active on the display\n");
slouken@6468
   250
#endif
slouken@2873
   251
        return SDL_FALSE;
slouken@2873
   252
    }
slouken@6468
   253
#ifdef X11MODES_DEBUG
slouken@6548
   254
    printf("XRandR available at version %d.%d!\n", *major, *minor);
slouken@6468
   255
#endif
slouken@2873
   256
    return SDL_TRUE;
slouken@2873
   257
}
slouken@6537
   258
slouken@6537
   259
#define XRANDR_ROTATION_LEFT    (1 << 1)
slouken@6537
   260
#define XRANDR_ROTATION_RIGHT   (1 << 3)
slouken@6537
   261
slouken@6548
   262
static int
slouken@6548
   263
CalculateXRandRRefreshRate(const XRRModeInfo *info)
slouken@6537
   264
{
slouken@6548
   265
    return (info->hTotal
slouken@6551
   266
            && info->vTotal) ? (info->dotClock / (info->hTotal * info->vTotal)) : 0;
slouken@6548
   267
}
slouken@6548
   268
slouken@6548
   269
static SDL_bool
slouken@6548
   270
SetXRandRModeInfo(Display *display, XRRScreenResources *res, XRROutputInfo *output_info,
slouken@6548
   271
                  RRMode modeID, SDL_DisplayMode *mode)
slouken@6548
   272
{
slouken@6548
   273
    int i;
slouken@6548
   274
    for (i = 0; i < res->nmode; ++i) {
slouken@6548
   275
        if (res->modes[i].id == modeID) {
slouken@6548
   276
            XRRCrtcInfo *crtc;
slouken@6548
   277
            Rotation rotation = 0;
slouken@6548
   278
            const XRRModeInfo *info = &res->modes[i];
slouken@6548
   279
icculus@7827
   280
            crtc = X11_XRRGetCrtcInfo(display, res, output_info->crtc);
slouken@6548
   281
            if (crtc) {
slouken@6548
   282
                rotation = crtc->rotation;
icculus@7827
   283
                X11_XRRFreeCrtcInfo(crtc);
slouken@6548
   284
            }
slouken@6548
   285
slouken@6548
   286
            if (rotation & (XRANDR_ROTATION_LEFT|XRANDR_ROTATION_RIGHT)) {
slouken@6548
   287
                mode->w = info->height;
slouken@6548
   288
                mode->h = info->width;
slouken@6548
   289
            } else {
slouken@6548
   290
                mode->w = info->width;
slouken@6548
   291
                mode->h = info->height;
slouken@6548
   292
            }
slouken@6548
   293
            mode->refresh_rate = CalculateXRandRRefreshRate(info);
slouken@6548
   294
            ((SDL_DisplayModeData*)mode->driverdata)->xrandr_mode = modeID;
slouken@6548
   295
#ifdef X11MODES_DEBUG
icculus@6560
   296
            printf("XRandR mode %d: %dx%d@%dHz\n", (int) modeID, mode->w, mode->h, mode->refresh_rate);
slouken@6548
   297
#endif
slouken@6548
   298
            return SDL_TRUE;
slouken@6548
   299
        }
slouken@6537
   300
    }
slouken@6548
   301
    return SDL_FALSE;
slouken@6537
   302
}
slouken@2873
   303
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
slouken@2873
   304
slouken@5408
   305
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@2873
   306
static SDL_bool
slouken@2874
   307
CheckVidMode(Display * display, int *major, int *minor)
slouken@2873
   308
{
slouken@2873
   309
    const char *env;
slouken@2873
   310
slouken@2873
   311
    /* Default the extension not available */
slouken@2873
   312
    *major = *minor = 0;
slouken@2873
   313
slouken@2873
   314
    /* Allow environment override */
slouken@6472
   315
    env = SDL_GetHint(SDL_HINT_VIDEO_X11_XVIDMODE);
slouken@2873
   316
    if (env && !SDL_atoi(env)) {
slouken@6468
   317
#ifdef X11MODES_DEBUG
slouken@6472
   318
        printf("XVidMode disabled due to hint\n");
slouken@6468
   319
#endif
slouken@2873
   320
        return SDL_FALSE;
slouken@2873
   321
    }
slouken@2874
   322
slouken@5408
   323
    if (!SDL_X11_HAVE_XVIDMODE) {
slouken@6468
   324
#ifdef X11MODES_DEBUG
slouken@6468
   325
        printf("XVidMode support not available\n");
slouken@6468
   326
#endif
slouken@5408
   327
        return SDL_FALSE;
slouken@5408
   328
    }
slouken@5408
   329
slouken@2873
   330
    /* Query the extension version */
slouken@2873
   331
    vm_error = -1;
icculus@7827
   332
    if (!X11_XF86VidModeQueryExtension(display, &vm_event, &vm_error)
icculus@7827
   333
        || !X11_XF86VidModeQueryVersion(display, major, minor)) {
slouken@6468
   334
#ifdef X11MODES_DEBUG
slouken@6468
   335
        printf("XVidMode not active on the display\n");
slouken@6468
   336
#endif
slouken@2873
   337
        return SDL_FALSE;
slouken@2873
   338
    }
slouken@6468
   339
#ifdef X11MODES_DEBUG
slouken@6548
   340
    printf("XVidMode available at version %d.%d!\n", *major, *minor);
slouken@6468
   341
#endif
slouken@2873
   342
    return SDL_TRUE;
slouken@2873
   343
}
slouken@2873
   344
slouken@4518
   345
static
slouken@5408
   346
Bool XF86VidModeGetModeInfo(Display * dpy, int scr,
slouken@5408
   347
                                       XF86VidModeModeInfo* info)
slouken@2873
   348
{
slouken@2873
   349
    Bool retval;
slouken@2873
   350
    int dotclock;
slouken@5408
   351
    XF86VidModeModeLine l;
slouken@2873
   352
    SDL_zerop(info);
slouken@2873
   353
    SDL_zero(l);
icculus@7827
   354
    retval = X11_XF86VidModeGetModeLine(dpy, scr, &dotclock, &l);
slouken@2873
   355
    info->dotclock = dotclock;
slouken@2873
   356
    info->hdisplay = l.hdisplay;
slouken@2873
   357
    info->hsyncstart = l.hsyncstart;
slouken@2873
   358
    info->hsyncend = l.hsyncend;
slouken@2873
   359
    info->htotal = l.htotal;
slouken@2873
   360
    info->hskew = l.hskew;
slouken@2873
   361
    info->vdisplay = l.vdisplay;
slouken@2873
   362
    info->vsyncstart = l.vsyncstart;
slouken@2873
   363
    info->vsyncend = l.vsyncend;
slouken@2873
   364
    info->vtotal = l.vtotal;
slouken@2873
   365
    info->flags = l.flags;
slouken@2873
   366
    info->privsize = l.privsize;
slouken@2873
   367
    info->private = l.private;
slouken@2873
   368
    return retval;
slouken@2873
   369
}
slouken@2873
   370
slouken@2873
   371
static int
slouken@6548
   372
CalculateXVidModeRefreshRate(const XF86VidModeModeInfo * info)
slouken@2873
   373
{
slouken@2874
   374
    return (info->htotal
slouken@2874
   375
            && info->vtotal) ? (1000 * info->dotclock / (info->htotal *
slouken@2874
   376
                                                         info->vtotal)) : 0;
slouken@2873
   377
}
slouken@2873
   378
slouken@6548
   379
SDL_bool
slouken@6548
   380
SetXVidModeModeInfo(const XF86VidModeModeInfo *info, SDL_DisplayMode *mode)
slouken@2873
   381
{
slouken@6548
   382
    mode->w = info->hdisplay;
slouken@6548
   383
    mode->h = info->vdisplay;
slouken@6548
   384
    mode->refresh_rate = CalculateXVidModeRefreshRate(info);
slouken@6548
   385
    ((SDL_DisplayModeData*)mode->driverdata)->vm_mode = *info;
slouken@6548
   386
    return SDL_TRUE;
slouken@2873
   387
}
slouken@6548
   388
#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
slouken@2873
   389
slouken@6548
   390
int
slouken@6548
   391
X11_InitModes(_THIS)
slouken@2873
   392
{
slouken@6548
   393
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
gabomdq@9167
   394
    int snum, screen, screencount;
slouken@6548
   395
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6548
   396
    int xinerama_major, xinerama_minor;
slouken@6548
   397
    int use_xinerama = 0;
slouken@6548
   398
    XineramaScreenInfo *xinerama = NULL;
slouken@6548
   399
#endif
slouken@6548
   400
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@6548
   401
    int xrandr_major, xrandr_minor;
slouken@6548
   402
    int use_xrandr = 0;
slouken@6548
   403
    XRRScreenResources *res = NULL;
slouken@6548
   404
#endif
slouken@6548
   405
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@6548
   406
    int vm_major, vm_minor;
slouken@6548
   407
    int use_vidmode = 0;
slouken@6548
   408
#endif
slouken@2873
   409
slouken@6548
   410
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6548
   411
    /* Query Xinerama extention
slouken@6548
   412
     * NOTE: This works with Nvidia Twinview correctly, but you need version 302.17 (released on June 2012)
slouken@6548
   413
     *       or newer of the Nvidia binary drivers
slouken@6548
   414
     */
slouken@6548
   415
    if (CheckXinerama(data->display, &xinerama_major, &xinerama_minor)) {
icculus@9789
   416
        int (*handler) (Display *, XErrorEvent *);
icculus@9789
   417
        X11_XSync(data->display, False);
icculus@9789
   418
        handler = X11_XSetErrorHandler(X11_XineramaFailed);
icculus@7827
   419
        xinerama = X11_XineramaQueryScreens(data->display, &screencount);
icculus@9789
   420
        X11_XSync(data->display, False);
icculus@9789
   421
        X11_XSetErrorHandler(handler);
icculus@9789
   422
        if (xinerama_triggered_error) {
icculus@9789
   423
            xinerama = 0;
icculus@9789
   424
        }
slouken@6548
   425
        if (xinerama) {
slouken@6548
   426
            use_xinerama = xinerama_major * 100 + xinerama_minor;
slouken@2873
   427
        }
slouken@2873
   428
    }
slouken@6548
   429
    if (!xinerama) {
slouken@6548
   430
        screencount = ScreenCount(data->display);
slouken@2873
   431
    }
slouken@6548
   432
#else
slouken@6548
   433
    screencount = ScreenCount(data->display);
slouken@6548
   434
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
slouken@6548
   435
slouken@6548
   436
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@6548
   437
    /* require at least XRandR v1.2 */
slouken@6548
   438
    if (CheckXRandR(data->display, &xrandr_major, &xrandr_minor) &&
slouken@6548
   439
        (xrandr_major >= 2 || (xrandr_major == 1 && xrandr_minor >= 2))) {
slouken@6548
   440
        use_xrandr = xrandr_major * 100 + xrandr_minor;
slouken@6548
   441
    }
slouken@6548
   442
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
slouken@6548
   443
slouken@6548
   444
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@6548
   445
    if (CheckVidMode(data->display, &vm_major, &vm_minor)) {
slouken@6548
   446
        use_vidmode = vm_major * 100 + vm_minor;
slouken@6548
   447
    }
slouken@6548
   448
#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
slouken@6548
   449
gabomdq@9167
   450
    for (snum = 0; snum < screencount; ++snum) {
slouken@6548
   451
        XVisualInfo vinfo;
slouken@6548
   452
        SDL_VideoDisplay display;
slouken@6548
   453
        SDL_DisplayData *displaydata;
slouken@6548
   454
        SDL_DisplayMode mode;
slouken@6548
   455
        SDL_DisplayModeData *modedata;
slouken@6548
   456
        XPixmapFormatValues *pixmapFormats;
slouken@6796
   457
        char display_name[128];
slouken@6548
   458
        int i, n;
slouken@6548
   459
gabomdq@9167
   460
        /* Re-order screens to always put default screen first */
gabomdq@9167
   461
        if (snum == 0) {
gabomdq@9167
   462
            screen = DefaultScreen(data->display);
gabomdq@9167
   463
        } else if (snum == DefaultScreen(data->display)) {
gabomdq@9167
   464
            screen = 0;
gabomdq@9167
   465
        } else {
gabomdq@9167
   466
            screen = snum;
gabomdq@9167
   467
        }
gabomdq@9167
   468
slouken@6548
   469
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6548
   470
        if (xinerama) {
slouken@6548
   471
            if (get_visualinfo(data->display, 0, &vinfo) < 0) {
slouken@6548
   472
                continue;
slouken@6548
   473
            }
slouken@6548
   474
        } else {
slouken@6548
   475
            if (get_visualinfo(data->display, screen, &vinfo) < 0) {
slouken@6548
   476
                continue;
slouken@6548
   477
            }
slouken@6548
   478
        }
slouken@6548
   479
#else
slouken@6548
   480
        if (get_visualinfo(data->display, screen, &vinfo) < 0) {
slouken@6548
   481
            continue;
slouken@6548
   482
        }
slouken@6548
   483
#endif
slouken@6548
   484
slouken@6548
   485
        displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
slouken@6548
   486
        if (!displaydata) {
slouken@6548
   487
            continue;
slouken@6548
   488
        }
slouken@6796
   489
        display_name[0] = '\0';
slouken@6548
   490
slouken@6548
   491
        mode.format = X11_GetPixelFormatFromVisualInfo(data->display, &vinfo);
slouken@6548
   492
        if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {
slouken@6548
   493
            /* We don't support palettized modes now */
slouken@6548
   494
            SDL_free(displaydata);
slouken@6548
   495
            continue;
slouken@6548
   496
        }
slouken@6548
   497
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6548
   498
        if (xinerama) {
slouken@6548
   499
            mode.w = xinerama[screen].width;
slouken@6548
   500
            mode.h = xinerama[screen].height;
slouken@6548
   501
        } else {
slouken@6548
   502
            mode.w = DisplayWidth(data->display, screen);
slouken@6548
   503
            mode.h = DisplayHeight(data->display, screen);
slouken@6548
   504
        }
slouken@6548
   505
#else
slouken@6548
   506
        mode.w = DisplayWidth(data->display, screen);
slouken@6548
   507
        mode.h = DisplayHeight(data->display, screen);
slouken@6548
   508
#endif
slouken@6548
   509
        mode.refresh_rate = 0;
slouken@6548
   510
slouken@6548
   511
        modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
slouken@6548
   512
        if (!modedata) {
slouken@6548
   513
            SDL_free(displaydata);
slouken@6548
   514
            continue;
slouken@6548
   515
        }
slouken@6548
   516
        mode.driverdata = modedata;
slouken@6548
   517
slouken@6548
   518
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6548
   519
        /* Most of SDL's calls to X11 are unwaware of Xinerama, and to X11 standard calls, when Xinerama is active,
slouken@6548
   520
         * there's only one screen available. So we force the screen number to zero and
slouken@6548
   521
         * let Xinerama specific code handle specific functionality using displaydata->xinerama_info
slouken@6548
   522
         */
slouken@6548
   523
        if (use_xinerama) {
slouken@6548
   524
            displaydata->screen = 0;
slouken@6548
   525
            displaydata->use_xinerama = use_xinerama;
slouken@6548
   526
            displaydata->xinerama_info = xinerama[screen];
slouken@6548
   527
            displaydata->xinerama_screen = screen;
slouken@6548
   528
        }
slouken@6548
   529
        else displaydata->screen = screen;
slouken@6548
   530
#else
slouken@6548
   531
        displaydata->screen = screen;
slouken@6548
   532
#endif
slouken@6548
   533
        displaydata->visual = vinfo.visual;
slouken@6548
   534
        displaydata->depth = vinfo.depth;
slouken@6548
   535
alfred@9814
   536
        // We use the displaydata screen index here so that this works
alfred@9814
   537
        // for both the Xinerama case, where we get the overall DPI,
alfred@9814
   538
        // and the regular X11 screen info case.
alfred@9814
   539
        displaydata->hdpi = (float)DisplayWidth(data->display, displaydata->screen) * 25.4f /
alfred@9814
   540
            DisplayWidthMM(data->display, displaydata->screen);
alfred@9814
   541
        displaydata->vdpi = (float)DisplayHeight(data->display, displaydata->screen) * 25.4f /
alfred@9814
   542
            DisplayHeightMM(data->display, displaydata->screen);
alfred@9814
   543
        displaydata->ddpi = SDL_ComputeDiagonalDPI(DisplayWidth(data->display, displaydata->screen),
alfred@9814
   544
                                                   DisplayHeight(data->display, displaydata->screen),
alfred@9814
   545
                                                   (float)DisplayWidthMM(data->display, displaydata->screen) / 25.4f,
alfred@9814
   546
                                                   (float)DisplayHeightMM(data->display, displaydata->screen) / 25.4f);
alfred@9814
   547
slouken@6548
   548
        displaydata->scanline_pad = SDL_BYTESPERPIXEL(mode.format) * 8;
icculus@7827
   549
        pixmapFormats = X11_XListPixmapFormats(data->display, &n);
slouken@6548
   550
        if (pixmapFormats) {
slouken@6548
   551
            for (i = 0; i < n; ++i) {
slouken@6548
   552
                if (pixmapFormats[i].depth == displaydata->depth) {
slouken@6548
   553
                    displaydata->scanline_pad = pixmapFormats[i].scanline_pad;
slouken@6548
   554
                    break;
slouken@6548
   555
                }
slouken@6548
   556
            }
icculus@7827
   557
            X11_XFree(pixmapFormats);
slouken@6548
   558
        }
slouken@6548
   559
slouken@6548
   560
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6548
   561
        if (use_xinerama) {
slouken@6548
   562
            displaydata->x = xinerama[screen].x_org;
slouken@6548
   563
            displaydata->y = xinerama[screen].y_org;
slouken@6548
   564
        }
slouken@6548
   565
        else
slouken@6548
   566
#endif
slouken@6548
   567
        {
slouken@6548
   568
            displaydata->x = 0;
slouken@6548
   569
            displaydata->y = 0;
slouken@6548
   570
        }
slouken@6548
   571
slouken@6548
   572
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@6548
   573
        if (use_xrandr) {
icculus@7827
   574
            res = X11_XRRGetScreenResources(data->display, RootWindow(data->display, displaydata->screen));
slouken@6548
   575
        }
slouken@6548
   576
        if (res) {
slouken@6548
   577
            XRROutputInfo *output_info;
slouken@6548
   578
            XRRCrtcInfo *crtc;
slouken@6548
   579
            int output;
icculus@7827
   580
            Atom EDID = X11_XInternAtom(data->display, "EDID", False);
slouken@6796
   581
            Atom *props;
slouken@6796
   582
            int nprop;
slouken@6796
   583
            unsigned long width_mm;
slouken@6796
   584
            unsigned long height_mm;
slouken@6796
   585
            int inches = 0;
slouken@6548
   586
slouken@6548
   587
            for (output = 0; output < res->noutput; output++) {
icculus@7827
   588
                output_info = X11_XRRGetOutputInfo(data->display, res, res->outputs[output]);
slouken@6550
   589
                if (!output_info || !output_info->crtc ||
slouken@6550
   590
                    output_info->connection == RR_Disconnected) {
icculus@7827
   591
                    X11_XRRFreeOutputInfo(output_info);
slouken@6548
   592
                    continue;
slouken@6548
   593
                }
slouken@6548
   594
slouken@6548
   595
                /* Is this the output that corresponds to the current screen?
slouken@6548
   596
                   We're checking the crtc position, but that may not be a valid test
slouken@6548
   597
                   in all cases.  Anybody want to give this some love?
slouken@6548
   598
                 */
icculus@7827
   599
                crtc = X11_XRRGetCrtcInfo(data->display, res, output_info->crtc);
slouken@7914
   600
                if (!crtc || crtc->x != displaydata->x || crtc->y != displaydata->y ||
slouken@7914
   601
                    crtc->width != mode.w || crtc->height != mode.h) {
icculus@7827
   602
                    X11_XRRFreeOutputInfo(output_info);
icculus@7827
   603
                    X11_XRRFreeCrtcInfo(crtc);
slouken@6548
   604
                    continue;
slouken@6548
   605
                }
slouken@6548
   606
slouken@6548
   607
                displaydata->use_xrandr = use_xrandr;
slouken@6548
   608
                displaydata->xrandr_output = res->outputs[output];
slouken@6548
   609
                SetXRandRModeInfo(data->display, res, output_info, crtc->mode, &mode);
slouken@6548
   610
slouken@6796
   611
                /* Get the name of this display */
slouken@6796
   612
                width_mm = output_info->mm_width;
slouken@6796
   613
                height_mm = output_info->mm_height;
slouken@6796
   614
                inches = (int)((sqrt(width_mm * width_mm +
slouken@6796
   615
                                     height_mm * height_mm) / 25.4f) + 0.5f);
slouken@6796
   616
                SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
slouken@6796
   617
slouken@6796
   618
                /* See if we can get the EDID data for the real monitor name */
icculus@7827
   619
                props = X11_XRRListOutputProperties(data->display, res->outputs[output], &nprop);
slouken@6796
   620
                for (i = 0; i < nprop; ++i) {
slouken@6796
   621
                    unsigned char *prop;
slouken@6796
   622
                    int actual_format;
slouken@6796
   623
                    unsigned long nitems, bytes_after;
slouken@6796
   624
                    Atom actual_type;
slouken@6940
   625
slouken@7191
   626
                    if (props[i] == EDID) {
icculus@7827
   627
                        if (X11_XRRGetOutputProperty(data->display,
slouken@6940
   628
                                                 res->outputs[output], props[i],
slouken@6940
   629
                                                 0, 100, False, False,
slouken@6940
   630
                                                 AnyPropertyType,
slouken@6940
   631
                                                 &actual_type, &actual_format,
slouken@6940
   632
                                                 &nitems, &bytes_after, &prop) == Success ) {
slouken@6940
   633
                            MonitorInfo *info = decode_edid(prop);
slouken@6940
   634
                            if (info) {
slouken@6940
   635
    #ifdef X11MODES_DEBUG
slouken@6940
   636
                                printf("Found EDID data for %s\n", output_info->name);
slouken@6940
   637
                                dump_monitor_info(info);
slouken@6940
   638
    #endif
slouken@6940
   639
                                SDL_strlcpy(display_name, info->dsc_product_name, sizeof(display_name));
slouken@6940
   640
                                free(info);
slouken@6940
   641
                            }
icculus@7827
   642
                            X11_XFree(prop);
slouken@6796
   643
                        }
slouken@6796
   644
                        break;
slouken@6796
   645
                    }
slouken@6796
   646
                }
slouken@6940
   647
                if (props) {
icculus@7827
   648
                    X11_XFree(props);
slouken@6940
   649
                }
slouken@6796
   650
slouken@6796
   651
                if (*display_name && inches) {
slouken@6796
   652
                    size_t len = SDL_strlen(display_name);
slouken@6796
   653
                    SDL_snprintf(&display_name[len], sizeof(display_name)-len, " %d\"", inches);
slouken@6796
   654
                }
slouken@6796
   655
#ifdef X11MODES_DEBUG
slouken@6796
   656
                printf("Display name: %s\n", display_name);
slouken@6796
   657
#endif
slouken@6796
   658
icculus@7827
   659
                X11_XRRFreeOutputInfo(output_info);
icculus@7827
   660
                X11_XRRFreeCrtcInfo(crtc);
slouken@6548
   661
                break;
slouken@6548
   662
            }
slouken@6548
   663
#ifdef X11MODES_DEBUG
slouken@6548
   664
            if (output == res->noutput) {
slouken@6548
   665
                printf("Couldn't find XRandR CRTC at %d,%d\n", displaydata->x, displaydata->y);
slouken@6548
   666
            }
slouken@6548
   667
#endif
icculus@7827
   668
            X11_XRRFreeScreenResources(res);
slouken@6548
   669
        }
slouken@6548
   670
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
slouken@6548
   671
slouken@6548
   672
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@6548
   673
        if (!displaydata->use_xrandr &&
slouken@6548
   674
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6564
   675
            /* XVidMode only works on the screen at the origin */
slouken@6564
   676
            (!displaydata->use_xinerama ||
slouken@6564
   677
             (displaydata->x == 0 && displaydata->y == 0)) &&
slouken@6548
   678
#endif
slouken@6548
   679
            use_vidmode) {
slouken@6548
   680
            displaydata->use_vidmode = use_vidmode;
slouken@6565
   681
            if (displaydata->use_xinerama) {
slouken@6565
   682
                displaydata->vidmode_screen = 0;
slouken@6565
   683
            } else {
slouken@6565
   684
                displaydata->vidmode_screen = screen;
slouken@6565
   685
            }
slouken@6565
   686
            XF86VidModeGetModeInfo(data->display, displaydata->vidmode_screen, &modedata->vm_mode);
slouken@6548
   687
        }
slouken@6548
   688
#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
slouken@6548
   689
slouken@6548
   690
        SDL_zero(display);
slouken@6796
   691
        if (*display_name) {
slouken@6796
   692
            display.name = display_name;
slouken@6796
   693
        }
slouken@6548
   694
        display.desktop_mode = mode;
slouken@6548
   695
        display.current_mode = mode;
slouken@6548
   696
        display.driverdata = displaydata;
slouken@6548
   697
        SDL_AddVideoDisplay(&display);
slouken@6548
   698
    }
slouken@6548
   699
slouken@6548
   700
#if SDL_VIDEO_DRIVER_X11_XINERAMA
icculus@7827
   701
    if (xinerama) X11_XFree(xinerama);
slouken@6548
   702
#endif
slouken@6548
   703
slouken@6548
   704
    if (_this->num_displays == 0) {
icculus@7037
   705
        return SDL_SetError("No available displays");
slouken@6548
   706
    }
slouken@6548
   707
    return 0;
slouken@2873
   708
}
slouken@2873
   709
slouken@1950
   710
void
slouken@3500
   711
X11_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display)
slouken@1950
   712
{
slouken@2870
   713
    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
slouken@3500
   714
    SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
slouken@5408
   715
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@2873
   716
    int nmodes;
slouken@5408
   717
    XF86VidModeModeInfo ** modes;
slouken@2873
   718
#endif
slouken@2873
   719
    int screen_w;
slouken@2873
   720
    int screen_h;
slouken@1950
   721
    SDL_DisplayMode mode;
slouken@2870
   722
slouken@2873
   723
    /* Unfortunately X11 requires the window to be created with the correct
slouken@2873
   724
     * visual and depth ahead of time, but the SDL API allows you to create
slouken@2873
   725
     * a window before setting the fullscreen display mode.  This means that
slouken@2873
   726
     * we have to use the same format for all windows and all display modes.
slouken@2873
   727
     * (or support recreating the window with a new visual behind the scenes)
slouken@2873
   728
     */
slouken@3500
   729
    mode.format = sdl_display->current_mode.format;
slouken@2873
   730
    mode.driverdata = NULL;
slouken@2873
   731
slouken@2873
   732
    screen_w = DisplayWidth(display, data->screen);
slouken@2873
   733
    screen_h = DisplayHeight(display, data->screen);
slouken@2873
   734
slouken@2873
   735
#if SDL_VIDEO_DRIVER_X11_XINERAMA
gabomdq@6331
   736
    if (data->use_xinerama) {
david@7361
   737
        if (data->use_vidmode && !data->xinerama_info.x_org && !data->xinerama_info.y_org &&
gabomdq@6331
   738
           (screen_w > data->xinerama_info.width || screen_h > data->xinerama_info.height)) {
slouken@8922
   739
            SDL_DisplayModeData *modedata;
david@7361
   740
            /* Add the full (both screens combined) xinerama mode only on the display that starts at 0,0
david@7361
   741
             * if we're using vidmode.
david@7361
   742
             */
gabomdq@6331
   743
            mode.w = screen_w;
gabomdq@6331
   744
            mode.h = screen_h;
slouken@2873
   745
            mode.refresh_rate = 0;
slouken@6548
   746
            modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
slouken@6548
   747
            if (modedata) {
slouken@6548
   748
                *modedata = *(SDL_DisplayModeData *)sdl_display->desktop_mode.driverdata;
slouken@6548
   749
            }
slouken@6548
   750
            mode.driverdata = modedata;
icculus@9832
   751
            if (!SDL_AddDisplayMode(sdl_display, &mode)) {
icculus@9832
   752
                SDL_free(modedata);
icculus@9832
   753
            }
slouken@2873
   754
        }
david@7431
   755
        else if (!data->use_xrandr)
david@7361
   756
        {
slouken@8922
   757
            SDL_DisplayModeData *modedata;
david@7431
   758
            /* Add the current mode of each monitor otherwise if we can't get them from xrandr */
david@7361
   759
            mode.w = data->xinerama_info.width;
david@7361
   760
            mode.h = data->xinerama_info.height;
david@7361
   761
            mode.refresh_rate = 0;
david@7361
   762
            modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
david@7361
   763
            if (modedata) {
david@7361
   764
                *modedata = *(SDL_DisplayModeData *)sdl_display->desktop_mode.driverdata;
david@7361
   765
            }
david@7361
   766
            mode.driverdata = modedata;
icculus@9832
   767
            if (!SDL_AddDisplayMode(sdl_display, &mode)) {
icculus@9832
   768
                SDL_free(modedata);
icculus@9832
   769
            }
david@7361
   770
        }
david@7361
   771
slouken@2873
   772
    }
slouken@2873
   773
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
slouken@2873
   774
slouken@2873
   775
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@6548
   776
    if (data->use_xrandr) {
slouken@6548
   777
        XRRScreenResources *res;
slouken@2873
   778
icculus@7827
   779
        res = X11_XRRGetScreenResources (display, RootWindow(display, data->screen));
slouken@6548
   780
        if (res) {
slouken@6548
   781
            SDL_DisplayModeData *modedata;
slouken@6548
   782
            XRROutputInfo *output_info;
slouken@6548
   783
            int i;
slouken@2873
   784
icculus@7827
   785
            output_info = X11_XRRGetOutputInfo(display, res, data->xrandr_output);
slouken@6548
   786
            if (output_info && output_info->connection != RR_Disconnected) {
slouken@6548
   787
                for (i = 0; i < output_info->nmode; ++i) {
slouken@6548
   788
                    modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
slouken@6548
   789
                    if (!modedata) {
slouken@6548
   790
                        continue;
slouken@6548
   791
                    }
slouken@6548
   792
                    mode.driverdata = modedata;
slouken@2873
   793
icculus@9832
   794
                    if (!SetXRandRModeInfo(display, res, output_info, output_info->modes[i], &mode) ||
icculus@9832
   795
                        !SDL_AddDisplayMode(sdl_display, &mode)) {
slouken@6548
   796
                        SDL_free(modedata);
slouken@6548
   797
                    }
slouken@2873
   798
                }
slouken@2873
   799
            }
icculus@7827
   800
            X11_XRRFreeOutputInfo(output_info);
icculus@7827
   801
            X11_XRRFreeScreenResources(res);
slouken@2873
   802
        }
slouken@6548
   803
        return;
slouken@2873
   804
    }
slouken@2873
   805
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
slouken@2873
   806
slouken@5408
   807
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@6548
   808
    if (data->use_vidmode &&
icculus@7827
   809
        X11_XF86VidModeGetAllModeLines(display, data->vidmode_screen, &nmodes, &modes)) {
slouken@2873
   810
        int i;
slouken@8922
   811
        SDL_DisplayModeData *modedata;
slouken@2873
   812
slouken@2873
   813
#ifdef X11MODES_DEBUG
slouken@2873
   814
        printf("VidMode modes: (unsorted)\n");
slouken@2873
   815
        for (i = 0; i < nmodes; ++i) {
slouken@6566
   816
            printf("Mode %d: %d x %d @ %d, flags: 0x%x\n", i,
slouken@2874
   817
                   modes[i]->hdisplay, modes[i]->vdisplay,
slouken@6566
   818
                   CalculateXVidModeRefreshRate(modes[i]), modes[i]->flags);
slouken@2873
   819
        }
slouken@2873
   820
#endif
slouken@2873
   821
        for (i = 0; i < nmodes; ++i) {
slouken@6548
   822
            modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
slouken@6548
   823
            if (!modedata) {
slouken@6548
   824
                continue;
slouken@6548
   825
            }
slouken@6548
   826
            mode.driverdata = modedata;
slouken@6548
   827
icculus@9832
   828
            if (!SetXVidModeModeInfo(modes[i], &mode) || !SDL_AddDisplayMode(sdl_display, &mode)) {
slouken@6548
   829
                SDL_free(modedata);
slouken@6548
   830
            }
slouken@2873
   831
        }
icculus@7827
   832
        X11_XFree(modes);
slouken@6548
   833
        return;
slouken@2873
   834
    }
slouken@5408
   835
#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
slouken@2873
   836
slouken@2873
   837
    if (!data->use_xrandr && !data->use_vidmode) {
slouken@8922
   838
        SDL_DisplayModeData *modedata;
slouken@6548
   839
        /* Add the desktop mode */
slouken@6548
   840
        mode = sdl_display->desktop_mode;
slouken@6548
   841
        modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
slouken@6548
   842
        if (modedata) {
slouken@6548
   843
            *modedata = *(SDL_DisplayModeData *)sdl_display->desktop_mode.driverdata;
slouken@6548
   844
        }
slouken@6548
   845
        mode.driverdata = modedata;
icculus@9832
   846
        if (!SDL_AddDisplayMode(sdl_display, &mode)) {
icculus@9832
   847
            SDL_free(modedata);
icculus@9832
   848
        }
slouken@2874
   849
    }
slouken@1950
   850
}
slouken@1950
   851
slouken@1950
   852
int
slouken@3500
   853
X11_SetDisplayMode(_THIS, SDL_VideoDisplay * sdl_display, SDL_DisplayMode * mode)
slouken@1950
   854
{
icculus@9319
   855
    SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
icculus@9319
   856
    Display *display = viddata->display;
slouken@3500
   857
    SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
slouken@6548
   858
    SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata;
slouken@2873
   859
icculus@9319
   860
    viddata->last_mode_change_deadline = SDL_GetTicks() + (PENDING_FOCUS_TIME * 2);
icculus@9319
   861
slouken@6548
   862
#if SDL_VIDEO_DRIVER_X11_XRANDR
slouken@6548
   863
    if (data->use_xrandr) {
slouken@6548
   864
        XRRScreenResources *res;
slouken@6548
   865
        XRROutputInfo *output_info;
slouken@6548
   866
        XRRCrtcInfo *crtc;
slouken@6548
   867
        Status status;
slouken@6548
   868
icculus@7827
   869
        res = X11_XRRGetScreenResources (display, RootWindow(display, data->screen));
slouken@6548
   870
        if (!res) {
icculus@7037
   871
            return SDL_SetError("Couldn't get XRandR screen resources");
slouken@6548
   872
        }
slouken@6548
   873
icculus@7827
   874
        output_info = X11_XRRGetOutputInfo(display, res, data->xrandr_output);
slouken@6548
   875
        if (!output_info || output_info->connection == RR_Disconnected) {
icculus@7827
   876
            X11_XRRFreeScreenResources(res);
icculus@7037
   877
            return SDL_SetError("Couldn't get XRandR output info");
slouken@6548
   878
        }
slouken@6548
   879
icculus@7827
   880
        crtc = X11_XRRGetCrtcInfo(display, res, output_info->crtc);
slouken@6548
   881
        if (!crtc) {
icculus@7827
   882
            X11_XRRFreeOutputInfo(output_info);
icculus@7827
   883
            X11_XRRFreeScreenResources(res);
icculus@7037
   884
            return SDL_SetError("Couldn't get XRandR crtc info");
slouken@6548
   885
        }
slouken@6548
   886
icculus@7827
   887
        status = X11_XRRSetCrtcConfig (display, res, output_info->crtc, CurrentTime,
slouken@6548
   888
          crtc->x, crtc->y, modedata->xrandr_mode, crtc->rotation,
slouken@6548
   889
          &data->xrandr_output, 1);
slouken@6548
   890
icculus@7827
   891
        X11_XRRFreeCrtcInfo(crtc);
icculus@7827
   892
        X11_XRRFreeOutputInfo(output_info);
icculus@7827
   893
        X11_XRRFreeScreenResources(res);
slouken@6548
   894
slouken@6548
   895
        if (status != Success) {
icculus@7827
   896
            return SDL_SetError("X11_XRRSetCrtcConfig failed");
slouken@6548
   897
        }
slouken@6548
   898
    }
slouken@6548
   899
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
slouken@6548
   900
slouken@6548
   901
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
slouken@6548
   902
    if (data->use_vidmode) {
icculus@7827
   903
        X11_XF86VidModeSwitchToMode(display, data->vidmode_screen, &modedata->vm_mode);
slouken@6548
   904
    }
slouken@6548
   905
#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
slouken@6548
   906
slouken@2873
   907
    return 0;
slouken@1950
   908
}
slouken@1950
   909
slouken@1950
   910
void
slouken@1950
   911
X11_QuitModes(_THIS)
slouken@1950
   912
{
slouken@1950
   913
}
slouken@1950
   914
gabomdq@6331
   915
int
gabomdq@6331
   916
X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect)
gabomdq@6331
   917
{
gabomdq@6331
   918
    SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
slouken@6502
   919
slouken@6548
   920
    rect->x = data->x;
slouken@6548
   921
    rect->y = data->y;
slouken@6548
   922
    rect->w = sdl_display->current_mode.w;
slouken@6548
   923
    rect->h = sdl_display->current_mode.h;
gabomdq@6331
   924
gabomdq@6331
   925
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@6548
   926
    /* Get the real current bounds of the display */
slouken@6502
   927
    if (data->use_xinerama) {
icculus@7485
   928
        Display *display = ((SDL_VideoData *) _this->driverdata)->display;
slouken@6548
   929
        int screencount;
icculus@7827
   930
        XineramaScreenInfo *xinerama = X11_XineramaQueryScreens(display, &screencount);
slouken@6548
   931
        if (xinerama) {
slouken@6548
   932
            rect->x = xinerama[data->xinerama_screen].x_org;
slouken@6548
   933
            rect->y = xinerama[data->xinerama_screen].y_org;
icculus@7827
   934
            X11_XFree(xinerama);
slouken@6548
   935
        }
gabomdq@6331
   936
    }
slouken@6548
   937
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
slouken@6475
   938
    return 0;
gabomdq@6331
   939
}
gabomdq@6331
   940
alfred@9814
   941
int
alfred@9814
   942
X11_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * hdpi, float * vdpi)
alfred@9814
   943
{
alfred@9814
   944
    SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
alfred@9814
   945
alfred@9814
   946
    if (ddpi) {
alfred@9814
   947
        *ddpi = data->ddpi;
alfred@9814
   948
    }
alfred@9814
   949
    if (hdpi) {
alfred@9814
   950
        *hdpi = data->hdpi;
alfred@9814
   951
    }
alfred@9814
   952
    if (vdpi) {
alfred@9815
   953
        *vdpi = data->vdpi;
alfred@9814
   954
    }
alfred@9814
   955
alfred@9814
   956
    return data->ddpi != 0.0f ? 0 : -1;
alfred@9814
   957
}
alfred@9814
   958
slouken@5481
   959
#endif /* SDL_VIDEO_DRIVER_X11 */
slouken@5481
   960
slouken@1950
   961
/* vi: set ts=4 sw=4 expandtab: */