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