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