[PATCH] XRandR video mode support

Seeing as I couldn’t find a patch for SDL to use the XRandR (resize
and rotate) extension, I whipped one up myself. I have tested it with
a couple of the applications in the SDL test/ directory, and all
seemed to function just fine. Switching back and forth between
fullscreen and window mode caused no problems.

Since the patch current makes XRandR higher priority than the old
XVidMode extension, I added an environment variable to disable XRandR
at runtime. The patch also includes documentation for this env var.

XRandR support can also be compile-time disabled with
–disable-video-x11-xrandr when running configure (I defaulted it to
enable if the Xrandr header file is found).

I applied the patch against the latest CVS (2005-02-22 JST) with no
problem, and it seems to apply cleanly to 1.2.7 as well.

I’m interested in hearing any feedback! I am not very familiar with
the XRandR extension, and the docs/man page for leave much to be
desired. Much of my code is based on the “xrandr” application and
reading the source for libXrandr.so. If there are any errors, please
let me know.

Thanks,
Aric–
Aric Cyr (http://acyr.net)
gpg fingerprint: 943A 1549 47AC D766 B7F8 D551 6703 7142 C282 D542
-------------- next part --------------
Index: configure.in

RCS file: /home/sdlweb/libsdl.org/cvs/SDL12/configure.in,v
retrieving revision 1.163
diff -u -5 -r1.163 configure.in
configure.in 12 Feb 2005 18:01:29 -0000 1.163
+++ configure.in 22 Feb 2005 07:19:07 -0000
@@ -716,10 +716,30 @@
CFLAGS="$CFLAGS -DHAVE_XINERAMA"
VIDEO_SUBDIRS="$VIDEO_SUBDIRS XFree86/Xinerama"
VIDEO_DRIVERS="$VIDEO_DRIVERS XFree86/Xinerama/libXFree86_Xinerama.la"
fi
fi

  •        AC_ARG_ENABLE(video-x11-xrandr,
    

+[ --enable-video-x11-xrandr enable X11 Xrandr extension for fullscreen [default=yes]],

  •                        , enable_video_x11_xrandr=yes)
    
  •        if test x$enable_video_x11_xrandr = xyes; then
    
  •            AC_MSG_CHECKING(for X11 Xrandr support)
    
  •            video_x11_xrandr=no
    
  •            AC_TRY_COMPILE([
    
  •             #include <X11/Xlib.h>
    
  •             #include <X11/extensions/Xrandr.h>
    
  •            ],[
    
  •             XRRScreenConfiguration *config;
    
  •            ],[
    
  •            video_x11_xrandr=yes
    
  •            ])
    
  •            AC_MSG_RESULT($video_x11_xrandr)
    
  •            if test x$video_x11_xrandr = xyes; then
    
  •                CFLAGS="$CFLAGS -DHAVE_XRANDR"
    
  •                SYSTEM_LIBS="$SYSTEM_LIBS -lXrandr -lXrender"
    
  •            fi
    
  •        fi
           AC_ARG_ENABLE(video-x11-xme,
    

[ --enable-video-x11-xme enable Xi Graphics XME for fullscreen [default=yes]],
, enable_video_x11_xme=yes)
if test x$enable_video_x11_xme = xyes; then
AC_MSG_CHECKING(for Xi Graphics XiGMiscExtension support)
Index: docs/html/sdlenvvars.html

RCS file: /home/sdlweb/libsdl.org/cvs/SDL12/docs/html/sdlenvvars.html,v
retrieving revision 1.1
diff -u -5 -r1.1 sdlenvvars.html
— docs/html/sdlenvvars.html 10 Feb 2004 15:15:39 -0000 1.1
+++ docs/html/sdlenvvars.html 22 Feb 2005 07:19:07 -0000
@@ -574,10 +574,22 @@
algorithm. It can be in decimal or in hex (prefixed by 0x).</P

</DD <DT <TT

CLASS=“LITERAL”
+>SDL_VIDEO_X11_NO_XRANDR</TT
+></DT
+><DD
+><P
+>If set, don’t attempt to use the Xrandr extension for resolution mode
+switching. Normally Xrandr takes precedence over the XF86VidMode
+extension, so setting this environment variable will cause the
+XF86VidMode extension to be used if it is available.</P
+></DD
+><DT
+><TT
+CLASS=“LITERAL”

SDL_VIDEO_YUV_DIRECT</TT

</DT <DD <P If set, display YUV overlay directly on the video surface if possible,

@@ -1207,6 +1219,6 @@

</TR </TABLE </DIV </BODY </HTML

->
\ No newline at end of file
+>
Index: src/video/x11/SDL_x11modes.c

RCS file: /home/sdlweb/libsdl.org/cvs/SDL12/src/video/x11/SDL_x11modes.c,v
retrieving revision 1.22
diff -u -5 -r1.22 SDL_x11modes.c
— src/video/x11/SDL_x11modes.c 12 Nov 2004 21:25:42 -0000 1.22
+++ src/video/x11/SDL_x11modes.c 22 Feb 2005 07:19:07 -0000
@@ -90,10 +90,22 @@
else
return b->hdisplay - a->hdisplay;
}
#endif

