SDL_x11modes.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:24k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_x11modes.c,v 1.4 2002/04/22 21:38:06 wmay Exp $";
  21. #endif
  22. /* Utilities for getting and setting the X display mode */
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include "SDL_timer.h"
  26. #include "SDL_error.h"
  27. #include "SDL_events.h"
  28. #include "SDL_events_c.h"
  29. #include "SDL_x11video.h"
  30. #include "SDL_x11wm_c.h"
  31. #include "SDL_x11modes_c.h"
  32. #include "SDL_x11image_c.h"
  33. #ifdef HAVE_XINERAMA
  34. #include <XFree86/extensions/Xinerama.h>
  35. #endif 
  36. #define MAX(a, b) (a > b ? a : b)
  37. #ifdef XFREE86_VM
  38. Bool SDL_NAME(XF86VidModeGetModeInfo)(Display *dpy, int scr, SDL_NAME(XF86VidModeModeInfo) *info)
  39. {
  40.     SDL_NAME(XF86VidModeModeLine) *l = (SDL_NAME(XF86VidModeModeLine)*)((char*)info + sizeof info->dotclock);
  41.     return SDL_NAME(XF86VidModeGetModeLine)(dpy, scr, &info->dotclock, l);
  42. }
  43. #endif /* XFREE86_VM */
  44. #ifdef XFREE86_VM
  45. static void save_mode(_THIS)
  46. {
  47.     memset(&saved_mode, 0, sizeof(saved_mode));
  48.     SDL_NAME(XF86VidModeGetModeInfo)(SDL_Display,SDL_Screen,&saved_mode);
  49.     SDL_NAME(XF86VidModeGetViewPort)(SDL_Display,SDL_Screen,&saved_view.x,&saved_view.y);
  50. }
  51. #endif
  52. #ifdef XFREE86_VM
  53. static void restore_mode(_THIS)
  54. {
  55.     SDL_NAME(XF86VidModeModeLine) mode;
  56.     int unused;
  57.     if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) {
  58.         if ( (saved_mode.hdisplay != mode.hdisplay) ||
  59.              (saved_mode.vdisplay != mode.vdisplay) ) {
  60.             SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, &saved_mode);
  61.         }
  62.     }
  63.     if ( (saved_view.x != 0) || (saved_view.y != 0) ) {
  64.         SDL_NAME(XF86VidModeSetViewPort)(SDL_Display, SDL_Screen, saved_view.x, saved_view.y);
  65.     }
  66. }
  67. #endif
  68. #ifdef XFREE86_VM
  69. static int cmpmodes(const void *va, const void *vb)
  70. {
  71.     const SDL_NAME(XF86VidModeModeInfo) *a = *(const SDL_NAME(XF86VidModeModeInfo)**)va;
  72.     const SDL_NAME(XF86VidModeModeInfo) *b = *(const SDL_NAME(XF86VidModeModeInfo)**)vb;
  73.     if(a->hdisplay > b->hdisplay)
  74.         return -1;
  75.     return b->vdisplay - a->vdisplay;
  76. }
  77. #endif
  78. static void get_real_resolution(_THIS, int* w, int* h);
  79. static void set_best_resolution(_THIS, int width, int height)
  80. {
  81. #ifdef XFREE86_VM
  82.     if ( use_vidmode ) {
  83.         SDL_NAME(XF86VidModeModeLine) mode;
  84.         SDL_NAME(XF86VidModeModeInfo) **modes;
  85.         int i;
  86.         int nmodes;
  87.         if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &i, &mode) &&
  88.              SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes)){
  89.             qsort(modes, nmodes, sizeof *modes, cmpmodes);
  90. #ifdef XFREE86_DEBUG
  91.             printf("Available modes:n");
  92.             for ( i = 0; i < nmodes; ++i ) {
  93.                 printf("Mode %d: %dx%dn", i,
  94.                         modes[i]->hdisplay, modes[i]->vdisplay);
  95.             }
  96. #endif
  97.             for ( i = nmodes-1; i > 0 ; --i ) {
  98.                 if ( (modes[i]->hdisplay >= width) &&
  99.                      (modes[i]->vdisplay >= height) )
  100.                     break;
  101.             }
  102.             if ( (modes[i]->hdisplay != mode.hdisplay) ||
  103.                  (modes[i]->vdisplay != mode.vdisplay) ) {
  104.                 SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, modes[i]);
  105.             }
  106.             XFree(modes);
  107.         }
  108.     }
  109. #endif /* XFREE86_VM */
  110. /* XiG */
  111. #ifdef HAVE_XIGXME
  112. #ifdef XIG_DEBUG
  113.     fprintf(stderr, "XME: set_best_resolution(): w = %d, h = %dn",
  114.     width, height);
  115. #endif
  116.     if ( SDL_modelist ) {
  117. int i;
  118.         for ( i=0; SDL_modelist[i]; ++i ) {
  119.     if ( (SDL_modelist[i]->w >= width) &&
  120.                  (SDL_modelist[i]->h >= height) ) {
  121. break;
  122.     }
  123.         }
  124. if ( SDL_modelist[i] ) { /* found one, lets try it */
  125.     int w, h;
  126.             /* check current mode so we can avoid uneccessary mode changes */
  127.     get_real_resolution(this, &w, &h);
  128.     if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) {
  129. # ifdef XIG_DEBUG
  130. fprintf(stderr, "XME: set_best_resolution: "
  131. "XiGMiscChangeResolution: %d %dn",
  132. SDL_modelist[s]->w, SDL_modelist[s]->h);
  133. # endif
  134. XiGMiscChangeResolution(SDL_Display, 
  135. SDL_Screen,
  136. 0, /* view */
  137. SDL_modelist[i]->w, 
  138. SDL_modelist[i]->h, 
  139. 0);
  140. XSync(SDL_Display, False);
  141.             }
  142.         }
  143.     }
  144. #endif /* HAVE_XIGXME */
  145. }
  146. static void get_real_resolution(_THIS, int* w, int* h)
  147. {
  148. #ifdef XFREE86_VM
  149.     if ( use_vidmode ) {
  150.         SDL_NAME(XF86VidModeModeLine) mode;
  151.         int unused;
  152.         if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) {
  153.             *w = mode.hdisplay;
  154.             *h = mode.vdisplay;
  155.             return;
  156.         }
  157.     }
  158. #endif
  159. #ifdef HAVE_XIGXME
  160.     if ( use_xme ) {
  161.         int ractive;
  162.         XiGMiscResolutionInfo *modelist;
  163.         XiGMiscQueryResolutions(SDL_Display, SDL_Screen,
  164.         0, /* view */
  165.         &ractive, &modelist);
  166.         *w = modelist[ractive].width;
  167.         *h = modelist[ractive].height;
  168. #ifdef XIG_DEBUG
  169.         fprintf(stderr, "XME: get_real_resolution: w = %d h = %dn", *w, *h);
  170. #endif
  171.         XFree(modelist);
  172.         return;
  173.     }
  174. #endif /* XIG_XME */
  175.     *w = DisplayWidth(SDL_Display, SDL_Screen);
  176.     *h = DisplayHeight(SDL_Display, SDL_Screen);
  177. }
  178. /* Called after mapping a window - waits until the window is mapped */
  179. void X11_WaitMapped(_THIS, Window win)
  180. {
  181.     XEvent event;
  182.     do {
  183.         XMaskEvent(SDL_Display, StructureNotifyMask, &event);
  184.     } while ( (event.type != MapNotify) || (event.xmap.event != win) );
  185. }
  186. /* Called after unmapping a window - waits until the window is unmapped */
  187. void X11_WaitUnmapped(_THIS, Window win)
  188. {
  189.     XEvent event;
  190.     do {
  191.         XMaskEvent(SDL_Display, StructureNotifyMask, &event);
  192.     } while ( (event.type != UnmapNotify) || (event.xunmap.event != win) );
  193. }
  194. static void move_cursor_to(_THIS, int x, int y)
  195. {
  196.     XWarpPointer(SDL_Display, None, SDL_Root, 0, 0, 0, 0, x, y);
  197. }
  198. static int add_visual(_THIS, int depth, int class)
  199. {
  200.     XVisualInfo vi;
  201.     if(XMatchVisualInfo(SDL_Display, SDL_Screen, depth, class, &vi)) {
  202. int n = this->hidden->nvisuals;
  203. this->hidden->visuals[n].depth = vi.depth;
  204. this->hidden->visuals[n].visual = vi.visual;
  205. this->hidden->nvisuals++;
  206.     }
  207.     return(this->hidden->nvisuals);
  208. }
  209. static int add_visual_byid(_THIS, const char *visual_id)
  210. {
  211.     XVisualInfo *vi, template;
  212.     int nvis;
  213.     if ( visual_id ) {
  214.         memset(&template, 0, (sizeof template));
  215.         template.visualid = strtol(visual_id, NULL, 0);
  216.         vi = XGetVisualInfo(SDL_Display, VisualIDMask, &template, &nvis);
  217.         if ( vi ) {
  218.     int n = this->hidden->nvisuals;
  219.     this->hidden->visuals[n].depth = vi->depth;
  220.     this->hidden->visuals[n].visual = vi->visual;
  221.     this->hidden->nvisuals++;
  222.             XFree(vi);
  223.         }
  224.     }
  225.     return(this->hidden->nvisuals);
  226. }
  227. /* Global for the error handler */
  228. int vm_event, vm_error = -1;
  229. int X11_GetVideoModes(_THIS)
  230. {
  231. #ifdef XFREE86_VM
  232.     int buggy_X11;
  233.     int vm_major, vm_minor;
  234.     int nmodes;
  235.     SDL_NAME(XF86VidModeModeInfo) **modes;
  236. #endif
  237. #ifdef HAVE_XIGXME
  238.     int xme_major, xme_minor;
  239.     int ractive, nummodes;
  240.     XiGMiscResolutionInfo *modelist;
  241. #endif
  242.     int i, n;
  243.     int screen_w;
  244.     int screen_h;
  245.     vm_error = -1;
  246.     use_vidmode = 0;
  247.     screen_w = DisplayWidth(SDL_Display, SDL_Screen);
  248.     screen_h = DisplayHeight(SDL_Display, SDL_Screen);
  249. #ifdef XFREE86_VM
  250.     /* Metro-X 4.3.0 and earlier has a broken implementation of
  251.        XF86VidModeGetAllModeLines() - it hangs the client.
  252.      */
  253.     buggy_X11 = 0;
  254.     if ( strcmp(ServerVendor(SDL_Display), "Metro Link Incorporated") == 0 ) {
  255.         FILE *metro_fp;
  256.         metro_fp = fopen("/usr/X11R6/lib/X11/Metro/.version", "r");
  257.         if ( metro_fp != NULL ) {
  258.             int major, minor, patch, version;
  259.             major = 0; minor = 0; patch = 0;
  260.             fscanf(metro_fp, "%d.%d.%d", &major, &minor, &patch);
  261.             version = major*100+minor*10+patch;
  262.             if ( version < 431 ) {
  263.                 buggy_X11 = 1;
  264.             }
  265.             fclose(metro_fp);
  266.         }
  267.     }
  268. #if defined(__alpha__) || defined(__powerpc__)
  269.     /* The alpha and PPC XFree86 servers are also buggy */
  270.     buggy_X11 = 1;
  271. #endif
  272.     /* Enumerate the available fullscreen modes */
  273.     if ( ! buggy_X11 ) {
  274.         if ( SDL_NAME(XF86VidModeQueryExtension)(SDL_Display, &vm_event, &vm_error) &&
  275.               SDL_NAME(XF86VidModeQueryVersion)(SDL_Display, &vm_major, &vm_minor) ) {
  276. #ifdef BROKEN_XFREE86_4001
  277. #ifdef X_XF86VidModeGetDotClocks  /* Compiled under XFree86 4.0 */
  278.                 /* Earlier X servers hang when doing vidmode */
  279. if ( vm_major < 2 ) {
  280. #ifdef XFREE86_DEBUG
  281.                     printf("Compiled under XFree86 4.0, server is XFree86 3.Xn");
  282. #endif
  283.                     buggy_X11 = 1;
  284.                 }
  285. #else
  286. /* XFree86 3.X code works with XFree86 4.0 servers */;
  287. #endif /* XFree86 4.0 */
  288. #endif /* XFree86 4.02 and newer are fixed wrt backwards compatibility */
  289.         } else {
  290.             buggy_X11 = 1;
  291.         }
  292.     }
  293.     if ( ! buggy_X11 &&
  294.          SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) {
  295.         qsort(modes, nmodes, sizeof *modes, cmpmodes);
  296.         SDL_modelist = (SDL_Rect **)malloc((nmodes+2)*sizeof(SDL_Rect *));
  297.         if ( SDL_modelist ) {
  298.             n = 0;
  299.             for ( i=0; i<nmodes; ++i ) {
  300.                 int w, h;
  301.                 /* Check to see if we should add the screen size (Xinerama) */
  302.                 w = modes[i]->hdisplay;
  303.                 h = modes[i]->vdisplay;
  304.                 if ( (screen_w * screen_h) >= (w * h) ) {
  305.                     if ( (screen_w != w) || (screen_h != h) ) {
  306.                         SDL_modelist[n] = (SDL_Rect *)malloc(sizeof(SDL_Rect));
  307.                         if ( SDL_modelist[n] ) {
  308.                             SDL_modelist[n]->x = 0;
  309.                             SDL_modelist[n]->y = 0;
  310.                             SDL_modelist[n]->w = screen_w;
  311.                             SDL_modelist[n]->h = screen_h;
  312.                             ++n;
  313.                         }
  314.                     }
  315.                     screen_w = 0;
  316.                     screen_h = 0;
  317.                 }
  318.                 /* Add the size from the video mode list */
  319.                 SDL_modelist[n] = (SDL_Rect *)malloc(sizeof(SDL_Rect));
  320.                 if ( SDL_modelist[n] == NULL ) {
  321.                     break;
  322.                 }
  323.                 SDL_modelist[n]->x = 0;
  324.                 SDL_modelist[n]->y = 0;
  325.                 SDL_modelist[n]->w = w;
  326.                 SDL_modelist[n]->h = h;
  327.                 ++n;
  328.             }
  329.             SDL_modelist[n] = NULL;
  330.         }
  331.         XFree(modes);
  332.         use_vidmode = vm_major * 100 + vm_minor;
  333.         save_mode(this);
  334.     }
  335. #endif /* XFREE86_VM */
  336. /* XiG */
  337. #ifdef HAVE_XIGXME
  338.     /* first lets make sure we have the extension, and it's at least v2.0 */
  339.     if (XiGMiscQueryVersion(SDL_Display, &xme_major, &xme_minor)) {
  340. #ifdef XIG_DEBUG
  341. fprintf(stderr, "XME: XiGMiscQueryVersion: V%d.%dn",
  342. xme_major, xme_minor);
  343. #endif
  344. /* work around a XiGMisc bogosity in our version of libXext */
  345. if (xme_major == 0 && xme_major == 0) {
  346.     /* Ideally libxme would spit this out, but the problem is that
  347.        the right Query func will never be called if using the bogus
  348.        libXext version.
  349.      */
  350.     fprintf(stderr, 
  351. "XME: If you are using Xi Graphics CDE and a Summit server, you need ton"
  352. "XME: get the libXext update from our ftp site before fullscreen switchingn"
  353. "XME: will work.  Fullscreen switching is only supported on Summit Serversn");
  354.   }
  355.     } else {
  356.         /* not there. Bummer. */
  357. xme_major = xme_minor = 0;
  358.     }
  359.     modelist = NULL;
  360.     if (xme_major >= 2 && (nummodes = XiGMiscQueryResolutions(SDL_Display, 
  361.     SDL_Screen,
  362.     0, /* view */
  363.     &ractive, 
  364.     &modelist)) > 1)
  365.     { /* then we actually have some */
  366. int j;
  367. #ifdef XIG_DEBUG
  368. fprintf(stderr, "XME: nummodes = %d, active mode = %dn",
  369. nummodes, ractive);
  370. #endif
  371. SDL_modelist = (SDL_Rect **)malloc((nummodes+1)*sizeof(SDL_Rect *));
  372. /* we get the list already sorted in */
  373. /* descending order.  We'll copy it in */
  374. /* reverse order so SDL is happy */
  375. if (SDL_modelist) {
  376.     for ( i=0, j=nummodes-1; j>=0; i++, j-- ) {
  377. if ((SDL_modelist[i] = 
  378.      (SDL_Rect *)malloc(sizeof(SDL_Rect))) == NULL)
  379.   break;
  380. #ifdef XIG_DEBUG
  381. fprintf(stderr, "XME: mode = %4d, w = %4d, h = %4dn",
  382.        i, modelist[i].width, modelist[i].height);
  383. #endif
  384. SDL_modelist[i]->x = 0;
  385. SDL_modelist[i]->y = 0;
  386. SDL_modelist[i]->w = modelist[j].width;
  387. SDL_modelist[i]->h = modelist[j].height;
  388.     }
  389.             SDL_modelist[i] = NULL; /* terminator */
  390. }
  391. use_xme = 1;
  392. saved_res = modelist[ractive]; /* save the current resolution */
  393.     } else {
  394.         use_xme = 0;
  395.     }
  396.     if ( modelist ) {
  397.         XFree(modelist);
  398.     }
  399. #endif /* HAVE_XIGXME */
  400.     {
  401. static int depth_list[] = { 32, 24, 16, 15, 8 };
  402. int j, np;
  403. int use_directcolor = 1;
  404. XPixmapFormatValues *pf;
  405. /* Search for the visuals in deepest-first order, so that the first
  406.    will be the richest one */
  407. if ( getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) {
  408. use_directcolor = 0;
  409. }
  410. this->hidden->nvisuals = 0;
  411. if ( ! add_visual_byid(this, getenv("SDL_VIDEO_X11_VISUALID")) ) {
  412. for ( i=0; i<SDL_TABLESIZE(depth_list); ++i ) {
  413. if ( depth_list[i] > 8 ) {
  414. if ( use_directcolor ) {
  415. add_visual(this, depth_list[i], DirectColor);
  416. }
  417. add_visual(this, depth_list[i], TrueColor);
  418. } else {
  419. add_visual(this, depth_list[i], PseudoColor);
  420. add_visual(this, depth_list[i], StaticColor);
  421. }
  422. }
  423. }
  424. if ( this->hidden->nvisuals == 0 ) {
  425.     SDL_SetError("Found no sufficiently capable X11 visuals");
  426.     return -1;
  427. }
  428.     
  429. /* look up the pixel quantum for each depth */
  430. pf = XListPixmapFormats(SDL_Display, &np);
  431. for(i = 0; i < this->hidden->nvisuals; i++) {
  432.     int d = this->hidden->visuals[i].depth;
  433.     for(j = 0; j < np; j++)
  434. if(pf[j].depth == d)
  435.     break;
  436.     this->hidden->visuals[i].bpp = j < np ? pf[j].bits_per_pixel : d;
  437. }
  438. XFree(pf);
  439.     }
  440.     if ( SDL_modelist == NULL ) {
  441.         SDL_modelist = (SDL_Rect **)malloc((1+1)*sizeof(SDL_Rect *));
  442.         if ( SDL_modelist ) {
  443.             n = 0;
  444.             SDL_modelist[n] = (SDL_Rect *)malloc(sizeof(SDL_Rect));
  445.             if ( SDL_modelist[n] ) {
  446.                 SDL_modelist[n]->x = 0;
  447.                 SDL_modelist[n]->y = 0;
  448.                 SDL_modelist[n]->w = screen_w;
  449.                 SDL_modelist[n]->h = screen_h;
  450.                 ++n;
  451.             }
  452.             SDL_modelist[n] = NULL;
  453.         }
  454.     }
  455. #if defined(XFREE86_DEBUG) || defined(XIG_DEBUG)
  456.     if ( use_vidmode ) {
  457.         printf("XFree86 VidMode is enabledn");
  458.     }
  459. #ifdef HAVE_XIGXME
  460.     if ( use_xme )
  461.       printf("Xi Graphics XME fullscreen is enabledn");
  462.     else
  463.       printf("Xi Graphics XME fullscreen is not availablen");
  464. #endif 
  465.     if ( SDL_modelist ) {
  466.         printf("X11 video mode list:n");
  467.         for ( i=0; SDL_modelist[i]; ++i ) {
  468.             printf("t%dx%dn", SDL_modelist[i]->w, SDL_modelist[i]->h);
  469.         }
  470.     }
  471. #endif /* XFREE86_DEBUG || XIG_DEBUG */
  472.     /* The default X/Y fullscreen offset is 0/0 */
  473.     xinerama_x = 0;
  474.     xinerama_y = 0;
  475. #ifdef HAVE_XINERAMA
  476.     /* Query Xinerama extention */
  477.     if ( SDL_NAME(XineramaQueryExtension)(SDL_Display, &i, &i) &&
  478.          SDL_NAME(XineramaIsActive)(SDL_Display) ) {
  479.         /* Find out which screen is the zero'th one */
  480.         int screens;
  481.         SDL_NAME(XineramaScreenInfo) *xinerama;
  482. #ifdef XINERAMA_DEBUG
  483.         printf("X11 detected Xinerama:n");
  484. #endif
  485.         xinerama = SDL_NAME(XineramaQueryScreens)(SDL_Display, &screens);
  486.         for ( i = 0; i < screens; i++ ) {
  487. #ifdef XINERAMA_DEBUG
  488.             printf("xinerama %d: %dx%d+%d+%dn",
  489.                 xinerama[i].screen_number,
  490.                 xinerama[i].width, xinerama[i].height,
  491.                 xinerama[i].x_org, xinerama[i].y_org);
  492. #endif
  493.             if ( xinerama[i].screen_number == 0 ) {
  494.                 xinerama_x = xinerama[i].x_org;
  495.                 xinerama_y = xinerama[i].y_org;
  496.             }
  497.         }
  498.         XFree(xinerama);
  499.     }
  500. #endif /* HAVE_XINERAMA */
  501.     return 0;
  502. }
  503. int X11_SupportedVisual(_THIS, SDL_PixelFormat *format)
  504. {
  505.     int i;
  506.     for(i = 0; i < this->hidden->nvisuals; i++)
  507. if(this->hidden->visuals[i].bpp == format->BitsPerPixel)
  508.     return 1;
  509.     return 0;
  510. }
  511. SDL_Rect **X11_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
  512. {
  513.     if ( X11_SupportedVisual(this, format) ) {
  514.         if ( flags & SDL_FULLSCREEN ) {
  515.             return(SDL_modelist);
  516.         } else {
  517.             return((SDL_Rect **)-1);
  518.         }
  519.     } else {
  520.         return((SDL_Rect **)0);
  521.     }
  522. }
  523. void X11_FreeVideoModes(_THIS)
  524. {
  525.     int i;
  526.     if ( SDL_modelist ) {
  527.         for ( i=0; SDL_modelist[i]; ++i ) {
  528.             free(SDL_modelist[i]);
  529.         }
  530.         free(SDL_modelist);
  531.         SDL_modelist = NULL;
  532.     }
  533. }
  534. int X11_ResizeFullScreen(_THIS)
  535. {
  536.     int x, y;
  537.     int real_w, real_h;
  538.     int screen_w;
  539.     int screen_h;
  540.     screen_w = DisplayWidth(SDL_Display, SDL_Screen);
  541.     screen_h = DisplayHeight(SDL_Display, SDL_Screen);
  542.     x = xinerama_x;
  543.     y = xinerama_y;
  544.     if ( currently_fullscreen ) {
  545.         /* Switch resolution and cover it with the FSwindow */
  546.         move_cursor_to(this, x, y);
  547.         set_best_resolution(this, current_w, current_h);
  548.         move_cursor_to(this, x, y);
  549.         get_real_resolution(this, &real_w, &real_h);
  550.         if ( current_w > real_w ) {
  551.             real_w = MAX(real_w, screen_w);
  552.         }
  553.         if ( current_h > real_h ) {
  554.             real_h = MAX(real_h, screen_h);
  555.         }
  556.         XMoveResizeWindow(SDL_Display, FSwindow, x, y, real_w, real_h);
  557.         move_cursor_to(this, real_w/2, real_h/2);
  558.         /* Center and reparent the drawing window */
  559.         x = (real_w - current_w)/2;
  560.         y = (real_h - current_h)/2;
  561.         XReparentWindow(SDL_Display, SDL_Window, FSwindow, x, y);
  562.         /* FIXME: move the mouse to the old relative location */
  563.         XSync(SDL_Display, True);   /* Flush spurious mode change events */
  564.     }
  565.     return(1);
  566. }
  567. void X11_QueueEnterFullScreen(_THIS)
  568. {
  569.     switch_waiting = 0x01 | SDL_FULLSCREEN;
  570.     switch_time = SDL_GetTicks() + 1500;
  571. #if 0 /* This causes a BadMatch error if the window is iconified (not needed) */
  572.     XSetInputFocus(SDL_Display, WMwindow, RevertToNone, CurrentTime);
  573. #endif
  574. }
  575. int X11_EnterFullScreen(_THIS)
  576. {
  577.     int okay;
  578. #if 0
  579.     Window tmpwin, *windows;
  580.     int i, nwindows;
  581. #endif
  582.     int real_w, real_h;
  583.     int screen_w;
  584.     int screen_h;
  585.     okay = 1;
  586.     if ( currently_fullscreen ) {
  587.         return(okay);
  588.     }
  589.     /* Ungrab the input so that we can move the mouse around */
  590.     X11_GrabInputNoLock(this, SDL_GRAB_OFF);
  591.     /* Map the fullscreen window to blank the screen */
  592.     screen_w = DisplayWidth(SDL_Display, SDL_Screen);
  593.     screen_h = DisplayHeight(SDL_Display, SDL_Screen);
  594.     get_real_resolution(this, &real_w, &real_h);
  595.     if ( current_w > real_w ) {
  596.         real_w = MAX(real_w, screen_w);
  597.     }
  598.     if ( current_h > real_h ) {
  599.         real_h = MAX(real_h, screen_h);
  600.     }
  601.     XMoveResizeWindow(SDL_Display, FSwindow, 0, 0, real_w, real_h);
  602.     XMapRaised(SDL_Display, FSwindow);
  603.     X11_WaitMapped(this, FSwindow);
  604. #if 0 /* This seems to break WindowMaker in focus-follows-mouse mode */
  605.     /* Make sure we got to the top of the window stack */
  606.     if ( XQueryTree(SDL_Display, SDL_Root, &tmpwin, &tmpwin,
  607.                             &windows, &nwindows) && windows ) {
  608.         /* If not, try to put us there - if fail... oh well */
  609.         if ( windows[nwindows-1] != FSwindow ) {
  610.             tmpwin = windows[nwindows-1];
  611.             for ( i=0; i<nwindows; ++i ) {
  612.                 if ( windows[i] == FSwindow ) {
  613.                     memcpy(&windows[i], &windows[i+1],
  614.                            (nwindows-i-1)*sizeof(windows[i]));
  615.                     break;
  616.                 }
  617.             }
  618.             windows[nwindows-1] = FSwindow;
  619.             XRestackWindows(SDL_Display, windows, nwindows);
  620.             XSync(SDL_Display, False);
  621.         }
  622.         XFree(windows);
  623.     }
  624. #else
  625.     XRaiseWindow(SDL_Display, FSwindow);
  626. #endif
  627. #ifdef XFREE86_VM
  628.     /* Save the current video mode */
  629.     if ( use_vidmode ) {
  630.         SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, True);
  631.     }
  632. #endif
  633.     currently_fullscreen = 1;
  634.     /* Set the new resolution */
  635.     okay = X11_ResizeFullScreen(this);
  636.     if ( ! okay ) {
  637.         X11_LeaveFullScreen(this);
  638.     }
  639.     /* Set the colormap */
  640.     if ( SDL_XColorMap ) {
  641.         XInstallColormap(SDL_Display, SDL_XColorMap);
  642.     }
  643.     if ( okay )
  644.         X11_GrabInputNoLock(this, this->input_grab | SDL_GRAB_FULLSCREEN);
  645.     /* We may need to refresh the screen at this point (no backing store)
  646.        We also don't get an event, which is why we explicitly refresh. */
  647.     if ( this->screen ) {
  648.         if ( this->screen->flags & SDL_OPENGL ) {
  649.             SDL_PrivateExpose();
  650.         } else {
  651.             X11_RefreshDisplay(this);
  652.         }
  653.     }
  654.     return(okay);
  655. }
  656. int X11_LeaveFullScreen(_THIS)
  657. {
  658.     if ( currently_fullscreen ) {
  659.         XReparentWindow(SDL_Display, SDL_Window, WMwindow, 0, 0);
  660. #ifdef XFREE86_VM
  661.         if ( use_vidmode ) {
  662.             restore_mode(this);
  663.             SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, False);
  664.         }
  665. #endif
  666. #ifdef HAVE_XIGXME
  667. if ( use_xme ) {
  668.     int rw, rh;
  669.     
  670.             /* check current mode so we can avoid uneccessary mode changes */
  671.     get_real_resolution(this, &rw, &rh);
  672.     if (rw != saved_res.width || rh != saved_res.height) {
  673. XiGMiscChangeResolution(SDL_Display, 
  674. SDL_Screen,
  675. 0, /* view */
  676. saved_res.width, 
  677. saved_res.height,
  678. 0);
  679. XSync(SDL_Display, False);
  680.     }
  681. }
  682. #endif
  683.         XUnmapWindow(SDL_Display, FSwindow);
  684.         X11_WaitUnmapped(this, FSwindow);
  685.         XSync(SDL_Display, True);   /* Flush spurious mode change events */
  686.         currently_fullscreen = 0;
  687.     }
  688.     /* If we get popped out of fullscreen mode for some reason, input_grab
  689.        will still have the SDL_GRAB_FULLSCREEN flag set, since this is only
  690.        temporary.  In this case, release the grab unless the input has been
  691.        explicitly grabbed.
  692.      */
  693.     X11_GrabInputNoLock(this, this->input_grab & ~SDL_GRAB_FULLSCREEN);
  694.     /* We may need to refresh the screen at this point (no backing store)
  695.        We also don't get an event, which is why we explicitly refresh. */
  696.     if ( this->screen ) {
  697.         if ( this->screen->flags & SDL_OPENGL ) {
  698.             SDL_PrivateExpose();
  699.         } else {
  700.             X11_RefreshDisplay(this);
  701.         }
  702.     }
  703.     return(0);
  704. }