diff options
Diffstat (limited to 'apps/plugins/sdl/src/video/x11/SDL_x11modes.c')
-rw-r--r-- | apps/plugins/sdl/src/video/x11/SDL_x11modes.c | 1143 |
1 files changed, 1143 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/video/x11/SDL_x11modes.c b/apps/plugins/sdl/src/video/x11/SDL_x11modes.c new file mode 100644 index 0000000000..c232e6aa36 --- /dev/null +++ b/apps/plugins/sdl/src/video/x11/SDL_x11modes.c | |||
@@ -0,0 +1,1143 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 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 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | 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 | /* Utilities for getting and setting the X display mode */ | ||
25 | |||
26 | #include <stdio.h> | ||
27 | |||
28 | #include "SDL_timer.h" | ||
29 | #include "SDL_events.h" | ||
30 | #include "../../events/SDL_events_c.h" | ||
31 | #include "SDL_x11video.h" | ||
32 | #include "SDL_x11wm_c.h" | ||
33 | #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 | #if SDL_VIDEO_DRIVER_X11_XRANDR | ||
41 | static int cmpmodelist(const void *va, const void *vb) | ||
42 | { | ||
43 | const SDL_Rect *a = *(const SDL_Rect **)va; | ||
44 | const SDL_Rect *b = *(const SDL_Rect **)vb; | ||
45 | if ( a->w == b->w ) | ||
46 | return b->h - a->h; | ||
47 | else | ||
48 | return b->w - a->w; | ||
49 | } | ||
50 | #endif | ||
51 | |||
52 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
53 | Bool SDL_NAME(XF86VidModeGetModeInfo)(Display *dpy, int scr, SDL_NAME(XF86VidModeModeInfo) *info) | ||
54 | { | ||
55 | Bool retval; | ||
56 | int dotclock; | ||
57 | SDL_NAME(XF86VidModeModeLine) l; | ||
58 | SDL_memset(&l, 0, sizeof(l)); | ||
59 | retval = SDL_NAME(XF86VidModeGetModeLine)(dpy, scr, &dotclock, &l); | ||
60 | info->dotclock = dotclock; | ||
61 | info->hdisplay = l.hdisplay; | ||
62 | info->hsyncstart = l.hsyncstart; | ||
63 | info->hsyncend = l.hsyncend; | ||
64 | info->htotal = l.htotal; | ||
65 | info->hskew = l.hskew; | ||
66 | info->vdisplay = l.vdisplay; | ||
67 | info->vsyncstart = l.vsyncstart; | ||
68 | info->vsyncend = l.vsyncend; | ||
69 | info->vtotal = l.vtotal; | ||
70 | info->flags = l.flags; | ||
71 | info->privsize = l.privsize; | ||
72 | info->private = l.private; | ||
73 | return retval; | ||
74 | } | ||
75 | #endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ | ||
76 | |||
77 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
78 | static void save_mode(_THIS) | ||
79 | { | ||
80 | SDL_memset(&saved_mode, 0, sizeof(saved_mode)); | ||
81 | SDL_NAME(XF86VidModeGetModeInfo)(SDL_Display,SDL_Screen,&saved_mode); | ||
82 | SDL_NAME(XF86VidModeGetViewPort)(SDL_Display,SDL_Screen,&saved_view.x,&saved_view.y); | ||
83 | } | ||
84 | #endif | ||
85 | |||
86 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
87 | static void restore_mode(_THIS) | ||
88 | { | ||
89 | SDL_NAME(XF86VidModeModeLine) mode; | ||
90 | int unused; | ||
91 | |||
92 | if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) { | ||
93 | if ( (saved_mode.hdisplay != mode.hdisplay) || | ||
94 | (saved_mode.vdisplay != mode.vdisplay) ) { | ||
95 | SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, &saved_mode); | ||
96 | } | ||
97 | } | ||
98 | if ( (saved_view.x != 0) || (saved_view.y != 0) ) { | ||
99 | SDL_NAME(XF86VidModeSetViewPort)(SDL_Display, SDL_Screen, saved_view.x, saved_view.y); | ||
100 | } | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
105 | static int cmpmodes(const void *va, const void *vb) | ||
106 | { | ||
107 | const SDL_NAME(XF86VidModeModeInfo) *a = *(const SDL_NAME(XF86VidModeModeInfo)**)va; | ||
108 | const SDL_NAME(XF86VidModeModeInfo) *b = *(const SDL_NAME(XF86VidModeModeInfo)**)vb; | ||
109 | if ( a->hdisplay == b->hdisplay ) | ||
110 | return b->vdisplay - a->vdisplay; | ||
111 | else | ||
112 | return b->hdisplay - a->hdisplay; | ||
113 | } | ||
114 | #endif | ||
115 | |||
116 | static void get_real_resolution(_THIS, int* w, int* h); | ||
117 | |||
118 | static void set_best_resolution(_THIS, int width, int height) | ||
119 | { | ||
120 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
121 | if ( use_vidmode ) { | ||
122 | SDL_NAME(XF86VidModeModeLine) mode; | ||
123 | SDL_NAME(XF86VidModeModeInfo) **modes; | ||
124 | int i; | ||
125 | int nmodes; | ||
126 | int best = -1; | ||
127 | |||
128 | if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &i, &mode) && | ||
129 | SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes) ) { | ||
130 | for ( i = 0; i < nmodes ; i++ ) { | ||
131 | if ( (modes[i]->hdisplay == width) && | ||
132 | (modes[i]->vdisplay == height) ) { | ||
133 | best = i; | ||
134 | break; | ||
135 | } | ||
136 | if ( modes[i]->hdisplay >= width && | ||
137 | modes[i]->vdisplay >= height ) { | ||
138 | if ( best < 0 || | ||
139 | (modes[i]->hdisplay < modes[best]->hdisplay && | ||
140 | modes[i]->vdisplay <= modes[best]->vdisplay) || | ||
141 | (modes[i]->vdisplay < modes[best]->vdisplay && | ||
142 | modes[i]->hdisplay <= modes[best]->hdisplay) ) { | ||
143 | best = i; | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | if ( best >= 0 && | ||
148 | ((modes[best]->hdisplay != mode.hdisplay) || | ||
149 | (modes[best]->vdisplay != mode.vdisplay)) ) { | ||
150 | #ifdef X11MODES_DEBUG | ||
151 | printf("Best Mode %d: %d x %d @ %d\n", best, | ||
152 | modes[best]->hdisplay, modes[best]->vdisplay, | ||
153 | (modes[best]->htotal && modes[best]->vtotal) ? (1000 * modes[best]->dotclock / (modes[best]->htotal * modes[best]->vtotal)) : 0 ); | ||
154 | #endif | ||
155 | SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, modes[best]); | ||
156 | } | ||
157 | XFree(modes); | ||
158 | } | ||
159 | } | ||
160 | #endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ | ||
161 | |||
162 | /* XiG */ | ||
163 | #if SDL_VIDEO_DRIVER_X11_XME | ||
164 | if ( use_xme && SDL_modelist ) { | ||
165 | int i; | ||
166 | |||
167 | #ifdef X11MODES_DEBUG | ||
168 | fprintf(stderr, "XME: set_best_resolution(): w = %d, h = %d\n", | ||
169 | width, height); | ||
170 | #endif | ||
171 | for ( i=0; SDL_modelist[i]; ++i ) { | ||
172 | if ( (SDL_modelist[i]->w >= width) && | ||
173 | (SDL_modelist[i]->h >= height) ) { | ||
174 | break; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | if ( SDL_modelist[i] ) { /* found one, lets try it */ | ||
179 | int w, h; | ||
180 | |||
181 | /* check current mode so we can avoid uneccessary mode changes */ | ||
182 | get_real_resolution(this, &w, &h); | ||
183 | |||
184 | if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) { | ||
185 | #ifdef X11MODES_DEBUG | ||
186 | fprintf(stderr, "XME: set_best_resolution: " | ||
187 | "XiGMiscChangeResolution: %d %d\n", | ||
188 | SDL_modelist[i]->w, SDL_modelist[i]->h); | ||
189 | #endif | ||
190 | XiGMiscChangeResolution(SDL_Display, | ||
191 | SDL_Screen, | ||
192 | 0, /* view */ | ||
193 | SDL_modelist[i]->w, | ||
194 | SDL_modelist[i]->h, | ||
195 | 0); | ||
196 | XSync(SDL_Display, False); | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | #endif /* SDL_VIDEO_DRIVER_X11_XME */ | ||
201 | |||
202 | #if SDL_VIDEO_DRIVER_X11_XRANDR | ||
203 | if ( use_xrandr && SDL_modelist ) { | ||
204 | #ifdef X11MODES_DEBUG | ||
205 | fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n", | ||
206 | width, height); | ||
207 | #endif | ||
208 | int i, nsizes; | ||
209 | XRRScreenSize *sizes; | ||
210 | |||
211 | /* find the smallest resolution that is at least as big as the user requested */ | ||
212 | sizes = XRRConfigSizes(screen_config, &nsizes); | ||
213 | for ( i = (nsizes-1); i >= 0; i-- ) { | ||
214 | if ( (SDL_modelist[i]->w >= width) && | ||
215 | (SDL_modelist[i]->h >= height) ) { | ||
216 | break; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | if ( i >= 0 && SDL_modelist[i] ) { /* found one, lets try it */ | ||
221 | int w, h; | ||
222 | |||
223 | /* check current mode so we can avoid uneccessary mode changes */ | ||
224 | get_real_resolution(this, &w, &h); | ||
225 | |||
226 | if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) { | ||
227 | int size_id; | ||
228 | |||
229 | #ifdef X11MODES_DEBUG | ||
230 | fprintf(stderr, "XRANDR: set_best_resolution: " | ||
231 | "XXRSetScreenConfig: %d %d\n", | ||
232 | SDL_modelist[i]->w, SDL_modelist[i]->h); | ||
233 | #endif | ||
234 | |||
235 | /* find the matching size entry index */ | ||
236 | for ( size_id = 0; size_id < nsizes; ++size_id ) { | ||
237 | if ( (sizes[size_id].width == SDL_modelist[i]->w) && | ||
238 | (sizes[size_id].height == SDL_modelist[i]->h) ) | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, | ||
243 | size_id, saved_rotation, CurrentTime); | ||
244 | } | ||
245 | } | ||
246 | } | ||
247 | #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ | ||
248 | } | ||
249 | |||
250 | static void get_real_resolution(_THIS, int* w, int* h) | ||
251 | { | ||
252 | #if SDL_VIDEO_DRIVER_X11_XME | ||
253 | if ( use_xme ) { | ||
254 | int ractive; | ||
255 | XiGMiscResolutionInfo *modelist; | ||
256 | |||
257 | XiGMiscQueryResolutions(SDL_Display, SDL_Screen, | ||
258 | 0, /* view */ | ||
259 | &ractive, &modelist); | ||
260 | *w = modelist[ractive].width; | ||
261 | *h = modelist[ractive].height; | ||
262 | #ifdef X11MODES_DEBUG | ||
263 | fprintf(stderr, "XME: get_real_resolution: w = %d h = %d\n", *w, *h); | ||
264 | #endif | ||
265 | XFree(modelist); | ||
266 | return; | ||
267 | } | ||
268 | #endif /* SDL_VIDEO_DRIVER_X11_XME */ | ||
269 | |||
270 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
271 | if ( use_vidmode ) { | ||
272 | SDL_NAME(XF86VidModeModeLine) mode; | ||
273 | int unused; | ||
274 | |||
275 | if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) { | ||
276 | *w = mode.hdisplay; | ||
277 | *h = mode.vdisplay; | ||
278 | return; | ||
279 | } | ||
280 | } | ||
281 | #endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ | ||
282 | |||
283 | #if SDL_VIDEO_DRIVER_X11_XRANDR | ||
284 | if ( use_xrandr ) { | ||
285 | int nsizes; | ||
286 | XRRScreenSize* sizes; | ||
287 | |||
288 | sizes = XRRConfigSizes(screen_config, &nsizes); | ||
289 | if ( nsizes > 0 ) { | ||
290 | int cur_size; | ||
291 | Rotation cur_rotation; | ||
292 | |||
293 | cur_size = XRRConfigCurrentConfiguration(screen_config, &cur_rotation); | ||
294 | if ( cur_size >= 0 && cur_size < nsizes ) { | ||
295 | *w = sizes[cur_size].width; | ||
296 | *h = sizes[cur_size].height; | ||
297 | } | ||
298 | #ifdef X11MODES_DEBUG | ||
299 | fprintf(stderr, "XRANDR: get_real_resolution: w = %d h = %d\n", *w, *h); | ||
300 | #endif | ||
301 | return; | ||
302 | } | ||
303 | } | ||
304 | #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ | ||
305 | |||
306 | #if SDL_VIDEO_DRIVER_X11_XINERAMA | ||
307 | if ( use_xinerama ) { | ||
308 | *w = xinerama_info.width; | ||
309 | *h = xinerama_info.height; | ||
310 | return; | ||
311 | } | ||
312 | #endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ | ||
313 | |||
314 | *w = DisplayWidth(SDL_Display, SDL_Screen); | ||
315 | *h = DisplayHeight(SDL_Display, SDL_Screen); | ||
316 | } | ||
317 | |||
318 | /* Called after mapping a window - waits until the window is mapped */ | ||
319 | void X11_WaitMapped(_THIS, Window win) | ||
320 | { | ||
321 | XEvent event; | ||
322 | do { | ||
323 | XMaskEvent(SDL_Display, StructureNotifyMask, &event); | ||
324 | } while ( (event.type != MapNotify) || (event.xmap.event != win) ); | ||
325 | } | ||
326 | |||
327 | /* Called after unmapping a window - waits until the window is unmapped */ | ||
328 | void X11_WaitUnmapped(_THIS, Window win) | ||
329 | { | ||
330 | XEvent event; | ||
331 | do { | ||
332 | XMaskEvent(SDL_Display, StructureNotifyMask, &event); | ||
333 | } while ( (event.type != UnmapNotify) || (event.xunmap.event != win) ); | ||
334 | } | ||
335 | |||
336 | static void move_cursor_to(_THIS, int x, int y) | ||
337 | { | ||
338 | XWarpPointer(SDL_Display, None, SDL_Root, 0, 0, 0, 0, x, y); | ||
339 | } | ||
340 | |||
341 | static int add_default_visual(_THIS) | ||
342 | { | ||
343 | int i; | ||
344 | int n = this->hidden->nvisuals; | ||
345 | for (i=0; i<n; i++) { | ||
346 | if (this->hidden->visuals[i].visual == DefaultVisual(SDL_Display, SDL_Screen)) return n; | ||
347 | } | ||
348 | this->hidden->visuals[n].depth = DefaultDepth(SDL_Display, SDL_Screen);; | ||
349 | this->hidden->visuals[n].visual = DefaultVisual(SDL_Display, SDL_Screen);; | ||
350 | this->hidden->nvisuals++; | ||
351 | return(this->hidden->nvisuals); | ||
352 | } | ||
353 | static int add_visual(_THIS, int depth, int class) | ||
354 | { | ||
355 | XVisualInfo vi; | ||
356 | if(XMatchVisualInfo(SDL_Display, SDL_Screen, depth, class, &vi)) { | ||
357 | int n = this->hidden->nvisuals; | ||
358 | this->hidden->visuals[n].depth = vi.depth; | ||
359 | this->hidden->visuals[n].visual = vi.visual; | ||
360 | this->hidden->nvisuals++; | ||
361 | } | ||
362 | return(this->hidden->nvisuals); | ||
363 | } | ||
364 | static int add_visual_byid(_THIS, const char *visual_id) | ||
365 | { | ||
366 | XVisualInfo *vi, template; | ||
367 | int nvis; | ||
368 | |||
369 | if ( visual_id ) { | ||
370 | SDL_memset(&template, 0, (sizeof template)); | ||
371 | template.visualid = SDL_strtol(visual_id, NULL, 0); | ||
372 | vi = XGetVisualInfo(SDL_Display, VisualIDMask, &template, &nvis); | ||
373 | if ( vi ) { | ||
374 | int n = this->hidden->nvisuals; | ||
375 | this->hidden->visuals[n].depth = vi->depth; | ||
376 | this->hidden->visuals[n].visual = vi->visual; | ||
377 | this->hidden->nvisuals++; | ||
378 | XFree(vi); | ||
379 | } | ||
380 | } | ||
381 | return(this->hidden->nvisuals); | ||
382 | } | ||
383 | |||
384 | /* Global for the error handler */ | ||
385 | int vm_event, vm_error = -1; | ||
386 | |||
387 | #if SDL_VIDEO_DRIVER_X11_XINERAMA | ||
388 | static int CheckXinerama(_THIS, int *major, int *minor) | ||
389 | { | ||
390 | const char *env; | ||
391 | |||
392 | /* Default the extension not available */ | ||
393 | *major = *minor = 0; | ||
394 | |||
395 | /* Allow environment override */ | ||
396 | env = getenv("SDL_VIDEO_X11_XINERAMA"); | ||
397 | if ( env && !SDL_atoi(env) ) { | ||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | /* Query the extension version */ | ||
402 | if ( !SDL_NAME(XineramaQueryExtension)(SDL_Display, major, minor) || | ||
403 | !SDL_NAME(XineramaIsActive)(SDL_Display) ) { | ||
404 | return 0; | ||
405 | } | ||
406 | return 1; | ||
407 | } | ||
408 | #endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ | ||
409 | |||
410 | #if SDL_VIDEO_DRIVER_X11_XRANDR | ||
411 | static int CheckXRandR(_THIS, int *major, int *minor) | ||
412 | { | ||
413 | const char *env; | ||
414 | |||
415 | /* Default the extension not available */ | ||
416 | *major = *minor = 0; | ||
417 | |||
418 | /* Allow environment override */ | ||
419 | env = getenv("SDL_VIDEO_X11_XRANDR"); | ||
420 | if ( env && !SDL_atoi(env) ) { | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | /* This defaults off now, due to KDE window maximize problems */ | ||
425 | if ( !env ) { | ||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | if ( !SDL_X11_HAVE_XRANDR ) { | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | /* Query the extension version */ | ||
434 | if ( !XRRQueryVersion(SDL_Display, major, minor) ) { | ||
435 | return 0; | ||
436 | } | ||
437 | return 1; | ||
438 | } | ||
439 | #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ | ||
440 | |||
441 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
442 | static int CheckVidMode(_THIS, int *major, int *minor) | ||
443 | { | ||
444 | const char *env; | ||
445 | |||
446 | /* Default the extension not available */ | ||
447 | *major = *minor = 0; | ||
448 | |||
449 | /* Allow environment override */ | ||
450 | env = getenv("SDL_VIDEO_X11_VIDMODE"); | ||
451 | if ( env && !SDL_atoi(env) ) { | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | /* Metro-X 4.3.0 and earlier has a broken implementation of | ||
456 | XF86VidModeGetAllModeLines() - it hangs the client. | ||
457 | */ | ||
458 | if ( SDL_strcmp(ServerVendor(SDL_Display), "Metro Link Incorporated") == 0 ) { | ||
459 | FILE *metro_fp; | ||
460 | |||
461 | metro_fp = fopen("/usr/X11R6/lib/X11/Metro/.version", "r"); | ||
462 | if ( metro_fp != NULL ) { | ||
463 | int major, minor, patch, version, scannum; | ||
464 | major = 0; minor = 0; patch = 0; | ||
465 | scannum = fscanf(metro_fp, "%d.%d.%d", &major, &minor, &patch); | ||
466 | fclose(metro_fp); | ||
467 | if ( (scannum < 0) || (scannum > 3) ) { | ||
468 | return 0; /* we need _something_ useful from fscanf(). */ | ||
469 | } | ||
470 | version = major*100+minor*10+patch; | ||
471 | if ( version < 431 ) { | ||
472 | return 0; | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | |||
477 | /* Query the extension version */ | ||
478 | vm_error = -1; | ||
479 | if ( !SDL_NAME(XF86VidModeQueryExtension)(SDL_Display, &vm_event, &vm_error) || | ||
480 | !SDL_NAME(XF86VidModeQueryVersion)(SDL_Display, major, minor) ) { | ||
481 | return 0; | ||
482 | } | ||
483 | return 1; | ||
484 | } | ||
485 | #endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ | ||
486 | |||
487 | #if SDL_VIDEO_DRIVER_X11_XME | ||
488 | static int CheckXME(_THIS, int *major, int *minor) | ||
489 | { | ||
490 | const char *env; | ||
491 | |||
492 | /* Default the extension not available */ | ||
493 | *major = *minor = 0; | ||
494 | |||
495 | /* Allow environment override */ | ||
496 | env = getenv("SDL_VIDEO_X11_VIDMODE"); | ||
497 | if ( env && !SDL_atoi(env) ) { | ||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | /* Query the extension version */ | ||
502 | if ( !XiGMiscQueryVersion(SDL_Display, major, minor) ) { | ||
503 | return 0; | ||
504 | } | ||
505 | return 1; | ||
506 | } | ||
507 | #endif /* SDL_VIDEO_DRIVER_X11_XME */ | ||
508 | |||
509 | int X11_GetVideoModes(_THIS) | ||
510 | { | ||
511 | #if SDL_VIDEO_DRIVER_X11_XINERAMA | ||
512 | int xinerama_major, xinerama_minor; | ||
513 | #endif | ||
514 | #if SDL_VIDEO_DRIVER_X11_XRANDR | ||
515 | int xrandr_major, xrandr_minor; | ||
516 | int nsizes; | ||
517 | XRRScreenSize *sizes; | ||
518 | #endif | ||
519 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
520 | int vm_major, vm_minor; | ||
521 | int nmodes; | ||
522 | SDL_NAME(XF86VidModeModeInfo) **modes; | ||
523 | #endif | ||
524 | #if SDL_VIDEO_DRIVER_X11_XME | ||
525 | int xme_major, xme_minor; | ||
526 | int ractive, nummodes; | ||
527 | XiGMiscResolutionInfo *modelist; | ||
528 | #endif | ||
529 | int i, n; | ||
530 | int screen_w; | ||
531 | int screen_h; | ||
532 | |||
533 | use_xinerama = 0; | ||
534 | use_xrandr = 0; | ||
535 | use_vidmode = 0; | ||
536 | use_xme = 0; | ||
537 | screen_w = DisplayWidth(SDL_Display, SDL_Screen); | ||
538 | screen_h = DisplayHeight(SDL_Display, SDL_Screen); | ||
539 | |||
540 | #if SDL_VIDEO_DRIVER_X11_XINERAMA | ||
541 | /* Query Xinerama extention */ | ||
542 | if ( CheckXinerama(this, &xinerama_major, &xinerama_minor) ) { | ||
543 | /* Find out which screen is the desired one */ | ||
544 | int desired = -1; | ||
545 | int screens; | ||
546 | int w, h; | ||
547 | SDL_NAME(XineramaScreenInfo) *xinerama; | ||
548 | |||
549 | const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY"); | ||
550 | if ( !variable ) { | ||
551 | variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD"); | ||
552 | } | ||
553 | if ( variable ) { | ||
554 | desired = SDL_atoi(variable); | ||
555 | } | ||
556 | #ifdef X11MODES_DEBUG | ||
557 | printf("X11 detected Xinerama:\n"); | ||
558 | #endif | ||
559 | xinerama = SDL_NAME(XineramaQueryScreens)(SDL_Display, &screens); | ||
560 | for ( i = 0; i < screens; i++ ) { | ||
561 | #ifdef X11MODES_DEBUG | ||
562 | printf("xinerama %d: %dx%d+%d+%d\n", | ||
563 | xinerama[i].screen_number, | ||
564 | xinerama[i].width, xinerama[i].height, | ||
565 | xinerama[i].x_org, xinerama[i].y_org); | ||
566 | #endif | ||
567 | if ( xinerama[i].screen_number == desired ) { | ||
568 | use_xinerama = 1; | ||
569 | xinerama_info = xinerama[i]; | ||
570 | } | ||
571 | } | ||
572 | XFree(xinerama); | ||
573 | |||
574 | if ( use_xinerama ) { | ||
575 | SDL_modelist = (SDL_Rect **)SDL_malloc(3*sizeof(SDL_Rect *)); | ||
576 | if ( !SDL_modelist ) { | ||
577 | SDL_OutOfMemory(); | ||
578 | return -1; | ||
579 | } | ||
580 | |||
581 | /* Add the full xinerama mode */ | ||
582 | n = 0; | ||
583 | w = xinerama_info.width; | ||
584 | h = xinerama_info.height; | ||
585 | if ( screen_w > w || screen_h > h) { | ||
586 | SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); | ||
587 | if ( SDL_modelist[n] ) { | ||
588 | SDL_modelist[n]->x = 0; | ||
589 | SDL_modelist[n]->y = 0; | ||
590 | SDL_modelist[n]->w = screen_w; | ||
591 | SDL_modelist[n]->h = screen_h; | ||
592 | ++n; | ||
593 | } | ||
594 | } | ||
595 | |||
596 | /* Add the head xinerama mode */ | ||
597 | SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); | ||
598 | if ( SDL_modelist[n] ) { | ||
599 | SDL_modelist[n]->x = 0; | ||
600 | SDL_modelist[n]->y = 0; | ||
601 | SDL_modelist[n]->w = w; | ||
602 | SDL_modelist[n]->h = h; | ||
603 | ++n; | ||
604 | } | ||
605 | SDL_modelist[n] = NULL; | ||
606 | } | ||
607 | } | ||
608 | #endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ | ||
609 | |||
610 | #if SDL_VIDEO_DRIVER_X11_XRANDR | ||
611 | /* XRandR */ | ||
612 | /* require at least XRandR v1.0 (arbitrary) */ | ||
613 | if ( CheckXRandR(this, &xrandr_major, &xrandr_minor) && (xrandr_major >= 1) ) | ||
614 | { | ||
615 | #ifdef X11MODES_DEBUG | ||
616 | fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n", | ||
617 | xrandr_major, xrandr_minor); | ||
618 | #endif | ||
619 | |||
620 | /* save the screen configuration since we must reference it | ||
621 | each time we toggle modes. | ||
622 | */ | ||
623 | screen_config = XRRGetScreenInfo(SDL_Display, SDL_Root); | ||
624 | |||
625 | /* retrieve the list of resolution */ | ||
626 | sizes = XRRConfigSizes(screen_config, &nsizes); | ||
627 | if (nsizes > 0) { | ||
628 | if ( SDL_modelist ) { | ||
629 | for ( i = 0; SDL_modelist[i]; ++i ) { | ||
630 | SDL_free(SDL_modelist[i]); | ||
631 | } | ||
632 | SDL_free(SDL_modelist); | ||
633 | } | ||
634 | SDL_modelist = (SDL_Rect **)malloc((nsizes+1)*sizeof(SDL_Rect *)); | ||
635 | if ( !SDL_modelist ) { | ||
636 | SDL_OutOfMemory(); | ||
637 | return -1; | ||
638 | } | ||
639 | for ( i=0; i < nsizes; i++ ) { | ||
640 | if ((SDL_modelist[i] = | ||
641 | (SDL_Rect *)malloc(sizeof(SDL_Rect))) == NULL) | ||
642 | break; | ||
643 | #ifdef X11MODES_DEBUG | ||
644 | fprintf(stderr, "XRANDR: mode = %4d, w = %4d, h = %4d\n", | ||
645 | i, sizes[i].width, sizes[i].height); | ||
646 | #endif | ||
647 | |||
648 | SDL_modelist[i]->x = 0; | ||
649 | SDL_modelist[i]->y = 0; | ||
650 | SDL_modelist[i]->w = sizes[i].width; | ||
651 | SDL_modelist[i]->h = sizes[i].height; | ||
652 | |||
653 | } | ||
654 | /* sort the mode list descending as SDL expects */ | ||
655 | SDL_qsort(SDL_modelist, nsizes, sizeof *SDL_modelist, cmpmodelist); | ||
656 | SDL_modelist[i] = NULL; /* terminator */ | ||
657 | |||
658 | use_xrandr = xrandr_major * 100 + xrandr_minor; | ||
659 | saved_size_id = XRRConfigCurrentConfiguration(screen_config, &saved_rotation); | ||
660 | } | ||
661 | } | ||
662 | #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ | ||
663 | |||
664 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
665 | /* XVidMode */ | ||
666 | if ( !use_xrandr && | ||
667 | #if SDL_VIDEO_DRIVER_X11_XINERAMA | ||
668 | (!use_xinerama || xinerama_info.screen_number == -1) && | ||
669 | #endif | ||
670 | CheckVidMode(this, &vm_major, &vm_minor) && | ||
671 | SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) | ||
672 | { | ||
673 | #ifdef X11MODES_DEBUG | ||
674 | printf("VidMode modes: (unsorted)\n"); | ||
675 | for ( i = 0; i < nmodes; ++i ) { | ||
676 | printf("Mode %d: %d x %d @ %d\n", i, | ||
677 | modes[i]->hdisplay, modes[i]->vdisplay, | ||
678 | (modes[i]->htotal && modes[i]->vtotal) ? (1000 * modes[i]->dotclock / (modes[i]->htotal * modes[i]->vtotal)) : 0 ); | ||
679 | } | ||
680 | #endif | ||
681 | if ( SDL_modelist ) { | ||
682 | for ( i = 0; SDL_modelist[i]; ++i ) { | ||
683 | SDL_free(SDL_modelist[i]); | ||
684 | } | ||
685 | SDL_free(SDL_modelist); | ||
686 | } | ||
687 | SDL_modelist = (SDL_Rect **)SDL_malloc((nmodes+2)*sizeof(SDL_Rect *)); | ||
688 | if ( !SDL_modelist ) { | ||
689 | SDL_OutOfMemory(); | ||
690 | return -1; | ||
691 | } | ||
692 | SDL_qsort(modes, nmodes, sizeof *modes, cmpmodes); | ||
693 | n = 0; | ||
694 | for ( i=0; i<nmodes; ++i ) { | ||
695 | int w, h; | ||
696 | |||
697 | /* Eliminate duplicate modes with different refresh rates */ | ||
698 | if ( i > 0 && | ||
699 | modes[i]->hdisplay == modes[i-1]->hdisplay && | ||
700 | modes[i]->vdisplay == modes[i-1]->vdisplay ) { | ||
701 | continue; | ||
702 | } | ||
703 | |||
704 | /* Check to see if we should add the screen size (Xinerama) */ | ||
705 | w = modes[i]->hdisplay; | ||
706 | h = modes[i]->vdisplay; | ||
707 | if ( (screen_w * screen_h) >= (w * h) ) { | ||
708 | if ( (screen_w != w) || (screen_h != h) ) { | ||
709 | SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); | ||
710 | if ( SDL_modelist[n] ) { | ||
711 | SDL_modelist[n]->x = 0; | ||
712 | SDL_modelist[n]->y = 0; | ||
713 | SDL_modelist[n]->w = screen_w; | ||
714 | SDL_modelist[n]->h = screen_h; | ||
715 | ++n; | ||
716 | } | ||
717 | } | ||
718 | screen_w = 0; | ||
719 | screen_h = 0; | ||
720 | } | ||
721 | |||
722 | /* Add the size from the video mode list */ | ||
723 | SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); | ||
724 | if ( SDL_modelist[n] == NULL ) { | ||
725 | break; | ||
726 | } | ||
727 | SDL_modelist[n]->x = 0; | ||
728 | SDL_modelist[n]->y = 0; | ||
729 | SDL_modelist[n]->w = w; | ||
730 | SDL_modelist[n]->h = h; | ||
731 | ++n; | ||
732 | } | ||
733 | SDL_modelist[n] = NULL; | ||
734 | XFree(modes); | ||
735 | |||
736 | use_vidmode = vm_major * 100 + vm_minor; | ||
737 | save_mode(this); | ||
738 | } | ||
739 | #endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ | ||
740 | |||
741 | #if SDL_VIDEO_DRIVER_X11_XME | ||
742 | /* XiG */ | ||
743 | modelist = NULL; | ||
744 | /* first lets make sure we have the extension, and it's at least v2.0 */ | ||
745 | if ( CheckXME(this, &xme_major, &xme_minor) && xme_major >= 2 && | ||
746 | (nummodes = XiGMiscQueryResolutions(SDL_Display, SDL_Screen, | ||
747 | 0, /* view */ | ||
748 | &ractive, &modelist)) > 1 ) | ||
749 | { /* then we actually have some */ | ||
750 | int j; | ||
751 | |||
752 | /* We get the list already sorted in descending order. | ||
753 | We'll copy it in reverse order so SDL is happy */ | ||
754 | #ifdef X11MODES_DEBUG | ||
755 | fprintf(stderr, "XME: nummodes = %d, active mode = %d\n", | ||
756 | nummodes, ractive); | ||
757 | #endif | ||
758 | if ( SDL_modelist ) { | ||
759 | for ( i = 0; SDL_modelist[i]; ++i ) { | ||
760 | SDL_free(SDL_modelist[i]); | ||
761 | } | ||
762 | SDL_free(SDL_modelist); | ||
763 | } | ||
764 | SDL_modelist = (SDL_Rect **)SDL_malloc((nummodes+1)*sizeof(SDL_Rect *)); | ||
765 | if ( !SDL_modelist ) { | ||
766 | SDL_OutOfMemory(); | ||
767 | return -1; | ||
768 | } | ||
769 | for ( i=0, j=nummodes-1; j>=0; i++, j-- ) { | ||
770 | if ((SDL_modelist[i] = | ||
771 | (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect))) == NULL) | ||
772 | break; | ||
773 | #ifdef X11MODES_DEBUG | ||
774 | fprintf(stderr, "XME: mode = %4d, w = %4d, h = %4d\n", | ||
775 | i, modelist[i].width, modelist[i].height); | ||
776 | #endif | ||
777 | |||
778 | SDL_modelist[i]->x = 0; | ||
779 | SDL_modelist[i]->y = 0; | ||
780 | SDL_modelist[i]->w = modelist[j].width; | ||
781 | SDL_modelist[i]->h = modelist[j].height; | ||
782 | |||
783 | } | ||
784 | SDL_modelist[i] = NULL; /* terminator */ | ||
785 | |||
786 | use_xme = xme_major * 100 + xme_minor; | ||
787 | saved_res = modelist[ractive]; /* save the current resolution */ | ||
788 | } | ||
789 | if ( modelist ) { | ||
790 | XFree(modelist); | ||
791 | } | ||
792 | #endif /* SDL_VIDEO_DRIVER_X11_XME */ | ||
793 | |||
794 | { | ||
795 | /* It's interesting to note that if we allow 32 bit depths, | ||
796 | we get a visual with an alpha mask on composite servers. | ||
797 | static int depth_list[] = { 32, 24, 16, 15, 8 }; | ||
798 | */ | ||
799 | static int depth_list[] = { 24, 16, 15, 8 }; | ||
800 | int j, np; | ||
801 | int use_directcolor = 1; | ||
802 | XPixmapFormatValues *pf; | ||
803 | |||
804 | /* Search for the visuals in deepest-first order, so that the first | ||
805 | will be the richest one */ | ||
806 | if ( SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) { | ||
807 | use_directcolor = 0; | ||
808 | } | ||
809 | this->hidden->nvisuals = 0; | ||
810 | if ( ! add_visual_byid(this, SDL_getenv("SDL_VIDEO_X11_VISUALID")) ) { | ||
811 | for ( i=0; i<SDL_arraysize(depth_list); ++i ) { | ||
812 | if ( depth_list[i] > 8 ) { | ||
813 | if ( use_directcolor ) { | ||
814 | add_visual(this, depth_list[i], DirectColor); | ||
815 | } | ||
816 | add_visual(this, depth_list[i], TrueColor); | ||
817 | } else { | ||
818 | add_visual(this, depth_list[i], PseudoColor); | ||
819 | add_visual(this, depth_list[i], StaticColor); | ||
820 | } | ||
821 | } | ||
822 | add_default_visual(this); | ||
823 | } | ||
824 | if ( this->hidden->nvisuals == 0 ) { | ||
825 | SDL_SetError("Found no sufficiently capable X11 visuals"); | ||
826 | return -1; | ||
827 | } | ||
828 | |||
829 | /* look up the pixel quantum for each depth */ | ||
830 | pf = XListPixmapFormats(SDL_Display, &np); | ||
831 | for(i = 0; i < this->hidden->nvisuals; i++) { | ||
832 | int d = this->hidden->visuals[i].depth; | ||
833 | for(j = 0; j < np; j++) | ||
834 | if(pf[j].depth == d) | ||
835 | break; | ||
836 | this->hidden->visuals[i].bpp = j < np ? pf[j].bits_per_pixel : d; | ||
837 | } | ||
838 | |||
839 | XFree(pf); | ||
840 | } | ||
841 | |||
842 | if ( SDL_modelist == NULL ) { | ||
843 | SDL_modelist = (SDL_Rect **)SDL_malloc((1+1)*sizeof(SDL_Rect *)); | ||
844 | if ( !SDL_modelist ) { | ||
845 | SDL_OutOfMemory(); | ||
846 | return -1; | ||
847 | } | ||
848 | n = 0; | ||
849 | SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); | ||
850 | if ( SDL_modelist[n] ) { | ||
851 | SDL_modelist[n]->x = 0; | ||
852 | SDL_modelist[n]->y = 0; | ||
853 | SDL_modelist[n]->w = screen_w; | ||
854 | SDL_modelist[n]->h = screen_h; | ||
855 | ++n; | ||
856 | } | ||
857 | SDL_modelist[n] = NULL; | ||
858 | } | ||
859 | |||
860 | #ifdef X11MODES_DEBUG | ||
861 | if ( use_xinerama ) { | ||
862 | printf("Xinerama is enabled\n"); | ||
863 | } | ||
864 | |||
865 | if ( use_xrandr ) { | ||
866 | printf("XRandR is enabled\n"); | ||
867 | } | ||
868 | |||
869 | if ( use_vidmode ) { | ||
870 | printf("VidMode is enabled\n"); | ||
871 | } | ||
872 | |||
873 | if ( use_xme ) { | ||
874 | printf("Xi Graphics XME fullscreen is enabled\n"); | ||
875 | } | ||
876 | |||
877 | if ( SDL_modelist ) { | ||
878 | printf("X11 video mode list:\n"); | ||
879 | for ( i=0; SDL_modelist[i]; ++i ) { | ||
880 | printf("\t%dx%d\n", SDL_modelist[i]->w, SDL_modelist[i]->h); | ||
881 | } | ||
882 | } | ||
883 | #endif /* X11MODES_DEBUG */ | ||
884 | |||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | int X11_SupportedVisual(_THIS, SDL_PixelFormat *format) | ||
889 | { | ||
890 | int i; | ||
891 | for(i = 0; i < this->hidden->nvisuals; i++) | ||
892 | if(this->hidden->visuals[i].bpp == format->BitsPerPixel) | ||
893 | return 1; | ||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | SDL_Rect **X11_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | ||
898 | { | ||
899 | if ( X11_SupportedVisual(this, format) ) { | ||
900 | if ( flags & SDL_FULLSCREEN ) { | ||
901 | return(SDL_modelist); | ||
902 | } else { | ||
903 | return((SDL_Rect **)-1); | ||
904 | } | ||
905 | } else { | ||
906 | return((SDL_Rect **)0); | ||
907 | } | ||
908 | } | ||
909 | |||
910 | void X11_FreeVideoModes(_THIS) | ||
911 | { | ||
912 | int i; | ||
913 | |||
914 | if ( SDL_modelist ) { | ||
915 | for ( i=0; SDL_modelist[i]; ++i ) { | ||
916 | SDL_free(SDL_modelist[i]); | ||
917 | } | ||
918 | SDL_free(SDL_modelist); | ||
919 | SDL_modelist = NULL; | ||
920 | } | ||
921 | |||
922 | #if SDL_VIDEO_DRIVER_X11_XRANDR | ||
923 | /* Free the Xrandr screen configuration */ | ||
924 | if ( screen_config ) { | ||
925 | XRRFreeScreenConfigInfo(screen_config); | ||
926 | screen_config = NULL; | ||
927 | } | ||
928 | #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ | ||
929 | } | ||
930 | |||
931 | int X11_ResizeFullScreen(_THIS) | ||
932 | { | ||
933 | int x = 0, y = 0; | ||
934 | int real_w, real_h; | ||
935 | int screen_w; | ||
936 | int screen_h; | ||
937 | |||
938 | screen_w = DisplayWidth(SDL_Display, SDL_Screen); | ||
939 | screen_h = DisplayHeight(SDL_Display, SDL_Screen); | ||
940 | |||
941 | #if SDL_VIDEO_DRIVER_X11_XINERAMA | ||
942 | if ( use_xinerama && | ||
943 | window_w <= xinerama_info.width && | ||
944 | window_h <= xinerama_info.height ) { | ||
945 | x = xinerama_info.x_org; | ||
946 | y = xinerama_info.y_org; | ||
947 | } | ||
948 | #endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ | ||
949 | |||
950 | if ( currently_fullscreen ) { | ||
951 | /* Switch resolution and cover it with the FSwindow */ | ||
952 | move_cursor_to(this, x, y); | ||
953 | set_best_resolution(this, window_w, window_h); | ||
954 | move_cursor_to(this, x, y); | ||
955 | get_real_resolution(this, &real_w, &real_h); | ||
956 | if ( window_w > real_w ) { | ||
957 | real_w = MAX(real_w, screen_w); | ||
958 | } | ||
959 | if ( window_h > real_h ) { | ||
960 | real_h = MAX(real_h, screen_h); | ||
961 | } | ||
962 | XMoveResizeWindow(SDL_Display, FSwindow, x, y, real_w, real_h); | ||
963 | move_cursor_to(this, real_w/2, real_h/2); | ||
964 | |||
965 | /* Center and reparent the drawing window */ | ||
966 | x = (real_w - window_w)/2; | ||
967 | y = (real_h - window_h)/2; | ||
968 | XReparentWindow(SDL_Display, SDL_Window, FSwindow, x, y); | ||
969 | /* FIXME: move the mouse to the old relative location */ | ||
970 | XSync(SDL_Display, True); /* Flush spurious mode change events */ | ||
971 | } | ||
972 | return(1); | ||
973 | } | ||
974 | |||
975 | void X11_QueueEnterFullScreen(_THIS) | ||
976 | { | ||
977 | switch_waiting = 0x01 | SDL_FULLSCREEN; | ||
978 | switch_time = SDL_GetTicks() + 1500; | ||
979 | #if 0 /* This causes a BadMatch error if the window is iconified (not needed) */ | ||
980 | XSetInputFocus(SDL_Display, WMwindow, RevertToNone, CurrentTime); | ||
981 | #endif | ||
982 | } | ||
983 | |||
984 | int X11_EnterFullScreen(_THIS) | ||
985 | { | ||
986 | int okay; | ||
987 | #if 0 | ||
988 | Window tmpwin, *windows; | ||
989 | int i, nwindows; | ||
990 | #endif | ||
991 | int x = 0, y = 0; | ||
992 | int real_w, real_h; | ||
993 | int screen_w; | ||
994 | int screen_h; | ||
995 | |||
996 | okay = 1; | ||
997 | if ( currently_fullscreen ) { | ||
998 | return(okay); | ||
999 | } | ||
1000 | |||
1001 | /* Ungrab the input so that we can move the mouse around */ | ||
1002 | X11_GrabInputNoLock(this, SDL_GRAB_OFF); | ||
1003 | |||
1004 | #if SDL_VIDEO_DRIVER_X11_XINERAMA | ||
1005 | if ( use_xinerama && | ||
1006 | window_w <= xinerama_info.width && | ||
1007 | window_h <= xinerama_info.height ) { | ||
1008 | x = xinerama_info.x_org; | ||
1009 | y = xinerama_info.y_org; | ||
1010 | } | ||
1011 | #endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ | ||
1012 | |||
1013 | /* Map the fullscreen window to blank the screen */ | ||
1014 | screen_w = DisplayWidth(SDL_Display, SDL_Screen); | ||
1015 | screen_h = DisplayHeight(SDL_Display, SDL_Screen); | ||
1016 | get_real_resolution(this, &real_w, &real_h); | ||
1017 | real_w = MAX(window_w, MAX(real_w, screen_w)); | ||
1018 | real_h = MAX(window_h, MAX(real_h, screen_h)); | ||
1019 | XMoveResizeWindow(SDL_Display, FSwindow, | ||
1020 | x, y, real_w, real_h); | ||
1021 | XMapRaised(SDL_Display, FSwindow); | ||
1022 | X11_WaitMapped(this, FSwindow); | ||
1023 | |||
1024 | #if 0 /* This seems to break WindowMaker in focus-follows-mouse mode */ | ||
1025 | /* Make sure we got to the top of the window stack */ | ||
1026 | if ( XQueryTree(SDL_Display, SDL_Root, &tmpwin, &tmpwin, | ||
1027 | &windows, &nwindows) && windows ) { | ||
1028 | /* If not, try to put us there - if fail... oh well */ | ||
1029 | if ( windows[nwindows-1] != FSwindow ) { | ||
1030 | tmpwin = windows[nwindows-1]; | ||
1031 | for ( i=0; i<nwindows; ++i ) { | ||
1032 | if ( windows[i] == FSwindow ) { | ||
1033 | SDL_memcpy(&windows[i], &windows[i+1], | ||
1034 | (nwindows-i-1)*sizeof(windows[i])); | ||
1035 | break; | ||
1036 | } | ||
1037 | } | ||
1038 | windows[nwindows-1] = FSwindow; | ||
1039 | XRestackWindows(SDL_Display, windows, nwindows); | ||
1040 | XSync(SDL_Display, False); | ||
1041 | } | ||
1042 | XFree(windows); | ||
1043 | } | ||
1044 | #else | ||
1045 | XRaiseWindow(SDL_Display, FSwindow); | ||
1046 | #endif | ||
1047 | |||
1048 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
1049 | /* Save the current video mode */ | ||
1050 | if ( use_vidmode ) { | ||
1051 | SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, True); | ||
1052 | save_mode(this); | ||
1053 | } | ||
1054 | #endif | ||
1055 | currently_fullscreen = 1; | ||
1056 | |||
1057 | /* Set the new resolution */ | ||
1058 | okay = X11_ResizeFullScreen(this); | ||
1059 | if ( ! okay ) { | ||
1060 | X11_LeaveFullScreen(this); | ||
1061 | } | ||
1062 | /* Set the colormap */ | ||
1063 | if ( SDL_XColorMap ) { | ||
1064 | XInstallColormap(SDL_Display, SDL_XColorMap); | ||
1065 | } | ||
1066 | if ( okay ) { | ||
1067 | X11_GrabInputNoLock(this, this->input_grab | SDL_GRAB_FULLSCREEN); | ||
1068 | } | ||
1069 | |||
1070 | /* We may need to refresh the screen at this point (no backing store) | ||
1071 | We also don't get an event, which is why we explicitly refresh. */ | ||
1072 | if ( this->screen ) { | ||
1073 | if ( this->screen->flags & SDL_OPENGL ) { | ||
1074 | SDL_PrivateExpose(); | ||
1075 | } else { | ||
1076 | X11_RefreshDisplay(this); | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1080 | return(okay); | ||
1081 | } | ||
1082 | |||
1083 | int X11_LeaveFullScreen(_THIS) | ||
1084 | { | ||
1085 | if ( currently_fullscreen ) { | ||
1086 | XReparentWindow(SDL_Display, SDL_Window, WMwindow, 0, 0); | ||
1087 | #if SDL_VIDEO_DRIVER_X11_VIDMODE | ||
1088 | if ( use_vidmode ) { | ||
1089 | restore_mode(this); | ||
1090 | SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, False); | ||
1091 | } | ||
1092 | #endif | ||
1093 | |||
1094 | #if SDL_VIDEO_DRIVER_X11_XME | ||
1095 | if ( use_xme ) { | ||
1096 | int rw, rh; | ||
1097 | |||
1098 | /* check current mode so we can avoid uneccessary mode changes */ | ||
1099 | get_real_resolution(this, &rw, &rh); | ||
1100 | |||
1101 | if (rw != saved_res.width || rh != saved_res.height) { | ||
1102 | XiGMiscChangeResolution(SDL_Display, | ||
1103 | SDL_Screen, | ||
1104 | 0, /* view */ | ||
1105 | saved_res.width, | ||
1106 | saved_res.height, | ||
1107 | 0); | ||
1108 | XSync(SDL_Display, False); | ||
1109 | } | ||
1110 | } | ||
1111 | #endif | ||
1112 | |||
1113 | #if SDL_VIDEO_DRIVER_X11_XRANDR | ||
1114 | if ( use_xrandr ) { | ||
1115 | XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, | ||
1116 | saved_size_id, saved_rotation, CurrentTime); | ||
1117 | } | ||
1118 | #endif | ||
1119 | |||
1120 | XUnmapWindow(SDL_Display, FSwindow); | ||
1121 | X11_WaitUnmapped(this, FSwindow); | ||
1122 | XSync(SDL_Display, True); /* Flush spurious mode change events */ | ||
1123 | currently_fullscreen = 0; | ||
1124 | } | ||
1125 | /* If we get popped out of fullscreen mode for some reason, input_grab | ||
1126 | will still have the SDL_GRAB_FULLSCREEN flag set, since this is only | ||
1127 | temporary. In this case, release the grab unless the input has been | ||
1128 | explicitly grabbed. | ||
1129 | */ | ||
1130 | X11_GrabInputNoLock(this, this->input_grab & ~SDL_GRAB_FULLSCREEN); | ||
1131 | |||
1132 | /* We may need to refresh the screen at this point (no backing store) | ||
1133 | We also don't get an event, which is why we explicitly refresh. */ | ||
1134 | if ( this->screen ) { | ||
1135 | if ( this->screen->flags & SDL_OPENGL ) { | ||
1136 | SDL_PrivateExpose(); | ||
1137 | } else { | ||
1138 | X11_RefreshDisplay(this); | ||
1139 | } | ||
1140 | } | ||
1141 | |||
1142 | return(0); | ||
1143 | } | ||