+#ifdef HAVE_XRANDR
+static int cmpmodelist(const void *va, const void *vb)
+{

  • const SDL_Rect *a = *(const SDL_Rect **)va;
  • const SDL_Rect *b = *(const SDL_Rect **)vb;
  • if ( a->w == b->w )
  •    return a->h - b->h;
    
  • else
  •    return a->w - b->w;
    

+}
+#endif
+
static void get_real_resolution(_THIS, int* w, int* h);

static void set_best_resolution(_THIS, int width, int height)
{
#ifdef XFREE86_VM
@@ -184,10 +196,58 @@
}
}
}
#endif /* HAVE_XIGXME */

+#ifdef HAVE_XRANDR

  • if ( use_xrandr ) {
    +#ifdef XRANDR_DEBUG
  •    fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n",
    
  •            width, height);
    

+#endif

  •    if ( SDL_modelist ) {
    
  •        int i;
    
  •        for ( i=0; SDL_modelist[i]; ++i ) {
    
  •            if ( (SDL_modelist[i]->w >= width) &&
    
  •                 (SDL_modelist[i]->h >= height) ) {
    
  •                break;
    
  •            }
    
  •        }
    
  •        if ( SDL_modelist[i] ) { /* found one, lets try it */
    
  •            int w, h;
    
  •            /* check current mode so we can avoid uneccessary mode changes */
    
  •            get_real_resolution(this, &w, &h);
    
  •            if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) {
    
  •                int nsizes, size_id;
    
  •                XRRScreenSize *sizes;
    

+#ifdef XRANDR_DEBUG

  •                fprintf(stderr, "XRANDR: set_best_resolution: "
    
  •                        "XXRSetScreenConfig: %d %d\n",
    
  •                        SDL_modelist[i]->w, SDL_modelist[i]->h);
    

+#endif

  •                sizes = XRRConfigSizes(screen_config, &nsizes);
    
  •                /* find the matching size entry index */
    
  •                for ( size_id = 0; size_id < nsizes; ++size_id ) {
    
  •                    if ( (sizes[size_id].width == SDL_modelist[i]->w) &&
    
  •                         (sizes[size_id].height == SDL_modelist[i]->h) )
    
  •                        break;
    
  •                }
    
  •                XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, 
    
  •                                   size_id, saved_rotation, CurrentTime);
    
  •            }
    
  •        }
    
  •    }
    
  • }
    +#endif /* HAVE_XRANDR */

}

static void get_real_resolution(_THIS, int* w, int* h)
{
#ifdef XFREE86_VM
@@ -219,10 +279,33 @@
XFree(modelist);
return;
}
#endif /* XIG_XME */

