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)
