/
SDL_x11modes.c
987 lines (879 loc) · 32.3 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2006 Sam Lantinga
4
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Lesser General Public
7
License as published by the Free Software Foundation; either
8
version 2.1 of the License, or (at your option) any later version.
9
10
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
14
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19
Sam Lantinga
20
slouken@libsdl.org
21
*/
22
#include "SDL_config.h"
23
24
25
/* Utilities for getting and setting the X display mode */
26
#include <stdio.h>
27
28
29
#include "SDL_timer.h"
#include "SDL_events.h"
30
#include "../../events/SDL_events_c.h"
31
32
33
#include "SDL_x11video.h"
#include "SDL_x11wm_c.h"
#include "SDL_x11modes_c.h"
34
#include "SDL_x11image_c.h"
35
36
37
#if SDL_VIDEO_DRIVER_X11_XINERAMA
#include "../Xext/extensions/Xinerama.h"
38
#endif
39
40
#define MAX(a, b) (a > b ? a : b)
41
42
#if SDL_VIDEO_DRIVER_X11_VIDMODE
43
Bool SDL_NAME(XF86VidModeGetModeInfo)(Display *dpy, int scr, SDL_NAME(XF86VidModeModeInfo) *info)
44
{
45
SDL_NAME(XF86VidModeModeLine) *l = (SDL_NAME(XF86VidModeModeLine)*)((char*)info + sizeof info->dotclock);
46
return SDL_NAME(XF86VidModeGetModeLine)(dpy, scr, (int*)&info->dotclock, l);
47
}
48
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
49
50
#if SDL_VIDEO_DRIVER_X11_VIDMODE
51
52
static void save_mode(_THIS)
{
53
SDL_memset(&saved_mode, 0, sizeof(saved_mode));
54
55
SDL_NAME(XF86VidModeGetModeInfo)(SDL_Display,SDL_Screen,&saved_mode);
SDL_NAME(XF86VidModeGetViewPort)(SDL_Display,SDL_Screen,&saved_view.x,&saved_view.y);
56
57
58
}
#endif
59
#if SDL_VIDEO_DRIVER_X11_VIDMODE
60
61
static void restore_mode(_THIS)
{
62
SDL_NAME(XF86VidModeModeLine) mode;
63
64
int unused;
65
if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) {
66
67
if ( (saved_mode.hdisplay != mode.hdisplay) ||
(saved_mode.vdisplay != mode.vdisplay) ) {
68
SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, &saved_mode);
69
70
71
}
}
if ( (saved_view.x != 0) || (saved_view.y != 0) ) {
72
SDL_NAME(XF86VidModeSetViewPort)(SDL_Display, SDL_Screen, saved_view.x, saved_view.y);
73
74
75
76
}
}
#endif
77
#if SDL_VIDEO_DRIVER_X11_VIDMODE
78
79
static int cmpmodes(const void *va, const void *vb)
{
80
81
const SDL_NAME(XF86VidModeModeInfo) *a = *(const SDL_NAME(XF86VidModeModeInfo)**)va;
const SDL_NAME(XF86VidModeModeInfo) *b = *(const SDL_NAME(XF86VidModeModeInfo)**)vb;
82
83
84
85
if ( a->hdisplay == b->hdisplay )
return b->vdisplay - a->vdisplay;
else
return b->hdisplay - a->hdisplay;
86
87
88
}
#endif
89
90
91
92
93
94
95
96
97
98
99
100
#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
101
102
static void get_real_resolution(_THIS, int* w, int* h);
103
104
static void set_best_resolution(_THIS, int width, int height)
{
105
#if SDL_VIDEO_DRIVER_X11_VIDMODE
106
if ( use_vidmode ) {
107
108
SDL_NAME(XF86VidModeModeLine) mode;
SDL_NAME(XF86VidModeModeInfo) **modes;
109
int i;
110
int best_width = 0, best_height = 0;
111
112
int nmodes;
113
if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &i, &mode) &&
114
SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes)){
115
#ifdef XFREE86_DEBUG
116
printf("Available modes (unsorted):\n");
117
for ( i = 0; i < nmodes; ++i ) {
118
119
120
121
printf("Mode %d: %d x %d @ %d\n", i,
modes[i]->hdisplay, modes[i]->vdisplay,
1000 * modes[i]->dotclock / (modes[i]->htotal *
modes[i]->vtotal) );
122
}
123
#endif
124
for ( i = 0; i < nmodes ; i++ ) {
125
if ( (modes[i]->hdisplay == width) &&
126
(modes[i]->vdisplay == height) )
127
128
goto match;
}
129
qsort(modes, nmodes, sizeof *modes, cmpmodes);
130
for ( i = nmodes-1; i > 0 ; i-- ) {
131
132
133
134
135
136
137
138
139
140
141
142
143
if ( ! best_width ) {
if ( (modes[i]->hdisplay >= width) &&
(modes[i]->vdisplay >= height) ) {
best_width = modes[i]->hdisplay;
best_height = modes[i]->vdisplay;
}
} else {
if ( (modes[i]->hdisplay != best_width) ||
(modes[i]->vdisplay != best_height) ) {
i++;
break;
}
}
144
}
145
match:
146
147
if ( (modes[i]->hdisplay != mode.hdisplay) ||
(modes[i]->vdisplay != mode.vdisplay) ) {
148
SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, modes[i]);
149
}
150
XFree(modes);
151
152
}
}
153
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
154
155
/* XiG */
156
#if SDL_VIDEO_DRIVER_X11_XME
157
158
#ifdef XIG_DEBUG
fprintf(stderr, "XME: set_best_resolution(): w = %d, h = %d\n",
159
width, height);
160
161
#endif
if ( SDL_modelist ) {
162
int i;
163
164
for ( i=0; SDL_modelist[i]; ++i ) {
165
if ( (SDL_modelist[i]->w >= width) &&
166
(SDL_modelist[i]->h >= height) ) {
167
168
break;
}
169
}
170
171
172
if ( SDL_modelist[i] ) { /* found one, lets try it */
int w, h;
173
174
/* check current mode so we can avoid uneccessary mode changes */
175
get_real_resolution(this, &w, &h);
176
177
if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) {
178
# ifdef XIG_DEBUG
179
180
181
fprintf(stderr, "XME: set_best_resolution: "
"XiGMiscChangeResolution: %d %d\n",
SDL_modelist[s]->w, SDL_modelist[s]->h);
182
# endif
183
184
185
186
187
188
XiGMiscChangeResolution(SDL_Display,
SDL_Screen,
0, /* view */
SDL_modelist[i]->w,
SDL_modelist[i]->h,
0);
189
XSync(SDL_Display, False);
190
191
192
}
}
}
193
#endif /* SDL_VIDEO_DRIVER_X11_XME */
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#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 */
244
245
246
247
}
static void get_real_resolution(_THIS, int* w, int* h)
{
248
#if SDL_VIDEO_DRIVER_X11_VIDMODE
249
if ( use_vidmode ) {
250
SDL_NAME(XF86VidModeModeLine) mode;
251
252
int unused;
253
if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) {
254
255
256
257
258
*w = mode.hdisplay;
*h = mode.vdisplay;
return;
}
}
259
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
260
261
#if SDL_VIDEO_DRIVER_X11_XME
262
263
264
265
266
if ( use_xme ) {
int ractive;
XiGMiscResolutionInfo *modelist;
XiGMiscQueryResolutions(SDL_Display, SDL_Screen,
267
268
0, /* view */
&ractive, &modelist);
269
270
271
272
273
274
275
276
*w = modelist[ractive].width;
*h = modelist[ractive].height;
#ifdef XIG_DEBUG
fprintf(stderr, "XME: get_real_resolution: w = %d h = %d\n", *w, *h);
#endif
XFree(modelist);
return;
}
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#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 */
301
302
303
304
305
306
307
308
309
310
*w = DisplayWidth(SDL_Display, SDL_Screen);
*h = DisplayHeight(SDL_Display, SDL_Screen);
}
/* Called after mapping a window - waits until the window is mapped */
void X11_WaitMapped(_THIS, Window win)
{
XEvent event;
do {
311
XMaskEvent(SDL_Display, StructureNotifyMask, &event);
312
313
314
315
316
317
318
319
} while ( (event.type != MapNotify) || (event.xmap.event != win) );
}
/* Called after unmapping a window - waits until the window is unmapped */
void X11_WaitUnmapped(_THIS, Window win)
{
XEvent event;
do {
320
XMaskEvent(SDL_Display, StructureNotifyMask, &event);
321
322
323
324
325
} while ( (event.type != UnmapNotify) || (event.xunmap.event != win) );
}
static void move_cursor_to(_THIS, int x, int y)
{
326
XWarpPointer(SDL_Display, None, SDL_Root, 0, 0, 0, 0, x, y);
327
328
329
330
331
}
static int add_visual(_THIS, int depth, int class)
{
XVisualInfo vi;
332
if(XMatchVisualInfo(SDL_Display, SDL_Screen, depth, class, &vi)) {
333
334
335
336
int n = this->hidden->nvisuals;
this->hidden->visuals[n].depth = vi.depth;
this->hidden->visuals[n].visual = vi.visual;
this->hidden->nvisuals++;
337
338
339
340
341
342
343
344
345
}
return(this->hidden->nvisuals);
}
static int add_visual_byid(_THIS, const char *visual_id)
{
XVisualInfo *vi, template;
int nvis;
if ( visual_id ) {
346
347
SDL_memset(&template, 0, (sizeof template));
template.visualid = SDL_strtol(visual_id, NULL, 0);
348
vi = XGetVisualInfo(SDL_Display, VisualIDMask, &template, &nvis);
349
if ( vi ) {
350
351
352
353
int n = this->hidden->nvisuals;
this->hidden->visuals[n].depth = vi->depth;
this->hidden->visuals[n].visual = vi->visual;
this->hidden->nvisuals++;
354
XFree(vi);
355
356
357
358
359
360
361
362
363
364
}
}
return(this->hidden->nvisuals);
}
/* Global for the error handler */
int vm_event, vm_error = -1;
int X11_GetVideoModes(_THIS)
{
365
#if SDL_VIDEO_DRIVER_X11_VIDMODE
366
367
368
int buggy_X11;
int vm_major, vm_minor;
int nmodes;
369
SDL_NAME(XF86VidModeModeInfo) **modes;
370
#endif
371
#if SDL_VIDEO_DRIVER_X11_XME
372
373
374
int xme_major, xme_minor;
int ractive, nummodes;
XiGMiscResolutionInfo *modelist;
375
376
377
378
379
#endif
#if SDL_VIDEO_DRIVER_X11_XRANDR
int xrandr_major, xrandr_minor;
int nsizes;
XRRScreenSize *sizes;
380
#endif
381
382
383
int i, n;
int screen_w;
int screen_h;
384
385
386
vm_error = -1;
use_vidmode = 0;
387
use_xrandr = 0;
388
389
390
screen_w = DisplayWidth(SDL_Display, SDL_Screen);
screen_h = DisplayHeight(SDL_Display, SDL_Screen);
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
/* 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 */
439
#if SDL_VIDEO_DRIVER_X11_VIDMODE
440
441
442
443
/* Metro-X 4.3.0 and earlier has a broken implementation of
XF86VidModeGetAllModeLines() - it hangs the client.
*/
buggy_X11 = 0;
444
if ( SDL_strcmp(ServerVendor(SDL_Display), "Metro Link Incorporated") == 0 ) {
445
446
447
448
449
450
451
452
453
454
455
456
457
458
FILE *metro_fp;
metro_fp = fopen("/usr/X11R6/lib/X11/Metro/.version", "r");
if ( metro_fp != NULL ) {
int major, minor, patch, version;
major = 0; minor = 0; patch = 0;
fscanf(metro_fp, "%d.%d.%d", &major, &minor, &patch);
version = major*100+minor*10+patch;
if ( version < 431 ) {
buggy_X11 = 1;
}
fclose(metro_fp);
}
}
459
#if 0 /* Let's try this again... hopefully X servers have improved... */
460
461
#if defined(__alpha__) || defined(__sparc64__) || defined(__powerpc__)
/* The alpha, sparc64 and PPC XFree86 servers are also buggy */
462
buggy_X11 = 1;
463
#endif
464
465
466
#endif
/* Enumerate the available fullscreen modes */
if ( ! buggy_X11 ) {
467
468
if ( SDL_NAME(XF86VidModeQueryExtension)(SDL_Display, &vm_event, &vm_error) &&
SDL_NAME(XF86VidModeQueryVersion)(SDL_Display, &vm_major, &vm_minor) ) {
469
470
471
#ifdef BROKEN_XFREE86_4001
#ifdef X_XF86VidModeGetDotClocks /* Compiled under XFree86 4.0 */
/* Earlier X servers hang when doing vidmode */
472
if ( vm_major < 2 ) {
473
474
#ifdef XFREE86_DEBUG
printf("Compiled under XFree86 4.0, server is XFree86 3.X\n");
475
476
477
478
#endif
buggy_X11 = 1;
}
#else
479
/* XFree86 3.X code works with XFree86 4.0 servers */;
480
481
482
483
484
485
#endif /* XFree86 4.0 */
#endif /* XFree86 4.02 and newer are fixed wrt backwards compatibility */
} else {
buggy_X11 = 1;
}
}
486
if ( ! buggy_X11 && ! use_xrandr &&
487
SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) {
488
489
#ifdef XFREE86_DEBUG
490
printf("Available modes: (sorted)\n");
491
492
493
494
495
496
497
498
for ( i = 0; i < nmodes; ++i ) {
printf("Mode %d: %d x %d @ %d\n", i,
modes[i]->hdisplay, modes[i]->vdisplay,
1000 * modes[i]->dotclock / (modes[i]->htotal *
modes[i]->vtotal) );
}
#endif
499
SDL_qsort(modes, nmodes, sizeof *modes, cmpmodes);
500
SDL_modelist = (SDL_Rect **)SDL_malloc((nmodes+2)*sizeof(SDL_Rect *));
501
if ( SDL_modelist ) {
502
n = 0;
503
for ( i=0; i<nmodes; ++i ) {
504
505
int w, h;
506
507
508
509
510
511
512
/* Eliminate duplicate modes with different refresh rates */
if ( i > 0 &&
modes[i]->hdisplay == modes[i-1]->hdisplay &&
modes[i]->vdisplay == modes[i-1]->vdisplay ) {
continue;
}
513
514
515
516
517
/* Check to see if we should add the screen size (Xinerama) */
w = modes[i]->hdisplay;
h = modes[i]->vdisplay;
if ( (screen_w * screen_h) >= (w * h) ) {
if ( (screen_w != w) || (screen_h != h) ) {
518
SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect));
519
520
521
522
523
524
525
526
527
528
529
530
531
if ( SDL_modelist[n] ) {
SDL_modelist[n]->x = 0;
SDL_modelist[n]->y = 0;
SDL_modelist[n]->w = screen_w;
SDL_modelist[n]->h = screen_h;
++n;
}
}
screen_w = 0;
screen_h = 0;
}
/* Add the size from the video mode list */
532
SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect));
533
if ( SDL_modelist[n] == NULL ) {
534
535
break;
}
536
537
538
539
540
SDL_modelist[n]->x = 0;
SDL_modelist[n]->y = 0;
SDL_modelist[n]->w = w;
SDL_modelist[n]->h = h;
++n;
541
}
542
SDL_modelist[n] = NULL;
543
}
544
XFree(modes);
545
546
use_vidmode = vm_major * 100 + vm_minor;
547
548
save_mode(this);
}
549
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
550
551
/* XiG */
552
#if SDL_VIDEO_DRIVER_X11_XME
553
554
555
/* first lets make sure we have the extension, and it's at least v2.0 */
if (XiGMiscQueryVersion(SDL_Display, &xme_major, &xme_minor)) {
#ifdef XIG_DEBUG
556
557
fprintf(stderr, "XME: XiGMiscQueryVersion: V%d.%d\n",
xme_major, xme_minor);
558
#endif
559
560
561
562
563
564
565
/* work around a XiGMisc bogosity in our version of libXext */
if (xme_major == 0 && xme_major == 0) {
/* Ideally libxme would spit this out, but the problem is that
the right Query func will never be called if using the bogus
libXext version.
*/
fprintf(stderr,
566
"XME: If you are using Xi Graphics CDE and a Summit server, you need to\n"
567
"XME: get the libXext update from Xi's ftp site before fullscreen switching\n"
568
"XME: will work. Fullscreen switching is only supported on Summit Servers\n");
569
}
570
571
} else {
/* not there. Bummer. */
572
xme_major = xme_minor = 0;
573
574
575
576
}
modelist = NULL;
if (xme_major >= 2 && (nummodes = XiGMiscQueryResolutions(SDL_Display,
577
578
579
580
581
582
SDL_Screen,
0, /* view */
&ractive,
&modelist)) > 1)
{ /* then we actually have some */
int j;
583
584
#ifdef XIG_DEBUG
585
586
fprintf(stderr, "XME: nummodes = %d, active mode = %d\n",
nummodes, ractive);
587
588
#endif
589
SDL_modelist = (SDL_Rect **)SDL_malloc((nummodes+1)*sizeof(SDL_Rect *));
590
591
592
593
594
595
596
/* we get the list already sorted in */
/* descending order. We'll copy it in */
/* reverse order so SDL is happy */
if (SDL_modelist) {
for ( i=0, j=nummodes-1; j>=0; i++, j-- ) {
if ((SDL_modelist[i] =
597
(SDL_Rect *)SDL_malloc(sizeof(SDL_Rect))) == NULL)
598
break;
599
#ifdef XIG_DEBUG
600
601
fprintf(stderr, "XME: mode = %4d, w = %4d, h = %4d\n",
i, modelist[i].width, modelist[i].height);
602
#endif
603
604
605
606
607
608
609
SDL_modelist[i]->x = 0;
SDL_modelist[i]->y = 0;
SDL_modelist[i]->w = modelist[j].width;
SDL_modelist[i]->h = modelist[j].height;
}
610
SDL_modelist[i] = NULL; /* terminator */
611
612
613
}
use_xme = 1;
saved_res = modelist[ractive]; /* save the current resolution */
614
615
616
617
} else {
use_xme = 0;
}
if ( modelist ) {
618
XFree(modelist);
619
}
620
#endif /* SDL_VIDEO_DRIVER_X11_XME */
621
622
{
623
624
/* It's interesting to note that if we allow 32 bit depths,
we get a visual with an alpha mask on composite servers.
625
static int depth_list[] = { 32, 24, 16, 15, 8 };
626
627
*/
static int depth_list[] = { 24, 16, 15, 8 };
628
629
630
631
632
633
int j, np;
int use_directcolor = 1;
XPixmapFormatValues *pf;
/* Search for the visuals in deepest-first order, so that the first
will be the richest one */
634
if ( SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) {
635
636
637
use_directcolor = 0;
}
this->hidden->nvisuals = 0;
638
if ( ! add_visual_byid(this, SDL_getenv("SDL_VIDEO_X11_VISUALID")) ) {
639
for ( i=0; i<SDL_arraysize(depth_list); ++i ) {
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
if ( depth_list[i] > 8 ) {
if ( use_directcolor ) {
add_visual(this, depth_list[i], DirectColor);
}
add_visual(this, depth_list[i], TrueColor);
} else {
add_visual(this, depth_list[i], PseudoColor);
add_visual(this, depth_list[i], StaticColor);
}
}
}
if ( this->hidden->nvisuals == 0 ) {
SDL_SetError("Found no sufficiently capable X11 visuals");
return -1;
}
/* look up the pixel quantum for each depth */
657
pf = XListPixmapFormats(SDL_Display, &np);
658
659
660
661
662
663
664
665
for(i = 0; i < this->hidden->nvisuals; i++) {
int d = this->hidden->visuals[i].depth;
for(j = 0; j < np; j++)
if(pf[j].depth == d)
break;
this->hidden->visuals[i].bpp = j < np ? pf[j].bits_per_pixel : d;
}
666
XFree(pf);
667
668
669
}
if ( SDL_modelist == NULL ) {
670
SDL_modelist = (SDL_Rect **)SDL_malloc((1+1)*sizeof(SDL_Rect *));
671
if ( SDL_modelist ) {
672
n = 0;
673
SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect));
674
675
676
677
678
679
if ( SDL_modelist[n] ) {
SDL_modelist[n]->x = 0;
SDL_modelist[n]->y = 0;
SDL_modelist[n]->w = screen_w;
SDL_modelist[n]->h = screen_h;
++n;
680
}
681
SDL_modelist[n] = NULL;
682
683
684
}
}
685
#if defined(XFREE86_DEBUG) || defined(XIG_DEBUG)
686
if ( use_vidmode ) {
687
printf("XFree86 VidMode is enabled\n");
688
}
689
690
#if SDL_VIDEO_DRIVER_X11_XME
691
692
693
694
695
696
if ( use_xme )
printf("Xi Graphics XME fullscreen is enabled\n");
else
printf("Xi Graphics XME fullscreen is not available\n");
#endif
697
if ( SDL_modelist ) {
698
printf("X11 video mode list:\n");
699
for ( i=0; SDL_modelist[i]; ++i ) {
700
printf("\t%dx%d\n", SDL_modelist[i]->w, SDL_modelist[i]->h);
701
702
}
}
703
#endif /* XFREE86_DEBUG || XIG_DEBUG */
704
705
706
707
708
/* The default X/Y fullscreen offset is 0/0 */
xinerama_x = 0;
xinerama_y = 0;
709
#if SDL_VIDEO_DRIVER_X11_XINERAMA
710
/* Query Xinerama extention */
711
712
if ( SDL_NAME(XineramaQueryExtension)(SDL_Display, &i, &i) &&
SDL_NAME(XineramaIsActive)(SDL_Display) ) {
713
714
/* Find out which screen is the desired one */
int desired = 0;
715
int screens;
716
SDL_NAME(XineramaScreenInfo) *xinerama;
717
718
719
#ifdef XINERAMA_DEBUG
printf("X11 detected Xinerama:\n");
720
721
#endif
#if 0 /* Apparently the vidmode extension doesn't work with Xinerama */
722
const char *variable = SDL_getenv("SDL_VIDEO_X11_XINERAMA_SCREEN");
723
724
725
if ( variable ) {
desired = atoi(variable);
}
726
#endif
727
xinerama = SDL_NAME(XineramaQueryScreens)(SDL_Display, &screens);
728
729
730
731
732
733
734
for ( i = 0; i < screens; i++ ) {
#ifdef XINERAMA_DEBUG
printf("xinerama %d: %dx%d+%d+%d\n",
xinerama[i].screen_number,
xinerama[i].width, xinerama[i].height,
xinerama[i].x_org, xinerama[i].y_org);
#endif
735
if ( xinerama[i].screen_number == desired ) {
736
737
738
739
xinerama_x = xinerama[i].x_org;
xinerama_y = xinerama[i].y_org;
}
}
740
XFree(xinerama);
741
}
742
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
743
744
745
746
747
748
749
750
return 0;
}
int X11_SupportedVisual(_THIS, SDL_PixelFormat *format)
{
int i;
for(i = 0; i < this->hidden->nvisuals; i++)
751
752
if(this->hidden->visuals[i].bpp == format->BitsPerPixel)
return 1;
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
return 0;
}
SDL_Rect **X11_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
{
if ( X11_SupportedVisual(this, format) ) {
if ( flags & SDL_FULLSCREEN ) {
return(SDL_modelist);
} else {
return((SDL_Rect **)-1);
}
} else {
return((SDL_Rect **)0);
}
}
void X11_FreeVideoModes(_THIS)
{
int i;
if ( SDL_modelist ) {
for ( i=0; SDL_modelist[i]; ++i ) {
775
SDL_free(SDL_modelist[i]);
776
}
777
SDL_free(SDL_modelist);
778
779
SDL_modelist = NULL;
}
780
781
782
783
784
785
786
787
#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 */
788
789
790
791
792
793
}
int X11_ResizeFullScreen(_THIS)
{
int x, y;
int real_w, real_h;
794
795
796
797
798
int screen_w;
int screen_h;
screen_w = DisplayWidth(SDL_Display, SDL_Screen);
screen_h = DisplayHeight(SDL_Display, SDL_Screen);
799
800
801
x = xinerama_x;
y = xinerama_y;
802
803
if ( currently_fullscreen ) {
/* Switch resolution and cover it with the FSwindow */
804
move_cursor_to(this, x, y);
805
set_best_resolution(this, window_w, window_h);
806
move_cursor_to(this, x, y);
807
get_real_resolution(this, &real_w, &real_h);
808
if ( window_w > real_w ) {
809
810
real_w = MAX(real_w, screen_w);
}
811
if ( window_h > real_h ) {
812
813
real_h = MAX(real_h, screen_h);
}
814
XMoveResizeWindow(SDL_Display, FSwindow, x, y, real_w, real_h);
815
816
817
move_cursor_to(this, real_w/2, real_h/2);
/* Center and reparent the drawing window */
818
819
x = (real_w - window_w)/2;
y = (real_h - window_h)/2;
820
XReparentWindow(SDL_Display, SDL_Window, FSwindow, x, y);
821
/* FIXME: move the mouse to the old relative location */
822
XSync(SDL_Display, True); /* Flush spurious mode change events */
823
824
825
826
827
828
829
830
831
}
return(1);
}
void X11_QueueEnterFullScreen(_THIS)
{
switch_waiting = 0x01 | SDL_FULLSCREEN;
switch_time = SDL_GetTicks() + 1500;
#if 0 /* This causes a BadMatch error if the window is iconified (not needed) */
832
XSetInputFocus(SDL_Display, WMwindow, RevertToNone, CurrentTime);
833
834
835
836
837
838
839
840
841
842
#endif
}
int X11_EnterFullScreen(_THIS)
{
int okay;
#if 0
Window tmpwin, *windows;
int i, nwindows;
#endif
843
int real_w, real_h;
844
845
int screen_w;
int screen_h;
846
847
okay = 1;
848
849
850
if ( currently_fullscreen ) {
return(okay);
}
851
852
853
854
855
/* Ungrab the input so that we can move the mouse around */
X11_GrabInputNoLock(this, SDL_GRAB_OFF);
/* Map the fullscreen window to blank the screen */
856
857
screen_w = DisplayWidth(SDL_Display, SDL_Screen);
screen_h = DisplayHeight(SDL_Display, SDL_Screen);
858
get_real_resolution(this, &real_w, &real_h);
859
if ( window_w > real_w ) {
860
861
real_w = MAX(real_w, screen_w);
}
862
if ( window_h > real_h ) {
863
864
real_h = MAX(real_h, screen_h);
}
865
XMoveResizeWindow(SDL_Display, FSwindow,
866
xinerama_x, xinerama_y, real_w, real_h);
867
XMapRaised(SDL_Display, FSwindow);
868
X11_WaitMapped(this, FSwindow);
869
870
#if 0 /* This seems to break WindowMaker in focus-follows-mouse mode */
871
/* Make sure we got to the top of the window stack */
872
if ( XQueryTree(SDL_Display, SDL_Root, &tmpwin, &tmpwin,
873
874
875
876
877
878
&windows, &nwindows) && windows ) {
/* If not, try to put us there - if fail... oh well */
if ( windows[nwindows-1] != FSwindow ) {
tmpwin = windows[nwindows-1];
for ( i=0; i<nwindows; ++i ) {
if ( windows[i] == FSwindow ) {
879
SDL_memcpy(&windows[i], &windows[i+1],
880
881
(nwindows-i-1)*sizeof(windows[i]));
break;
882
883
}
}
884
windows[nwindows-1] = FSwindow;
885
886
XRestackWindows(SDL_Display, windows, nwindows);
XSync(SDL_Display, False);
887
}
888
XFree(windows);
889
}
890
#else
891
XRaiseWindow(SDL_Display, FSwindow);
892
893
#endif
894
#if SDL_VIDEO_DRIVER_X11_VIDMODE
895
896
/* Save the current video mode */
if ( use_vidmode ) {
897
SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, True);
898
}
899
#endif
900
currently_fullscreen = 1;
901
902
903
904
905
906
907
908
/* Set the new resolution */
okay = X11_ResizeFullScreen(this);
if ( ! okay ) {
X11_LeaveFullScreen(this);
}
/* Set the colormap */
if ( SDL_XColorMap ) {
909
XInstallColormap(SDL_Display, SDL_XColorMap);
910
}
911
912
913
914
915
916
917
918
919
920
921
922
923
if ( okay )
X11_GrabInputNoLock(this, this->input_grab | SDL_GRAB_FULLSCREEN);
/* We may need to refresh the screen at this point (no backing store)
We also don't get an event, which is why we explicitly refresh. */
if ( this->screen ) {
if ( this->screen->flags & SDL_OPENGL ) {
SDL_PrivateExpose();
} else {
X11_RefreshDisplay(this);
}
}
924
925
926
927
928
929
return(okay);
}
int X11_LeaveFullScreen(_THIS)
{
if ( currently_fullscreen ) {
930
XReparentWindow(SDL_Display, SDL_Window, WMwindow, 0, 0);
931
#if SDL_VIDEO_DRIVER_X11_VIDMODE
932
933
if ( use_vidmode ) {
restore_mode(this);
934
SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, False);
935
936
}
#endif
937
938
#if SDL_VIDEO_DRIVER_X11_XME
939
940
941
if ( use_xme ) {
int rw, rh;
942
/* check current mode so we can avoid uneccessary mode changes */
943
944
945
946
947
948
949
950
951
get_real_resolution(this, &rw, &rh);
if (rw != saved_res.width || rh != saved_res.height) {
XiGMiscChangeResolution(SDL_Display,
SDL_Screen,
0, /* view */
saved_res.width,
saved_res.height,
0);
952
XSync(SDL_Display, False);
953
954
}
}
955
956
#endif
957
958
959
960
961
962
963
#if SDL_VIDEO_DRIVER_X11_XRANDR
if ( use_xrandr ) {
XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root,
saved_size_id, saved_rotation, CurrentTime);
}
#endif
964
XUnmapWindow(SDL_Display, FSwindow);
965
X11_WaitUnmapped(this, FSwindow);
966
XSync(SDL_Display, True); /* Flush spurious mode change events */
967
968
969
970
971
972
973
974
currently_fullscreen = 0;
}
/* If we get popped out of fullscreen mode for some reason, input_grab
will still have the SDL_GRAB_FULLSCREEN flag set, since this is only
temporary. In this case, release the grab unless the input has been
explicitly grabbed.
*/
X11_GrabInputNoLock(this, this->input_grab & ~SDL_GRAB_FULLSCREEN);
975
976
977
978
979
980
981
982
983
984
985
/* We may need to refresh the screen at this point (no backing store)
We also don't get an event, which is why we explicitly refresh. */
if ( this->screen ) {
if ( this->screen->flags & SDL_OPENGL ) {
SDL_PrivateExpose();
} else {
X11_RefreshDisplay(this);
}
}
986
987
return(0);
}