+#ifdef HAVE_XRANDR

  • if ( use_xrandr ) {
  •    int nsizes;
    
  •    XRRScreenSize* sizes;
    
  •    sizes = XRRConfigSizes(screen_config, &nsizes);
    
  •    if ( nsizes > 0 ) {
    
  •        int cur_size;
    
  •        Rotation cur_rotation;
    
  •        cur_size = XRRConfigCurrentConfiguration(screen_config, &cur_rotation);
    
  •        if ( cur_size >= 0 && cur_size < nsizes ) {
    
  •            *w = sizes[cur_size].width;
    
  •            *h = sizes[cur_size].height;
    
  •        }
    

+#ifdef XRANDR_DEBUG

  •        fprintf(stderr, "XRANDR: get_real_resolution: w = %d h = %d\n", *w, *h);
    

+#endif

  •        return;
    
  •    }
    
  • }
    +#endif
  • *w = DisplayWidth(SDL_Display, SDL_Screen);
    *h = DisplayHeight(SDL_Display, SDL_Screen);
    }

/* Called after mapping a window - waits until the window is mapped */
@@ -293,19 +376,72 @@
#ifdef HAVE_XIGXME
int xme_major, xme_minor;
int ractive, nummodes;
XiGMiscResolutionInfo *modelist;
#endif
+#ifdef HAVE_XRANDR

  • int xrandr_major, xrandr_minor;

  • int nsizes;

  • XRRScreenSize *sizes;
    +#endif
    int i, n;
    int screen_w;
    int screen_h;

    vm_error = -1;
    use_vidmode = 0;

  • use_xrandr = 0;
    screen_w = DisplayWidth(SDL_Display, SDL_Screen);
    screen_h = DisplayHeight(SDL_Display, SDL_Screen);

  • /* XRandR */
    +#ifdef HAVE_XRANDR

  • /* require at least XRandR v1.0 (arbitrary) */

  • if ( ( getenv(“SDL_VIDEO_X11_NO_XRANDR”) == NULL ) &&

  •     ( XRRQueryVersion(SDL_Display, &xrandr_major, &xrandr_minor) ) &&
    
  •     ( xrandr_major >= 1 ) ) {
    

+#ifdef XRANDR_DEBUG

  •    fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n",
    
  •            xrandr_major, xrandr_minor);
    

+#endif
+

  •    /* save the screen configuration since we must reference it
    
  •       each time we toggle modes.
    
  •    */
    
  •    screen_config = XRRGetScreenInfo(SDL_Display, SDL_Root);
    
  •    /* retrieve the list of resolution */
    
  •    sizes = XRRConfigSizes(screen_config, &nsizes);
    
  •    if (nsizes > 0) {
    
  •        SDL_modelist = (SDL_Rect **)malloc((nsizes+1)*sizeof(SDL_Rect *));
    
  •        if (SDL_modelist) {
    
  •            for ( i=0; i < nsizes; i++ ) {
    
  •                if ((SDL_modelist[i] = 
    
  •                     (SDL_Rect *)malloc(sizeof(SDL_Rect))) == NULL)
    
  •                    break;
    

+#ifdef XRANDR_DEBUG

  •                fprintf(stderr, "XRANDR: mode = %4d, w = %4d, h = %4d\n",
    
  •                        i, sizes[i].width, sizes[i].height);
    

+#endif
+

  •                SDL_modelist[i]->x = 0;
    
  •                SDL_modelist[i]->y = 0;
    
  •                SDL_modelist[i]->w = sizes[i].width;
    
  •                SDL_modelist[i]->h = sizes[i].height;
    
  •            }
    
  •            /* sort the mode list accending as SDL expects */
    
  •            qsort(SDL_modelist, nsizes, sizeof *SDL_modelist, cmpmodelist);
    
  •            SDL_modelist[i] = NULL; /* terminator */
    
  •        }
    
  •        use_xrandr = xrandr_major * 100 + xrandr_minor;
    
  •        saved_size_id = XRRConfigCurrentConfiguration(screen_config, &saved_rotation);
    
  •    }
    
  • }
    +#endif

