This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_x11modes.c
965 lines (848 loc) · 28.6 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
/*#define X11MODES_DEBUG*/
37
38
#define MAX(a, b) (a > b ? a : b)
39
40
41
#if SDL_VIDEO_DRIVER_X11_VIDMODE
int
42
vidmode_refreshrate(SDL_NAME(XF86VidModeModeInfo) * mode)
43
{
44
45
46
return (mode->htotal
&& mode->vtotal) ? (1000 * mode->dotclock / (mode->htotal *
mode->vtotal)) : 0;
47
48
49
}
#endif
50
#if SDL_VIDEO_DRIVER_X11_VIDMODE
51
52
Bool SDL_NAME(XF86VidModeGetModeInfo) (Display * dpy, int scr,
SDL_NAME(XF86VidModeModeInfo) * info)
53
{
54
55
56
57
58
SDL_NAME(XF86VidModeModeLine) * l =
(SDL_NAME(XF86VidModeModeLine) *) ((char *) info +
sizeof info->dotclock);
return SDL_NAME(XF86VidModeGetModeLine) (dpy, scr,
(int *) &info->dotclock, l);
59
}
60
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
61
62
#if SDL_VIDEO_DRIVER_X11_VIDMODE
63
static void
64
save_mode(_THIS)
65
{
66
67
68
69
SDL_memset(&saved_mode, 0, sizeof(saved_mode));
SDL_NAME(XF86VidModeGetModeInfo) (SDL_Display, SDL_Screen, &saved_mode);
SDL_NAME(XF86VidModeGetViewPort) (SDL_Display, SDL_Screen, &saved_view.x,
&saved_view.y);
70
71
72
}
#endif
73
#if SDL_VIDEO_DRIVER_X11_VIDMODE
74
static void
75
restore_mode(_THIS)
76
{
77
SDL_NAME(XF86VidModeModeLine) mode;
78
79
int unused;
80
if (SDL_NAME(XF86VidModeGetModeLine)
81
82
83
(SDL_Display, SDL_Screen, &unused, &mode)) {
if ((saved_mode.hdisplay != mode.hdisplay) ||
(saved_mode.vdisplay != mode.vdisplay)) {
84
85
SDL_NAME(XF86VidModeSwitchToMode) (SDL_Display, SDL_Screen,
&saved_mode);
86
87
}
}
88
if ((saved_view.x != 0) || (saved_view.y != 0)) {
89
90
SDL_NAME(XF86VidModeSetViewPort) (SDL_Display, SDL_Screen,
saved_view.x, saved_view.y);
91
92
93
94
}
}
#endif
95
static void get_real_resolution(_THIS, int *w, int *h);
96
97
static void
98
set_best_resolution(_THIS, int width, int height)
99
{
100
SDL_DisplayMode mode;
101
102
103
104
105
mode.format = 0;
mode.w = width;
mode.h = height;
mode.refresh_rate = 0;
106
SDL_GetClosestDisplayMode(&mode, &mode, SDL_FULLSCREEN);
107
108
#if SDL_VIDEO_DRIVER_X11_VIDMODE
109
if (use_vidmode) {
110
111
112
SDL_NAME(XF86VidModeModeLine) vmode;
SDL_NAME(XF86VidModeModeInfo) vinfo;
SDL_NAME(XF86VidModeModeInfo) ** modes;
113
int i, dotclock;
114
int nmodes;
115
int best = -1;
116
117
if (SDL_NAME(XF86VidModeGetModeLine)
118
(SDL_Display, SDL_Screen, &dotclock, &vmode)
119
120
121
&& SDL_NAME(XF86VidModeGetAllModeLines) (SDL_Display,
SDL_Screen, &nmodes,
&modes)) {
122
vinfo.dotclock = dotclock;
123
SDL_memcpy(&vinfo.hdisplay, &vmode, sizeof(vmode));
124
125
126
127
for (i = 0; i < nmodes; i++) {
if ((modes[i]->hdisplay == mode.w) &&
(modes[i]->vdisplay == mode.h) &&
128
(vidmode_refreshrate(modes[i]) == mode.refresh_rate)) {
129
130
131
best = i;
break;
}
132
}
133
134
135
if (best >= 0 &&
((modes[best]->hdisplay != vmode.hdisplay) ||
(modes[best]->vdisplay != vmode.vdisplay) ||
136
137
(vidmode_refreshrate(modes[best]) !=
vidmode_refreshrate(&vinfo)))) {
138
#ifdef X11MODES_DEBUG
139
140
141
printf("Best Mode %d: %d x %d @ %d\n", best,
modes[best]->hdisplay, modes[best]->vdisplay,
vidmode_refreshrate(modes[best]));
142
#endif
143
144
SDL_NAME(XF86VidModeSwitchToMode) (SDL_Display,
SDL_Screen, modes[best]);
145
}
146
XFree(modes);
147
148
}
}
149
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
150
151
/* XiG */
152
#if SDL_VIDEO_DRIVER_X11_XME
153
if (use_xme) {
154
int i;
155
int w, h;
156
157
/* check current mode so we can avoid uneccessary mode changes */
158
get_real_resolution(this, &w, &h);
159
160
if ((mode.w != w) || (mode.h != h)) {
161
#ifdef X11MODES_DEBUG
162
163
fprintf(stderr, "XME: set_best_resolution: "
"XiGMiscChangeResolution: %d %d\n", mode.w, mode.h);
164
#endif
165
166
167
XiGMiscChangeResolution(SDL_Display, SDL_Screen, 0, /* view */
mode.w, mode.h, 0);
XSync(SDL_Display, False);
168
169
}
}
170
#endif /* SDL_VIDEO_DRIVER_X11_XME */
171
172
#if SDL_VIDEO_DRIVER_X11_XRANDR
173
if (use_xrandr) {
174
175
176
177
int i, nsizes;
XRRScreenSize *sizes;
/* find the smallest resolution that is at least as big as the user requested */
178
sizes = XRRConfigSizes(screen_config, &nsizes);
179
180
for (i = (nsizes - 1); i >= 0; i--) {
if ((mode.w >= width) && (mode.h >= height)) {
181
break;
182
}
183
}
184
185
if (i >= 0) { /* found one, lets try it */
186
int w, h;
187
188
/* check current mode so we can avoid uneccessary mode changes */
189
get_real_resolution(this, &w, &h);
190
191
if ((mode.w != w) || (mode.h != h)) {
192
int size_id;
193
194
#ifdef X11MODES_DEBUG
195
196
fprintf(stderr, "XRANDR: set_best_resolution: "
"XXRSetScreenConfig: %d %d\n", mode.w, mode.h);
197
198
#endif
199
/* find the matching size entry index */
200
201
202
for (size_id = 0; size_id < nsizes; ++size_id) {
if ((sizes[size_id].width == mode.w) &&
(sizes[size_id].height == mode.h))
203
break;
204
}
205
206
207
208
XRRSetScreenConfig(SDL_Display, screen_config,
SDL_Root, size_id, saved_rotation,
CurrentTime);
209
210
211
212
}
}
}
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
213
214
}
215
static void
216
get_real_resolution(_THIS, int *w, int *h)
217
{
218
#if SDL_VIDEO_DRIVER_X11_XME
219
if (use_xme) {
220
221
222
int ractive;
XiGMiscResolutionInfo *modelist;
223
224
XiGMiscQueryResolutions(SDL_Display, SDL_Screen, 0, /* view */
&ractive, &modelist);
225
226
*w = modelist[ractive].width;
*h = modelist[ractive].height;
227
#ifdef X11MODES_DEBUG
228
fprintf(stderr, "XME: get_real_resolution: w = %d h = %d\n", *w, *h);
229
#endif
230
XFree(modelist);
231
232
return;
}
233
234
#endif /* SDL_VIDEO_DRIVER_X11_XME */
235
#if SDL_VIDEO_DRIVER_X11_VIDMODE
236
if (use_vidmode) {
237
SDL_NAME(XF86VidModeModeLine) mode;
238
239
int unused;
240
if (SDL_NAME(XF86VidModeGetModeLine)
241
(SDL_Display, SDL_Screen, &unused, &mode)) {
242
243
244
245
246
247
248
*w = mode.hdisplay;
*h = mode.vdisplay;
return;
}
}
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
249
#if SDL_VIDEO_DRIVER_X11_XRANDR
250
if (use_xrandr) {
251
int nsizes;
252
XRRScreenSize *sizes;
253
254
sizes = XRRConfigSizes(screen_config, &nsizes);
255
if (nsizes > 0) {
256
257
258
int cur_size;
Rotation cur_rotation;
259
cur_size =
260
XRRConfigCurrentConfiguration(screen_config, &cur_rotation);
261
if (cur_size >= 0 && cur_size < nsizes) {
262
263
264
*w = sizes[cur_size].width;
*h = sizes[cur_size].height;
}
265
#ifdef X11MODES_DEBUG
266
267
fprintf(stderr,
"XRANDR: get_real_resolution: w = %d h = %d\n", *w, *h);
268
269
270
271
272
#endif
return;
}
}
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
273
274
#if SDL_VIDEO_DRIVER_X11_XINERAMA
275
276
277
if (use_xinerama) {
*w = xinerama[this->current_display].width;
*h = xinerama[this->current_display].height;
278
279
280
281
return;
}
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
282
283
*w = DisplayWidth(SDL_Display, SDL_Screen);
*h = DisplayHeight(SDL_Display, SDL_Screen);
284
285
286
}
/* Called after mapping a window - waits until the window is mapped */
287
void
288
X11_WaitMapped(_THIS, Window win)
289
290
291
{
XEvent event;
do {
292
XMaskEvent(SDL_Display, StructureNotifyMask, &event);
293
294
}
while ((event.type != MapNotify) || (event.xmap.event != win));
295
296
297
}
/* Called after unmapping a window - waits until the window is unmapped */
298
void
299
X11_WaitUnmapped(_THIS, Window win)
300
301
302
{
XEvent event;
do {
303
XMaskEvent(SDL_Display, StructureNotifyMask, &event);
304
305
}
while ((event.type != UnmapNotify) || (event.xunmap.event != win));
306
307
}
308
static void
309
move_cursor_to(_THIS, int x, int y)
310
{
311
XWarpPointer(SDL_Display, None, SDL_Root, 0, 0, 0, 0, x, y);
312
313
}
314
static int
315
add_visual(_THIS, int depth, int class)
316
317
{
XVisualInfo vi;
318
if (XMatchVisualInfo(SDL_Display, SDL_Screen, depth, class, &vi)) {
319
320
321
322
int n = this->hidden->nvisuals;
this->hidden->visuals[n].depth = vi.depth;
this->hidden->visuals[n].visual = vi.visual;
this->hidden->nvisuals++;
323
}
324
return (this->hidden->nvisuals);
325
}
326
static int
327
add_visual_byid(_THIS, const char *visual_id)
328
329
330
331
{
XVisualInfo *vi, template;
int nvis;
332
if (visual_id) {
333
334
335
SDL_memset(&template, 0, (sizeof template));
template.visualid = SDL_strtol(visual_id, NULL, 0);
vi = XGetVisualInfo(SDL_Display, VisualIDMask, &template, &nvis);
336
if (vi) {
337
338
339
340
int n = this->hidden->nvisuals;
this->hidden->visuals[n].depth = vi->depth;
this->hidden->visuals[n].visual = vi->visual;
this->hidden->nvisuals++;
341
XFree(vi);
342
343
344
345
346
347
}
}
return (this->hidden->nvisuals);
}
int
348
X11_GetVisuals(_THIS)
349
350
351
352
353
354
355
356
357
358
359
360
{
/* It's interesting to note that if we allow 32 bit depths,
we get a visual with an alpha mask on composite servers.
static int depth_list[] = { 32, 24, 16, 15, 8 };
*/
static int depth_list[] = { 24, 16, 15, 8 };
int i, 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 */
361
if (SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR")) {
362
363
364
use_directcolor = 0;
}
this->hidden->nvisuals = 0;
365
366
if (!add_visual_byid(this, SDL_getenv("SDL_VIDEO_X11_VISUALID"))) {
for (i = 0; i < SDL_arraysize(depth_list); ++i) {
367
368
if (depth_list[i] > 8) {
if (use_directcolor) {
369
add_visual(this, depth_list[i], DirectColor);
370
}
371
add_visual(this, depth_list[i], TrueColor);
372
} else {
373
374
add_visual(this, depth_list[i], PseudoColor);
add_visual(this, depth_list[i], StaticColor);
375
}
376
377
}
}
378
if (this->hidden->nvisuals == 0) {
379
SDL_SetError("Found no sufficiently capable X11 visuals");
380
381
382
383
return -1;
}
/* look up the pixel quantum for each depth */
384
pf = XListPixmapFormats(SDL_Display, &np);
385
386
387
388
389
390
391
392
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;
}
393
XFree(pf);
394
return 0;
395
396
397
398
399
}
/* Global for the error handler */
int vm_event, vm_error = -1;
400
#if SDL_VIDEO_DRIVER_X11_XINERAMA
401
static int
402
CheckXinerama(_THIS, int *major, int *minor)
403
404
405
406
407
408
409
{
const char *env;
/* Default the extension not available */
*major = *minor = 0;
/* Allow environment override */
410
411
env = getenv("SDL_VIDEO_X11_XINERAMA");
if (env && !SDL_atoi(env)) {
412
413
414
415
return 0;
}
/* Query the extension version */
416
417
if (!SDL_NAME(XineramaQueryExtension) (SDL_Display, major, minor) ||
!SDL_NAME(XineramaIsActive) (SDL_Display)) {
418
419
420
421
422
423
424
return 0;
}
return 1;
}
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
#if SDL_VIDEO_DRIVER_X11_XRANDR
425
static int
426
CheckXRandR(_THIS, int *major, int *minor)
427
428
429
430
431
432
433
{
const char *env;
/* Default the extension not available */
*major = *minor = 0;
/* Allow environment override */
434
435
env = getenv("SDL_VIDEO_X11_XRANDR");
if (env && !SDL_atoi(env)) {
436
437
438
439
return 0;
}
/* This defaults off now, due to KDE window maximize problems */
440
if (!env) {
441
442
443
return 0;
}
444
if (!SDL_X11_HAVE_XRANDR) {
445
446
447
448
return 0;
}
/* Query the extension version */
449
if (!XRRQueryVersion(SDL_Display, major, minor)) {
450
451
452
453
454
455
456
return 0;
}
return 1;
}
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
#if SDL_VIDEO_DRIVER_X11_VIDMODE
457
static int
458
CheckVidMode(_THIS, int *major, int *minor)
459
460
461
462
463
464
465
{
const char *env;
/* Default the extension not available */
*major = *minor = 0;
/* Allow environment override */
466
467
env = getenv("SDL_VIDEO_X11_VIDMODE");
if (env && !SDL_atoi(env)) {
468
469
return 0;
}
470
471
472
473
/* Metro-X 4.3.0 and earlier has a broken implementation of
XF86VidModeGetAllModeLines() - it hangs the client.
*/
474
if (SDL_strcmp(ServerVendor(SDL_Display), "Metro Link Incorporated") == 0) {
475
476
FILE *metro_fp;
477
metro_fp = fopen("/usr/X11R6/lib/X11/Metro/.version", "r");
478
if (metro_fp != NULL) {
479
int major, minor, patch, version;
480
481
482
major = 0;
minor = 0;
patch = 0;
483
484
fscanf(metro_fp, "%d.%d.%d", &major, &minor, &patch);
fclose(metro_fp);
485
486
version = major * 100 + minor * 10 + patch;
if (version < 431) {
487
488
489
490
491
492
493
return 0;
}
}
}
/* Query the extension version */
vm_error = -1;
494
if (!SDL_NAME(XF86VidModeQueryExtension)
495
(SDL_Display, &vm_event, &vm_error)
496
|| !SDL_NAME(XF86VidModeQueryVersion) (SDL_Display, major, minor)) {
497
498
499
500
501
502
503
return 0;
}
return 1;
}
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
#if SDL_VIDEO_DRIVER_X11_XME
504
static int
505
CheckXME(_THIS, int *major, int *minor)
506
507
508
509
510
511
512
{
const char *env;
/* Default the extension not available */
*major = *minor = 0;
/* Allow environment override */
513
514
env = getenv("SDL_VIDEO_X11_VIDMODE");
if (env && !SDL_atoi(env)) {
515
516
return 0;
}
517
518
/* Query the extension version */
519
if (!XiGMiscQueryVersion(SDL_Display, major, minor)) {
520
521
522
523
524
525
return 0;
}
return 1;
}
#endif /* SDL_VIDEO_DRIVER_X11_XME */
526
int
527
X11_GetVideoModes(_THIS)
528
{
529
530
531
532
533
534
535
#if SDL_VIDEO_DRIVER_X11_XINERAMA
int xinerama_major, xinerama_minor;
#endif
#if SDL_VIDEO_DRIVER_X11_XRANDR
int xrandr_major, xrandr_minor;
int nsizes;
XRRScreenSize *sizes;
536
537
int nrates;
short *rates;
538
#endif
539
#if SDL_VIDEO_DRIVER_X11_VIDMODE
540
541
int vm_major, vm_minor;
int nmodes;
542
SDL_NAME(XF86VidModeModeInfo) ** modes;
543
#endif
544
#if SDL_VIDEO_DRIVER_X11_XME
545
546
547
int xme_major, xme_minor;
int ractive, nummodes;
XiGMiscResolutionInfo *modelist;
548
#endif
549
int i;
550
551
int screen_w;
int screen_h;
552
SDL_DisplayMode mode;
553
554
use_xinerama = 0;
555
use_xrandr = 0;
556
557
use_vidmode = 0;
use_xme = 0;
558
559
screen_w = DisplayWidth(SDL_Display, SDL_Screen);
screen_h = DisplayHeight(SDL_Display, SDL_Screen);
560
561
562
563
564
mode.format = this->displays[this->current_display].desktop_mode.format;
mode.w = screen_w;
mode.h = screen_h;
mode.refresh_rate = 0;
565
SDL_AddDisplayMode(0, &mode);
566
567
568
#if SDL_VIDEO_DRIVER_X11_XINERAMA
/* Query Xinerama extention */
569
if (CheckXinerama(this, &xinerama_major, &xinerama_minor)) {
570
571
572
int screens;
#ifdef X11MODES_DEBUG
573
printf("X11 detected Xinerama:\n");
574
#endif
575
xinerama = SDL_NAME(XineramaQueryScreens) (SDL_Display, &screens);
576
for (i = 0; i < screens; i++) {
577
#ifdef X11MODES_DEBUG
578
579
580
581
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);
582
#endif
583
if (xinerama[i].screen_number != 0) {
584
SDL_AddVideoDisplay(&mode);
585
}
586
587
mode.w = xinerama[i].width;
mode.h = xinerama[i].height;
588
SDL_AddDisplayMode(xinerama[i].screen_number, &mode);
589
}
590
use_xinerama = 1;
591
592
593
}
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
594
#if SDL_VIDEO_DRIVER_X11_XRANDR
595
/* XRandR */
596
/* require at least XRandR v1.0 (arbitrary) */
597
if (CheckXRandR(this, &xrandr_major, &xrandr_minor)
598
&& (xrandr_major >= 1)) {
599
#ifdef X11MODES_DEBUG
600
601
fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n",
xrandr_major, xrandr_minor);
602
603
604
605
#endif
/* save the screen configuration since we must reference it
each time we toggle modes.
606
*/
607
screen_config = XRRGetScreenInfo(SDL_Display, SDL_Root);
608
609
/* retrieve the list of resolution */
610
sizes = XRRConfigSizes(screen_config, &nsizes);
611
if (nsizes > 0) {
612
613
614
615
for (i = 0; i < nsizes; i++) {
mode.w = sizes[i].width;
mode.h = sizes[i].height;
616
rates = XRRConfigRates(screen_config, i, &nrates);
617
618
if (nrates == 0) {
mode.refresh_rate = 0;
619
SDL_AddDisplayMode(0, &mode);
620
621
622
623
} else {
int j;
for (j = 0; j < nrates; ++j) {
mode.refresh_rate = rates[j];
624
SDL_AddDisplayMode(0, &mode);
625
}
626
}
627
}
628
629
use_xrandr = xrandr_major * 100 + xrandr_minor;
630
saved_size_id =
631
XRRConfigCurrentConfiguration(screen_config, &saved_rotation);
632
633
634
635
}
}
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
636
#if SDL_VIDEO_DRIVER_X11_VIDMODE
637
/* XVidMode */
638
if (!use_xrandr &&
639
640
641
CheckVidMode(this, &vm_major, &vm_minor) &&
SDL_NAME(XF86VidModeGetAllModeLines) (SDL_Display, SDL_Screen,
&nmodes, &modes)) {
642
#ifdef X11MODES_DEBUG
643
printf("VidMode modes: (unsorted)\n");
644
for (i = 0; i < nmodes; ++i) {
645
646
647
printf("Mode %d: %d x %d @ %d\n", i,
modes[i]->hdisplay, modes[i]->vdisplay,
vidmode_refreshrate(modes[i]));
648
649
}
#endif
650
651
652
for (i = 0; i < nmodes; ++i) {
mode.w = modes[i]->hdisplay;
mode.h = modes[i]->vdisplay;
653
654
mode.refresh_rate = vidmode_refreshrate(modes[i]);
SDL_AddDisplayMode(0, &mode);
655
}
656
XFree(modes);
657
658
use_vidmode = vm_major * 100 + vm_minor;
659
save_mode(this);
660
}
661
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
662
663
#if SDL_VIDEO_DRIVER_X11_XME
664
/* XiG */
665
modelist = NULL;
666
/* first lets make sure we have the extension, and it's at least v2.0 */
667
668
669
if (CheckXME(this, &xme_major, &xme_minor) && xme_major >= 2 && (nummodes = XiGMiscQueryResolutions(SDL_Display, SDL_Screen, 0, /* view */
&ractive,
&modelist))
670
> 1) { /* then we actually have some */
671
672
673
/* We get the list already sorted in descending order.
We'll copy it in reverse order so SDL is happy */
#ifdef X11MODES_DEBUG
674
675
fprintf(stderr, "XME: nummodes = %d, active mode = %d\n",
nummodes, ractive);
676
#endif
677
678
mode.refresh_rate = 0;
for (i = 0; i < nummodes; ++i) {
679
#ifdef X11MODES_DEBUG
680
681
fprintf(stderr, "XME: mode = %4d, w = %4d, h = %4d\n",
i, modelist[i].width, modelist[i].height);
682
#endif
683
684
mode.w = modelist[i].width;
mode.h = modelist[i].height;
685
SDL_AddDisplayMode(0, &mode);
686
}
687
688
use_xme = xme_major * 100 + xme_minor;
689
saved_res = modelist[ractive]; /* save the current resolution */
690
}
691
if (modelist) {
692
XFree(modelist);
693
}
694
#endif /* SDL_VIDEO_DRIVER_X11_XME */
695
696
#ifdef X11MODES_DEBUG
697
if (use_xinerama) {
698
printf("Xinerama is enabled\n");
699
700
}
701
if (use_xrandr) {
702
printf("XRandR is enabled\n");
703
}
704
705
if (use_vidmode) {
706
printf("VidMode is enabled\n");
707
}
708
709
if (use_xme) {
710
printf("Xi Graphics XME fullscreen is enabled\n");
711
}
712
#endif /* X11MODES_DEBUG */
713
714
715
716
return 0;
}
717
void
718
X11_FreeVideoModes(_THIS)
719
{
720
721
#if SDL_VIDEO_DRIVER_X11_XRANDR
/* Free the Xrandr screen configuration */
722
if (screen_config) {
723
XRRFreeScreenConfigInfo(screen_config);
724
725
726
screen_config = NULL;
}
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
727
728
}
729
int
730
X11_ResizeFullScreen(_THIS)
731
{
732
int x = 0, y = 0;
733
int real_w, real_h;
734
735
736
int screen_w;
int screen_h;
737
738
screen_w = DisplayWidth(SDL_Display, SDL_Screen);
screen_h = DisplayHeight(SDL_Display, SDL_Screen);
739
740
#if SDL_VIDEO_DRIVER_X11_XINERAMA
741
742
743
744
745
if (use_xinerama &&
window_w <= xinerama[this->current_display].width &&
window_h <= xinerama[this->current_display].height) {
x = xinerama[this->current_display].x_org;
y = xinerama[this->current_display].y_org;
746
}
747
748
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
749
if (currently_fullscreen) {
750
/* Switch resolution and cover it with the FSwindow */
751
752
753
754
move_cursor_to(this, x, y);
set_best_resolution(this, window_w, window_h);
move_cursor_to(this, x, y);
get_real_resolution(this, &real_w, &real_h);
755
if (window_w > real_w) {
756
real_w = MAX(real_w, screen_w);
757
}
758
if (window_h > real_h) {
759
real_h = MAX(real_h, screen_h);
760
}
761
762
XMoveResizeWindow(SDL_Display, FSwindow, x, y, real_w, real_h);
move_cursor_to(this, real_w / 2, real_h / 2);
763
764
/* Center and reparent the drawing window */
765
766
x = (real_w - window_w) / 2;
y = (real_h - window_h) / 2;
767
XReparentWindow(SDL_Display, SDL_Window, FSwindow, x, y);
768
/* FIXME: move the mouse to the old relative location */
769
XSync(SDL_Display, True); /* Flush spurious mode change events */
770
}
771
return (1);
772
773
}
774
void
775
X11_QueueEnterFullScreen(_THIS)
776
777
{
switch_waiting = 0x01 | SDL_FULLSCREEN;
778
switch_time = SDL_GetTicks() + 1500;
779
#if 0 /* This causes a BadMatch error if the window is iconified (not needed) */
780
XSetInputFocus(SDL_Display, WMwindow, RevertToNone, CurrentTime);
781
782
783
#endif
}
784
int
785
X11_EnterFullScreen(_THIS)
786
787
788
789
790
791
{
int okay;
#if 0
Window tmpwin, *windows;
int i, nwindows;
#endif
792
int x = 0, y = 0;
793
int real_w, real_h;
794
795
int screen_w;
int screen_h;
796
797
okay = 1;
798
799
if (currently_fullscreen) {
return (okay);
800
}
801
802
/* Ungrab the input so that we can move the mouse around */
803
X11_GrabInputNoLock(this, SDL_GRAB_OFF);
804
805
#if SDL_VIDEO_DRIVER_X11_XINERAMA
806
807
808
809
810
if (use_xinerama &&
window_w <= xinerama[this->current_display].width &&
window_h <= xinerama[this->current_display].height) {
x = xinerama[this->current_display].x_org;
y = xinerama[this->current_display].y_org;
811
}
812
813
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
814
/* Map the fullscreen window to blank the screen */
815
816
817
screen_w = DisplayWidth(SDL_Display, SDL_Screen);
screen_h = DisplayHeight(SDL_Display, SDL_Screen);
get_real_resolution(this, &real_w, &real_h);
818
if (window_w > real_w) {
819
real_w = MAX(real_w, screen_w);
820
}
821
if (window_h > real_h) {
822
real_h = MAX(real_h, screen_h);
823
}
824
825
826
XMoveResizeWindow(SDL_Display, FSwindow, x, y, real_w, real_h);
XMapRaised(SDL_Display, FSwindow);
X11_WaitMapped(this, FSwindow);
827
828
#if 0 /* This seems to break WindowMaker in focus-follows-mouse mode */
829
/* Make sure we got to the top of the window stack */
830
831
if (XQueryTree(SDL_Display, SDL_Root, &tmpwin, &tmpwin,
&windows, &nwindows) && windows) {
832
/* If not, try to put us there - if fail... oh well */
833
834
835
836
if (windows[nwindows - 1] != FSwindow) {
tmpwin = windows[nwindows - 1];
for (i = 0; i < nwindows; ++i) {
if (windows[i] == FSwindow) {
837
838
SDL_memcpy(&windows[i], &windows[i + 1],
(nwindows - i - 1) * sizeof(windows[i]));
839
break;
840
841
}
}
842
windows[nwindows - 1] = FSwindow;
843
844
XRestackWindows(SDL_Display, windows, nwindows);
XSync(SDL_Display, False);
845
}
846
XFree(windows);
847
}
848
#else
849
XRaiseWindow(SDL_Display, FSwindow);
850
851
#endif
852
#if SDL_VIDEO_DRIVER_X11_VIDMODE
853
/* Save the current video mode */
854
if (use_vidmode) {
855
SDL_NAME(XF86VidModeLockModeSwitch) (SDL_Display, SDL_Screen, True);
856
}
857
#endif
858
currently_fullscreen = 1;
859
860
/* Set the new resolution */
861
okay = X11_ResizeFullScreen(this);
862
if (!okay) {
863
X11_LeaveFullScreen(this);
864
865
}
/* Set the colormap */
866
if (SDL_XColorMap) {
867
XInstallColormap(SDL_Display, SDL_XColorMap);
868
}
869
if (okay) {
870
871
872
X11_GrabInputNoLock(this,
SDL_CurrentWindow.
input_grab | SDL_GRAB_FULLSCREEN);
873
}
874
875
876
/* 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. */
877
878
if (SDL_VideoSurface) {
if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) {
879
SDL_PrivateExpose();
880
} else {
881
X11_RefreshDisplay(this);
882
883
884
}
}
885
return (okay);
886
887
}
888
int
889
X11_LeaveFullScreen(_THIS)
890
{
891
if (currently_fullscreen) {
892
XReparentWindow(SDL_Display, SDL_Window, WMwindow, 0, 0);
893
#if SDL_VIDEO_DRIVER_X11_VIDMODE
894
if (use_vidmode) {
895
896
897
restore_mode(this);
SDL_NAME(XF86VidModeLockModeSwitch) (SDL_Display, SDL_Screen,
False);
898
899
}
#endif
900
901
#if SDL_VIDEO_DRIVER_X11_XME
902
903
904
if (use_xme) {
int rw, rh;
905
/* check current mode so we can avoid uneccessary mode changes */
906
get_real_resolution(this, &rw, &rh);
907
908
if (rw != saved_res.width || rh != saved_res.height) {
909
910
911
XiGMiscChangeResolution(SDL_Display, SDL_Screen, 0, /* view */
saved_res.width, saved_res.height, 0);
XSync(SDL_Display, False);
912
913
}
}
914
915
#endif
916
#if SDL_VIDEO_DRIVER_X11_XRANDR
917
if (use_xrandr) {
918
919
XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root,
saved_size_id, saved_rotation, CurrentTime);
920
921
922
}
#endif
923
924
925
XUnmapWindow(SDL_Display, FSwindow);
X11_WaitUnmapped(this, FSwindow);
XSync(SDL_Display, True); /* Flush spurious mode change events */
926
927
928
929
930
931
932
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.
*/
933
934
X11_GrabInputNoLock(this,
SDL_CurrentWindow.input_grab & ~SDL_GRAB_FULLSCREEN);
935
936
937
/* 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. */
938
939
if (SDL_VideoSurface) {
if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) {
940
SDL_PrivateExpose();
941
} else {
942
X11_RefreshDisplay(this);
943
944
945
}
}
946
return (0);
947
}
948
949
Uint32
950
X11_VisualToFormat(const Visual * visual, int depth, int bpp)
951
952
953
954
955
956
957
958
959
960
961
{
Uint32 Rmask = visual->red_mask;
Uint32 Gmask = visual->green_mask;
Uint32 Bmask = visual->blue_mask;
Uint32 Amask;
if (depth == 32) {
Amask = (0xFFFFFFFF & ~(Rmask | Gmask | Bmask));
} else {
Amask = 0;
}
962
return (SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask));
963
964
965
}
/* vi: set ts=4 sw=4 expandtab: */