1 | /* |
2 | * fg_gamemode_x11.c |
3 | * |
4 | * The game mode handling code. |
5 | * |
6 | * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. |
7 | * Written by Pawel W. Olszta, <olszta@sourceforge.net> |
8 | * Copied for Platform code by Evan Felix <karcaw at gmail.com> |
9 | * Creation date: Thur Feb 2 2012 |
10 | * |
11 | * Permission is hereby granted, free of charge, to any person obtaining a |
12 | * copy of this software and associated documentation files (the "Software"), |
13 | * to deal in the Software without restriction, including without limitation |
14 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
15 | * and/or sell copies of the Software, and to permit persons to whom the |
16 | * Software is furnished to do so, subject to the following conditions: |
17 | * |
18 | * The above copyright notice and this permission notice shall be included |
19 | * in all copies or substantial portions of the Software. |
20 | * |
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
22 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
24 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
25 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
26 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
27 | */ |
28 | |
29 | #include <GL/freeglut.h> |
30 | #include "../fg_internal.h" |
31 | |
32 | /* we'll try to use XR&R if it's available at compile-time, and at runtime, and the user |
33 | * hasn't explicitly disabled it by setting the FREEGLUT_NO_XRANDR env-var. |
34 | */ |
35 | static int use_xrandr(void) |
36 | { |
37 | #ifdef HAVE_X11_EXTENSIONS_XRANDR_H |
38 | int event_base, error_base; |
39 | if(!XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) { |
40 | return 0; |
41 | } |
42 | if(getenv("FREEGLUT_NO_XRANDR" )) { |
43 | return 0; |
44 | } |
45 | return 1; |
46 | #else |
47 | return 0; /* no compile-time support */ |
48 | #endif |
49 | } |
50 | |
51 | /* we'll try to use XF86VidMode if it's available at compile-time, and at runtime, and the |
52 | * user hasn't explicitly disabled it by setting the FREEGLUT_NO_XF86VM env-var. |
53 | */ |
54 | static int use_xf86vm(void) |
55 | { |
56 | #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H |
57 | int event_base, error_base; |
58 | if(!XF86VidModeQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) { |
59 | return 0; |
60 | } |
61 | if(getenv("FREEGLUT_NO_XF86VM" )) { |
62 | return 0; |
63 | } |
64 | return 1; |
65 | #else |
66 | return 0; /* no compile-time support */ |
67 | #endif |
68 | } |
69 | |
70 | |
71 | #ifdef HAVE_X11_EXTENSIONS_XRANDR_H |
72 | static int xrandr_resize(int xsz, int ysz, int rate, int just_checking) |
73 | { |
74 | int ver_major, ver_minor, use_rate; |
75 | XRRScreenConfiguration *xrr_config = 0; |
76 | Status result = -1; |
77 | |
78 | /* NOTE: we have already determined that XR&R is available and enabled before calling this */ |
79 | |
80 | XRRQueryVersion(fgDisplay.pDisplay.Display, &ver_major, &ver_minor); |
81 | |
82 | /* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and |
83 | * the user actually cares about it (rate > 0) |
84 | */ |
85 | use_rate = ( rate > 0 ) && ( ( ver_major > 1 ) || |
86 | ( ( ver_major == 1 ) && ( ver_minor >= 1 ) ) ); |
87 | |
88 | /* this loop is only so that the whole thing will be repeated if someone |
89 | * else changes video mode between our query of the current information and |
90 | * the attempt to change it. |
91 | */ |
92 | do { |
93 | XRRScreenSize *ssizes; |
94 | short *rates; |
95 | Rotation rot; |
96 | int i, ssizes_count, rates_count, curr, res_idx = -1; |
97 | Time timestamp, cfg_timestamp; |
98 | |
99 | if(xrr_config) { |
100 | XRRFreeScreenConfigInfo(xrr_config); |
101 | } |
102 | |
103 | if(!(xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) { |
104 | fgWarning("XRRGetScreenInfo failed" ); |
105 | break; |
106 | } |
107 | ssizes = XRRConfigSizes(xrr_config, &ssizes_count); |
108 | curr = XRRConfigCurrentConfiguration(xrr_config, &rot); |
109 | timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp); |
110 | |
111 | /* if either of xsz or ysz are unspecified, use the current values */ |
112 | if(xsz <= 0) |
113 | xsz = fgState.GameModeSize.X = ssizes[curr].width; |
114 | if(ysz <= 0) |
115 | ysz = fgState.GameModeSize.Y = ssizes[curr].height; |
116 | |
117 | |
118 | if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) { |
119 | /* no need to switch, we're already in the requested resolution */ |
120 | res_idx = curr; |
121 | } else { |
122 | for(i=0; i<ssizes_count; i++) { |
123 | if(ssizes[i].width == xsz && ssizes[i].height == ysz) { |
124 | res_idx = i; |
125 | break; /* found it */ |
126 | } |
127 | } |
128 | } |
129 | if(res_idx == -1) |
130 | break; /* no matching resolution */ |
131 | |
132 | #if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) |
133 | if(use_rate) { |
134 | rate = fgState.GameModeRefresh; |
135 | |
136 | /* for the selected resolution, let's find out if there is |
137 | * a matching refresh rate available. |
138 | */ |
139 | rates = XRRConfigRates(xrr_config, res_idx, &rates_count); |
140 | |
141 | for(i=0; i<rates_count; i++) { |
142 | if(rates[i] == rate) { |
143 | break; |
144 | } |
145 | } |
146 | if(i == rates_count) { |
147 | break; /* no matching rate */ |
148 | } |
149 | } |
150 | #endif |
151 | |
152 | if(just_checking) { |
153 | result = 0; |
154 | break; |
155 | } |
156 | |
157 | #if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) |
158 | if(use_rate) |
159 | result = XRRSetScreenConfigAndRate(fgDisplay.pDisplay.Display, xrr_config, |
160 | fgDisplay.pDisplay.RootWindow, res_idx, rot, rate, timestamp); |
161 | else |
162 | #endif |
163 | result = XRRSetScreenConfig(fgDisplay.pDisplay.Display, xrr_config, |
164 | fgDisplay.pDisplay.RootWindow, res_idx, rot, timestamp); |
165 | |
166 | } while(result == RRSetConfigInvalidTime); |
167 | |
168 | if(xrr_config) { |
169 | XRRFreeScreenConfigInfo(xrr_config); |
170 | } |
171 | |
172 | if(result == 0) { |
173 | return 0; |
174 | } |
175 | |
176 | return -1; |
177 | } |
178 | #endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ |
179 | |
180 | /* |
181 | * Remembers the current visual settings, so that |
182 | * we can change them and restore later... |
183 | */ |
184 | void fgPlatformRememberState( void ) |
185 | { |
186 | /* |
187 | * Remember the current pointer location before going fullscreen |
188 | * for restoring it later: |
189 | */ |
190 | Window junk_window; |
191 | unsigned int junk_mask; |
192 | |
193 | XQueryPointer(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow, |
194 | &junk_window, &junk_window, |
195 | &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, |
196 | &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, &junk_mask); |
197 | |
198 | # ifdef HAVE_X11_EXTENSIONS_XRANDR_H |
199 | if(use_xrandr()) { |
200 | XRRScreenConfiguration *xrr_config; |
201 | XRRScreenSize *ssizes; |
202 | Rotation rot; |
203 | int ssize_count, curr; |
204 | |
205 | if((xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) { |
206 | ssizes = XRRConfigSizes(xrr_config, &ssize_count); |
207 | curr = XRRConfigCurrentConfiguration(xrr_config, &rot); |
208 | |
209 | fgDisplay.pDisplay.prev_xsz = ssizes[curr].width; |
210 | fgDisplay.pDisplay.prev_ysz = ssizes[curr].height; |
211 | fgDisplay.pDisplay.prev_refresh = -1; |
212 | |
213 | # if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) |
214 | if(fgState.GameModeRefresh != -1) { |
215 | fgDisplay.pDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config); |
216 | } |
217 | # endif |
218 | |
219 | fgDisplay.pDisplay.prev_size_valid = 1; |
220 | |
221 | XRRFreeScreenConfigInfo(xrr_config); |
222 | } |
223 | } |
224 | # endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ |
225 | |
226 | /* |
227 | * This highly depends on the XFree86 extensions, |
228 | * not approved as X Consortium standards |
229 | */ |
230 | # ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H |
231 | if(use_xf86vm()) { |
232 | /* |
233 | * Remember the current ViewPort location of the screen to be able to |
234 | * restore the ViewPort on LeaveGameMode(): |
235 | */ |
236 | if( !XF86VidModeGetViewPort( |
237 | fgDisplay.pDisplay.Display, |
238 | fgDisplay.pDisplay.Screen, |
239 | &fgDisplay.pDisplay.DisplayViewPortX, |
240 | &fgDisplay.pDisplay.DisplayViewPortY ) ) |
241 | fgWarning( "XF86VidModeGetViewPort failed" ); |
242 | |
243 | |
244 | /* Query the current display settings: */ |
245 | fgDisplay.pDisplay.DisplayModeValid = |
246 | XF86VidModeGetModeLine( |
247 | fgDisplay.pDisplay.Display, |
248 | fgDisplay.pDisplay.Screen, |
249 | &fgDisplay.pDisplay.DisplayModeClock, |
250 | &fgDisplay.pDisplay.DisplayMode |
251 | ); |
252 | |
253 | if( !fgDisplay.pDisplay.DisplayModeValid ) |
254 | fgWarning( "XF86VidModeGetModeLine failed" ); |
255 | } |
256 | # endif |
257 | |
258 | } |
259 | |
260 | /* |
261 | * Restores the previously remembered visual settings |
262 | */ |
263 | void fgPlatformRestoreState( void ) |
264 | { |
265 | /* Restore the remembered pointer position: */ |
266 | XWarpPointer( |
267 | fgDisplay.pDisplay.Display, None, fgDisplay.pDisplay.RootWindow, 0, 0, 0, 0, |
268 | fgDisplay.pDisplay.DisplayPointerX, fgDisplay.pDisplay.DisplayPointerY |
269 | ); |
270 | |
271 | #ifdef HAVE_X11_EXTENSIONS_XRANDR_H |
272 | if(use_xrandr()) { |
273 | if(fgDisplay.pDisplay.prev_size_valid) { |
274 | if(xrandr_resize(fgDisplay.pDisplay.prev_xsz, fgDisplay.pDisplay.prev_ysz, fgDisplay.pDisplay.prev_refresh, 0) != -1) { |
275 | fgDisplay.pDisplay.prev_size_valid = 0; |
276 | #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H |
277 | fgDisplay.pDisplay.DisplayModeValid = 0; |
278 | #endif |
279 | } |
280 | } |
281 | return; /* don't fall back to XF86VidMode if we have XR&R */ |
282 | } |
283 | #endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ |
284 | |
285 | |
286 | |
287 | #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H |
288 | /* |
289 | * This highly depends on the XFree86 extensions, |
290 | * not approved as X Consortium standards |
291 | */ |
292 | if(use_xf86vm()) { |
293 | |
294 | if( fgDisplay.pDisplay.DisplayModeValid ) |
295 | { |
296 | XF86VidModeModeInfo** displayModes; |
297 | int i, displayModesCount; |
298 | |
299 | if( !XF86VidModeGetAllModeLines( |
300 | fgDisplay.pDisplay.Display, |
301 | fgDisplay.pDisplay.Screen, |
302 | &displayModesCount, |
303 | &displayModes ) ) |
304 | { |
305 | fgWarning( "XF86VidModeGetAllModeLines failed" ); |
306 | return; |
307 | } |
308 | |
309 | |
310 | /* |
311 | * Check every of the modes looking for one that matches our demands. |
312 | * If we find one, switch to it and restore the remembered viewport. |
313 | */ |
314 | for( i = 0; i < displayModesCount; i++ ) |
315 | { |
316 | if(displayModes[ i ]->hdisplay == fgDisplay.pDisplay.DisplayMode.hdisplay && |
317 | displayModes[ i ]->vdisplay == fgDisplay.pDisplay.DisplayMode.vdisplay && |
318 | displayModes[ i ]->dotclock == fgDisplay.pDisplay.DisplayModeClock ) |
319 | { |
320 | if( !XF86VidModeSwitchToMode( |
321 | fgDisplay.pDisplay.Display, |
322 | fgDisplay.pDisplay.Screen, |
323 | displayModes[ i ] ) ) |
324 | { |
325 | fgWarning( "XF86VidModeSwitchToMode failed" ); |
326 | break; |
327 | } |
328 | |
329 | if( !XF86VidModeSetViewPort( |
330 | fgDisplay.pDisplay.Display, |
331 | fgDisplay.pDisplay.Screen, |
332 | fgDisplay.pDisplay.DisplayViewPortX, |
333 | fgDisplay.pDisplay.DisplayViewPortY ) ) |
334 | fgWarning( "XF86VidModeSetViewPort failed" ); |
335 | |
336 | |
337 | /* |
338 | * For the case this would be the last X11 call the application |
339 | * calls exit() we've to flush the X11 output queue to have the |
340 | * commands sent to the X server before the application exits. |
341 | */ |
342 | XFlush( fgDisplay.pDisplay.Display ); |
343 | |
344 | fgDisplay.pDisplay.DisplayModeValid = 0; |
345 | #ifdef HAVE_X11_EXTENSIONS_XRANDR_H |
346 | fgDisplay.pDisplay.prev_size_valid = 0; |
347 | #endif |
348 | break; |
349 | } |
350 | } |
351 | XFree( displayModes ); |
352 | } |
353 | } |
354 | #endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */ |
355 | } |
356 | |
357 | #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H |
358 | |
359 | /* |
360 | * Checks a single display mode settings against user's preferences. |
361 | */ |
362 | static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh ) |
363 | { |
364 | /* The desired values should be stored in fgState structure... */ |
365 | return ( width == fgState.GameModeSize.X ) && |
366 | ( height == fgState.GameModeSize.Y ) && |
367 | ( depth == fgState.GameModeDepth ) && |
368 | ( refresh == fgState.GameModeRefresh ); |
369 | } |
370 | |
371 | /* |
372 | * Checks all display modes settings against user's preferences. |
373 | * Returns the mode number found or -1 if none could be found. |
374 | */ |
375 | static int fghCheckDisplayModes( GLboolean exactMatch, int displayModesCount, XF86VidModeModeInfo** displayModes ) |
376 | { |
377 | int i; |
378 | for( i = 0; i < displayModesCount; i++ ) |
379 | { |
380 | /* Compute the displays refresh rate, dotclock comes in kHz. */ |
381 | int refresh = ( displayModes[ i ]->dotclock * 1000 ) / |
382 | ( displayModes[ i ]->htotal * displayModes[ i ]->vtotal ); |
383 | |
384 | if( fghCheckDisplayMode( displayModes[ i ]->hdisplay, |
385 | displayModes[ i ]->vdisplay, |
386 | fgState.GameModeDepth, |
387 | ( exactMatch ? refresh : fgState.GameModeRefresh ) ) ) { |
388 | if (!exactMatch) |
389 | { |
390 | /* Update the chosen refresh rate, otherwise a |
391 | * glutGameModeGet(GLUT_GAME_MODE_REFRESH_RATE) would not |
392 | * return the right values |
393 | */ |
394 | fgState.GameModeRefresh = refresh; |
395 | } |
396 | |
397 | return i; |
398 | } |
399 | } |
400 | return -1; |
401 | } |
402 | |
403 | #endif |
404 | |
405 | /* |
406 | * Changes the current display mode to match user's settings |
407 | */ |
408 | GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest ) |
409 | { |
410 | GLboolean success = GL_FALSE; |
411 | #ifdef HAVE_X11_EXTENSIONS_XRANDR_H |
412 | if(use_xrandr()) { |
413 | if(xrandr_resize(fgState.GameModeSize.X, fgState.GameModeSize.Y, |
414 | fgState.GameModeRefresh, haveToTest) != -1) { |
415 | return GL_TRUE; |
416 | } |
417 | return GL_FALSE; /* don't fall back to XF86VidMode */ |
418 | } |
419 | #endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ |
420 | |
421 | |
422 | /* |
423 | * This highly depends on the XFree86 extensions, |
424 | * not approved as X Consortium standards |
425 | */ |
426 | #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H |
427 | if(use_xf86vm()) { |
428 | /* |
429 | * This is also used by applications which check modes by calling |
430 | * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check: |
431 | */ |
432 | if( haveToTest || fgDisplay.pDisplay.DisplayModeValid ) |
433 | { |
434 | XF86VidModeModeInfo** displayModes; |
435 | int i, displayModesCount; |
436 | |
437 | /* If we don't have a valid modeline in the display structure, which |
438 | * can happen if this is called from glutGameModeGet instead of |
439 | * glutEnterGameMode, then we need to query the current mode, to make |
440 | * unspecified settings to default to their current values. |
441 | */ |
442 | if(!fgDisplay.pDisplay.DisplayModeValid) { |
443 | if(!XF86VidModeGetModeLine(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, |
444 | &fgDisplay.pDisplay.DisplayModeClock, &fgDisplay.pDisplay.DisplayMode)) { |
445 | return success; |
446 | } |
447 | } |
448 | |
449 | if (fgState.GameModeSize.X == -1) |
450 | { |
451 | fgState.GameModeSize.X = fgDisplay.pDisplay.DisplayMode.hdisplay; |
452 | } |
453 | if (fgState.GameModeSize.Y == -1) |
454 | { |
455 | fgState.GameModeSize.Y = fgDisplay.pDisplay.DisplayMode.vdisplay; |
456 | } |
457 | if (fgState.GameModeDepth == -1) |
458 | { |
459 | /* can't get color depth from this, nor can we change it, do nothing |
460 | * TODO: get with XGetVisualInfo()? but then how to set? |
461 | */ |
462 | } |
463 | if (fgState.GameModeRefresh == -1) |
464 | { |
465 | /* Compute the displays refresh rate, dotclock comes in kHz. */ |
466 | int refresh = ( fgDisplay.pDisplay.DisplayModeClock * 1000 ) / |
467 | ( fgDisplay.pDisplay.DisplayMode.htotal * fgDisplay.pDisplay.DisplayMode.vtotal ); |
468 | |
469 | fgState.GameModeRefresh = refresh; |
470 | } |
471 | |
472 | /* query all possible display modes */ |
473 | if( !XF86VidModeGetAllModeLines( |
474 | fgDisplay.pDisplay.Display, |
475 | fgDisplay.pDisplay.Screen, |
476 | &displayModesCount, |
477 | &displayModes ) ) |
478 | { |
479 | fgWarning( "XF86VidModeGetAllModeLines failed" ); |
480 | return success; |
481 | } |
482 | |
483 | |
484 | /* |
485 | * Check every of the modes looking for one that matches our demands, |
486 | * ignoring the refresh rate if no exact match could be found. |
487 | */ |
488 | i = fghCheckDisplayModes( GL_TRUE, displayModesCount, displayModes ); |
489 | if( i < 0 ) { |
490 | i = fghCheckDisplayModes( GL_FALSE, displayModesCount, displayModes ); |
491 | } |
492 | success = ( i < 0 ) ? GL_FALSE : GL_TRUE; |
493 | |
494 | if( !haveToTest && success ) { |
495 | if( !XF86VidModeSwitchToMode( |
496 | fgDisplay.pDisplay.Display, |
497 | fgDisplay.pDisplay.Screen, |
498 | displayModes[ i ] ) ) |
499 | fgWarning( "XF86VidModeSwitchToMode failed" ); |
500 | } |
501 | |
502 | XFree( displayModes ); |
503 | } |
504 | } |
505 | |
506 | #endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */ |
507 | |
508 | return success; |
509 | } |
510 | |
511 | |
512 | void fgPlatformEnterGameMode( void ) |
513 | { |
514 | |
515 | /* |
516 | * Sync needed to avoid a real race, the Xserver must have really created |
517 | * the window before we can grab the pointer into it: |
518 | */ |
519 | XSync( fgDisplay.pDisplay.Display, False ); |
520 | /* |
521 | * Grab the pointer to confine it into the window after the calls to |
522 | * XWrapPointer() which ensure that the pointer really enters the window. |
523 | * |
524 | * We also need to wait here until XGrabPointer() returns GrabSuccess, |
525 | * otherwise the new window is not viewable yet and if the next function |
526 | * (XSetInputFocus) is called with a not yet viewable window, it will exit |
527 | * the application which we have to aviod, so wait until it's viewable: |
528 | */ |
529 | while( GrabSuccess != XGrabPointer( |
530 | fgDisplay.pDisplay.Display, fgStructure.GameModeWindow->Window.Handle, |
531 | TRUE, |
532 | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
533 | | PointerMotionMask, |
534 | GrabModeAsync, GrabModeAsync, |
535 | fgStructure.GameModeWindow->Window.Handle, None, CurrentTime) ) |
536 | usleep( 100 ); |
537 | /* |
538 | * Change input focus to the new window. This will exit the application |
539 | * if the new window is not viewable yet, see the XGrabPointer loop above. |
540 | */ |
541 | XSetInputFocus( |
542 | fgDisplay.pDisplay.Display, |
543 | fgStructure.GameModeWindow->Window.Handle, |
544 | RevertToNone, |
545 | CurrentTime |
546 | ); |
547 | |
548 | /* Move the Pointer to the middle of the fullscreen window */ |
549 | XWarpPointer( |
550 | fgDisplay.pDisplay.Display, |
551 | None, |
552 | fgDisplay.pDisplay.RootWindow, |
553 | 0, 0, 0, 0, |
554 | fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2 |
555 | ); |
556 | |
557 | #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H |
558 | if(use_xf86vm()) { |
559 | |
560 | if( fgDisplay.pDisplay.DisplayModeValid ) |
561 | { |
562 | int x, y; |
563 | Window child; |
564 | |
565 | /* Change to viewport to the window topleft edge: */ |
566 | if( !XF86VidModeSetViewPort( fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, 0, 0 ) ) |
567 | fgWarning( "XF86VidModeSetViewPort failed" ); |
568 | |
569 | /* |
570 | * Final window repositioning: It could be avoided using an undecorated |
571 | * window using override_redirect, but this * would possily require |
572 | * more changes and investigation. |
573 | */ |
574 | |
575 | /* Get the current position of the drawable area on screen */ |
576 | XTranslateCoordinates( |
577 | fgDisplay.pDisplay.Display, |
578 | fgStructure.CurrentWindow->Window.Handle, |
579 | fgDisplay.pDisplay.RootWindow, |
580 | 0, 0, &x, &y, |
581 | &child |
582 | ); |
583 | |
584 | /* Move the decorataions out of the topleft corner of the display */ |
585 | XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle, |
586 | -x, -y); |
587 | } |
588 | } |
589 | |
590 | #endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */ |
591 | |
592 | /* Grab the keyboard, too */ |
593 | XGrabKeyboard( |
594 | fgDisplay.pDisplay.Display, |
595 | fgStructure.GameModeWindow->Window.Handle, |
596 | FALSE, |
597 | GrabModeAsync, GrabModeAsync, |
598 | CurrentTime |
599 | ); |
600 | |
601 | } |
602 | |
603 | void fgPlatformLeaveGameMode( void ) |
604 | { |
605 | XUngrabPointer( fgDisplay.pDisplay.Display, CurrentTime ); |
606 | XUngrabKeyboard( fgDisplay.pDisplay.Display, CurrentTime ); |
607 | } |
608 | |
609 | |