#ifdef XFREE86_VM
/* Metro-X 4.3.0 and earlier has a broken implementation of
XF86VidModeGetAllModeLines() - it hangs the client.
/
buggy_X11 = 0;
@@ -347,11 +483,11 @@
#endif /
XFree86 4.02 and newer are fixed wrt backwards compatibility */
} else {
buggy_X11 = 1;
}
}

  • if ( ! buggy_X11 &&
  • if ( ! buggy_X11 && ! use_xrandr &&
    SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) {

#ifdef XFREE86_DEBUG
printf(“Available modes: (sorted)\n”);
for ( i = 0; i < nmodes; ++i ) {
@@ -779,10 +915,16 @@
if ( use_vidmode ) {
restore_mode(this);
SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, False);
}
#endif
+#ifdef HAVE_XRANDR

  •    if ( use_xrandr ) {
    
  •        XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root,
    
  •                           saved_size_id, saved_rotation, CurrentTime);
    
  •    }
    

+#endif

#ifdef HAVE_XIGXME
if ( use_xme ) {
int rw, rh;

Index: src/video/x11/SDL_x11video.c

RCS file: /home/sdlweb/libsdl.org/cvs/SDL12/src/video/x11/SDL_x11video.c,v
retrieving revision 1.17
diff -u -5 -r1.17 SDL_x11video.c
— src/video/x11/SDL_x11video.c 2 Mar 2004 19:38:55 -0000 1.17
+++ src/video/x11/SDL_x11video.c 22 Feb 2005 07:19:08 -0000
@@ -509,10 +509,16 @@
/* Free the graphics context */
if ( SDL_GC ) {
XFreeGC(SDL_Display, SDL_GC);
SDL_GC = 0;
}
+

  •   /* Free the Xrandr screen configuration */
    
  •   if ( screen_config ) {
    
  •   	XRRFreeScreenConfigInfo(screen_config);
    
  •   	screen_config = NULL;
    
  •   }
    
    }
    }

