Mercurial > sdl-ios-xcode
diff src/video/x11/SDL_x11modes.c @ 1589:34cca785be57
Xrandr support in the X11 target.
Fixes Bugzilla #109, and as a bonus, Bugzilla #145, too!
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Wed, 22 Mar 2006 11:13:58 +0000 |
parents | 3ba88cb7eb1b |
children | 5cf11b00b900 |
line wrap: on
line diff
--- a/src/video/x11/SDL_x11modes.c Wed Mar 22 09:18:10 2006 +0000 +++ b/src/video/x11/SDL_x11modes.c Wed Mar 22 11:13:58 2006 +0000 @@ -86,6 +86,18 @@ } #endif +#if SDL_VIDEO_DRIVER_X11_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) @@ -180,6 +192,55 @@ } #endif /* SDL_VIDEO_DRIVER_X11_XME */ +#if SDL_VIDEO_DRIVER_X11_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 /* SDL_VIDEO_DRIVER_X11_XRANDR */ + } static void get_real_resolution(_THIS, int* w, int* h) @@ -195,7 +256,7 @@ return; } } -#endif +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ #if SDL_VIDEO_DRIVER_X11_XME if ( use_xme ) { @@ -213,7 +274,30 @@ XFree(modelist); return; } -#endif /* XIG_XME */ +#endif /* SDL_VIDEO_DRIVER_X11_XME */ + +#if SDL_VIDEO_DRIVER_X11_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 /* SDL_VIDEO_DRIVER_X11_XRANDR */ *w = DisplayWidth(SDL_Display, SDL_Screen); *h = DisplayHeight(SDL_Display, SDL_Screen); @@ -289,15 +373,69 @@ int ractive, nummodes; XiGMiscResolutionInfo *modelist; #endif +#if SDL_VIDEO_DRIVER_X11_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 */ +#if SDL_VIDEO_DRIVER_X11_XRANDR + /* require at least XRandR v1.0 (arbitrary) */ + if ( ( SDL_X11_HAVE_XRANDR ) && + ( 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 /* SDL_VIDEO_DRIVER_X11_XRANDR */ + #if SDL_VIDEO_DRIVER_X11_VIDMODE /* Metro-X 4.3.0 and earlier has a broken implementation of XF86VidModeGetAllModeLines() - it hangs the client. @@ -345,7 +483,7 @@ buggy_X11 = 1; } } - if ( ! buggy_X11 && + if ( ! buggy_X11 && ! use_xrandr && SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) { #ifdef XFREE86_DEBUG @@ -426,7 +564,7 @@ */ fprintf(stderr, "XME: If you are using Xi Graphics CDE and a Summit server, you need to\n" -"XME: get the libXext update from our ftp site before fullscreen switching\n" +"XME: get the libXext update from Xi's ftp site before fullscreen switching\n" "XME: will work. Fullscreen switching is only supported on Summit Servers\n"); } } else { @@ -635,6 +773,14 @@ SDL_free(SDL_modelist); SDL_modelist = NULL; } + +#if SDL_VIDEO_DRIVER_X11_XRANDR + /* Free the Xrandr screen configuration */ + if ( screen_config ) { + XRRFreeScreenConfigInfo(screen_config); + screen_config = NULL; + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ } int X11_ResizeFullScreen(_THIS) @@ -804,6 +950,13 @@ } #endif +#if SDL_VIDEO_DRIVER_X11_XRANDR + if ( use_xrandr ) { + XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, + saved_size_id, saved_rotation, CurrentTime); + } +#endif + XUnmapWindow(SDL_Display, FSwindow); X11_WaitUnmapped(this, FSwindow); XSync(SDL_Display, True); /* Flush spurious mode change events */