/
SDL_x11modes.c
1014 lines (893 loc) · 32 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
}
}
return(this->hidden->nvisuals);
}
/* Global for the error handler */
int vm_event, vm_error = -1;
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
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
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
#if SDL_VIDEO_DRIVER_X11_XRANDR
static int CheckXRandR(_THIS, int *major, int *minor)
{
char *env;
/* Default the extension not available */
*major = *minor = 0;
/* Allow environment override */
env = getenv("SDL_VIDEO_X11_XRANDR");
if ( env && !SDL_atoi(env) ) {
return 0;
}
/* This defaults off now, due to KDE window maximize problems */
if ( !env ) {
return 0;
}
if ( !SDL_X11_HAVE_XRANDR ) {
return 0;
}
/* Query the extension version */
if ( !XRRQueryVersion(SDL_Display, major, minor) ) {
return 0;
}
return 1;
}
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
#if SDL_VIDEO_DRIVER_X11_VIDMODE
static int CheckVidMode(_THIS, int *major, int *minor)
{
char *env;
/* Default the extension not available */
*major = *minor = 0;
/* Allow environment override */
env = getenv("SDL_VIDEO_X11_VIDMODE");
if ( env && !SDL_atoi(env) ) {
return 0;
}
/* Metro-X 4.3.0 and earlier has a broken implementation of
XF86VidModeGetAllModeLines() - it hangs the client.
*/
if ( SDL_strcmp(ServerVendor(SDL_Display), "Metro Link Incorporated") == 0 ) {
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);
fclose(metro_fp);
version = major*100+minor*10+patch;
if ( version < 431 ) {
return 0;
}
}
}
/* Query the extension version */
if ( !SDL_NAME(XF86VidModeQueryExtension)(SDL_Display, &vm_event, &vm_error) ||
!SDL_NAME(XF86VidModeQueryVersion)(SDL_Display, major, minor) ) {
return 0;
}
return 1;
}
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
#if SDL_VIDEO_DRIVER_X11_XME
static int CheckXME(_THIS, int *major, int *minor)
{
char *env;
/* Default the extension not available */
*major = *minor = 0;
/* Allow environment override */
env = getenv("SDL_VIDEO_X11_VIDMODE");
if ( env && !SDL_atoi(env) ) {
return 0;
}
/* Query the extension version */
if ( !XiGMiscQueryVersion(SDL_Display, major, minor) ) {
return 0;
}
return 1;
}
#endif /* SDL_VIDEO_DRIVER_X11_XME */
458
459
int X11_GetVideoModes(_THIS)
{
460
461
462
463
464
#if SDL_VIDEO_DRIVER_X11_XRANDR
int xrandr_major, xrandr_minor;
int nsizes;
XRRScreenSize *sizes;
#endif
465
#if SDL_VIDEO_DRIVER_X11_VIDMODE
466
467
int vm_major, vm_minor;
int nmodes;
468
SDL_NAME(XF86VidModeModeInfo) **modes;
469
#endif
470
#if SDL_VIDEO_DRIVER_X11_XME
471
472
473
int xme_major, xme_minor;
int ractive, nummodes;
XiGMiscResolutionInfo *modelist;
474
#endif
475
476
477
int i, n;
int screen_w;
int screen_h;
478
479
use_vidmode = 0;
480
use_xrandr = 0;
481
482
483
screen_w = DisplayWidth(SDL_Display, SDL_Screen);
screen_h = DisplayHeight(SDL_Display, SDL_Screen);
484
#if SDL_VIDEO_DRIVER_X11_XRANDR
485
/* XRandR */
486
/* require at least XRandR v1.0 (arbitrary) */
487
488
if ( CheckXRandR(this, &xrandr_major, &xrandr_minor) && (xrandr_major >= 1) )
{
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
#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 */
529
#if SDL_VIDEO_DRIVER_X11_VIDMODE
530
531
532
533
/* XVidMode */
if ( !use_xrandr && CheckVidMode(this, &vm_major, &vm_minor) &&
SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) )
{
534
#ifdef XFREE86_DEBUG
535
printf("Available modes: (sorted)\n");
536
537
538
539
540
541
542
543
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
544
SDL_qsort(modes, nmodes, sizeof *modes, cmpmodes);
545
SDL_modelist = (SDL_Rect **)SDL_malloc((nmodes+2)*sizeof(SDL_Rect *));
546
if ( SDL_modelist ) {
547
n = 0;
548
for ( i=0; i<nmodes; ++i ) {
549
550
int w, h;
551
552
553
554
555
556
557
/* 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;
}
558
559
560
561
562
/* 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) ) {
563
SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect));
564
565
566
567
568
569
570
571
572
573
574
575
576
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 */
577
SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect));
578
if ( SDL_modelist[n] == NULL ) {
579
580
break;
}
581
582
583
584
585
SDL_modelist[n]->x = 0;
SDL_modelist[n]->y = 0;
SDL_modelist[n]->w = w;
SDL_modelist[n]->h = h;
++n;
586
}
587
SDL_modelist[n] = NULL;
588
}
589
XFree(modes);
590
591
use_vidmode = vm_major * 100 + vm_minor;
592
593
save_mode(this);
}
594
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
595
596
#if SDL_VIDEO_DRIVER_X11_XME
597
/* XiG */
598
modelist = NULL;
599
600
601
602
603
/* first lets make sure we have the extension, and it's at least v2.0 */
if ( CheckXME(this, &xme_major, &xme_minor) && xme_major >= 2 &&
(nummodes = XiGMiscQueryResolutions(SDL_Display, SDL_Screen,
0, /* view */
&ractive, &modelist)) > 1 )
604
605
{ /* then we actually have some */
int j;
606
607
#ifdef XIG_DEBUG
608
609
fprintf(stderr, "XME: nummodes = %d, active mode = %d\n",
nummodes, ractive);
610
611
#endif
612
SDL_modelist = (SDL_Rect **)SDL_malloc((nummodes+1)*sizeof(SDL_Rect *));
613
614
615
616
617
618
619
/* 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] =
620
(SDL_Rect *)SDL_malloc(sizeof(SDL_Rect))) == NULL)
621
break;
622
#ifdef XIG_DEBUG
623
624
fprintf(stderr, "XME: mode = %4d, w = %4d, h = %4d\n",
i, modelist[i].width, modelist[i].height);
625
#endif
626
627
628
629
630
631
632
SDL_modelist[i]->x = 0;
SDL_modelist[i]->y = 0;
SDL_modelist[i]->w = modelist[j].width;
SDL_modelist[i]->h = modelist[j].height;
}
633
SDL_modelist[i] = NULL; /* terminator */
634
635
636
}
use_xme = 1;
saved_res = modelist[ractive]; /* save the current resolution */
637
638
639
640
} else {
use_xme = 0;
}
if ( modelist ) {
641
XFree(modelist);
642
}
643
#endif /* SDL_VIDEO_DRIVER_X11_XME */
644
645
{
646
647
/* It's interesting to note that if we allow 32 bit depths,
we get a visual with an alpha mask on composite servers.
648
static int depth_list[] = { 32, 24, 16, 15, 8 };
649
650
*/
static int depth_list[] = { 24, 16, 15, 8 };
651
652
653
654
655
656
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 */
657
if ( SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) {
658
659
660
use_directcolor = 0;
}
this->hidden->nvisuals = 0;
661
if ( ! add_visual_byid(this, SDL_getenv("SDL_VIDEO_X11_VISUALID")) ) {
662
for ( i=0; i<SDL_arraysize(depth_list); ++i ) {
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
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 */
680
pf = XListPixmapFormats(SDL_Display, &np);
681
682
683
684
685
686
687
688
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;
}
689
XFree(pf);
690
691
692
}
if ( SDL_modelist == NULL ) {
693
SDL_modelist = (SDL_Rect **)SDL_malloc((1+1)*sizeof(SDL_Rect *));
694
if ( SDL_modelist ) {
695
n = 0;
696
SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect));
697
698
699
700
701
702
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;
703
}
704
SDL_modelist[n] = NULL;
705
706
707
}
}
708
#if defined(XFREE86_DEBUG) || defined(XIG_DEBUG)
709
710
711
712
if ( use_xrandr ) {
printf("XRandR is enabled\n");
}
713
if ( use_vidmode ) {
714
printf("XFree86 VidMode is enabled\n");
715
}
716
717
#if SDL_VIDEO_DRIVER_X11_XME
718
719
720
721
722
723
if ( use_xme )
printf("Xi Graphics XME fullscreen is enabled\n");
else
printf("Xi Graphics XME fullscreen is not available\n");
#endif
724
if ( SDL_modelist ) {
725
printf("X11 video mode list:\n");
726
for ( i=0; SDL_modelist[i]; ++i ) {
727
printf("\t%dx%d\n", SDL_modelist[i]->w, SDL_modelist[i]->h);
728
729
}
}
730
#endif /* XFREE86_DEBUG || XIG_DEBUG */
731
732
733
734
735
/* The default X/Y fullscreen offset is 0/0 */
xinerama_x = 0;
xinerama_y = 0;
736
#if SDL_VIDEO_DRIVER_X11_XINERAMA
737
/* Query Xinerama extention */
738
739
if ( SDL_NAME(XineramaQueryExtension)(SDL_Display, &i, &i) &&
SDL_NAME(XineramaIsActive)(SDL_Display) ) {
740
741
/* Find out which screen is the desired one */
int desired = 0;
742
int screens;
743
SDL_NAME(XineramaScreenInfo) *xinerama;
744
745
746
#ifdef XINERAMA_DEBUG
printf("X11 detected Xinerama:\n");
747
748
#endif
#if 0 /* Apparently the vidmode extension doesn't work with Xinerama */
749
const char *variable = SDL_getenv("SDL_VIDEO_X11_XINERAMA_SCREEN");
750
751
752
if ( variable ) {
desired = atoi(variable);
}
753
#endif
754
xinerama = SDL_NAME(XineramaQueryScreens)(SDL_Display, &screens);
755
756
757
758
759
760
761
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
762
if ( xinerama[i].screen_number == desired ) {
763
764
765
766
xinerama_x = xinerama[i].x_org;
xinerama_y = xinerama[i].y_org;
}
}
767
XFree(xinerama);
768
}
769
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
770
771
772
773
774
775
776
777
return 0;
}
int X11_SupportedVisual(_THIS, SDL_PixelFormat *format)
{
int i;
for(i = 0; i < this->hidden->nvisuals; i++)
778
779
if(this->hidden->visuals[i].bpp == format->BitsPerPixel)
return 1;
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
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 ) {
802
SDL_free(SDL_modelist[i]);
803
}
804
SDL_free(SDL_modelist);
805
806
SDL_modelist = NULL;
}
807
808
809
810
811
812
813
814
#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 */
815
816
817
818
819
820
}
int X11_ResizeFullScreen(_THIS)
{
int x, y;
int real_w, real_h;
821
822
823
824
825
int screen_w;
int screen_h;
screen_w = DisplayWidth(SDL_Display, SDL_Screen);
screen_h = DisplayHeight(SDL_Display, SDL_Screen);
826
827
828
x = xinerama_x;
y = xinerama_y;
829
830
if ( currently_fullscreen ) {
/* Switch resolution and cover it with the FSwindow */
831
move_cursor_to(this, x, y);
832
set_best_resolution(this, window_w, window_h);
833
move_cursor_to(this, x, y);
834
get_real_resolution(this, &real_w, &real_h);
835
if ( window_w > real_w ) {
836
837
real_w = MAX(real_w, screen_w);
}
838
if ( window_h > real_h ) {
839
840
real_h = MAX(real_h, screen_h);
}
841
XMoveResizeWindow(SDL_Display, FSwindow, x, y, real_w, real_h);
842
843
844
move_cursor_to(this, real_w/2, real_h/2);
/* Center and reparent the drawing window */
845
846
x = (real_w - window_w)/2;
y = (real_h - window_h)/2;
847
XReparentWindow(SDL_Display, SDL_Window, FSwindow, x, y);
848
/* FIXME: move the mouse to the old relative location */
849
XSync(SDL_Display, True); /* Flush spurious mode change events */
850
851
852
853
854
855
856
857
858
}
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) */
859
XSetInputFocus(SDL_Display, WMwindow, RevertToNone, CurrentTime);
860
861
862
863
864
865
866
867
868
869
#endif
}
int X11_EnterFullScreen(_THIS)
{
int okay;
#if 0
Window tmpwin, *windows;
int i, nwindows;
#endif
870
int real_w, real_h;
871
872
int screen_w;
int screen_h;
873
874
okay = 1;
875
876
877
if ( currently_fullscreen ) {
return(okay);
}
878
879
880
881
882
/* 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 */
883
884
screen_w = DisplayWidth(SDL_Display, SDL_Screen);
screen_h = DisplayHeight(SDL_Display, SDL_Screen);
885
get_real_resolution(this, &real_w, &real_h);
886
if ( window_w > real_w ) {
887
888
real_w = MAX(real_w, screen_w);
}
889
if ( window_h > real_h ) {
890
891
real_h = MAX(real_h, screen_h);
}
892
XMoveResizeWindow(SDL_Display, FSwindow,
893
xinerama_x, xinerama_y, real_w, real_h);
894
XMapRaised(SDL_Display, FSwindow);
895
X11_WaitMapped(this, FSwindow);
896
897
#if 0 /* This seems to break WindowMaker in focus-follows-mouse mode */
898
/* Make sure we got to the top of the window stack */
899
if ( XQueryTree(SDL_Display, SDL_Root, &tmpwin, &tmpwin,
900
901
902
903
904
905
&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 ) {
906
SDL_memcpy(&windows[i], &windows[i+1],
907
908
(nwindows-i-1)*sizeof(windows[i]));
break;
909
910
}
}
911
windows[nwindows-1] = FSwindow;
912
913
XRestackWindows(SDL_Display, windows, nwindows);
XSync(SDL_Display, False);
914
}
915
XFree(windows);
916
}
917
#else
918
XRaiseWindow(SDL_Display, FSwindow);
919
920
#endif
921
#if SDL_VIDEO_DRIVER_X11_VIDMODE
922
923
/* Save the current video mode */
if ( use_vidmode ) {
924
SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, True);
925
}
926
#endif
927
currently_fullscreen = 1;
928
929
930
931
932
933
934
935
/* Set the new resolution */
okay = X11_ResizeFullScreen(this);
if ( ! okay ) {
X11_LeaveFullScreen(this);
}
/* Set the colormap */
if ( SDL_XColorMap ) {
936
XInstallColormap(SDL_Display, SDL_XColorMap);
937
}
938
939
940
941
942
943
944
945
946
947
948
949
950
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);
}
}
951
952
953
954
955
956
return(okay);
}
int X11_LeaveFullScreen(_THIS)
{
if ( currently_fullscreen ) {
957
XReparentWindow(SDL_Display, SDL_Window, WMwindow, 0, 0);
958
#if SDL_VIDEO_DRIVER_X11_VIDMODE
959
960
if ( use_vidmode ) {
restore_mode(this);
961
SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, False);
962
963
}
#endif
964
965
#if SDL_VIDEO_DRIVER_X11_XME
966
967
968
if ( use_xme ) {
int rw, rh;
969
/* check current mode so we can avoid uneccessary mode changes */
970
971
972
973
974
975
976
977
978
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);
979
XSync(SDL_Display, False);
980
981
}
}
982
983
#endif
984
985
986
987
988
989
990
#if SDL_VIDEO_DRIVER_X11_XRANDR
if ( use_xrandr ) {
XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root,
saved_size_id, saved_rotation, CurrentTime);
}
#endif
991
XUnmapWindow(SDL_Display, FSwindow);
992
X11_WaitUnmapped(this, FSwindow);
993
XSync(SDL_Display, True); /* Flush spurious mode change events */
994
995
996
997
998
999
1000
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.
*/