static SDL_bool X11_WindowPosition(_THIS, int *x, int *y, int w, int h)
{
Index: src/video/x11/SDL_x11video.h

RCS file: /home/sdlweb/libsdl.org/cvs/SDL12/src/video/x11/SDL_x11video.h,v
retrieving revision 1.9
diff -u -5 -r1.9 SDL_x11video.h
— src/video/x11/SDL_x11video.h 4 Jan 2004 16:49:27 -0000 1.9
+++ src/video/x11/SDL_x11video.h 22 Feb 2005 07:19:08 -0000
@@ -43,10 +43,13 @@
#include <XFree86/extensions/xf86vmode.h>
#endif
#ifdef HAVE_XIGXME
#include <X11/extensions/xme.h>
#endif
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif

#include <string.h>

#include “SDL_mouse.h”
#include “SDL_sysvideo.h”
@@ -120,14 +123,20 @@
#endif
#ifdef HAVE_XIGXME /* XiG XME fullscreen */
int use_xme;
XiGMiscResolutionInfo saved_res;
#endif
+#ifdef HAVE_XRANDR

  • XRRScreenConfiguration* screen_config;

  • int saved_size_id;

  • Rotation saved_rotation;
    +#endif

    int xinerama_x;
    int xinerama_y;
    int use_vidmode;

  • int use_xrandr;
    int currently_fullscreen;

    /* Automatic mode switching support (entering/leaving fullscreen) */
    Uint32 switch_waiting;
    Uint32 switch_time;
    @@ -173,10 +182,14 @@
    #define SDL_modelist (this->hidden->modelist)
    #define saved_mode (this->hidden->saved_mode)
    #define saved_view (this->hidden->saved_view)
    #define use_xme (this->hidden->use_xme)
    #define saved_res (this->hidden->saved_res)
    +#define use_xrandr (this->hidden->use_xrandr)
    +#define screen_config (this->hidden->screen_config)
    +#define saved_size_id (this->hidden->saved_size_id)
    +#define saved_rotation (this->hidden->saved_rotation)
    #define xinerama_x (this->hidden->xinerama_x)
    #define xinerama_y (this->hidden->xinerama_y)
    #define use_vidmode (this->hidden->use_vidmode)
    #define currently_fullscreen (this->hidden->currently_fullscreen)
    #define switch_waiting (this->hidden->switch_waiting)

Here is a new and improved version of the XRandR patch… this one is
better tested and includes two important fixes:

  1. the video mode list is sorted largest to smallest, instead of
    vice-versa. This meant that some of the resolution matching
    logic had to be reversed, so set_best_resolution() changed a fair
    bit for the XRandR case.

  2. freeing of the screen_config state variable was removed from
    X11_DestroyWindow() and placed into X11_FreeVideoModes(). This
    fixes a segfault for applications that destroy and recreate their
    windows and use XRandR for mode switching (i.e. UT2004).

I have only tested on an GeForce and an Radeon system in Linux. I’d
like to get this tested on a few more systems that support XRandR, so
please try it out and let me know how it goes.On Tue, Feb 22, 2005 at 05:09:16PM +0900, Aric Cyr wrote:

Seeing as I couldn’t find a patch for SDL to use the XRandR (resize
and rotate) extension, I whipped one up myself. I have tested it with
a couple of the applications in the SDL test/ directory, and all
seemed to function just fine. Switching back and forth between
fullscreen and window mode caused no problems.

Since the patch current makes XRandR higher priority than the old
XVidMode extension, I added an environment variable to disable XRandR
at runtime. The patch also includes documentation for this env var.

XRandR support can also be compile-time disabled with
–disable-video-x11-xrandr when running configure (I defaulted it to
enable if the Xrandr header file is found).

I applied the patch against the latest CVS (2005-02-22 JST) with no
problem, and it seems to apply cleanly to 1.2.7 as well.

I’m interested in hearing any feedback! I am not very familiar with
the XRandR extension, and the docs/man page for leave much to be
desired. Much of my code is based on the “xrandr” application and
reading the source for libXrandr.so. If there are any errors, please
let me know.


Aric Cyr (http://acyr.net)
gpg fingerprint: 943A 1549 47AC D766 B7F8 D551 6703 7142 C282 D542
-------------- next part --------------
Index: configure.in

RCS file: /home/sdlweb/libsdl.org/cvs/SDL12/configure.in,v
retrieving revision 1.163
diff -u -5 -r1.163 configure.in
configure.in 12 Feb 2005 18:01:29 -0000 1.163
+++ configure.in 22 Feb 2005 10:05:01 -0000
@@ -716,10 +716,30 @@
CFLAGS="$CFLAGS -DHAVE_XINERAMA"
VIDEO_SUBDIRS="$VIDEO_SUBDIRS XFree86/Xinerama"
VIDEO_DRIVERS="$VIDEO_DRIVERS XFree86/Xinerama/libXFree86_Xinerama.la"
fi
fi

  •        AC_ARG_ENABLE(video-x11-xrandr,
    

+[ --enable-video-x11-xrandr enable X11 Xrandr extension for fullscreen [default=yes]],

  •                        , enable_video_x11_xrandr=yes)
    
  •        if test x$enable_video_x11_xrandr = xyes; then
    
  •            AC_MSG_CHECKING(for X11 Xrandr support)
    
  •            video_x11_xrandr=no
    
  •            AC_TRY_COMPILE([
    
  •             #include <X11/Xlib.h>
    
  •             #include <X11/extensions/Xrandr.h>
    
  •            ],[
    
  •             XRRScreenConfiguration *config;
    
  •            ],[
    
  •            video_x11_xrandr=yes
    
  •            ])
    
  •            AC_MSG_RESULT($video_x11_xrandr)
    
  •            if test x$video_x11_xrandr = xyes; then
    
  •                CFLAGS="$CFLAGS -DHAVE_XRANDR"
    
  •                SYSTEM_LIBS="$SYSTEM_LIBS -lXrandr -lXrender"
    
  •            fi
    
  •        fi
           AC_ARG_ENABLE(video-x11-xme,
    

[ --enable-video-x11-xme enable Xi Graphics XME for fullscreen [default=yes]],
, enable_video_x11_xme=yes)
if test x$enable_video_x11_xme = xyes; then
AC_MSG_CHECKING(for Xi Graphics XiGMiscExtension support)
Index: docs/html/sdlenvvars.html

RCS file: /home/sdlweb/libsdl.org/cvs/SDL12/docs/html/sdlenvvars.html,v
retrieving revision 1.1
diff -u -5 -r1.1 sdlenvvars.html
— docs/html/sdlenvvars.html 10 Feb 2004 15:15:39 -0000 1.1
+++ docs/html/sdlenvvars.html 22 Feb 2005 10:05:01 -0000
@@ -574,10 +574,22 @@
algorithm. It can be in decimal or in hex (prefixed by 0x).</P

</DD <DT <TT

CLASS=“LITERAL”
+>SDL_VIDEO_X11_NO_XRANDR</TT
+></DT
+><DD
+><P
+>If set, don’t attempt to use the Xrandr extension for resolution mode
+switching. Normally Xrandr takes precedence over the XF86VidMode
+extension, so setting this environment variable will cause the
+XF86VidMode extension to be used if it is available.</P
+></DD
+><DT
+><TT
+CLASS=“LITERAL”

SDL_VIDEO_YUV_DIRECT</TT

</DT <DD <P If set, display YUV overlay directly on the video surface if possible,

@@ -1207,6 +1219,6 @@

</TR </TABLE </DIV </BODY </HTML

->
\ No newline at end of file
+>
Index: src/video/x11/SDL_x11modes.c

RCS file: /home/sdlweb/libsdl.org/cvs/SDL12/src/video/x11/SDL_x11modes.c,v
retrieving revision 1.22
diff -u -5 -r1.22 SDL_x11modes.c
— src/video/x11/SDL_x11modes.c 12 Nov 2004 21:25:42 -0000 1.22
+++ src/video/x11/SDL_x11modes.c 22 Feb 2005 10:05:01 -0000
@@ -90,10 +90,22 @@
else
return b->hdisplay - a->hdisplay;
}
#endif

+#ifdef HAVE_XRANDR
+static int cmpmodelist(const void *va, const void *vb)
+{

  • const SDL_Rect *a = *(const SDL_Rect **)va;
  • const SDL_Rect *b = *(const SDL_Rect **)vb;
  • if ( a->w == b->w )
  •    return b->h - a->h;
    
  • else
  •    return b->w - a->w;
    

+}
+#endif
+
static void get_real_resolution(_THIS, int* w, int* h);

static void set_best_resolution(_THIS, int width, int height)
{
#ifdef XFREE86_VM
@@ -184,10 +196,59 @@
}
}
}
#endif /* HAVE_XIGXME */

