e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 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 used to default off, due to KDE window maximize problems */ |
425 | /* Reactivated since I haven't encountered such problems with KDE, but if |
426 | one does encounter such problems he/she can just set |
427 | SDL_VIDEO_X11_XRANDR to 0 |
428 | Closes Debian bug: #450689 |
429 | */ |
430 | /* if ( !env ) { |
431 | return 0; |
432 | } |
433 | */ |
434 | if ( !SDL_X11_HAVE_XRANDR ) { |
435 | return 0; |
436 | } |
437 | |
438 | /* Query the extension version */ |
439 | if ( !XRRQueryVersion(SDL_Display, major, minor) ) { |
440 | return 0; |
441 | } |
442 | return 1; |
443 | } |
444 | #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ |
445 | |
446 | #if SDL_VIDEO_DRIVER_X11_VIDMODE |
447 | static int CheckVidMode(_THIS, int *major, int *minor) |
448 | { |
449 | const char *env; |
450 | |
451 | /* Default the extension not available */ |
452 | *major = *minor = 0; |
453 | |
454 | /* Allow environment override */ |
455 | env = getenv("SDL_VIDEO_X11_VIDMODE"); |
456 | if ( env && !SDL_atoi(env) ) { |
457 | return 0; |
458 | } |
459 | |
460 | /* Metro-X 4.3.0 and earlier has a broken implementation of |
461 | XF86VidModeGetAllModeLines() - it hangs the client. |
462 | */ |
463 | if ( SDL_strcmp(ServerVendor(SDL_Display), "Metro Link Incorporated") == 0 ) { |
464 | FILE *metro_fp; |
465 | |
466 | metro_fp = fopen("/usr/X11R6/lib/X11/Metro/.version", "r"); |
467 | if ( metro_fp != NULL ) { |
468 | int major, minor, patch, version; |
469 | major = 0; minor = 0; patch = 0; |
470 | fscanf(metro_fp, "%d.%d.%d", &major, &minor, &patch); |
471 | fclose(metro_fp); |
472 | version = major*100+minor*10+patch; |
473 | if ( version < 431 ) { |
474 | return 0; |
475 | } |
476 | } |
477 | } |
478 | |
479 | /* Query the extension version */ |
480 | vm_error = -1; |
481 | if ( !SDL_NAME(XF86VidModeQueryExtension)(SDL_Display, &vm_event, &vm_error) || |
482 | !SDL_NAME(XF86VidModeQueryVersion)(SDL_Display, major, minor) ) { |
483 | return 0; |
484 | } |
485 | return 1; |
486 | } |
487 | #endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ |
488 | |
489 | #if SDL_VIDEO_DRIVER_X11_XME |
490 | static int CheckXME(_THIS, int *major, int *minor) |
491 | { |
492 | const char *env; |
493 | |
494 | /* Default the extension not available */ |
495 | *major = *minor = 0; |
496 | |
497 | /* Allow environment override */ |
498 | env = getenv("SDL_VIDEO_X11_VIDMODE"); |
499 | if ( env && !SDL_atoi(env) ) { |
500 | return 0; |
501 | } |
502 | |
503 | /* Query the extension version */ |
504 | if ( !XiGMiscQueryVersion(SDL_Display, major, minor) ) { |
505 | return 0; |
506 | } |
507 | return 1; |
508 | } |
509 | #endif /* SDL_VIDEO_DRIVER_X11_XME */ |
510 | |
511 | int X11_GetVideoModes(_THIS) |
512 | { |
513 | #if SDL_VIDEO_DRIVER_X11_XINERAMA |
514 | int xinerama_major, xinerama_minor; |
515 | #endif |
516 | #if SDL_VIDEO_DRIVER_X11_XRANDR |
517 | int xrandr_major, xrandr_minor; |
518 | int nsizes; |
519 | XRRScreenSize *sizes; |
520 | #endif |
521 | #if SDL_VIDEO_DRIVER_X11_VIDMODE |
522 | int vm_major, vm_minor; |
523 | int nmodes; |
524 | SDL_NAME(XF86VidModeModeInfo) **modes; |
525 | #endif |
526 | #if SDL_VIDEO_DRIVER_X11_XME |
527 | int xme_major, xme_minor; |
528 | int ractive, nummodes; |
529 | XiGMiscResolutionInfo *modelist; |
530 | #endif |
531 | int i, n; |
532 | int screen_w; |
533 | int screen_h; |
534 | |
535 | use_xinerama = 0; |
536 | use_xrandr = 0; |
537 | use_vidmode = 0; |
538 | use_xme = 0; |
539 | screen_w = DisplayWidth(SDL_Display, SDL_Screen); |
540 | screen_h = DisplayHeight(SDL_Display, SDL_Screen); |
541 | |
542 | #if SDL_VIDEO_DRIVER_X11_XINERAMA |
543 | /* Query Xinerama extention */ |
544 | if ( CheckXinerama(this, &xinerama_major, &xinerama_minor) ) { |
545 | /* Find out which screen is the desired one */ |
546 | int desired = -1; |
547 | int screens; |
548 | int w, h; |
549 | SDL_NAME(XineramaScreenInfo) *xinerama; |
550 | |
551 | const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY"); |
552 | if ( !variable ) { |
553 | variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD"); |
554 | } |
555 | if ( variable ) { |
556 | desired = SDL_atoi(variable); |
557 | } |
558 | #ifdef X11MODES_DEBUG |
559 | printf("X11 detected Xinerama:\n"); |
560 | #endif |
561 | xinerama = SDL_NAME(XineramaQueryScreens)(SDL_Display, &screens); |
562 | for ( i = 0; i < screens; i++ ) { |
563 | #ifdef X11MODES_DEBUG |
564 | printf("xinerama %d: %dx%d+%d+%d\n", |
565 | xinerama[i].screen_number, |
566 | xinerama[i].width, xinerama[i].height, |
567 | xinerama[i].x_org, xinerama[i].y_org); |
568 | #endif |
569 | if ( xinerama[i].screen_number == desired ) { |
570 | use_xinerama = 1; |
571 | xinerama_info = xinerama[i]; |
572 | } |
573 | } |
574 | XFree(xinerama); |
575 | |
576 | if ( use_xinerama ) { |
577 | SDL_modelist = (SDL_Rect **)SDL_malloc(3*sizeof(SDL_Rect *)); |
578 | if ( !SDL_modelist ) { |
579 | SDL_OutOfMemory(); |
580 | return -1; |
581 | } |
582 | |
583 | /* Add the full xinerama mode */ |
584 | n = 0; |
585 | w = xinerama_info.width; |
586 | h = xinerama_info.height; |
587 | if ( screen_w > w || screen_h > h) { |
588 | SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); |
589 | if ( SDL_modelist[n] ) { |
590 | SDL_modelist[n]->x = 0; |
591 | SDL_modelist[n]->y = 0; |
592 | SDL_modelist[n]->w = screen_w; |
593 | SDL_modelist[n]->h = screen_h; |
594 | ++n; |
595 | } |
596 | } |
597 | |
598 | /* Add the head xinerama mode */ |
599 | SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); |
600 | if ( SDL_modelist[n] ) { |
601 | SDL_modelist[n]->x = 0; |
602 | SDL_modelist[n]->y = 0; |
603 | SDL_modelist[n]->w = w; |
604 | SDL_modelist[n]->h = h; |
605 | ++n; |
606 | } |
607 | SDL_modelist[n] = NULL; |
608 | } |
609 | } |
610 | #endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ |
611 | |
612 | #if SDL_VIDEO_DRIVER_X11_XRANDR |
613 | /* XRandR */ |
614 | /* require at least XRandR v1.0 (arbitrary) */ |
615 | if ( CheckXRandR(this, &xrandr_major, &xrandr_minor) && (xrandr_major >= 1) ) |
616 | { |
617 | #ifdef X11MODES_DEBUG |
618 | fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n", |
619 | xrandr_major, xrandr_minor); |
620 | #endif |
621 | |
622 | /* save the screen configuration since we must reference it |
623 | each time we toggle modes. |
624 | */ |
625 | screen_config = XRRGetScreenInfo(SDL_Display, SDL_Root); |
626 | |
627 | /* retrieve the list of resolution */ |
628 | sizes = XRRConfigSizes(screen_config, &nsizes); |
629 | if (nsizes > 0) { |
630 | if ( SDL_modelist ) { |
631 | for ( i = 0; SDL_modelist[i]; ++i ) { |
632 | SDL_free(SDL_modelist[i]); |
633 | } |
634 | SDL_free(SDL_modelist); |
635 | } |
636 | SDL_modelist = (SDL_Rect **)malloc((nsizes+1)*sizeof(SDL_Rect *)); |
637 | if ( !SDL_modelist ) { |
638 | SDL_OutOfMemory(); |
639 | return -1; |
640 | } |
641 | for ( i=0; i < nsizes; i++ ) { |
642 | if ((SDL_modelist[i] = |
643 | (SDL_Rect *)malloc(sizeof(SDL_Rect))) == NULL) |
644 | break; |
645 | #ifdef X11MODES_DEBUG |
646 | fprintf(stderr, "XRANDR: mode = %4d, w = %4d, h = %4d\n", |
647 | i, sizes[i].width, sizes[i].height); |
648 | #endif |
649 | |
650 | SDL_modelist[i]->x = 0; |
651 | SDL_modelist[i]->y = 0; |
652 | SDL_modelist[i]->w = sizes[i].width; |
653 | SDL_modelist[i]->h = sizes[i].height; |
654 | |
655 | } |
656 | /* sort the mode list descending as SDL expects */ |
657 | SDL_qsort(SDL_modelist, nsizes, sizeof *SDL_modelist, cmpmodelist); |
658 | SDL_modelist[i] = NULL; /* terminator */ |
659 | |
660 | use_xrandr = xrandr_major * 100 + xrandr_minor; |
661 | saved_size_id = XRRConfigCurrentConfiguration(screen_config, &saved_rotation); |
662 | } |
663 | } |
664 | #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ |
665 | |
666 | #if SDL_VIDEO_DRIVER_X11_VIDMODE |
667 | /* XVidMode */ |
668 | if ( !use_xrandr && |
669 | #if SDL_VIDEO_DRIVER_X11_XINERAMA |
670 | (!use_xinerama || xinerama_info.screen_number == -1) && |
671 | #endif |
672 | CheckVidMode(this, &vm_major, &vm_minor) && |
673 | SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) |
674 | { |
675 | #ifdef X11MODES_DEBUG |
676 | printf("VidMode modes: (unsorted)\n"); |
677 | for ( i = 0; i < nmodes; ++i ) { |
678 | printf("Mode %d: %d x %d @ %d\n", i, |
679 | modes[i]->hdisplay, modes[i]->vdisplay, |
680 | (modes[i]->htotal && modes[i]->vtotal) ? (1000 * modes[i]->dotclock / (modes[i]->htotal * modes[i]->vtotal)) : 0 ); |
681 | } |
682 | #endif |
683 | if ( SDL_modelist ) { |
684 | for ( i = 0; SDL_modelist[i]; ++i ) { |
685 | SDL_free(SDL_modelist[i]); |
686 | } |
687 | SDL_free(SDL_modelist); |
688 | } |
689 | SDL_modelist = (SDL_Rect **)SDL_malloc((nmodes+2)*sizeof(SDL_Rect *)); |
690 | if ( !SDL_modelist ) { |
691 | SDL_OutOfMemory(); |
692 | return -1; |
693 | } |
694 | SDL_qsort(modes, nmodes, sizeof *modes, cmpmodes); |
695 | n = 0; |
696 | for ( i=0; i<nmodes; ++i ) { |
697 | int w, h; |
698 | |
699 | /* Eliminate duplicate modes with different refresh rates */ |
700 | if ( i > 0 && |
701 | modes[i]->hdisplay == modes[i-1]->hdisplay && |
702 | modes[i]->vdisplay == modes[i-1]->vdisplay ) { |
703 | continue; |
704 | } |
705 | |
706 | /* Check to see if we should add the screen size (Xinerama) */ |
707 | w = modes[i]->hdisplay; |
708 | h = modes[i]->vdisplay; |
709 | if ( (screen_w * screen_h) >= (w * h) ) { |
710 | if ( (screen_w != w) || (screen_h != h) ) { |
711 | SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); |
712 | if ( SDL_modelist[n] ) { |
713 | SDL_modelist[n]->x = 0; |
714 | SDL_modelist[n]->y = 0; |
715 | SDL_modelist[n]->w = screen_w; |
716 | SDL_modelist[n]->h = screen_h; |
717 | ++n; |
718 | } |
719 | } |
720 | screen_w = 0; |
721 | screen_h = 0; |
722 | } |
723 | |
724 | /* Add the size from the video mode list */ |
725 | SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); |
726 | if ( SDL_modelist[n] == NULL ) { |
727 | break; |
728 | } |
729 | SDL_modelist[n]->x = 0; |
730 | SDL_modelist[n]->y = 0; |
731 | SDL_modelist[n]->w = w; |
732 | SDL_modelist[n]->h = h; |
733 | ++n; |
734 | } |
735 | SDL_modelist[n] = NULL; |
736 | XFree(modes); |
737 | |
738 | use_vidmode = vm_major * 100 + vm_minor; |
739 | save_mode(this); |
740 | } |
741 | #endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ |
742 | |
743 | #if SDL_VIDEO_DRIVER_X11_XME |
744 | /* XiG */ |
745 | modelist = NULL; |
746 | /* first lets make sure we have the extension, and it's at least v2.0 */ |
747 | if ( CheckXME(this, &xme_major, &xme_minor) && xme_major >= 2 && |
748 | (nummodes = XiGMiscQueryResolutions(SDL_Display, SDL_Screen, |
749 | 0, /* view */ |
750 | &ractive, &modelist)) > 1 ) |
751 | { /* then we actually have some */ |
752 | int j; |
753 | |
754 | /* We get the list already sorted in descending order. |
755 | We'll copy it in reverse order so SDL is happy */ |
756 | #ifdef X11MODES_DEBUG |
757 | fprintf(stderr, "XME: nummodes = %d, active mode = %d\n", |
758 | nummodes, ractive); |
759 | #endif |
760 | if ( SDL_modelist ) { |
761 | for ( i = 0; SDL_modelist[i]; ++i ) { |
762 | SDL_free(SDL_modelist[i]); |
763 | } |
764 | SDL_free(SDL_modelist); |
765 | } |
766 | SDL_modelist = (SDL_Rect **)SDL_malloc((nummodes+1)*sizeof(SDL_Rect *)); |
767 | if ( !SDL_modelist ) { |
768 | SDL_OutOfMemory(); |
769 | return -1; |
770 | } |
771 | for ( i=0, j=nummodes-1; j>=0; i++, j-- ) { |
772 | if ((SDL_modelist[i] = |
773 | (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect))) == NULL) |
774 | break; |
775 | #ifdef X11MODES_DEBUG |
776 | fprintf(stderr, "XME: mode = %4d, w = %4d, h = %4d\n", |
777 | i, modelist[i].width, modelist[i].height); |
778 | #endif |
779 | |
780 | SDL_modelist[i]->x = 0; |
781 | SDL_modelist[i]->y = 0; |
782 | SDL_modelist[i]->w = modelist[j].width; |
783 | SDL_modelist[i]->h = modelist[j].height; |
784 | |
785 | } |
786 | SDL_modelist[i] = NULL; /* terminator */ |
787 | |
788 | use_xme = xme_major * 100 + xme_minor; |
789 | saved_res = modelist[ractive]; /* save the current resolution */ |
790 | } |
791 | if ( modelist ) { |
792 | XFree(modelist); |
793 | } |
794 | #endif /* SDL_VIDEO_DRIVER_X11_XME */ |
795 | |
796 | { |
797 | /* It's interesting to note that if we allow 32 bit depths, |
798 | we get a visual with an alpha mask on composite servers. |
799 | static int depth_list[] = { 32, 24, 16, 15, 8 }; |
800 | */ |
801 | static int depth_list[] = { 24, 16, 15, 8 }; |
802 | int j, np; |
803 | int use_directcolor = 1; |
804 | XPixmapFormatValues *pf; |
805 | |
806 | /* Search for the visuals in deepest-first order, so that the first |
807 | will be the richest one */ |
808 | if ( SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) { |
809 | use_directcolor = 0; |
810 | } |
811 | this->hidden->nvisuals = 0; |
812 | if ( ! add_visual_byid(this, SDL_getenv("SDL_VIDEO_X11_VISUALID")) ) { |
813 | for ( i=0; i<SDL_arraysize(depth_list); ++i ) { |
814 | if ( depth_list[i] > 8 ) { |
815 | if ( use_directcolor ) { |
816 | add_visual(this, depth_list[i], DirectColor); |
817 | } |
818 | add_visual(this, depth_list[i], TrueColor); |
819 | } else { |
820 | add_visual(this, depth_list[i], PseudoColor); |
821 | add_visual(this, depth_list[i], StaticColor); |
822 | } |
823 | } |
824 | add_default_visual(this); |
825 | } |
826 | if ( this->hidden->nvisuals == 0 ) { |
827 | SDL_SetError("Found no sufficiently capable X11 visuals"); |
828 | return -1; |
829 | } |
830 | |
831 | /* look up the pixel quantum for each depth */ |
832 | pf = XListPixmapFormats(SDL_Display, &np); |
833 | for(i = 0; i < this->hidden->nvisuals; i++) { |
834 | int d = this->hidden->visuals[i].depth; |
835 | for(j = 0; j < np; j++) |
836 | if(pf[j].depth == d) |
837 | break; |
838 | this->hidden->visuals[i].bpp = j < np ? pf[j].bits_per_pixel : d; |
839 | } |
840 | |
841 | XFree(pf); |
842 | } |
843 | |
844 | if ( SDL_modelist == NULL ) { |
845 | SDL_modelist = (SDL_Rect **)SDL_malloc((1+1)*sizeof(SDL_Rect *)); |
846 | if ( !SDL_modelist ) { |
847 | SDL_OutOfMemory(); |
848 | return -1; |
849 | } |
850 | n = 0; |
851 | SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); |
852 | if ( SDL_modelist[n] ) { |
853 | SDL_modelist[n]->x = 0; |
854 | SDL_modelist[n]->y = 0; |
855 | SDL_modelist[n]->w = screen_w; |
856 | SDL_modelist[n]->h = screen_h; |
857 | ++n; |
858 | } |
859 | SDL_modelist[n] = NULL; |
860 | } |
861 | |
862 | #ifdef X11MODES_DEBUG |
863 | if ( use_xinerama ) { |
864 | printf("Xinerama is enabled\n"); |
865 | } |
866 | |
867 | if ( use_xrandr ) { |
868 | printf("XRandR is enabled\n"); |
869 | } |
870 | |
871 | if ( use_vidmode ) { |
872 | printf("VidMode is enabled\n"); |
873 | } |
874 | |
875 | if ( use_xme ) { |
876 | printf("Xi Graphics XME fullscreen is enabled\n"); |
877 | } |
878 | |
879 | if ( SDL_modelist ) { |
880 | printf("X11 video mode list:\n"); |
881 | for ( i=0; SDL_modelist[i]; ++i ) { |
882 | printf("\t%dx%d\n", SDL_modelist[i]->w, SDL_modelist[i]->h); |
883 | } |
884 | } |
885 | #endif /* X11MODES_DEBUG */ |
886 | |
887 | return 0; |
888 | } |
889 | |
890 | int X11_SupportedVisual(_THIS, SDL_PixelFormat *format) |
891 | { |
892 | int i; |
893 | for(i = 0; i < this->hidden->nvisuals; i++) |
894 | if(this->hidden->visuals[i].bpp == format->BitsPerPixel) |
895 | return 1; |
896 | return 0; |
897 | } |
898 | |
899 | SDL_Rect **X11_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) |
900 | { |
901 | if ( X11_SupportedVisual(this, format) ) { |
902 | if ( flags & SDL_FULLSCREEN ) { |
903 | return(SDL_modelist); |
904 | } else { |
905 | return((SDL_Rect **)-1); |
906 | } |
907 | } else { |
908 | return((SDL_Rect **)0); |
909 | } |
910 | } |
911 | |
912 | void X11_FreeVideoModes(_THIS) |
913 | { |
914 | int i; |
915 | |
916 | if ( SDL_modelist ) { |
917 | for ( i=0; SDL_modelist[i]; ++i ) { |
918 | SDL_free(SDL_modelist[i]); |
919 | } |
920 | SDL_free(SDL_modelist); |
921 | SDL_modelist = NULL; |
922 | } |
923 | |
924 | #if SDL_VIDEO_DRIVER_X11_XRANDR |
925 | /* Free the Xrandr screen configuration */ |
926 | if ( screen_config ) { |
927 | XRRFreeScreenConfigInfo(screen_config); |
928 | screen_config = NULL; |
929 | } |
930 | #endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ |
931 | } |
932 | |
933 | int X11_ResizeFullScreen(_THIS) |
934 | { |
935 | int x = 0, y = 0; |
936 | int real_w, real_h; |
937 | int screen_w; |
938 | int screen_h; |
939 | |
940 | screen_w = DisplayWidth(SDL_Display, SDL_Screen); |
941 | screen_h = DisplayHeight(SDL_Display, SDL_Screen); |
942 | |
943 | #if SDL_VIDEO_DRIVER_X11_XINERAMA |
944 | if ( use_xinerama && |
945 | window_w <= xinerama_info.width && |
946 | window_h <= xinerama_info.height ) { |
947 | x = xinerama_info.x_org; |
948 | y = xinerama_info.y_org; |
949 | } |
950 | #endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ |
951 | |
952 | if ( currently_fullscreen ) { |
953 | /* Switch resolution and cover it with the FSwindow */ |
954 | move_cursor_to(this, x, y); |
955 | set_best_resolution(this, window_w, window_h); |
956 | move_cursor_to(this, x, y); |
957 | get_real_resolution(this, &real_w, &real_h); |
958 | if ( window_w > real_w ) { |
959 | real_w = MAX(real_w, screen_w); |
960 | } |
961 | if ( window_h > real_h ) { |
962 | real_h = MAX(real_h, screen_h); |
963 | } |
964 | XMoveResizeWindow(SDL_Display, FSwindow, x, y, real_w, real_h); |
965 | move_cursor_to(this, real_w/2, real_h/2); |
966 | |
967 | /* Center and reparent the drawing window */ |
968 | x = (real_w - window_w)/2; |
969 | y = (real_h - window_h)/2; |
970 | XReparentWindow(SDL_Display, SDL_Window, FSwindow, x, y); |
971 | /* FIXME: move the mouse to the old relative location */ |
972 | XSync(SDL_Display, True); /* Flush spurious mode change events */ |
973 | } |
974 | return(1); |
975 | } |
976 | |
977 | void X11_QueueEnterFullScreen(_THIS) |
978 | { |
979 | switch_waiting = 0x01 | SDL_FULLSCREEN; |
980 | switch_time = SDL_GetTicks() + 1500; |
981 | #if 0 /* This causes a BadMatch error if the window is iconified (not needed) */ |
982 | XSetInputFocus(SDL_Display, WMwindow, RevertToNone, CurrentTime); |
983 | #endif |
984 | } |
985 | |
986 | int X11_EnterFullScreen(_THIS) |
987 | { |
988 | int okay; |
989 | #if 0 |
990 | Window tmpwin, *windows; |
991 | int i, nwindows; |
992 | #endif |
993 | int x = 0, y = 0; |
994 | int real_w, real_h; |
995 | int screen_w; |
996 | int screen_h; |
997 | |
998 | okay = 1; |
999 | if ( currently_fullscreen ) { |
1000 | return(okay); |
1001 | } |
1002 | |
1003 | /* Ungrab the input so that we can move the mouse around */ |
1004 | X11_GrabInputNoLock(this, SDL_GRAB_OFF); |
1005 | |
1006 | #if SDL_VIDEO_DRIVER_X11_XINERAMA |
1007 | if ( use_xinerama && |
1008 | window_w <= xinerama_info.width && |
1009 | window_h <= xinerama_info.height ) { |
1010 | x = xinerama_info.x_org; |
1011 | y = xinerama_info.y_org; |
1012 | } |
1013 | #endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ |
1014 | |
1015 | /* Map the fullscreen window to blank the screen */ |
1016 | screen_w = DisplayWidth(SDL_Display, SDL_Screen); |
1017 | screen_h = DisplayHeight(SDL_Display, SDL_Screen); |
1018 | get_real_resolution(this, &real_w, &real_h); |
1019 | real_w = MAX(window_w, MAX(real_w, screen_w)); |
1020 | real_h = MAX(window_h, MAX(real_h, screen_h)); |
1021 | XMoveResizeWindow(SDL_Display, FSwindow, |
1022 | x, y, real_w, real_h); |
1023 | XMapRaised(SDL_Display, FSwindow); |
1024 | X11_WaitMapped(this, FSwindow); |
1025 | |
1026 | #if 0 /* This seems to break WindowMaker in focus-follows-mouse mode */ |
1027 | /* Make sure we got to the top of the window stack */ |
1028 | if ( XQueryTree(SDL_Display, SDL_Root, &tmpwin, &tmpwin, |
1029 | &windows, &nwindows) && windows ) { |
1030 | /* If not, try to put us there - if fail... oh well */ |
1031 | if ( windows[nwindows-1] != FSwindow ) { |
1032 | tmpwin = windows[nwindows-1]; |
1033 | for ( i=0; i<nwindows; ++i ) { |
1034 | if ( windows[i] == FSwindow ) { |
1035 | SDL_memcpy(&windows[i], &windows[i+1], |
1036 | (nwindows-i-1)*sizeof(windows[i])); |
1037 | break; |
1038 | } |
1039 | } |
1040 | windows[nwindows-1] = FSwindow; |
1041 | XRestackWindows(SDL_Display, windows, nwindows); |
1042 | XSync(SDL_Display, False); |
1043 | } |
1044 | XFree(windows); |
1045 | } |
1046 | #else |
1047 | XRaiseWindow(SDL_Display, FSwindow); |
1048 | #endif |
1049 | |
1050 | #if SDL_VIDEO_DRIVER_X11_VIDMODE |
1051 | /* Save the current video mode */ |
1052 | if ( use_vidmode ) { |
1053 | SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, True); |
1054 | save_mode(this); |
1055 | } |
1056 | #endif |
1057 | currently_fullscreen = 1; |
1058 | |
1059 | /* Set the new resolution */ |
1060 | okay = X11_ResizeFullScreen(this); |
1061 | if ( ! okay ) { |
1062 | X11_LeaveFullScreen(this); |
1063 | } |
1064 | /* Set the colormap */ |
1065 | if ( SDL_XColorMap ) { |
1066 | XInstallColormap(SDL_Display, SDL_XColorMap); |
1067 | } |
1068 | if ( okay ) { |
1069 | X11_GrabInputNoLock(this, this->input_grab | SDL_GRAB_FULLSCREEN); |
1070 | } |
1071 | |
1072 | /* We may need to refresh the screen at this point (no backing store) |
1073 | We also don't get an event, which is why we explicitly refresh. */ |
1074 | if ( this->screen ) { |
1075 | if ( this->screen->flags & SDL_OPENGL ) { |
1076 | SDL_PrivateExpose(); |
1077 | } else { |
1078 | X11_RefreshDisplay(this); |
1079 | } |
1080 | } |
1081 | |
1082 | return(okay); |
1083 | } |
1084 | |
1085 | int X11_LeaveFullScreen(_THIS) |
1086 | { |
1087 | if ( currently_fullscreen ) { |
1088 | XReparentWindow(SDL_Display, SDL_Window, WMwindow, 0, 0); |
1089 | #if SDL_VIDEO_DRIVER_X11_VIDMODE |
1090 | if ( use_vidmode ) { |
1091 | restore_mode(this); |
1092 | SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, False); |
1093 | } |
1094 | #endif |
1095 | |
1096 | #if SDL_VIDEO_DRIVER_X11_XME |
1097 | if ( use_xme ) { |
1098 | int rw, rh; |
1099 | |
1100 | /* check current mode so we can avoid uneccessary mode changes */ |
1101 | get_real_resolution(this, &rw, &rh); |
1102 | |
1103 | if (rw != saved_res.width || rh != saved_res.height) { |
1104 | XiGMiscChangeResolution(SDL_Display, |
1105 | SDL_Screen, |
1106 | 0, /* view */ |
1107 | saved_res.width, |
1108 | saved_res.height, |
1109 | 0); |
1110 | XSync(SDL_Display, False); |
1111 | } |
1112 | } |
1113 | #endif |
1114 | |
1115 | #if SDL_VIDEO_DRIVER_X11_XRANDR |
1116 | if ( use_xrandr ) { |
1117 | XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, |
1118 | saved_size_id, saved_rotation, CurrentTime); |
1119 | } |
1120 | #endif |
1121 | |
1122 | XUnmapWindow(SDL_Display, FSwindow); |
1123 | X11_WaitUnmapped(this, FSwindow); |
1124 | XSync(SDL_Display, True); /* Flush spurious mode change events */ |
1125 | currently_fullscreen = 0; |
1126 | } |
1127 | /* If we get popped out of fullscreen mode for some reason, input_grab |
1128 | will still have the SDL_GRAB_FULLSCREEN flag set, since this is only |
1129 | temporary. In this case, release the grab unless the input has been |
1130 | explicitly grabbed. |
1131 | */ |
1132 | X11_GrabInputNoLock(this, this->input_grab & ~SDL_GRAB_FULLSCREEN); |
1133 | |
1134 | /* We may need to refresh the screen at this point (no backing store) |
1135 | We also don't get an event, which is why we explicitly refresh. */ |
1136 | if ( this->screen ) { |
1137 | if ( this->screen->flags & SDL_OPENGL ) { |
1138 | SDL_PrivateExpose(); |
1139 | } else { |
1140 | X11_RefreshDisplay(this); |
1141 | } |
1142 | } |
1143 | |
1144 | return(0); |
1145 | } |