comparison 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
comparison
equal deleted inserted replaced
1588:e20dcef5647c 1589:34cca785be57
81 const SDL_NAME(XF86VidModeModeInfo) *b = *(const SDL_NAME(XF86VidModeModeInfo)**)vb; 81 const SDL_NAME(XF86VidModeModeInfo) *b = *(const SDL_NAME(XF86VidModeModeInfo)**)vb;
82 if ( a->hdisplay == b->hdisplay ) 82 if ( a->hdisplay == b->hdisplay )
83 return b->vdisplay - a->vdisplay; 83 return b->vdisplay - a->vdisplay;
84 else 84 else
85 return b->hdisplay - a->hdisplay; 85 return b->hdisplay - a->hdisplay;
86 }
87 #endif
88
89 #if SDL_VIDEO_DRIVER_X11_XRANDR
90 static int cmpmodelist(const void *va, const void *vb)
91 {
92 const SDL_Rect *a = *(const SDL_Rect **)va;
93 const SDL_Rect *b = *(const SDL_Rect **)vb;
94 if ( a->w == b->w )
95 return b->h - a->h;
96 else
97 return b->w - a->w;
86 } 98 }
87 #endif 99 #endif
88 100
89 static void get_real_resolution(_THIS, int* w, int* h); 101 static void get_real_resolution(_THIS, int* w, int* h);
90 102
178 } 190 }
179 } 191 }
180 } 192 }
181 #endif /* SDL_VIDEO_DRIVER_X11_XME */ 193 #endif /* SDL_VIDEO_DRIVER_X11_XME */
182 194
195 #if SDL_VIDEO_DRIVER_X11_XRANDR
196 if ( use_xrandr ) {
197 #ifdef XRANDR_DEBUG
198 fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n",
199 width, height);
200 #endif
201 if ( SDL_modelist ) {
202 int i, nsizes;
203 XRRScreenSize *sizes;
204
205 /* find the smallest resolution that is at least as big as the user requested */
206 sizes = XRRConfigSizes(screen_config, &nsizes);
207 for ( i = (nsizes-1); i >= 0; i-- ) {
208 if ( (SDL_modelist[i]->w >= width) &&
209 (SDL_modelist[i]->h >= height) ) {
210 break;
211 }
212 }
213
214 if ( i >= 0 && SDL_modelist[i] ) { /* found one, lets try it */
215 int w, h;
216
217 /* check current mode so we can avoid uneccessary mode changes */
218 get_real_resolution(this, &w, &h);
219
220 if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) {
221 int size_id;
222
223 #ifdef XRANDR_DEBUG
224 fprintf(stderr, "XRANDR: set_best_resolution: "
225 "XXRSetScreenConfig: %d %d\n",
226 SDL_modelist[i]->w, SDL_modelist[i]->h);
227 #endif
228
229 /* find the matching size entry index */
230 for ( size_id = 0; size_id < nsizes; ++size_id ) {
231 if ( (sizes[size_id].width == SDL_modelist[i]->w) &&
232 (sizes[size_id].height == SDL_modelist[i]->h) )
233 break;
234 }
235
236 XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root,
237 size_id, saved_rotation, CurrentTime);
238 }
239 }
240 }
241 }
242 #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
243
183 } 244 }
184 245
185 static void get_real_resolution(_THIS, int* w, int* h) 246 static void get_real_resolution(_THIS, int* w, int* h)
186 { 247 {
187 #if SDL_VIDEO_DRIVER_X11_VIDMODE 248 #if SDL_VIDEO_DRIVER_X11_VIDMODE
193 *w = mode.hdisplay; 254 *w = mode.hdisplay;
194 *h = mode.vdisplay; 255 *h = mode.vdisplay;
195 return; 256 return;
196 } 257 }
197 } 258 }
198 #endif 259 #endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
199 260
200 #if SDL_VIDEO_DRIVER_X11_XME 261 #if SDL_VIDEO_DRIVER_X11_XME
201 if ( use_xme ) { 262 if ( use_xme ) {
202 int ractive; 263 int ractive;
203 XiGMiscResolutionInfo *modelist; 264 XiGMiscResolutionInfo *modelist;
211 fprintf(stderr, "XME: get_real_resolution: w = %d h = %d\n", *w, *h); 272 fprintf(stderr, "XME: get_real_resolution: w = %d h = %d\n", *w, *h);
212 #endif 273 #endif
213 XFree(modelist); 274 XFree(modelist);
214 return; 275 return;
215 } 276 }
216 #endif /* XIG_XME */ 277 #endif /* SDL_VIDEO_DRIVER_X11_XME */
278
279 #if SDL_VIDEO_DRIVER_X11_XRANDR
280 if ( use_xrandr ) {
281 int nsizes;
282 XRRScreenSize* sizes;
283
284 sizes = XRRConfigSizes(screen_config, &nsizes);
285 if ( nsizes > 0 ) {
286 int cur_size;
287 Rotation cur_rotation;
288
289 cur_size = XRRConfigCurrentConfiguration(screen_config, &cur_rotation);
290 if ( cur_size >= 0 && cur_size < nsizes ) {
291 *w = sizes[cur_size].width;
292 *h = sizes[cur_size].height;
293 }
294 #ifdef XRANDR_DEBUG
295 fprintf(stderr, "XRANDR: get_real_resolution: w = %d h = %d\n", *w, *h);
296 #endif
297 return;
298 }
299 }
300 #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
217 301
218 *w = DisplayWidth(SDL_Display, SDL_Screen); 302 *w = DisplayWidth(SDL_Display, SDL_Screen);
219 *h = DisplayHeight(SDL_Display, SDL_Screen); 303 *h = DisplayHeight(SDL_Display, SDL_Screen);
220 } 304 }
221 305
287 #if SDL_VIDEO_DRIVER_X11_XME 371 #if SDL_VIDEO_DRIVER_X11_XME
288 int xme_major, xme_minor; 372 int xme_major, xme_minor;
289 int ractive, nummodes; 373 int ractive, nummodes;
290 XiGMiscResolutionInfo *modelist; 374 XiGMiscResolutionInfo *modelist;
291 #endif 375 #endif
376 #if SDL_VIDEO_DRIVER_X11_XRANDR
377 int xrandr_major, xrandr_minor;
378 int nsizes;
379 XRRScreenSize *sizes;
380 #endif
292 int i, n; 381 int i, n;
293 int screen_w; 382 int screen_w;
294 int screen_h; 383 int screen_h;
295 384
296 vm_error = -1; 385 vm_error = -1;
297 use_vidmode = 0; 386 use_vidmode = 0;
387 use_xrandr = 0;
298 screen_w = DisplayWidth(SDL_Display, SDL_Screen); 388 screen_w = DisplayWidth(SDL_Display, SDL_Screen);
299 screen_h = DisplayHeight(SDL_Display, SDL_Screen); 389 screen_h = DisplayHeight(SDL_Display, SDL_Screen);
390
391 /* XRandR */
392 #if SDL_VIDEO_DRIVER_X11_XRANDR
393 /* require at least XRandR v1.0 (arbitrary) */
394 if ( ( SDL_X11_HAVE_XRANDR ) &&
395 ( getenv("SDL_VIDEO_X11_NO_XRANDR") == NULL ) &&
396 ( XRRQueryVersion(SDL_Display, &xrandr_major, &xrandr_minor) ) &&
397 ( xrandr_major >= 1 ) ) {
398
399 #ifdef XRANDR_DEBUG
400 fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n",
401 xrandr_major, xrandr_minor);
402 #endif
403
404 /* save the screen configuration since we must reference it
405 each time we toggle modes.
406 */
407 screen_config = XRRGetScreenInfo(SDL_Display, SDL_Root);
408
409 /* retrieve the list of resolution */
410 sizes = XRRConfigSizes(screen_config, &nsizes);
411 if (nsizes > 0) {
412 SDL_modelist = (SDL_Rect **)malloc((nsizes+1)*sizeof(SDL_Rect *));
413 if (SDL_modelist) {
414 for ( i=0; i < nsizes; i++ ) {
415 if ((SDL_modelist[i] =
416 (SDL_Rect *)malloc(sizeof(SDL_Rect))) == NULL)
417 break;
418 #ifdef XRANDR_DEBUG
419 fprintf(stderr, "XRANDR: mode = %4d, w = %4d, h = %4d\n",
420 i, sizes[i].width, sizes[i].height);
421 #endif
422
423 SDL_modelist[i]->x = 0;
424 SDL_modelist[i]->y = 0;
425 SDL_modelist[i]->w = sizes[i].width;
426 SDL_modelist[i]->h = sizes[i].height;
427
428 }
429 /* sort the mode list descending as SDL expects */
430 qsort(SDL_modelist, nsizes, sizeof *SDL_modelist, cmpmodelist);
431 SDL_modelist[i] = NULL; /* terminator */
432 }
433 use_xrandr = xrandr_major * 100 + xrandr_minor;
434 saved_size_id = XRRConfigCurrentConfiguration(screen_config, &saved_rotation);
435 }
436 }
437 #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
300 438
301 #if SDL_VIDEO_DRIVER_X11_VIDMODE 439 #if SDL_VIDEO_DRIVER_X11_VIDMODE
302 /* Metro-X 4.3.0 and earlier has a broken implementation of 440 /* Metro-X 4.3.0 and earlier has a broken implementation of
303 XF86VidModeGetAllModeLines() - it hangs the client. 441 XF86VidModeGetAllModeLines() - it hangs the client.
304 */ 442 */
343 #endif /* XFree86 4.02 and newer are fixed wrt backwards compatibility */ 481 #endif /* XFree86 4.02 and newer are fixed wrt backwards compatibility */
344 } else { 482 } else {
345 buggy_X11 = 1; 483 buggy_X11 = 1;
346 } 484 }
347 } 485 }
348 if ( ! buggy_X11 && 486 if ( ! buggy_X11 && ! use_xrandr &&
349 SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) { 487 SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) {
350 488
351 #ifdef XFREE86_DEBUG 489 #ifdef XFREE86_DEBUG
352 printf("Available modes: (sorted)\n"); 490 printf("Available modes: (sorted)\n");
353 for ( i = 0; i < nmodes; ++i ) { 491 for ( i = 0; i < nmodes; ++i ) {
424 the right Query func will never be called if using the bogus 562 the right Query func will never be called if using the bogus
425 libXext version. 563 libXext version.
426 */ 564 */
427 fprintf(stderr, 565 fprintf(stderr,
428 "XME: If you are using Xi Graphics CDE and a Summit server, you need to\n" 566 "XME: If you are using Xi Graphics CDE and a Summit server, you need to\n"
429 "XME: get the libXext update from our ftp site before fullscreen switching\n" 567 "XME: get the libXext update from Xi's ftp site before fullscreen switching\n"
430 "XME: will work. Fullscreen switching is only supported on Summit Servers\n"); 568 "XME: will work. Fullscreen switching is only supported on Summit Servers\n");
431 } 569 }
432 } else { 570 } else {
433 /* not there. Bummer. */ 571 /* not there. Bummer. */
434 xme_major = xme_minor = 0; 572 xme_major = xme_minor = 0;
633 SDL_free(SDL_modelist[i]); 771 SDL_free(SDL_modelist[i]);
634 } 772 }
635 SDL_free(SDL_modelist); 773 SDL_free(SDL_modelist);
636 SDL_modelist = NULL; 774 SDL_modelist = NULL;
637 } 775 }
776
777 #if SDL_VIDEO_DRIVER_X11_XRANDR
778 /* Free the Xrandr screen configuration */
779 if ( screen_config ) {
780 XRRFreeScreenConfigInfo(screen_config);
781 screen_config = NULL;
782 }
783 #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
638 } 784 }
639 785
640 int X11_ResizeFullScreen(_THIS) 786 int X11_ResizeFullScreen(_THIS)
641 { 787 {
642 int x, y; 788 int x, y;
802 XSync(SDL_Display, False); 948 XSync(SDL_Display, False);
803 } 949 }
804 } 950 }
805 #endif 951 #endif
806 952
953 #if SDL_VIDEO_DRIVER_X11_XRANDR
954 if ( use_xrandr ) {
955 XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root,
956 saved_size_id, saved_rotation, CurrentTime);
957 }
958 #endif
959
807 XUnmapWindow(SDL_Display, FSwindow); 960 XUnmapWindow(SDL_Display, FSwindow);
808 X11_WaitUnmapped(this, FSwindow); 961 X11_WaitUnmapped(this, FSwindow);
809 XSync(SDL_Display, True); /* Flush spurious mode change events */ 962 XSync(SDL_Display, True); /* Flush spurious mode change events */
810 currently_fullscreen = 0; 963 currently_fullscreen = 0;
811 } 964 }