+#ifdef HAVE_XRANDR

  • if ( use_xrandr ) {
    +#ifdef XRANDR_DEBUG
  •    fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n",
    
  •            width, height);
    

+#endif

  •    if ( SDL_modelist ) {
    
  •        int i, nsizes;
    
  •        XRRScreenSize *sizes;
    
  •        /* find the smallest resolution that is at least as big as the user requested */
    
  •        sizes = XRRConfigSizes(screen_config, &nsizes);
    
  •        for ( i = (nsizes-1); i >= 0; i-- ) {
    
  •            if ( (SDL_modelist[i]->w >= width) &&
    
  •                 (SDL_modelist[i]->h >= height) ) {
    
  •                break;
    
  •            }
    
  •        }
    
  •        if ( i >= 0 && SDL_modelist[i] ) { /* found one, lets try it */
    
  •            int w, h;
    
  •            /* check current mode so we can avoid uneccessary mode changes */
    
  •            get_real_resolution(this, &w, &h);
    
  •            if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) {
    
  •                int size_id;
    

+#ifdef XRANDR_DEBUG

  •                fprintf(stderr, "XRANDR: set_best_resolution: "
    
  •                        "XXRSetScreenConfig: %d %d\n",
    
  •                        SDL_modelist[i]->w, SDL_modelist[i]->h);
    

+#endif
+

  •                /* find the matching size entry index */
    
  •                for ( size_id = 0; size_id < nsizes; ++size_id ) {
    
  •                    if ( (sizes[size_id].width == SDL_modelist[i]->w) &&
    
  •                         (sizes[size_id].height == SDL_modelist[i]->h) )
    
  •                        break;
    
  •                }
    
  •                XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, 
    
  •                                   size_id, saved_rotation, CurrentTime);
    
  •            }
    
  •        }
    
  •    }
    
  • }
    +#endif /* HAVE_XRANDR */

}

static void get_real_resolution(_THIS, int* w, int* h)
{
#ifdef XFREE86_VM
@@ -219,10 +280,33 @@
XFree(modelist);
return;
}
#endif /* XIG_XME */

+#ifdef HAVE_XRANDR

  • if ( use_xrandr ) {
  •    int nsizes;
    
  •    XRRScreenSize* sizes;
    
  •    sizes = XRRConfigSizes(screen_config, &nsizes);
    
  •    if ( nsizes > 0 ) {
    
  •        int cur_size;
    
  •        Rotation cur_rotation;
    
  •        cur_size = XRRConfigCurrentConfiguration(screen_config, &cur_rotation);
    
  •        if ( cur_size >= 0 && cur_size < nsizes ) {
    
  •            *w = sizes[cur_size].width;
    
  •            *h = sizes[cur_size].height;
    
  •        }
    

+#ifdef XRANDR_DEBUG

  •        fprintf(stderr, "XRANDR: get_real_resolution: w = %d h = %d\n", *w, *h);
    

+#endif

  •        return;
    
  •    }
    
  • }
    +#endif
  • *w = DisplayWidth(SDL_Display, SDL_Screen);
    *h = DisplayHeight(SDL_Display, SDL_Screen);
    }

/* Called after mapping a window - waits until the window is mapped */
@@ -293,19 +377,72 @@
#ifdef HAVE_XIGXME
int xme_major, xme_minor;
int ractive, nummodes;
XiGMiscResolutionInfo *modelist;
#endif
+#ifdef HAVE_XRANDR

  • int xrandr_major, xrandr_minor;

  • int nsizes;

  • XRRScreenSize *sizes;
    +#endif
    int i, n;
    int screen_w;
    int screen_h;

    vm_error = -1;
    use_vidmode = 0;

  • use_xrandr = 0;
    screen_w = DisplayWidth(SDL_Display, SDL_Screen);
    screen_h = DisplayHeight(SDL_Display, SDL_Screen);

  • /* XRandR */
    +#ifdef HAVE_XRANDR

  • /* require at least XRandR v1.0 (arbitrary) */

  • if ( ( getenv(“SDL_VIDEO_X11_NO_XRANDR”) == NULL ) &&

  •     ( XRRQueryVersion(SDL_Display, &xrandr_major, &xrandr_minor) ) &&
    
  •     ( xrandr_major >= 1 ) ) {
    

+#ifdef XRANDR_DEBUG

  •    fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n",
    
  •            xrandr_major, xrandr_minor);
    

+#endif
+

  •    /* save the screen configuration since we must reference it
    
  •       each time we toggle modes.
    
  •    */
    
  •    screen_config = XRRGetScreenInfo(SDL_Display, SDL_Root);
    
  •    /* retrieve the list of resolution */
    
  •    sizes = XRRConfigSizes(screen_config, &nsizes);
    
  •    if (nsizes > 0) {
    
  •        SDL_modelist = (SDL_Rect **)malloc((nsizes+1)*sizeof(SDL_Rect *));
    
  •        if (SDL_modelist) {
    
  •            for ( i=0; i < nsizes; i++ ) {
    
  •                if ((SDL_modelist[i] = 
    
  •                     (SDL_Rect *)malloc(sizeof(SDL_Rect))) == NULL)
    
  •                    break;
    

+#ifdef XRANDR_DEBUG

  •                fprintf(stderr, "XRANDR: mode = %4d, w = %4d, h = %4d\n",
    
  •                        i, sizes[i].width, sizes[i].height);
    

+#endif
+

  •                SDL_modelist[i]->x = 0;
    
  •                SDL_modelist[i]->y = 0;
    
  •                SDL_modelist[i]->w = sizes[i].width;
    
  •                SDL_modelist[i]->h = sizes[i].height;
    
  •            }
    
  •            /* sort the mode list descending as SDL expects */
    
  •            qsort(SDL_modelist, nsizes, sizeof *SDL_modelist, cmpmodelist);
    
  •            SDL_modelist[i] = NULL; /* terminator */
    
  •        }
    
  •        use_xrandr = xrandr_major * 100 + xrandr_minor;
    
  •        saved_size_id = XRRConfigCurrentConfiguration(screen_config, &saved_rotation);
    
  •    }
    
  • }
    +#endif

#ifdef XFREE86_VM
/* Metro-X 4.3.0 and earlier has a broken implementation of
XF86VidModeGetAllModeLines() - it hangs the client.
/
buggy_X11 = 0;
@@ -347,11 +484,11 @@
#endif /
XFree86 4.02 and newer are fixed wrt backwards compatibility */
} else {
buggy_X11 = 1;
}
}

  • if ( ! buggy_X11 &&
  • if ( ! buggy_X11 && ! use_xrandr &&
    SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) {

#ifdef XFREE86_DEBUG
printf(“Available modes: (sorted)\n”);
for ( i = 0; i < nmodes; ++i ) {
@@ -630,10 +767,16 @@
free(SDL_modelist[i]);
}
free(SDL_modelist);
SDL_modelist = NULL;
}
+

  • /* Free the Xrandr screen configuration */
  • if ( screen_config ) {
  •    XRRFreeScreenConfigInfo(screen_config);
    
  •    screen_config = NULL;
    
  • }
    }

int X11_ResizeFullScreen(_THIS)
{
int x, y;
@@ -779,10 +922,16 @@
if ( use_vidmode ) {
restore_mode(this);
SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, False);
}
#endif
+#ifdef HAVE_XRANDR

  •    if ( use_xrandr ) {
    
  •        XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root,
    
  •                           saved_size_id, saved_rotation, CurrentTime);
    
  •    }
    

+#endif

#ifdef HAVE_XIGXME
if ( use_xme ) {
int rw, rh;

Index: src/video/x11/SDL_x11video.h

RCS file: /home/sdlweb/libsdl.org/cvs/SDL12/src/video/x11/SDL_x11video.h,v
retrieving revision 1.9
diff -u -5 -r1.9 SDL_x11video.h
— src/video/x11/SDL_x11video.h 4 Jan 2004 16:49:27 -0000 1.9
+++ src/video/x11/SDL_x11video.h 22 Feb 2005 10:05:01 -0000
@@ -43,10 +43,13 @@
#include <XFree86/extensions/xf86vmode.h>
#endif
#ifdef HAVE_XIGXME
#include <X11/extensions/xme.h>
#endif
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif

#include <string.h>

#include “SDL_mouse.h”
#include “SDL_sysvideo.h”
@@ -120,14 +123,20 @@
#endif
#ifdef HAVE_XIGXME /* XiG XME fullscreen */
int use_xme;
XiGMiscResolutionInfo saved_res;
#endif
+#ifdef HAVE_XRANDR

  • XRRScreenConfiguration* screen_config;

  • int saved_size_id;

  • Rotation saved_rotation;
    +#endif

    int xinerama_x;
    int xinerama_y;
    int use_vidmode;

  • int use_xrandr;
    int currently_fullscreen;

    /* Automatic mode switching support (entering/leaving fullscreen) */
    Uint32 switch_waiting;
    Uint32 switch_time;
    @@ -173,10 +182,14 @@
    #define SDL_modelist (this->hidden->modelist)
    #define saved_mode (this->hidden->saved_mode)
    #define saved_view (this->hidden->saved_view)
    #define use_xme (this->hidden->use_xme)
    #define saved_res (this->hidden->saved_res)
    +#define use_xrandr (this->hidden->use_xrandr)
    +#define screen_config (this->hidden->screen_config)
    +#define saved_size_id (this->hidden->saved_size_id)
    +#define saved_rotation (this->hidden->saved_rotation)
    #define xinerama_x (this->hidden->xinerama_x)
    #define xinerama_y (this->hidden->xinerama_y)
    #define use_vidmode (this->hidden->use_vidmode)
    #define currently_fullscreen (this->hidden->currently_fullscreen)
    #define switch_waiting (this->hidden->switch_waiting)