about summary refs log tree commit diff
path: root/src/engine/external/glfw/lib/x11
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2007-08-22 07:52:33 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2007-08-22 07:52:33 +0000
commit8b3c16e6152a527f9aec1a88a9eed74119de7000 (patch)
treef0bde5cea15e696e42cade06a3b12ff6b13acc57 /src/engine/external/glfw/lib/x11
parent9899666a7ce6679a3b9667ab09f615f4d0769c16 (diff)
downloadzcatch-8b3c16e6152a527f9aec1a88a9eed74119de7000.tar.gz
zcatch-8b3c16e6152a527f9aec1a88a9eed74119de7000.zip
major engine cleanup. dependency on baselib removed. engine is now C code (not ansi tho). some other cruft removed aswell
Diffstat (limited to 'src/engine/external/glfw/lib/x11')
-rw-r--r--src/engine/external/glfw/lib/x11/platform.h415
-rw-r--r--src/engine/external/glfw/lib/x11/x11_enable.c51
-rw-r--r--src/engine/external/glfw/lib/x11/x11_fullscreen.c524
-rw-r--r--src/engine/external/glfw/lib/x11/x11_glext.c69
-rw-r--r--src/engine/external/glfw/lib/x11/x11_init.c275
-rw-r--r--src/engine/external/glfw/lib/x11/x11_joystick.c371
-rw-r--r--src/engine/external/glfw/lib/x11/x11_keysym2unicode.c902
-rw-r--r--src/engine/external/glfw/lib/x11/x11_thread.c507
-rw-r--r--src/engine/external/glfw/lib/x11/x11_time.c154
-rw-r--r--src/engine/external/glfw/lib/x11/x11_window.c1746
10 files changed, 5014 insertions, 0 deletions
diff --git a/src/engine/external/glfw/lib/x11/platform.h b/src/engine/external/glfw/lib/x11/platform.h
new file mode 100644
index 00000000..d03d3582
--- /dev/null
+++ b/src/engine/external/glfw/lib/x11/platform.h
@@ -0,0 +1,415 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        platform.h

+// Platform:    X11 (Unix)

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#ifndef _platform_h_

+#define _platform_h_

+

+

+// This is the X11 version of GLFW

+#define _GLFW_X11

+

+

+// Include files

+#include <sys/time.h>

+#include <unistd.h>

+#include <signal.h>

+#include <X11/Xlib.h>

+#include <X11/keysym.h>

+#include <X11/Xatom.h>

+#include <GL/glx.h>

+#include "../../include/GL/glfw.h"

+

+// Do we have pthread support?

+#ifdef _GLFW_HAS_PTHREAD

+ #include <pthread.h>

+ #include <sched.h>

+#endif

+

+// With XFree86, we can use the XF86VidMode extension

+#if defined( _GLFW_HAS_XF86VIDMODE )

+ #include <X11/extensions/xf86vmode.h>

+#endif

+

+#if defined( _GLFW_HAS_XRANDR )

+ #include <X11/extensions/Xrandr.h>

+#endif

+

+// Do we have support for dlopen/dlsym?

+#if defined( _GLFW_HAS_DLOPEN )

+ #include <dlfcn.h>

+#endif

+

+// We support two different ways for getting the number of processors in

+// the system: sysconf (POSIX) and sysctl (BSD?)

+#if defined( _GLFW_HAS_SYSCONF )

+

+ // Use a single constant for querying number of online processors using

+ // the sysconf function (e.g. SGI defines _SC_NPROC_ONLN instead of

+ // _SC_NPROCESSORS_ONLN)

+ #ifndef _SC_NPROCESSORS_ONLN

+  #ifdef  _SC_NPROC_ONLN

+   #define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN

+  #else

+   #error POSIX constant _SC_NPROCESSORS_ONLN not defined!

+  #endif

+ #endif

+

+ // Macro for querying the number of processors

+ #define _glfw_numprocessors(n) n=(int)sysconf(_SC_NPROCESSORS_ONLN)

+

+#elif defined( _GLFW_HAS_SYSCTL )

+

+ #include <sys/types.h>

+ #include <sys/sysctl.h>

+

+ // Macro for querying the number of processors

+ #define _glfw_numprocessors(n) { \

+    int mib[2], ncpu; \

+    size_t len = 1; \

+    mib[0] = CTL_HW; \

+    mib[1] = HW_NCPU; \

+    n      = 1; \

+    if( sysctl( mib, 2, &ncpu, &len, NULL, 0 ) != -1 ) \

+    { \

+        if( len > 0 ) \

+        { \

+            n = ncpu; \

+        } \

+    } \

+ }

+

+#else

+

+ // If neither sysconf nor sysctl is supported, assume single processor

+ // system

+ #define _glfw_numprocessors(n) n=1

+

+#endif

+

+void (*glXGetProcAddress(const GLubyte *procName))();

+void (*glXGetProcAddressARB(const GLubyte *procName))();

+void (*glXGetProcAddressEXT(const GLubyte *procName))();

+

+// We support four different ways for getting addresses for GL/GLX

+// extension functions: glXGetProcAddress, glXGetProcAddressARB,

+// glXGetProcAddressEXT, and dlsym

+#if   defined( _GLFW_HAS_GLXGETPROCADDRESSARB )

+ #define _glfw_glXGetProcAddress(x) glXGetProcAddressARB(x)

+#elif defined( _GLFW_HAS_GLXGETPROCADDRESS )

+ #define _glfw_glXGetProcAddress(x) glXGetProcAddress(x)

+#elif defined( _GLFW_HAS_GLXGETPROCADDRESSEXT )

+ #define _glfw_glXGetProcAddress(x) glXGetProcAddressEXT(x)

+#elif defined( _GLFW_HAS_DLOPEN )

+ #define _glfw_glXGetProcAddress(x) dlsym(_glfwLibs.libGL,x)

+ #define _GLFW_DLOPEN_LIBGL

+#else

+#define _glfw_glXGetProcAddress(x) NULL

+#endif

+

+// glXSwapIntervalSGI typedef (X11 buffer-swap interval control)

+typedef int ( * GLXSWAPINTERVALSGI_T) (int interval);

+

+

+//========================================================================

+// Global variables (GLFW internals)

+//========================================================================

+

+//------------------------------------------------------------------------

+// Window structure

+//------------------------------------------------------------------------

+typedef struct _GLFWwin_struct _GLFWwin;

+

+struct _GLFWwin_struct {

+

+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================

+

+    // User callback functions

+    GLFWwindowsizefun    WindowSizeCallback;

+    GLFWwindowclosefun   WindowCloseCallback;

+    GLFWwindowrefreshfun WindowRefreshCallback;

+    GLFWmousebuttonfun   MouseButtonCallback;

+    GLFWmouseposfun      MousePosCallback;

+    GLFWmousewheelfun    MouseWheelCallback;

+    GLFWkeyfun           KeyCallback;

+    GLFWcharfun          CharCallback;

+

+    // User selected window settings

+    int       Fullscreen;      // Fullscreen flag

+    int       MouseLock;       // Mouse-lock flag

+    int       AutoPollEvents;  // Auto polling flag

+    int       SysKeysDisabled; // System keys disabled flag

+    int       WindowNoResize;  // Resize- and maximize gadgets disabled flag

+

+    // Window status & parameters

+    int       Opened;          // Flag telling if window is opened or not

+    int       Active;          // Application active flag

+    int       Iconified;       // Window iconified flag

+    int       Width, Height;   // Window width and heigth

+    int       Accelerated;     // GL_TRUE if window is HW accelerated

+    int       RedBits;

+    int       GreenBits;

+    int       BlueBits;

+    int       AlphaBits;

+    int       DepthBits;

+    int       StencilBits;

+    int       AccumRedBits;

+    int       AccumGreenBits;

+    int       AccumBlueBits;

+    int       AccumAlphaBits;

+    int       AuxBuffers;

+    int       Stereo;

+    int       RefreshRate;     // Vertical monitor refresh rate

+    int       Samples;

+

+    // Extensions & OpenGL version

+    int       Has_GL_SGIS_generate_mipmap;

+    int       Has_GL_ARB_texture_non_power_of_two;

+    int       GLVerMajor,GLVerMinor;

+

+

+// ========= PLATFORM SPECIFIC PART ======================================

+

+    // Platform specific window resources

+    Window      Win;             // Window

+    int         Scrn;            // Screen ID

+    XVisualInfo *VI;             // Visual

+    GLXContext  CX;              // OpenGL rendering context

+    Atom        WMDeleteWindow;  // For WM close detection

+    Atom        WMPing;          // For WM ping response

+    XSizeHints  *Hints;          // WM size hints

+

+    // Platform specific extensions

+    GLXSWAPINTERVALSGI_T SwapInterval;

+

+    // Various platform specific internal variables

+    int         OverrideRedirect; // True if window is OverrideRedirect

+    int         KeyboardGrabbed; // True if keyboard is currently grabbed

+    int         PointerGrabbed;  // True if pointer is currently grabbed

+    int         PointerHidden;   // True if pointer is currently hidden

+    int         MapNotifyCount;  // Used for during processing

+    int         FocusInCount;    // Used for during processing

+

+    // Screensaver data

+    struct {

+	int     Changed;

+	int     Timeout;

+	int     Interval;

+	int     Blanking;

+	int     Exposure;

+    } Saver;

+

+    // Fullscreen data

+    struct {

+	int     ModeChanged;

+#if defined( _GLFW_HAS_XF86VIDMODE )

+	XF86VidModeModeInfo OldMode;

+#endif

+#if defined( _GLFW_HAS_XRANDR )

+        SizeID   OldSizeID;

+	int      OldWidth;

+	int      OldHeight;

+	Rotation OldRotation;

+#endif

+    } FS;

+};

+

+GLFWGLOBAL _GLFWwin _glfwWin;

+

+

+//------------------------------------------------------------------------

+// User input status (most of this should go in _GLFWwin)

+//------------------------------------------------------------------------

+GLFWGLOBAL struct {

+

+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================

+

+    // Mouse status

+    int  MousePosX, MousePosY;

+    int  WheelPos;

+    char MouseButton[ GLFW_MOUSE_BUTTON_LAST+1 ];

+

+    // Keyboard status

+    char Key[ GLFW_KEY_LAST+1 ];

+    int  LastChar;

+

+    // User selected settings

+    int  StickyKeys;

+    int  StickyMouseButtons;

+    int  KeyRepeat;

+

+

+// ========= PLATFORM SPECIFIC PART ======================================

+

+    // Platform specific internal variables

+    int  MouseMoved, CursorPosX, CursorPosY;

+

+} _glfwInput;

+

+

+//------------------------------------------------------------------------

+// Library global data

+//------------------------------------------------------------------------

+GLFWGLOBAL struct {

+

+// ========= PLATFORM SPECIFIC PART ======================================

+

+    Display     *Dpy;

+    int         NumScreens;

+    int         DefaultScreen;

+

+    struct {

+	int	Available;

+	int     EventBase;

+	int     ErrorBase;

+    } XF86VidMode;

+

+    struct {

+	int	Available;

+	int     EventBase;

+	int     ErrorBase;

+    } XRandR;

+

+    // Timer data

+    struct {

+	double       Resolution;

+	long long    t0;

+    } Timer;

+

+#if defined(_GLFW_DLOPEN_LIBGL)

+    struct {

+	void        *libGL;          // dlopen handle for libGL.so

+    } Libs;

+#endif

+} _glfwLibrary;

+

+

+//------------------------------------------------------------------------

+// Thread record (one for each thread)

+//------------------------------------------------------------------------

+typedef struct _GLFWthread_struct _GLFWthread;

+

+struct _GLFWthread_struct {

+

+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================

+

+    // Pointer to previous and next threads in linked list

+    _GLFWthread   *Previous, *Next;

+

+    // GLFW user side thread information

+    GLFWthread    ID;

+    GLFWthreadfun Function;

+

+// ========= PLATFORM SPECIFIC PART ======================================

+

+    // System side thread information

+#ifdef _GLFW_HAS_PTHREAD

+    pthread_t     PosixID;

+#endif

+

+};

+

+

+//------------------------------------------------------------------------

+// General thread information

+//------------------------------------------------------------------------

+GLFWGLOBAL struct {

+

+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================

+

+    // Next thread ID to use (increments for every created thread)

+    GLFWthread       NextID;

+

+    // First thread in linked list (always the main thread)

+    _GLFWthread      First;

+

+// ========= PLATFORM SPECIFIC PART ======================================

+

+    // Critical section lock

+#ifdef _GLFW_HAS_PTHREAD

+    pthread_mutex_t  CriticalSection;

+#endif

+

+} _glfwThrd;

+

+

+//------------------------------------------------------------------------

+// Joystick information & state

+//------------------------------------------------------------------------

+GLFWGLOBAL struct {

+    int           Present;

+    int           fd;

+    int           NumAxes;

+    int           NumButtons;

+    float         *Axis;

+    unsigned char *Button;

+} _glfwJoy[ GLFW_JOYSTICK_LAST + 1 ];

+

+

+//========================================================================

+// Macros for encapsulating critical code sections (i.e. making parts

+// of GLFW thread safe)

+//========================================================================

+

+// Thread list management

+#ifdef _GLFW_HAS_PTHREAD

+ #define ENTER_THREAD_CRITICAL_SECTION \

+         pthread_mutex_lock( &_glfwThrd.CriticalSection );

+ #define LEAVE_THREAD_CRITICAL_SECTION \

+         pthread_mutex_unlock( &_glfwThrd.CriticalSection );

+#else

+ #define ENTER_THREAD_CRITICAL_SECTION

+ #define LEAVE_THREAD_CRITICAL_SECTION

+#endif

+

+

+//========================================================================

+// Prototypes for platform specific internal functions

+//========================================================================

+

+// Time

+void _glfwInitTimer( void );

+

+// Fullscreen support

+int  _glfwGetClosestVideoMode( int screen, int *width, int *height, int *rate );

+void _glfwSetVideoModeMODE( int screen, int mode, int rate );

+void _glfwSetVideoMode( int screen, int *width, int *height, int *rate );

+

+// Cursor handling

+Cursor _glfwCreateNULLCursor( Display *display, Window root );

+

+// Joystick input

+void _glfwInitJoysticks( void );

+void _glfwTerminateJoysticks( void );

+

+// Unicode support

+long _glfwKeySym2Unicode( KeySym keysym );

+

+

+#endif // _platform_h_

diff --git a/src/engine/external/glfw/lib/x11/x11_enable.c b/src/engine/external/glfw/lib/x11/x11_enable.c
new file mode 100644
index 00000000..486833f7
--- /dev/null
+++ b/src/engine/external/glfw/lib/x11/x11_enable.c
@@ -0,0 +1,51 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        x11_enable.c

+// Platform:    X11 (Unix)

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#include "internal.h"

+

+

+//************************************************************************

+//****               Platform implementation functions                ****

+//************************************************************************

+

+//========================================================================

+// _glfwPlatformEnableSystemKeys() - Enable system keys

+// _glfwPlatformDisableSystemKeys() - Disable system keys

+//========================================================================

+

+void _glfwPlatformEnableSystemKeys( void )

+{

+    // Not supported under X11 (yet)

+}

+

+void _glfwPlatformDisableSystemKeys( void )

+{

+    // Not supported under X11 (yet)

+}

diff --git a/src/engine/external/glfw/lib/x11/x11_fullscreen.c b/src/engine/external/glfw/lib/x11/x11_fullscreen.c
new file mode 100644
index 00000000..2eb3cf75
--- /dev/null
+++ b/src/engine/external/glfw/lib/x11/x11_fullscreen.c
@@ -0,0 +1,524 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        x11_fullscreen.c

+// Platform:    X11 (Unix)

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#include "internal.h"

+

+

+//************************************************************************

+//****                  GLFW internal functions                       ****

+//************************************************************************

+

+//========================================================================

+// _glfwBPP2RGB() - Convert BPP to RGB bits (based on "best guess")

+//========================================================================

+

+static void _glfwBPP2RGB( int bpp, int *r, int *g, int *b )

+{

+    int delta;

+

+    // Special case: BPP = 32 (I don't think this is necessary for X11??)

+    if( bpp == 32 )

+	bpp = 24;

+

+    // Convert "bits per pixel" to red, green & blue sizes

+    *r = *g = *b = bpp / 3;

+    delta = bpp - (*r * 3);

+    if( delta >= 1 )

+    {

+        *g = *g + 1;

+    }

+    if( delta == 2 )

+    {

+        *r = *r + 1;

+    }

+}

+

+

+//========================================================================

+// Finds the video mode closest in size to the specified desired size

+//========================================================================

+

+int _glfwGetClosestVideoMode( int screen, int *width, int *height, int *rate )

+{

+#if defined( _GLFW_HAS_XRANDR )

+    int i, match, bestmatch;

+    int sizecount, bestsize;

+    int ratecount, bestrate;

+    short *ratelist;

+    XRRScreenConfiguration *sc;

+    XRRScreenSize *sizelist;

+

+    if( _glfwLibrary.XRandR.Available )

+    {

+	sc = XRRGetScreenInfo( _glfwLibrary.Dpy,

+			       RootWindow( _glfwLibrary.Dpy, screen ) );

+

+	sizelist = XRRConfigSizes( sc, &sizecount );

+

+        // Find the best matching mode

+        bestsize  = -1;

+        bestmatch = 999999;

+        for( i = 0; i < sizecount; i++ )

+        {

+            match = (*width - sizelist[i].width) *

+                    (*width - sizelist[i].width) +

+                    (*height - sizelist[i].height) *

+                    (*height - sizelist[i].height);

+            if( match < bestmatch )

+            {

+                bestmatch = match;

+                bestsize  = i;

+            }

+        }

+

+	if( bestsize != -1 )

+	{

+	    // Report width & height of best matching mode

+	    *width = sizelist[bestsize].width;

+	    *height = sizelist[bestsize].height;

+

+	    if( *rate > 0 )

+	    {

+		ratelist = XRRConfigRates( sc, bestsize, &ratecount );

+

+		bestrate = -1;

+		bestmatch = 999999;

+		for( i = 0; i < ratecount; i++ )

+		{

+		    match = abs( ratelist[i] - *rate );

+		    if( match < bestmatch )

+		    {

+			bestmatch = match;

+			bestrate = ratelist[i];

+		    }

+		}

+		

+		if( bestrate != -1 )

+		{

+		    *rate = bestrate;

+		}

+	    }

+	}

+

+        // Free modelist

+	XRRFreeScreenConfigInfo( sc );

+

+	if( bestsize != -1 )

+	{

+	    return bestsize;

+	}

+    }

+#elif defined( _GLFW_HAS_XF86VIDMODE )

+    XF86VidModeModeInfo **modelist;

+    int modecount, i, bestmode, bestmatch, match;

+

+    // Use the XF86VidMode extension to control video resolution

+    if( _glfwLibrary.XF86VidMode.Available )

+    {

+        // Get a list of all available display modes

+        XF86VidModeGetAllModeLines( _glfwLibrary.Dpy, screen,

+                                    &modecount, &modelist );

+

+        // Find the best matching mode

+        bestmode  = -1;

+        bestmatch = 999999;

+        for( i = 0; i < modecount; i++ )

+        {

+            match = (*width - modelist[i]->hdisplay) *

+                    (*width - modelist[i]->hdisplay) +

+                    (*height - modelist[i]->vdisplay) *

+                    (*height - modelist[i]->vdisplay);

+            if( match < bestmatch )

+            {

+                bestmatch = match;

+                bestmode  = i;

+            }

+        }

+

+	if( bestmode != -1 )

+	{

+	    // Report width & height of best matching mode

+	    *width = modelist[ bestmode ]->hdisplay;

+	    *h = modelist[ bestmode ]->vdisplay;

+	}

+

+        // Free modelist

+        XFree( modelist );

+

+	if( bestmode != -1 )

+	{

+	    return bestmode;

+	}

+    }

+#endif

+

+    // Default: Simply use the screen resolution

+    *width = DisplayWidth( _glfwLibrary.Dpy, screen );

+    *height = DisplayHeight( _glfwLibrary.Dpy, screen );

+

+    return 0;

+}

+

+

+//========================================================================

+// Change the current video mode

+//========================================================================

+

+void _glfwSetVideoModeMODE( int screen, int mode, int rate )

+{

+#if defined( _GLFW_HAS_XRANDR )

+    XRRScreenConfiguration *sc;

+    Window root;

+

+    if( _glfwLibrary.XRandR.Available )

+    {

+	root = RootWindow( _glfwLibrary.Dpy, screen );

+	sc   = XRRGetScreenInfo( _glfwLibrary.Dpy, root );

+

+        // Remember old size and flag that we have changed the mode

+        if( !_glfwWin.FS.ModeChanged )

+        {

+	    _glfwWin.FS.OldSizeID = XRRConfigCurrentConfiguration( sc, &_glfwWin.FS.OldRotation );

+	    _glfwWin.FS.OldWidth  = DisplayWidth( _glfwLibrary.Dpy, screen );

+	    _glfwWin.FS.OldHeight = DisplayHeight( _glfwLibrary.Dpy, screen );

+

+            _glfwWin.FS.ModeChanged = GL_TRUE;

+        }

+

+	if( rate > 0 )

+	{

+	    // Set desired configuration

+	    XRRSetScreenConfigAndRate( _glfwLibrary.Dpy,

+				       sc,

+				       root,

+				       mode,

+				       RR_Rotate_0,

+				       (short) rate,

+				       CurrentTime );

+	}

+	else

+	{

+	    // Set desired configuration

+	    XRRSetScreenConfig( _glfwLibrary.Dpy,

+				sc,

+				root,

+				mode,

+				RR_Rotate_0,

+				CurrentTime );

+	}

+

+	XRRFreeScreenConfigInfo( sc );

+    }

+#elif defined( _GLFW_HAS_XF86VIDMODE )

+    XF86VidModeModeInfo **modelist;

+    int modecount;

+

+    // Use the XF86VidMode extension to control video resolution

+    if( _glfwLibrary.XF86VidMode.Available )

+    {

+        // Get a list of all available display modes

+        XF86VidModeGetAllModeLines( _glfwLibrary.Dpy, screen,

+                                    &modecount, &modelist );

+

+        // Unlock mode switch if necessary

+        if( _glfwWin.FS.ModeChanged )

+        {

+            XF86VidModeLockModeSwitch( _glfwLibrary.Dpy, screen, 0 );

+        }

+

+        // Change the video mode to the desired mode

+        XF86VidModeSwitchToMode(  _glfwLibrary.Dpy, screen,

+                                  modelist[ mode ] );

+

+        // Set viewport to upper left corner (where our window will be)

+        XF86VidModeSetViewPort( _glfwLibrary.Dpy, screen, 0, 0 );

+

+        // Lock mode switch

+        XF86VidModeLockModeSwitch( _glfwLibrary.Dpy, screen, 1 );

+

+        // Remember old mode and flag that we have changed the mode

+        if( !_glfwWin.FS.ModeChanged )

+        {

+            _glfwWin.FS.OldMode = *modelist[ 0 ];

+            _glfwWin.FS.ModeChanged = GL_TRUE;

+        }

+

+        // Free mode list

+        XFree( modelist );

+    }

+#endif

+}

+

+

+//========================================================================

+// Change the current video mode

+//========================================================================

+

+void _glfwSetVideoMode( int screen, int *width, int *height, int *rate )

+{

+    int     bestmode;

+

+    // Find a best match mode

+    bestmode = _glfwGetClosestVideoMode( screen, width, height, rate );

+

+    // Change mode

+    _glfwSetVideoModeMODE( screen, bestmode, *rate );

+}

+

+

+

+//************************************************************************

+//****               Platform implementation functions                ****

+//************************************************************************

+

+struct _glfwResolution {

+    int width;

+    int height;

+};

+

+//========================================================================

+// List available video modes

+//========================================================================

+

+int _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount )

+{

+    int     count, k, l, r, g, b, rgba, gl;

+    int     depth, screen;

+    Display *dpy;

+    XVisualInfo *vislist, dummy;

+    int     viscount, rgbcount, rescount;

+    int     *rgbarray;

+    struct _glfwResolution *resarray;

+#if defined( _GLFW_HAS_XRANDR )

+    XRRScreenConfiguration *sc;

+    XRRScreenSize *sizelist;

+    int     sizecount;

+#elif defined( _GLFW_HAS_XF86VIDMODE )

+    XF86VidModeModeInfo **modelist;

+    int     modecount, width, height;

+#endif

+

+    // Get display and screen

+    dpy = _glfwLibrary.Dpy;

+    screen = DefaultScreen( dpy );

+

+    // Get list of visuals

+    vislist = XGetVisualInfo( dpy, 0, &dummy, &viscount );

+    if( vislist == NULL )

+    {

+	return 0;

+    }

+

+    rgbarray = (int*) malloc( sizeof(int) * viscount );

+    rgbcount = 0;

+

+    // Build RGB array

+    for( k = 0; k < viscount; k++ )

+    {

+        // Does the visual support OpenGL & true color?

+        glXGetConfig( dpy, &vislist[k], GLX_USE_GL, &gl );

+        glXGetConfig( dpy, &vislist[k], GLX_RGBA, &rgba );

+        if( gl && rgba )

+        {

+            // Get color depth for this visual

+            depth = vislist[k].depth;

+

+            // Convert to RGB

+            _glfwBPP2RGB( depth, &r, &g, &b );

+            depth = (r<<16) | (g<<8) | b;

+

+            // Is this mode unique?

+            for( l = 0; l < rgbcount; l++ )

+            {

+                if( depth == rgbarray[ l ] )

+                {

+                    break;

+                }

+            }

+            if( l >= rgbcount )

+            {

+                rgbarray[ rgbcount ] = depth;

+                rgbcount++;

+            }

+        }

+    }

+

+    rescount = 0;

+    resarray = NULL;

+

+    // Build resolution array

+#if defined( _GLFW_HAS_XRANDR )

+    if( _glfwLibrary.XRandR.Available )

+    {

+	sc = XRRGetScreenInfo( dpy, RootWindow( dpy, screen ) );

+	sizelist = XRRConfigSizes( sc, &sizecount );

+

+	resarray = (struct _glfwResolution*) malloc( sizeof(struct _glfwResolution) * sizecount );

+

+        for( k = 0; k < sizecount; k++ )

+        {

+	    resarray[ rescount ].width = sizelist[ k ].width;

+	    resarray[ rescount ].height = sizelist[ k ].height;

+	    rescount++;

+        }

+

+	XRRFreeScreenConfigInfo( sc );

+    }

+#elif defined( _GLFW_HAS_XF86VIDMODE )

+    if( _glfwLibrary.XF86VidMode.Available )

+    {

+        XF86VidModeGetAllModeLines( dpy, screen, &modecount, &modelist );

+

+	resarray = (struct _glfwResolution*) malloc( sizeof(struct _glfwResolution) * modecount );

+

+        for( k = 0; k < modecount; k++ )

+        {

+            width  = modelist[ k ]->hdisplay;

+            height = modelist[ k ]->vdisplay;

+

+            // Is this mode unique?

+            for( l = 0; l < rescount; l++ )

+            {

+                if( width == resarray[ l ].width && height == resarray[ l ].height )

+                {

+                    break;

+                }

+            }

+            if( l >= rescount )

+            {

+                resarray[ rescount ].width = width;

+                resarray[ rescount ].height = height;

+                rescount++;

+            }

+        }

+

+	XFree( modelist );

+    }

+#endif

+

+    if( !resarray )

+    {

+	rescount = 1;

+	resarray = (struct _glfwResolution*) malloc( sizeof(struct _glfwResolution) * rescount );

+

+	resarray[ 0 ].width = DisplayWidth( dpy, screen );

+	resarray[ 0 ].height = DisplayHeight( dpy, screen );

+    }

+

+    // Build permutations of colors and resolutions

+    count = 0;

+    for( k = 0; k < rgbcount && count < maxcount; k++ )

+    {

+        for( l = 0; l < rescount && count < maxcount; l++ )

+        {

+            list[count].Width     = resarray[ l ].width;

+            list[count].Height    = resarray[ l ].height;

+            list[count].RedBits   = (rgbarray[ k ] >> 16) & 255;

+            list[count].GreenBits = (rgbarray[ k ] >> 8) & 255;

+            list[count].BlueBits  = rgbarray[ k ] & 255;

+            count++;

+        }

+    }

+

+    // Free visuals list

+    XFree( vislist );

+

+    free( resarray );

+    free( rgbarray );

+

+    return count;

+}

+

+

+//========================================================================

+// Get the desktop video mode

+//========================================================================

+

+void _glfwPlatformGetDesktopMode( GLFWvidmode *mode )

+{

+    Display *dpy;

+    int     bpp, screen;

+#if defined( _GLFW_HAS_XF86VIDMODE )

+    XF86VidModeModeInfo **modelist;

+    int     modecount;

+#endif

+

+    // Get display and screen

+    dpy = _glfwLibrary.Dpy;

+    screen = DefaultScreen( dpy );

+

+    // Get display depth

+    bpp = DefaultDepth( dpy, screen );

+

+    // Convert BPP to RGB bits

+    _glfwBPP2RGB( bpp, &mode->RedBits, &mode->GreenBits, &mode->BlueBits );

+

+#if defined( _GLFW_HAS_XRANDR )

+    if( _glfwLibrary.XRandR.Available )

+    {

+        if( _glfwWin.FS.ModeChanged )

+        {

+	    mode->Width  = _glfwWin.FS.OldWidth;

+	    mode->Height = _glfwWin.FS.OldHeight;

+	    return;

+	}

+    }

+#elif defined( _GLFW_HAS_XF86VIDMODE )

+    if( _glfwLibrary.XF86VidMode.Available )

+    {

+        if( _glfwWin.FS.ModeChanged )

+        {

+            // The old (desktop) mode is stored in _glfwWin.FS.OldMode

+            mode->Width  = _glfwWin.FS.OldMode.hdisplay;

+            mode->Height = _glfwWin.FS.OldMode.vdisplay;

+        }

+        else

+        {

+            // Use the XF86VidMode extension to get list of video modes

+            XF86VidModeGetAllModeLines( dpy, screen, &modecount,

+                                        &modelist );

+

+            // The first mode in the list is the current (desktio) mode

+            mode->Width  = modelist[ 0 ]->hdisplay;

+            mode->Height = modelist[ 0 ]->vdisplay;

+

+            // Free list

+            XFree( modelist );

+        }

+

+	return;

+    }

+#endif

+

+    // Get current display width and height

+    mode->Width  = DisplayWidth( dpy, screen );

+    mode->Height = DisplayHeight( dpy, screen );

+}

+

diff --git a/src/engine/external/glfw/lib/x11/x11_glext.c b/src/engine/external/glfw/lib/x11/x11_glext.c
new file mode 100644
index 00000000..242c9eb1
--- /dev/null
+++ b/src/engine/external/glfw/lib/x11/x11_glext.c
@@ -0,0 +1,69 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        x11_glext.c

+// Platform:    X11 (Unix)

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#include "internal.h"

+

+

+//************************************************************************

+//****               Platform implementation functions                ****

+//************************************************************************

+

+//========================================================================

+// Check if an OpenGL extension is available at runtime

+//========================================================================

+

+int _glfwPlatformExtensionSupported( const char *extension )

+{

+    const GLubyte *extensions;

+

+    // Get list of GLX extensions

+    extensions = (const GLubyte*) glXQueryExtensionsString( _glfwLibrary.Dpy,

+                                                            _glfwWin.Scrn );

+    if( extensions != NULL )

+    {

+        if( _glfwStringInExtensionString( extension, extensions ) )

+        {

+            return GL_TRUE;

+        }

+    }

+

+    return GL_FALSE;

+}

+

+

+//========================================================================

+// Get the function pointer to an OpenGL function

+//========================================================================

+

+void * _glfwPlatformGetProcAddress( const char *procname )

+{

+    return (void *) _glfw_glXGetProcAddress( (const GLubyte *) procname );

+}

+

diff --git a/src/engine/external/glfw/lib/x11/x11_init.c b/src/engine/external/glfw/lib/x11/x11_init.c
new file mode 100644
index 00000000..9e406156
--- /dev/null
+++ b/src/engine/external/glfw/lib/x11/x11_init.c
@@ -0,0 +1,275 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        x11_init.c

+// Platform:    X11 (Unix)

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#include "internal.h"

+

+

+

+//************************************************************************

+//****                  GLFW internal functions                       ****

+//************************************************************************

+

+//========================================================================

+// Initialize GLFW thread package

+//========================================================================

+

+static void _glfwInitThreads( void )

+{

+    // Initialize critical section handle

+#ifdef _GLFW_HAS_PTHREAD

+    (void) pthread_mutex_init( &_glfwThrd.CriticalSection, NULL );

+#endif

+

+    // The first thread (the main thread) has ID 0

+    _glfwThrd.NextID = 0;

+

+    // Fill out information about the main thread (this thread)

+    _glfwThrd.First.ID       = _glfwThrd.NextID++;

+    _glfwThrd.First.Function = NULL;

+    _glfwThrd.First.Previous = NULL;

+    _glfwThrd.First.Next     = NULL;

+#ifdef _GLFW_HAS_PTHREAD

+    _glfwThrd.First.PosixID  = pthread_self();

+#endif

+}

+

+

+//========================================================================

+// Terminate GLFW thread package

+//========================================================================

+

+static void _glfwTerminateThreads( void )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    _GLFWthread *t, *t_next;

+

+    // Enter critical section

+    ENTER_THREAD_CRITICAL_SECTION

+

+    // Kill all threads (NOTE: THE USER SHOULD WAIT FOR ALL THREADS TO

+    // DIE, _BEFORE_ CALLING glfwTerminate()!!!)

+    t = _glfwThrd.First.Next;

+    while( t != NULL )

+    {

+        // Get pointer to next thread

+        t_next = t->Next;

+

+        // Simply murder the process, no mercy!

+        pthread_kill( t->PosixID, SIGKILL );

+

+        // Free memory allocated for this thread

+        free( (void *) t );

+

+        // Select next thread in list

+        t = t_next;

+    }

+

+    // Leave critical section

+    LEAVE_THREAD_CRITICAL_SECTION

+

+    // Delete critical section handle

+    pthread_mutex_destroy( &_glfwThrd.CriticalSection );

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// Dynamically load libraries

+//========================================================================

+

+#ifdef _GLFW_DLOPEN_LIBGL

+static char * _glfw_libGL_name[ ] =

+{

+    "libGL.so",

+    "libGL.so.1",

+    "/usr/lib/libGL.so",

+    "/usr/lib/libGL.so.1",

+    NULL

+};

+#endif

+

+static void _glfwInitLibraries( void )

+{

+#ifdef _GLFW_DLOPEN_LIBGL

+    int i;

+

+    _glfwLibrary.Libs.libGL = NULL;

+    for( i = 0; !_glfw_libGL_name[ i ] != NULL; i ++ )

+    {

+        _glfwLibrary.Libs.libGL = dlopen( _glfw_libGL_name[ i ],

+                                          RTLD_LAZY | RTLD_GLOBAL );

+	if( _glfwLibrary.Libs.libGL )

+	    break;

+    }

+#endif

+}

+

+

+//========================================================================

+// Terminate GLFW when exiting application

+//========================================================================

+

+void _glfwTerminate_atexit( void )

+{

+    glfwTerminate();

+}

+

+

+//========================================================================

+// Initialize X11 display

+//========================================================================

+

+static int _glfwInitDisplay( void )

+{

+    // Open display

+    _glfwLibrary.Dpy = XOpenDisplay( 0 );

+    if( !_glfwLibrary.Dpy )

+    {

+        return GL_FALSE;

+    }

+

+    // Check screens

+    _glfwLibrary.NumScreens = ScreenCount( _glfwLibrary.Dpy );

+    _glfwLibrary.DefaultScreen = DefaultScreen( _glfwLibrary.Dpy );

+

+    // Check for XF86VidMode extension

+#ifdef _GLFW_HAS_XF86VIDMODE

+    _glfwLibrary.XF86VidMode.Available =

+        XF86VidModeQueryExtension( _glfwLibrary.Dpy,

+	                           &_glfwLibrary.XF86VidMode.EventBase,

+	                           &_glfwLibrary.XF86VidMode.ErrorBase);

+#else

+    _glfwLibrary.XF86VidMode.Available = 0;

+#endif

+

+    // Check for XRandR extension

+#ifdef _GLFW_HAS_XRANDR

+    _glfwLibrary.XRandR.Available =

+        XRRQueryExtension( _glfwLibrary.Dpy,

+	                   &_glfwLibrary.XRandR.EventBase,

+			   &_glfwLibrary.XRandR.ErrorBase );

+#else

+    _glfwLibrary.XRandR.Available = 0;

+#endif

+

+     return GL_TRUE;

+}

+

+

+//========================================================================

+// Terminate X11 display

+//========================================================================

+

+static void _glfwTerminateDisplay( void )

+{

+    // Open display

+    if( _glfwLibrary.Dpy )

+    {

+        XCloseDisplay( _glfwLibrary.Dpy );

+        _glfwLibrary.Dpy = NULL;

+    }

+}

+

+

+//************************************************************************

+//****               Platform implementation functions                ****

+//************************************************************************

+

+//========================================================================

+// Initialize various GLFW state

+//========================================================================

+

+int _glfwPlatformInit( void )

+{

+    // Initialize display

+    if( !_glfwInitDisplay() )

+    {

+        return GL_FALSE;

+    }

+

+    // Initialize thread package

+    _glfwInitThreads();

+

+    // Try to load libGL.so if necessary

+    _glfwInitLibraries();

+

+    // Install atexit() routine

+    atexit( _glfwTerminate_atexit );

+

+    // Initialize joysticks

+    _glfwInitJoysticks();

+

+    // Start the timer

+    _glfwInitTimer();

+

+    return GL_TRUE;

+}

+

+

+//========================================================================

+// Close window and kill all threads

+//========================================================================

+

+int _glfwPlatformTerminate( void )

+{

+#ifdef _GLFW_HAS_PTHREAD

+    // Only the main thread is allowed to do this...

+    if( pthread_self() != _glfwThrd.First.PosixID )

+    {

+        return GL_FALSE;

+    }

+#endif // _GLFW_HAS_PTHREAD

+

+    // Close OpenGL window

+    glfwCloseWindow();

+

+    // Kill thread package

+    _glfwTerminateThreads();

+

+    // Terminate display

+    _glfwTerminateDisplay();

+

+    // Terminate joysticks

+    _glfwTerminateJoysticks();

+

+    // Unload libGL.so if necessary

+#ifdef _GLFW_DLOPEN_LIBGL

+    if( _glfwLibrary.Libs.libGL != NULL )

+    {

+        dlclose( _glfwLibrary.Libs.libGL );

+        _glfwLibrary.Libs.libGL = NULL;

+    }

+#endif

+

+    return GL_TRUE;

+}

+

diff --git a/src/engine/external/glfw/lib/x11/x11_joystick.c b/src/engine/external/glfw/lib/x11/x11_joystick.c
new file mode 100644
index 00000000..26d67d8c
--- /dev/null
+++ b/src/engine/external/glfw/lib/x11/x11_joystick.c
@@ -0,0 +1,371 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        x11_joystick.c

+// Platform:    X11 (Unix)

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#include "internal.h"

+

+

+//========================================================================

+// Note: Only Linux joystick input is supported at the moment. Other

+// systems will behave as if there are no joysticks connected.

+//========================================================================

+

+#ifdef linux

+#define _GLFW_USE_LINUX_JOYSTICKS

+#endif // linux

+

+

+

+//************************************************************************

+//****                  GLFW internal functions                       ****

+//************************************************************************

+

+#ifdef _GLFW_USE_LINUX_JOYSTICKS

+

+//------------------------------------------------------------------------

+// Here are the Linux joystick driver v1.x interface definitions that we

+// use (we do not want to rely on <linux/joystick.h>):

+//------------------------------------------------------------------------

+

+#include <sys/ioctl.h>

+#include <fcntl.h>

+#include <errno.h>

+

+// Joystick event types

+#define JS_EVENT_BUTTON     0x01    /* button pressed/released */

+#define JS_EVENT_AXIS       0x02    /* joystick moved */

+#define JS_EVENT_INIT       0x80    /* initial state of device */

+

+// Joystick event structure

+struct js_event {

+    unsigned int  time;    /* (u32) event timestamp in milliseconds */

+    signed short  value;   /* (s16) value */

+    unsigned char type;    /* (u8)  event type */

+    unsigned char number;  /* (u8)  axis/button number */

+};

+

+// Joystick IOCTL commands

+#define JSIOCGVERSION  _IOR('j', 0x01, int)   /* get driver version (u32) */

+#define JSIOCGAXES     _IOR('j', 0x11, char)  /* get number of axes (u8) */

+#define JSIOCGBUTTONS  _IOR('j', 0x12, char)  /* get number of buttons (u8) */

+

+#endif // _GLFW_USE_LINUX_JOYSTICKS

+

+

+//========================================================================

+// _glfwInitJoysticks() - Initialize joystick interface

+//========================================================================

+

+void _glfwInitJoysticks( void )

+{

+#ifdef _GLFW_USE_LINUX_JOYSTICKS

+    int  k, n, fd, joy_count;

+    char *joy_base_name, joy_dev_name[ 20 ];

+    int  driver_version = 0x000800;

+    char ret_data;

+#endif // _GLFW_USE_LINUX_JOYSTICKS

+    int  i;

+

+    // Start by saying that there are no sticks

+    for( i = 0; i <= GLFW_JOYSTICK_LAST; ++ i )

+    {

+        _glfwJoy[ i ].Present = GL_FALSE;

+    }

+

+#ifdef _GLFW_USE_LINUX_JOYSTICKS

+

+    // Try to open joysticks (nonblocking)

+    joy_count = 0;

+    for( k = 0; k <= 1 && joy_count <= GLFW_JOYSTICK_LAST; ++ k )

+    {

+        // Pick joystick base name

+        switch( k )

+        {

+        case 0:

+            joy_base_name = "/dev/input/js";  // USB sticks

+            break;

+        case 1:

+            joy_base_name = "/dev/js";        // "Legacy" sticks

+            break;

+        default:

+            continue;                         // (should never happen)

+        }

+

+        // Try to open a few of these sticks

+        for( i = 0; i <= 50 && joy_count <= GLFW_JOYSTICK_LAST; ++ i )

+        {

+            sprintf( joy_dev_name, "%s%d", joy_base_name, i );

+            fd = open( joy_dev_name, O_NONBLOCK );

+            if( fd != -1 )

+            {

+                // Remember fd

+                _glfwJoy[ joy_count ].fd = fd;

+    

+                // Check that the joystick driver version is 1.0+

+                ioctl( fd, JSIOCGVERSION, &driver_version );

+                if( driver_version < 0x010000 )

+                {

+                    // It's an old 0.x interface (we don't support it)

+                    close( fd );

+                    continue;

+                }

+    

+                // Get number of joystick axes

+                ioctl( fd, JSIOCGAXES, &ret_data );

+                _glfwJoy[ joy_count ].NumAxes = (int) ret_data;

+    

+                // Get number of joystick buttons

+                ioctl( fd, JSIOCGBUTTONS, &ret_data );

+                _glfwJoy[ joy_count ].NumButtons = (int) ret_data;

+    

+                // Allocate memory for joystick state

+                _glfwJoy[ joy_count ].Axis =

+                    (float *) malloc( sizeof(float) *

+                                      _glfwJoy[ joy_count ].NumAxes );

+                if( _glfwJoy[ joy_count ].Axis == NULL )

+                {

+                    close( fd );

+                    continue;

+                }

+                _glfwJoy[ joy_count ].Button =

+                    (char *) malloc( sizeof(char) *

+                                     _glfwJoy[ joy_count ].NumButtons );

+                if( _glfwJoy[ joy_count ].Button == NULL )

+                {

+                    free( _glfwJoy[ joy_count ].Axis );

+                    close( fd );

+                    continue;

+                }

+

+                // Clear joystick state

+                for( n = 0; n < _glfwJoy[ joy_count ].NumAxes; ++ n )

+                {

+                    _glfwJoy[ joy_count ].Axis[ n ] = 0.0f;

+                }

+                for( n = 0; n < _glfwJoy[ joy_count ].NumButtons; ++ n )

+                {

+                    _glfwJoy[ joy_count ].Button[ n ] = GLFW_RELEASE;

+                }

+    

+                // The joystick is supported and connected

+                _glfwJoy[ joy_count ].Present = GL_TRUE;

+                joy_count ++;

+            }

+        }

+    }

+

+#endif // _GLFW_USE_LINUX_JOYSTICKS

+

+}

+

+

+//========================================================================

+// _glfwTerminateJoysticks() - Close all opened joystick handles

+//========================================================================

+

+void _glfwTerminateJoysticks( void )

+{

+

+#ifdef _GLFW_USE_LINUX_JOYSTICKS

+

+    int i;

+

+    // Close any opened joysticks

+    for( i = 0; i <= GLFW_JOYSTICK_LAST; ++ i )

+    {

+        if( _glfwJoy[ i ].Present )

+        {

+            close( _glfwJoy[ i ].fd );

+            free( _glfwJoy[ i ].Axis );

+            free( _glfwJoy[ i ].Button );

+            _glfwJoy[ i ].Present = GL_FALSE;

+        }

+    }

+

+#endif // _GLFW_USE_LINUX_JOYSTICKS

+

+}

+

+

+//========================================================================

+// _glfwPollJoystickEvents() - Empty joystick event queue

+//========================================================================

+

+static void _glfwPollJoystickEvents( void )

+{

+

+#ifdef _GLFW_USE_LINUX_JOYSTICKS

+

+    struct js_event e;

+    int    i;

+

+    // Get joystick events for all GLFW joysticks

+    for( i = 0; i <= GLFW_JOYSTICK_LAST; ++ i )

+    {

+        // Is the stick present?

+        if( _glfwJoy[ i ].Present )

+        {

+            // Read all queued events (non-blocking)

+            while( read(_glfwJoy[i].fd, &e, sizeof(struct js_event)) > 0 )

+            {

+                // We don't care if it's an init event or not

+                e.type &= ~JS_EVENT_INIT;

+

+                // Check event type

+                switch( e.type )

+                {

+                case JS_EVENT_AXIS:

+                    _glfwJoy[ i ].Axis[ e.number ] = (float) e.value /

+                                                             32767.0f;

+                    // We need to change the sign for the Y axes, so that

+                    // positive = up/forward, according to the GLFW spec.

+                    if( e.number & 1 )

+                    {

+                        _glfwJoy[ i ].Axis[ e.number ] =

+                            -_glfwJoy[ i ].Axis[ e.number ];

+                    }

+                    break;

+

+                case JS_EVENT_BUTTON:

+                    _glfwJoy[ i ].Button[ e.number ] =

+                        e.value ? GLFW_PRESS : GLFW_RELEASE;

+                    break;

+

+                default:

+                    break;

+                }

+            }

+        }

+    }

+

+#endif // _GLFW_USE_LINUX_JOYSTICKS

+

+}

+

+

+//************************************************************************

+//****               Platform implementation functions                ****

+//************************************************************************

+

+//========================================================================

+// _glfwPlatformGetJoystickParam() - Determine joystick capabilities

+//========================================================================

+

+int _glfwPlatformGetJoystickParam( int joy, int param )

+{

+    // Is joystick present?

+    if( !_glfwJoy[ joy ].Present )

+    {

+        return 0;

+    }

+

+    switch( param )

+    {

+    case GLFW_PRESENT:

+        return GL_TRUE;

+

+    case GLFW_AXES:

+        return _glfwJoy[ joy ].NumAxes;

+

+    case GLFW_BUTTONS:

+        return _glfwJoy[ joy ].NumButtons;

+

+    default:

+        break;

+    }

+

+    return 0;

+}

+

+

+//========================================================================

+// _glfwPlatformGetJoystickPos() - Get joystick axis positions

+//========================================================================

+

+int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes )

+{

+    int       i;

+

+    // Is joystick present?

+    if( !_glfwJoy[ joy ].Present )

+    {

+        return 0;

+    }

+

+    // Update joystick state

+    _glfwPollJoystickEvents();

+

+    // Does the joystick support less axes than requested?

+    if( _glfwJoy[ joy ].NumAxes < numaxes )

+    {

+        numaxes = _glfwJoy[ joy ].NumAxes;

+    }

+

+    // Copy axis positions from internal state

+    for( i = 0; i < numaxes; ++ i )

+    {

+        pos[ i ] = _glfwJoy[ joy ].Axis[ i ];

+    }

+

+    return numaxes;

+}

+

+

+//========================================================================

+// _glfwPlatformGetJoystickButtons() - Get joystick button states

+//========================================================================

+

+int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons,

+    int numbuttons )

+{

+    int       i;

+

+    // Is joystick present?

+    if( !_glfwJoy[ joy ].Present )

+    {

+        return 0;

+    }

+

+    // Update joystick state

+    _glfwPollJoystickEvents();

+

+    // Does the joystick support less buttons than requested?

+    if( _glfwJoy[ joy ].NumButtons < numbuttons )

+    {

+        numbuttons = _glfwJoy[ joy ].NumButtons;

+    }

+

+    // Copy button states from internal state

+    for( i = 0; i < numbuttons; ++ i )

+    {

+        buttons[ i ] = _glfwJoy[ joy ].Button[ i ];

+    }

+

+    return numbuttons;

+}

diff --git a/src/engine/external/glfw/lib/x11/x11_keysym2unicode.c b/src/engine/external/glfw/lib/x11/x11_keysym2unicode.c
new file mode 100644
index 00000000..6a308734
--- /dev/null
+++ b/src/engine/external/glfw/lib/x11/x11_keysym2unicode.c
@@ -0,0 +1,902 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        x11_keysym2unicode.c

+// Platform:    X11 (Unix)

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#include "internal.h"

+

+

+/*

+ * Marcus: This code was originally written by Markus G. Kuhn.

+ * I have made some slight changes (trimmed it down a bit from >60 KB to

+ * 20 KB), but the functionality is the same.

+ */

+

+/*

+ * This module converts keysym values into the corresponding ISO 10646

+ * (UCS, Unicode) values.

+ *

+ * The array keysymtab[] contains pairs of X11 keysym values for graphical

+ * characters and the corresponding Unicode value. The function

+ * _glfwKeySym2Unicode() maps a keysym onto a Unicode value using a binary

+ * search, therefore keysymtab[] must remain SORTED by keysym value.

+ *

+ * We allow to represent any UCS character in the range U-00000000 to

+ * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.

+ * This admittedly does not cover the entire 31-bit space of UCS, but

+ * it does cover all of the characters up to U-10FFFF, which can be

+ * represented by UTF-16, and more, and it is very unlikely that higher

+ * UCS codes will ever be assigned by ISO. So to get Unicode character

+ * U+ABCD you can directly use keysym 0x0100abcd.

+ *

+ * Original author: Markus G. Kuhn <mkuhn@acm.org>, University of

+ *                  Cambridge, April 2001

+ *

+ * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing

+ * an initial draft of the mapping table.

+ *

+ */

+

+

+//************************************************************************

+//****                KeySym to Unicode mapping table                 ****

+//************************************************************************

+

+static struct codepair {

+  unsigned short keysym;

+  unsigned short ucs;

+} keysymtab[] = {

+  { 0x01a1, 0x0104 },

+  { 0x01a2, 0x02d8 },

+  { 0x01a3, 0x0141 },

+  { 0x01a5, 0x013d },

+  { 0x01a6, 0x015a },

+  { 0x01a9, 0x0160 },

+  { 0x01aa, 0x015e },

+  { 0x01ab, 0x0164 },

+  { 0x01ac, 0x0179 },

+  { 0x01ae, 0x017d },

+  { 0x01af, 0x017b },

+  { 0x01b1, 0x0105 },

+  { 0x01b2, 0x02db },

+  { 0x01b3, 0x0142 },

+  { 0x01b5, 0x013e },

+  { 0x01b6, 0x015b },

+  { 0x01b7, 0x02c7 },

+  { 0x01b9, 0x0161 },

+  { 0x01ba, 0x015f },

+  { 0x01bb, 0x0165 },

+  { 0x01bc, 0x017a },

+  { 0x01bd, 0x02dd },

+  { 0x01be, 0x017e },

+  { 0x01bf, 0x017c },

+  { 0x01c0, 0x0154 },

+  { 0x01c3, 0x0102 },

+  { 0x01c5, 0x0139 },

+  { 0x01c6, 0x0106 },

+  { 0x01c8, 0x010c },

+  { 0x01ca, 0x0118 },

+  { 0x01cc, 0x011a },

+  { 0x01cf, 0x010e },

+  { 0x01d0, 0x0110 },

+  { 0x01d1, 0x0143 },

+  { 0x01d2, 0x0147 },

+  { 0x01d5, 0x0150 },

+  { 0x01d8, 0x0158 },

+  { 0x01d9, 0x016e },

+  { 0x01db, 0x0170 },

+  { 0x01de, 0x0162 },

+  { 0x01e0, 0x0155 },

+  { 0x01e3, 0x0103 },

+  { 0x01e5, 0x013a },

+  { 0x01e6, 0x0107 },

+  { 0x01e8, 0x010d },

+  { 0x01ea, 0x0119 },

+  { 0x01ec, 0x011b },

+  { 0x01ef, 0x010f },

+  { 0x01f0, 0x0111 },

+  { 0x01f1, 0x0144 },

+  { 0x01f2, 0x0148 },

+  { 0x01f5, 0x0151 },

+  { 0x01f8, 0x0159 },

+  { 0x01f9, 0x016f },

+  { 0x01fb, 0x0171 },

+  { 0x01fe, 0x0163 },

+  { 0x01ff, 0x02d9 },

+  { 0x02a1, 0x0126 },

+  { 0x02a6, 0x0124 },

+  { 0x02a9, 0x0130 },

+  { 0x02ab, 0x011e },

+  { 0x02ac, 0x0134 },

+  { 0x02b1, 0x0127 },

+  { 0x02b6, 0x0125 },

+  { 0x02b9, 0x0131 },

+  { 0x02bb, 0x011f },

+  { 0x02bc, 0x0135 },

+  { 0x02c5, 0x010a },

+  { 0x02c6, 0x0108 },

+  { 0x02d5, 0x0120 },

+  { 0x02d8, 0x011c },

+  { 0x02dd, 0x016c },

+  { 0x02de, 0x015c },

+  { 0x02e5, 0x010b },

+  { 0x02e6, 0x0109 },

+  { 0x02f5, 0x0121 },

+  { 0x02f8, 0x011d },

+  { 0x02fd, 0x016d },

+  { 0x02fe, 0x015d },

+  { 0x03a2, 0x0138 },

+  { 0x03a3, 0x0156 },

+  { 0x03a5, 0x0128 },

+  { 0x03a6, 0x013b },

+  { 0x03aa, 0x0112 },

+  { 0x03ab, 0x0122 },

+  { 0x03ac, 0x0166 },

+  { 0x03b3, 0x0157 },

+  { 0x03b5, 0x0129 },

+  { 0x03b6, 0x013c },

+  { 0x03ba, 0x0113 },

+  { 0x03bb, 0x0123 },

+  { 0x03bc, 0x0167 },

+  { 0x03bd, 0x014a },

+  { 0x03bf, 0x014b },

+  { 0x03c0, 0x0100 },

+  { 0x03c7, 0x012e },

+  { 0x03cc, 0x0116 },

+  { 0x03cf, 0x012a },

+  { 0x03d1, 0x0145 },

+  { 0x03d2, 0x014c },

+  { 0x03d3, 0x0136 },

+  { 0x03d9, 0x0172 },

+  { 0x03dd, 0x0168 },

+  { 0x03de, 0x016a },

+  { 0x03e0, 0x0101 },

+  { 0x03e7, 0x012f },

+  { 0x03ec, 0x0117 },

+  { 0x03ef, 0x012b },

+  { 0x03f1, 0x0146 },

+  { 0x03f2, 0x014d },

+  { 0x03f3, 0x0137 },

+  { 0x03f9, 0x0173 },

+  { 0x03fd, 0x0169 },

+  { 0x03fe, 0x016b },

+  { 0x047e, 0x203e },

+  { 0x04a1, 0x3002 },

+  { 0x04a2, 0x300c },

+  { 0x04a3, 0x300d },

+  { 0x04a4, 0x3001 },

+  { 0x04a5, 0x30fb },

+  { 0x04a6, 0x30f2 },

+  { 0x04a7, 0x30a1 },

+  { 0x04a8, 0x30a3 },

+  { 0x04a9, 0x30a5 },

+  { 0x04aa, 0x30a7 },

+  { 0x04ab, 0x30a9 },

+  { 0x04ac, 0x30e3 },

+  { 0x04ad, 0x30e5 },

+  { 0x04ae, 0x30e7 },

+  { 0x04af, 0x30c3 },

+  { 0x04b0, 0x30fc },

+  { 0x04b1, 0x30a2 },

+  { 0x04b2, 0x30a4 },

+  { 0x04b3, 0x30a6 },

+  { 0x04b4, 0x30a8 },

+  { 0x04b5, 0x30aa },

+  { 0x04b6, 0x30ab },

+  { 0x04b7, 0x30ad },

+  { 0x04b8, 0x30af },

+  { 0x04b9, 0x30b1 },

+  { 0x04ba, 0x30b3 },

+  { 0x04bb, 0x30b5 },

+  { 0x04bc, 0x30b7 },

+  { 0x04bd, 0x30b9 },

+  { 0x04be, 0x30bb },

+  { 0x04bf, 0x30bd },

+  { 0x04c0, 0x30bf },

+  { 0x04c1, 0x30c1 },

+  { 0x04c2, 0x30c4 },

+  { 0x04c3, 0x30c6 },

+  { 0x04c4, 0x30c8 },

+  { 0x04c5, 0x30ca },

+  { 0x04c6, 0x30cb },

+  { 0x04c7, 0x30cc },

+  { 0x04c8, 0x30cd },

+  { 0x04c9, 0x30ce },

+  { 0x04ca, 0x30cf },

+  { 0x04cb, 0x30d2 },

+  { 0x04cc, 0x30d5 },

+  { 0x04cd, 0x30d8 },

+  { 0x04ce, 0x30db },

+  { 0x04cf, 0x30de },

+  { 0x04d0, 0x30df },

+  { 0x04d1, 0x30e0 },

+  { 0x04d2, 0x30e1 },

+  { 0x04d3, 0x30e2 },

+  { 0x04d4, 0x30e4 },

+  { 0x04d5, 0x30e6 },

+  { 0x04d6, 0x30e8 },

+  { 0x04d7, 0x30e9 },

+  { 0x04d8, 0x30ea },

+  { 0x04d9, 0x30eb },

+  { 0x04da, 0x30ec },

+  { 0x04db, 0x30ed },

+  { 0x04dc, 0x30ef },

+  { 0x04dd, 0x30f3 },

+  { 0x04de, 0x309b },

+  { 0x04df, 0x309c },

+  { 0x05ac, 0x060c },

+  { 0x05bb, 0x061b },

+  { 0x05bf, 0x061f },

+  { 0x05c1, 0x0621 },

+  { 0x05c2, 0x0622 },

+  { 0x05c3, 0x0623 },

+  { 0x05c4, 0x0624 },

+  { 0x05c5, 0x0625 },

+  { 0x05c6, 0x0626 },

+  { 0x05c7, 0x0627 },

+  { 0x05c8, 0x0628 },

+  { 0x05c9, 0x0629 },

+  { 0x05ca, 0x062a },

+  { 0x05cb, 0x062b },

+  { 0x05cc, 0x062c },

+  { 0x05cd, 0x062d },

+  { 0x05ce, 0x062e },

+  { 0x05cf, 0x062f },

+  { 0x05d0, 0x0630 },

+  { 0x05d1, 0x0631 },

+  { 0x05d2, 0x0632 },

+  { 0x05d3, 0x0633 },

+  { 0x05d4, 0x0634 },

+  { 0x05d5, 0x0635 },

+  { 0x05d6, 0x0636 },

+  { 0x05d7, 0x0637 },

+  { 0x05d8, 0x0638 },

+  { 0x05d9, 0x0639 },

+  { 0x05da, 0x063a },

+  { 0x05e0, 0x0640 },

+  { 0x05e1, 0x0641 },

+  { 0x05e2, 0x0642 },

+  { 0x05e3, 0x0643 },

+  { 0x05e4, 0x0644 },

+  { 0x05e5, 0x0645 },

+  { 0x05e6, 0x0646 },

+  { 0x05e7, 0x0647 },

+  { 0x05e8, 0x0648 },

+  { 0x05e9, 0x0649 },

+  { 0x05ea, 0x064a },

+  { 0x05eb, 0x064b },

+  { 0x05ec, 0x064c },

+  { 0x05ed, 0x064d },

+  { 0x05ee, 0x064e },

+  { 0x05ef, 0x064f },

+  { 0x05f0, 0x0650 },

+  { 0x05f1, 0x0651 },

+  { 0x05f2, 0x0652 },

+  { 0x06a1, 0x0452 },

+  { 0x06a2, 0x0453 },

+  { 0x06a3, 0x0451 },

+  { 0x06a4, 0x0454 },

+  { 0x06a5, 0x0455 },

+  { 0x06a6, 0x0456 },

+  { 0x06a7, 0x0457 },

+  { 0x06a8, 0x0458 },

+  { 0x06a9, 0x0459 },

+  { 0x06aa, 0x045a },

+  { 0x06ab, 0x045b },

+  { 0x06ac, 0x045c },

+  { 0x06ae, 0x045e },

+  { 0x06af, 0x045f },

+  { 0x06b0, 0x2116 },

+  { 0x06b1, 0x0402 },

+  { 0x06b2, 0x0403 },

+  { 0x06b3, 0x0401 },

+  { 0x06b4, 0x0404 },

+  { 0x06b5, 0x0405 },

+  { 0x06b6, 0x0406 },

+  { 0x06b7, 0x0407 },

+  { 0x06b8, 0x0408 },

+  { 0x06b9, 0x0409 },

+  { 0x06ba, 0x040a },

+  { 0x06bb, 0x040b },

+  { 0x06bc, 0x040c },

+  { 0x06be, 0x040e },

+  { 0x06bf, 0x040f },

+  { 0x06c0, 0x044e },

+  { 0x06c1, 0x0430 },

+  { 0x06c2, 0x0431 },

+  { 0x06c3, 0x0446 },

+  { 0x06c4, 0x0434 },

+  { 0x06c5, 0x0435 },

+  { 0x06c6, 0x0444 },

+  { 0x06c7, 0x0433 },

+  { 0x06c8, 0x0445 },

+  { 0x06c9, 0x0438 },

+  { 0x06ca, 0x0439 },

+  { 0x06cb, 0x043a },

+  { 0x06cc, 0x043b },

+  { 0x06cd, 0x043c },

+  { 0x06ce, 0x043d },

+  { 0x06cf, 0x043e },

+  { 0x06d0, 0x043f },

+  { 0x06d1, 0x044f },

+  { 0x06d2, 0x0440 },

+  { 0x06d3, 0x0441 },

+  { 0x06d4, 0x0442 },

+  { 0x06d5, 0x0443 },

+  { 0x06d6, 0x0436 },

+  { 0x06d7, 0x0432 },

+  { 0x06d8, 0x044c },

+  { 0x06d9, 0x044b },

+  { 0x06da, 0x0437 },

+  { 0x06db, 0x0448 },

+  { 0x06dc, 0x044d },

+  { 0x06dd, 0x0449 },

+  { 0x06de, 0x0447 },

+  { 0x06df, 0x044a },

+  { 0x06e0, 0x042e },

+  { 0x06e1, 0x0410 },

+  { 0x06e2, 0x0411 },

+  { 0x06e3, 0x0426 },

+  { 0x06e4, 0x0414 },

+  { 0x06e5, 0x0415 },

+  { 0x06e6, 0x0424 },

+  { 0x06e7, 0x0413 },

+  { 0x06e8, 0x0425 },

+  { 0x06e9, 0x0418 },

+  { 0x06ea, 0x0419 },

+  { 0x06eb, 0x041a },

+  { 0x06ec, 0x041b },

+  { 0x06ed, 0x041c },

+  { 0x06ee, 0x041d },

+  { 0x06ef, 0x041e },

+  { 0x06f0, 0x041f },

+  { 0x06f1, 0x042f },

+  { 0x06f2, 0x0420 },

+  { 0x06f3, 0x0421 },

+  { 0x06f4, 0x0422 },

+  { 0x06f5, 0x0423 },

+  { 0x06f6, 0x0416 },

+  { 0x06f7, 0x0412 },

+  { 0x06f8, 0x042c },

+  { 0x06f9, 0x042b },

+  { 0x06fa, 0x0417 },

+  { 0x06fb, 0x0428 },

+  { 0x06fc, 0x042d },

+  { 0x06fd, 0x0429 },

+  { 0x06fe, 0x0427 },

+  { 0x06ff, 0x042a },

+  { 0x07a1, 0x0386 },

+  { 0x07a2, 0x0388 },

+  { 0x07a3, 0x0389 },

+  { 0x07a4, 0x038a },

+  { 0x07a5, 0x03aa },

+  { 0x07a7, 0x038c },

+  { 0x07a8, 0x038e },

+  { 0x07a9, 0x03ab },

+  { 0x07ab, 0x038f },

+  { 0x07ae, 0x0385 },

+  { 0x07af, 0x2015 },

+  { 0x07b1, 0x03ac },

+  { 0x07b2, 0x03ad },

+  { 0x07b3, 0x03ae },

+  { 0x07b4, 0x03af },

+  { 0x07b5, 0x03ca },

+  { 0x07b6, 0x0390 },

+  { 0x07b7, 0x03cc },

+  { 0x07b8, 0x03cd },

+  { 0x07b9, 0x03cb },

+  { 0x07ba, 0x03b0 },

+  { 0x07bb, 0x03ce },

+  { 0x07c1, 0x0391 },

+  { 0x07c2, 0x0392 },

+  { 0x07c3, 0x0393 },

+  { 0x07c4, 0x0394 },

+  { 0x07c5, 0x0395 },

+  { 0x07c6, 0x0396 },

+  { 0x07c7, 0x0397 },

+  { 0x07c8, 0x0398 },

+  { 0x07c9, 0x0399 },

+  { 0x07ca, 0x039a },

+  { 0x07cb, 0x039b },

+  { 0x07cc, 0x039c },

+  { 0x07cd, 0x039d },

+  { 0x07ce, 0x039e },

+  { 0x07cf, 0x039f },

+  { 0x07d0, 0x03a0 },

+  { 0x07d1, 0x03a1 },

+  { 0x07d2, 0x03a3 },

+  { 0x07d4, 0x03a4 },

+  { 0x07d5, 0x03a5 },

+  { 0x07d6, 0x03a6 },

+  { 0x07d7, 0x03a7 },

+  { 0x07d8, 0x03a8 },

+  { 0x07d9, 0x03a9 },

+  { 0x07e1, 0x03b1 },

+  { 0x07e2, 0x03b2 },

+  { 0x07e3, 0x03b3 },

+  { 0x07e4, 0x03b4 },

+  { 0x07e5, 0x03b5 },

+  { 0x07e6, 0x03b6 },

+  { 0x07e7, 0x03b7 },

+  { 0x07e8, 0x03b8 },

+  { 0x07e9, 0x03b9 },

+  { 0x07ea, 0x03ba },

+  { 0x07eb, 0x03bb },

+  { 0x07ec, 0x03bc },

+  { 0x07ed, 0x03bd },

+  { 0x07ee, 0x03be },

+  { 0x07ef, 0x03bf },

+  { 0x07f0, 0x03c0 },

+  { 0x07f1, 0x03c1 },

+  { 0x07f2, 0x03c3 },

+  { 0x07f3, 0x03c2 },

+  { 0x07f4, 0x03c4 },

+  { 0x07f5, 0x03c5 },

+  { 0x07f6, 0x03c6 },

+  { 0x07f7, 0x03c7 },

+  { 0x07f8, 0x03c8 },

+  { 0x07f9, 0x03c9 },

+  { 0x08a1, 0x23b7 },

+  { 0x08a2, 0x250c },

+  { 0x08a3, 0x2500 },

+  { 0x08a4, 0x2320 },

+  { 0x08a5, 0x2321 },

+  { 0x08a6, 0x2502 },

+  { 0x08a7, 0x23a1 },

+  { 0x08a8, 0x23a3 },

+  { 0x08a9, 0x23a4 },

+  { 0x08aa, 0x23a6 },

+  { 0x08ab, 0x239b },

+  { 0x08ac, 0x239d },

+  { 0x08ad, 0x239e },

+  { 0x08ae, 0x23a0 },

+  { 0x08af, 0x23a8 },

+  { 0x08b0, 0x23ac },

+  { 0x08bc, 0x2264 },

+  { 0x08bd, 0x2260 },

+  { 0x08be, 0x2265 },

+  { 0x08bf, 0x222b },

+  { 0x08c0, 0x2234 },

+  { 0x08c1, 0x221d },

+  { 0x08c2, 0x221e },

+  { 0x08c5, 0x2207 },

+  { 0x08c8, 0x223c },

+  { 0x08c9, 0x2243 },

+  { 0x08cd, 0x21d4 },

+  { 0x08ce, 0x21d2 },

+  { 0x08cf, 0x2261 },

+  { 0x08d6, 0x221a },

+  { 0x08da, 0x2282 },

+  { 0x08db, 0x2283 },

+  { 0x08dc, 0x2229 },

+  { 0x08dd, 0x222a },

+  { 0x08de, 0x2227 },

+  { 0x08df, 0x2228 },

+  { 0x08ef, 0x2202 },

+  { 0x08f6, 0x0192 },

+  { 0x08fb, 0x2190 },

+  { 0x08fc, 0x2191 },

+  { 0x08fd, 0x2192 },

+  { 0x08fe, 0x2193 },

+  { 0x09e0, 0x25c6 },

+  { 0x09e1, 0x2592 },

+  { 0x09e2, 0x2409 },

+  { 0x09e3, 0x240c },

+  { 0x09e4, 0x240d },

+  { 0x09e5, 0x240a },

+  { 0x09e8, 0x2424 },

+  { 0x09e9, 0x240b },

+  { 0x09ea, 0x2518 },

+  { 0x09eb, 0x2510 },

+  { 0x09ec, 0x250c },

+  { 0x09ed, 0x2514 },

+  { 0x09ee, 0x253c },

+  { 0x09ef, 0x23ba },

+  { 0x09f0, 0x23bb },

+  { 0x09f1, 0x2500 },

+  { 0x09f2, 0x23bc },

+  { 0x09f3, 0x23bd },

+  { 0x09f4, 0x251c },

+  { 0x09f5, 0x2524 },

+  { 0x09f6, 0x2534 },

+  { 0x09f7, 0x252c },

+  { 0x09f8, 0x2502 },

+  { 0x0aa1, 0x2003 },

+  { 0x0aa2, 0x2002 },

+  { 0x0aa3, 0x2004 },

+  { 0x0aa4, 0x2005 },

+  { 0x0aa5, 0x2007 },

+  { 0x0aa6, 0x2008 },

+  { 0x0aa7, 0x2009 },

+  { 0x0aa8, 0x200a },

+  { 0x0aa9, 0x2014 },

+  { 0x0aaa, 0x2013 },

+  { 0x0aae, 0x2026 },

+  { 0x0aaf, 0x2025 },

+  { 0x0ab0, 0x2153 },

+  { 0x0ab1, 0x2154 },

+  { 0x0ab2, 0x2155 },

+  { 0x0ab3, 0x2156 },

+  { 0x0ab4, 0x2157 },

+  { 0x0ab5, 0x2158 },

+  { 0x0ab6, 0x2159 },

+  { 0x0ab7, 0x215a },

+  { 0x0ab8, 0x2105 },

+  { 0x0abb, 0x2012 },

+  { 0x0abc, 0x2329 },

+  { 0x0abe, 0x232a },

+  { 0x0ac3, 0x215b },

+  { 0x0ac4, 0x215c },

+  { 0x0ac5, 0x215d },

+  { 0x0ac6, 0x215e },

+  { 0x0ac9, 0x2122 },

+  { 0x0aca, 0x2613 },

+  { 0x0acc, 0x25c1 },

+  { 0x0acd, 0x25b7 },

+  { 0x0ace, 0x25cb },

+  { 0x0acf, 0x25af },

+  { 0x0ad0, 0x2018 },

+  { 0x0ad1, 0x2019 },

+  { 0x0ad2, 0x201c },

+  { 0x0ad3, 0x201d },

+  { 0x0ad4, 0x211e },

+  { 0x0ad6, 0x2032 },

+  { 0x0ad7, 0x2033 },

+  { 0x0ad9, 0x271d },

+  { 0x0adb, 0x25ac },

+  { 0x0adc, 0x25c0 },

+  { 0x0add, 0x25b6 },

+  { 0x0ade, 0x25cf },

+  { 0x0adf, 0x25ae },

+  { 0x0ae0, 0x25e6 },

+  { 0x0ae1, 0x25ab },

+  { 0x0ae2, 0x25ad },

+  { 0x0ae3, 0x25b3 },

+  { 0x0ae4, 0x25bd },

+  { 0x0ae5, 0x2606 },

+  { 0x0ae6, 0x2022 },

+  { 0x0ae7, 0x25aa },

+  { 0x0ae8, 0x25b2 },

+  { 0x0ae9, 0x25bc },

+  { 0x0aea, 0x261c },

+  { 0x0aeb, 0x261e },

+  { 0x0aec, 0x2663 },

+  { 0x0aed, 0x2666 },

+  { 0x0aee, 0x2665 },

+  { 0x0af0, 0x2720 },

+  { 0x0af1, 0x2020 },

+  { 0x0af2, 0x2021 },

+  { 0x0af3, 0x2713 },

+  { 0x0af4, 0x2717 },

+  { 0x0af5, 0x266f },

+  { 0x0af6, 0x266d },

+  { 0x0af7, 0x2642 },

+  { 0x0af8, 0x2640 },

+  { 0x0af9, 0x260e },

+  { 0x0afa, 0x2315 },

+  { 0x0afb, 0x2117 },

+  { 0x0afc, 0x2038 },

+  { 0x0afd, 0x201a },

+  { 0x0afe, 0x201e },

+  { 0x0ba3, 0x003c },

+  { 0x0ba6, 0x003e },

+  { 0x0ba8, 0x2228 },

+  { 0x0ba9, 0x2227 },

+  { 0x0bc0, 0x00af },

+  { 0x0bc2, 0x22a5 },

+  { 0x0bc3, 0x2229 },

+  { 0x0bc4, 0x230a },

+  { 0x0bc6, 0x005f },

+  { 0x0bca, 0x2218 },

+  { 0x0bcc, 0x2395 },

+  { 0x0bce, 0x22a4 },

+  { 0x0bcf, 0x25cb },

+  { 0x0bd3, 0x2308 },

+  { 0x0bd6, 0x222a },

+  { 0x0bd8, 0x2283 },

+  { 0x0bda, 0x2282 },

+  { 0x0bdc, 0x22a2 },

+  { 0x0bfc, 0x22a3 },

+  { 0x0cdf, 0x2017 },

+  { 0x0ce0, 0x05d0 },

+  { 0x0ce1, 0x05d1 },

+  { 0x0ce2, 0x05d2 },

+  { 0x0ce3, 0x05d3 },

+  { 0x0ce4, 0x05d4 },

+  { 0x0ce5, 0x05d5 },

+  { 0x0ce6, 0x05d6 },

+  { 0x0ce7, 0x05d7 },

+  { 0x0ce8, 0x05d8 },

+  { 0x0ce9, 0x05d9 },

+  { 0x0cea, 0x05da },

+  { 0x0ceb, 0x05db },

+  { 0x0cec, 0x05dc },

+  { 0x0ced, 0x05dd },

+  { 0x0cee, 0x05de },

+  { 0x0cef, 0x05df },

+  { 0x0cf0, 0x05e0 },

+  { 0x0cf1, 0x05e1 },

+  { 0x0cf2, 0x05e2 },

+  { 0x0cf3, 0x05e3 },

+  { 0x0cf4, 0x05e4 },

+  { 0x0cf5, 0x05e5 },

+  { 0x0cf6, 0x05e6 },

+  { 0x0cf7, 0x05e7 },

+  { 0x0cf8, 0x05e8 },

+  { 0x0cf9, 0x05e9 },

+  { 0x0cfa, 0x05ea },

+  { 0x0da1, 0x0e01 },

+  { 0x0da2, 0x0e02 },

+  { 0x0da3, 0x0e03 },

+  { 0x0da4, 0x0e04 },

+  { 0x0da5, 0x0e05 },

+  { 0x0da6, 0x0e06 },

+  { 0x0da7, 0x0e07 },

+  { 0x0da8, 0x0e08 },

+  { 0x0da9, 0x0e09 },

+  { 0x0daa, 0x0e0a },

+  { 0x0dab, 0x0e0b },

+  { 0x0dac, 0x0e0c },

+  { 0x0dad, 0x0e0d },

+  { 0x0dae, 0x0e0e },

+  { 0x0daf, 0x0e0f },

+  { 0x0db0, 0x0e10 },

+  { 0x0db1, 0x0e11 },

+  { 0x0db2, 0x0e12 },

+  { 0x0db3, 0x0e13 },

+  { 0x0db4, 0x0e14 },

+  { 0x0db5, 0x0e15 },

+  { 0x0db6, 0x0e16 },

+  { 0x0db7, 0x0e17 },

+  { 0x0db8, 0x0e18 },

+  { 0x0db9, 0x0e19 },

+  { 0x0dba, 0x0e1a },

+  { 0x0dbb, 0x0e1b },

+  { 0x0dbc, 0x0e1c },

+  { 0x0dbd, 0x0e1d },

+  { 0x0dbe, 0x0e1e },

+  { 0x0dbf, 0x0e1f },

+  { 0x0dc0, 0x0e20 },

+  { 0x0dc1, 0x0e21 },

+  { 0x0dc2, 0x0e22 },

+  { 0x0dc3, 0x0e23 },

+  { 0x0dc4, 0x0e24 },

+  { 0x0dc5, 0x0e25 },

+  { 0x0dc6, 0x0e26 },

+  { 0x0dc7, 0x0e27 },

+  { 0x0dc8, 0x0e28 },

+  { 0x0dc9, 0x0e29 },

+  { 0x0dca, 0x0e2a },

+  { 0x0dcb, 0x0e2b },

+  { 0x0dcc, 0x0e2c },

+  { 0x0dcd, 0x0e2d },

+  { 0x0dce, 0x0e2e },

+  { 0x0dcf, 0x0e2f },

+  { 0x0dd0, 0x0e30 },

+  { 0x0dd1, 0x0e31 },

+  { 0x0dd2, 0x0e32 },

+  { 0x0dd3, 0x0e33 },

+  { 0x0dd4, 0x0e34 },

+  { 0x0dd5, 0x0e35 },

+  { 0x0dd6, 0x0e36 },

+  { 0x0dd7, 0x0e37 },

+  { 0x0dd8, 0x0e38 },

+  { 0x0dd9, 0x0e39 },

+  { 0x0dda, 0x0e3a },

+  { 0x0ddf, 0x0e3f },

+  { 0x0de0, 0x0e40 },

+  { 0x0de1, 0x0e41 },

+  { 0x0de2, 0x0e42 },

+  { 0x0de3, 0x0e43 },

+  { 0x0de4, 0x0e44 },

+  { 0x0de5, 0x0e45 },

+  { 0x0de6, 0x0e46 },

+  { 0x0de7, 0x0e47 },

+  { 0x0de8, 0x0e48 },

+  { 0x0de9, 0x0e49 },

+  { 0x0dea, 0x0e4a },

+  { 0x0deb, 0x0e4b },

+  { 0x0dec, 0x0e4c },

+  { 0x0ded, 0x0e4d },

+  { 0x0df0, 0x0e50 },

+  { 0x0df1, 0x0e51 },

+  { 0x0df2, 0x0e52 },

+  { 0x0df3, 0x0e53 },

+  { 0x0df4, 0x0e54 },

+  { 0x0df5, 0x0e55 },

+  { 0x0df6, 0x0e56 },

+  { 0x0df7, 0x0e57 },

+  { 0x0df8, 0x0e58 },

+  { 0x0df9, 0x0e59 },

+  { 0x0ea1, 0x3131 },

+  { 0x0ea2, 0x3132 },

+  { 0x0ea3, 0x3133 },

+  { 0x0ea4, 0x3134 },

+  { 0x0ea5, 0x3135 },

+  { 0x0ea6, 0x3136 },

+  { 0x0ea7, 0x3137 },

+  { 0x0ea8, 0x3138 },

+  { 0x0ea9, 0x3139 },

+  { 0x0eaa, 0x313a },

+  { 0x0eab, 0x313b },

+  { 0x0eac, 0x313c },

+  { 0x0ead, 0x313d },

+  { 0x0eae, 0x313e },

+  { 0x0eaf, 0x313f },

+  { 0x0eb0, 0x3140 },

+  { 0x0eb1, 0x3141 },

+  { 0x0eb2, 0x3142 },

+  { 0x0eb3, 0x3143 },

+  { 0x0eb4, 0x3144 },

+  { 0x0eb5, 0x3145 },

+  { 0x0eb6, 0x3146 },

+  { 0x0eb7, 0x3147 },

+  { 0x0eb8, 0x3148 },

+  { 0x0eb9, 0x3149 },

+  { 0x0eba, 0x314a },

+  { 0x0ebb, 0x314b },

+  { 0x0ebc, 0x314c },

+  { 0x0ebd, 0x314d },

+  { 0x0ebe, 0x314e },

+  { 0x0ebf, 0x314f },

+  { 0x0ec0, 0x3150 },

+  { 0x0ec1, 0x3151 },

+  { 0x0ec2, 0x3152 },

+  { 0x0ec3, 0x3153 },

+  { 0x0ec4, 0x3154 },

+  { 0x0ec5, 0x3155 },

+  { 0x0ec6, 0x3156 },

+  { 0x0ec7, 0x3157 },

+  { 0x0ec8, 0x3158 },

+  { 0x0ec9, 0x3159 },

+  { 0x0eca, 0x315a },

+  { 0x0ecb, 0x315b },

+  { 0x0ecc, 0x315c },

+  { 0x0ecd, 0x315d },

+  { 0x0ece, 0x315e },

+  { 0x0ecf, 0x315f },

+  { 0x0ed0, 0x3160 },

+  { 0x0ed1, 0x3161 },

+  { 0x0ed2, 0x3162 },

+  { 0x0ed3, 0x3163 },

+  { 0x0ed4, 0x11a8 },

+  { 0x0ed5, 0x11a9 },

+  { 0x0ed6, 0x11aa },

+  { 0x0ed7, 0x11ab },

+  { 0x0ed8, 0x11ac },

+  { 0x0ed9, 0x11ad },

+  { 0x0eda, 0x11ae },

+  { 0x0edb, 0x11af },

+  { 0x0edc, 0x11b0 },

+  { 0x0edd, 0x11b1 },

+  { 0x0ede, 0x11b2 },

+  { 0x0edf, 0x11b3 },

+  { 0x0ee0, 0x11b4 },

+  { 0x0ee1, 0x11b5 },

+  { 0x0ee2, 0x11b6 },

+  { 0x0ee3, 0x11b7 },

+  { 0x0ee4, 0x11b8 },

+  { 0x0ee5, 0x11b9 },

+  { 0x0ee6, 0x11ba },

+  { 0x0ee7, 0x11bb },

+  { 0x0ee8, 0x11bc },

+  { 0x0ee9, 0x11bd },

+  { 0x0eea, 0x11be },

+  { 0x0eeb, 0x11bf },

+  { 0x0eec, 0x11c0 },

+  { 0x0eed, 0x11c1 },

+  { 0x0eee, 0x11c2 },

+  { 0x0eef, 0x316d },

+  { 0x0ef0, 0x3171 },

+  { 0x0ef1, 0x3178 },

+  { 0x0ef2, 0x317f },

+  { 0x0ef3, 0x3181 },

+  { 0x0ef4, 0x3184 },

+  { 0x0ef5, 0x3186 },

+  { 0x0ef6, 0x318d },

+  { 0x0ef7, 0x318e },

+  { 0x0ef8, 0x11eb },

+  { 0x0ef9, 0x11f0 },

+  { 0x0efa, 0x11f9 },

+  { 0x0eff, 0x20a9 },

+  { 0x13a4, 0x20ac },

+  { 0x13bc, 0x0152 },

+  { 0x13bd, 0x0153 },

+  { 0x13be, 0x0178 },

+  { 0x20ac, 0x20ac }, 

+  // Numeric keypad with numlock on 

+  { XK_KP_Space, ' ' },

+  { XK_KP_Equal, '=' },

+  { XK_KP_Multiply, '*' },

+  { XK_KP_Add, '+' },

+  { XK_KP_Separator, ',' },

+  { XK_KP_Subtract, '-' },

+  { XK_KP_Decimal, '.' },

+  { XK_KP_Divide, '/' },

+  { XK_KP_0, 0x0030 }, 

+  { XK_KP_1, 0x0031 }, 

+  { XK_KP_2, 0x0032 }, 

+  { XK_KP_3, 0x0033 }, 

+  { XK_KP_4, 0x0034 }, 

+  { XK_KP_5, 0x0035 }, 

+  { XK_KP_6, 0x0036 }, 

+  { XK_KP_7, 0x0037 }, 

+  { XK_KP_8, 0x0038 }, 

+  { XK_KP_9, 0x0039 } 

+};

+

+

+//************************************************************************

+//****                  GLFW internal functions                       ****

+//************************************************************************

+

+//========================================================================

+// _glfwKeySym2Unicode() - Convert X11 KeySym to Unicode

+//========================================================================

+

+long _glfwKeySym2Unicode( KeySym keysym )

+{

+    int min = 0;

+    int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;

+    int mid;

+

+    /* First check for Latin-1 characters (1:1 mapping) */

+    if( (keysym >= 0x0020 && keysym <= 0x007e) ||

+        (keysym >= 0x00a0 && keysym <= 0x00ff) )

+    {

+        return keysym;

+    }

+

+    /* Also check for directly encoded 24-bit UCS characters */

+    if( (keysym & 0xff000000) == 0x01000000 )

+    {

+        return keysym & 0x00ffffff;

+    }

+

+    /* Binary search in table */

+    while( max >= min )

+    {

+        mid = (min + max) / 2;

+        if( keysymtab[mid].keysym < keysym )

+        {

+            min = mid + 1;

+        }

+        else if( keysymtab[mid].keysym > keysym )

+        {

+            max = mid - 1;

+        }

+        else

+        {

+            /* Found it! */

+            return keysymtab[mid].ucs;

+        }

+    }

+

+    /* No matching Unicode value found */

+    return -1;

+}

diff --git a/src/engine/external/glfw/lib/x11/x11_thread.c b/src/engine/external/glfw/lib/x11/x11_thread.c
new file mode 100644
index 00000000..1a5db7e7
--- /dev/null
+++ b/src/engine/external/glfw/lib/x11/x11_thread.c
@@ -0,0 +1,507 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        x11_thread.c

+// Platform:    X11 (Unix)

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#include "internal.h"

+

+

+

+//************************************************************************

+//****                  GLFW internal functions                       ****

+//************************************************************************

+

+#ifdef _GLFW_HAS_PTHREAD

+

+//========================================================================

+// _glfwNewThread() - This is simply a "wrapper" for calling the user

+// thread function.

+//========================================================================

+

+void * _glfwNewThread( void * arg )

+{

+    GLFWthreadfun threadfun;

+    _GLFWthread   *t;

+    pthread_t   posixID;

+

+    // Get current thread ID

+    posixID = pthread_self();

+

+    // Enter critical section

+    ENTER_THREAD_CRITICAL_SECTION

+

+    // Loop through entire list of threads to find the matching POSIX

+    // thread ID

+    for( t = &_glfwThrd.First; t != NULL; t = t->Next )

+    {

+        if( t->PosixID == posixID )

+        {

+            break;

+        }

+    }

+    if( t == NULL )

+    {

+        LEAVE_THREAD_CRITICAL_SECTION

+        return NULL;

+    }

+

+    // Get user thread function pointer

+    threadfun = t->Function;

+

+    // Leave critical section

+    LEAVE_THREAD_CRITICAL_SECTION

+

+    // Call the user thread function

+    threadfun( arg );

+

+    // Remove thread from thread list

+    ENTER_THREAD_CRITICAL_SECTION

+    _glfwRemoveThread( t );

+    LEAVE_THREAD_CRITICAL_SECTION

+

+    // When the thread function returns, the thread will die...

+    return NULL;

+}

+

+#endif // _GLFW_HAS_PTHREAD

+

+

+

+//************************************************************************

+//****               Platform implementation functions                ****

+//************************************************************************

+

+//========================================================================

+// _glfwPlatformCreateThread() - Create a new thread

+//========================================================================

+

+GLFWthread _glfwPlatformCreateThread( GLFWthreadfun fun, void *arg )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    GLFWthread  ID;

+    _GLFWthread *t;

+    int         result;

+

+    // Enter critical section

+    ENTER_THREAD_CRITICAL_SECTION

+

+    // Create a new thread information memory area

+    t = (_GLFWthread *) malloc( sizeof(_GLFWthread) );

+    if( t == NULL )

+    {

+        // Leave critical section

+        LEAVE_THREAD_CRITICAL_SECTION

+        return -1;

+    }

+

+    // Get a new unique thread id

+    ID = _glfwThrd.NextID ++;

+

+    // Store thread information in the thread list

+    t->Function = fun;

+    t->ID       = ID;

+

+    // Create thread

+    result = pthread_create(

+        &t->PosixID,      // Thread handle

+        NULL,             // Default thread attributes

+        _glfwNewThread,   // Thread function (a wrapper function)

+        (void *)arg       // Argument to thread is user argument

+    );

+

+    // Did the thread creation fail?

+    if( result != 0 )

+    {

+        free( (void *) t );

+        LEAVE_THREAD_CRITICAL_SECTION

+        return -1;

+    }

+

+    // Append thread to thread list

+    _glfwAppendThread( t );

+

+    // Leave critical section

+    LEAVE_THREAD_CRITICAL_SECTION

+

+    // Return the GLFW thread ID

+    return ID;

+

+#else

+

+    return -1;

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformDestroyThread() - Kill a thread. NOTE: THIS IS A VERY

+// DANGEROUS OPERATION, AND SHOULD NOT BE USED EXCEPT IN EXTREME

+// SITUATIONS!

+//========================================================================

+

+void _glfwPlatformDestroyThread( GLFWthread ID )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    _GLFWthread *t;

+

+    // Enter critical section

+    ENTER_THREAD_CRITICAL_SECTION

+

+    // Get thread information pointer

+    t = _glfwGetThreadPointer( ID );

+    if( t == NULL )

+    {

+        LEAVE_THREAD_CRITICAL_SECTION

+        return;

+    }

+

+    // Simply murder the process, no mercy!

+    pthread_kill( t->PosixID, SIGKILL );

+

+    // Remove thread from thread list

+    _glfwRemoveThread( t );

+

+    // Leave critical section

+    LEAVE_THREAD_CRITICAL_SECTION

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformWaitThread() - Wait for a thread to die

+//========================================================================

+

+int _glfwPlatformWaitThread( GLFWthread ID, int waitmode )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    pthread_t   thread;

+    _GLFWthread *t;

+

+    // Enter critical section

+    ENTER_THREAD_CRITICAL_SECTION

+

+    // Get thread information pointer

+    t = _glfwGetThreadPointer( ID );

+

+    // Is the thread already dead?

+    if( t == NULL )

+    {

+        LEAVE_THREAD_CRITICAL_SECTION

+        return GL_TRUE;

+    }

+

+    // If got this far, the thread is alive => polling returns FALSE

+    if( waitmode == GLFW_NOWAIT )

+    {

+        LEAVE_THREAD_CRITICAL_SECTION

+        return GL_FALSE;

+    }

+

+    // Get thread handle

+    thread = t->PosixID;

+

+    // Leave critical section

+    LEAVE_THREAD_CRITICAL_SECTION

+

+    // Wait for thread to die

+    (void) pthread_join( thread, NULL );

+

+    return GL_TRUE;

+

+#else

+

+    return GL_TRUE;

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformGetThreadID() - Return the thread ID for the current

+// thread

+//========================================================================

+

+GLFWthread _glfwPlatformGetThreadID( void )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    _GLFWthread *t;

+    GLFWthread  ID = -1;

+    pthread_t   posixID;

+

+    // Get current thread ID

+    posixID = pthread_self();

+

+    // Enter critical section

+    ENTER_THREAD_CRITICAL_SECTION

+

+    // Loop through entire list of threads to find the matching POSIX

+    // thread ID

+    for( t = &_glfwThrd.First; t != NULL; t = t->Next )

+    {

+        if( t->PosixID == posixID )

+        {

+            ID = t->ID;

+            break;

+        }

+    }

+

+    // Leave critical section

+    LEAVE_THREAD_CRITICAL_SECTION

+

+    // Return the found GLFW thread identifier

+    return ID;

+

+#else

+

+    return 0;

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformCreateMutex() - Create a mutual exclusion object

+//========================================================================

+

+GLFWmutex _glfwPlatformCreateMutex( void )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    pthread_mutex_t *mutex;

+

+    // Allocate memory for mutex

+    mutex = (pthread_mutex_t *) malloc( sizeof( pthread_mutex_t ) );

+    if( !mutex )

+    {

+        return NULL;

+    }

+

+    // Initialise a mutex object

+    (void) pthread_mutex_init( mutex, NULL );

+

+    // Cast to GLFWmutex and return

+    return (GLFWmutex) mutex;

+

+#else

+

+    return (GLFWmutex) 0;

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformDestroyMutex() - Destroy a mutual exclusion object

+//========================================================================

+

+void _glfwPlatformDestroyMutex( GLFWmutex mutex )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    // Destroy the mutex object

+    pthread_mutex_destroy( (pthread_mutex_t *) mutex );

+

+    // Free memory for mutex object

+    free( (void *) mutex );

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformLockMutex() - Request access to a mutex

+//========================================================================

+

+void _glfwPlatformLockMutex( GLFWmutex mutex )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    // Wait for mutex to be released

+    (void) pthread_mutex_lock( (pthread_mutex_t *) mutex );

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformUnlockMutex() - Release a mutex

+//========================================================================

+

+void _glfwPlatformUnlockMutex( GLFWmutex mutex )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    // Release mutex

+    pthread_mutex_unlock( (pthread_mutex_t *) mutex );

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformCreateCond() - Create a new condition variable object

+//========================================================================

+

+GLFWcond _glfwPlatformCreateCond( void )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    pthread_cond_t *cond;

+

+    // Allocate memory for condition variable

+    cond = (pthread_cond_t *) malloc( sizeof(pthread_cond_t) );

+    if( !cond )

+    {

+        return NULL;

+    }

+

+    // Initialise condition variable

+    (void) pthread_cond_init( cond, NULL );

+

+    // Cast to GLFWcond and return

+    return (GLFWcond) cond;

+

+#else

+

+    return (GLFWcond) 0;

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformDestroyCond() - Destroy a condition variable object

+//========================================================================

+

+void _glfwPlatformDestroyCond( GLFWcond cond )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    // Destroy the condition variable object

+    (void) pthread_cond_destroy( (pthread_cond_t *) cond );

+

+    // Free memory for condition variable object

+    free( (void *) cond );

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformWaitCond() - Wait for a condition to be raised

+//========================================================================

+

+void _glfwPlatformWaitCond( GLFWcond cond, GLFWmutex mutex,

+    double timeout )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    struct timeval  currenttime;

+    struct timespec wait;

+    long dt_sec, dt_usec;

+

+    // Select infinite or timed wait

+    if( timeout >= GLFW_INFINITY )

+    {

+        // Wait for condition (infinite wait)

+        (void) pthread_cond_wait( (pthread_cond_t *) cond,

+                  (pthread_mutex_t *) mutex );

+    }

+    else

+    {

+        // Set timeout time, relatvie to current time

+        gettimeofday( &currenttime, NULL );

+        dt_sec  = (long) timeout;

+        dt_usec = (long) ((timeout - (double)dt_sec) * 1000000.0);

+        wait.tv_nsec = (currenttime.tv_usec + dt_usec) * 1000L;

+        if( wait.tv_nsec > 1000000000L )

+        {

+            wait.tv_nsec -= 1000000000L;

+            dt_sec ++;

+        }

+        wait.tv_sec  = currenttime.tv_sec + dt_sec;

+

+        // Wait for condition (timed wait)

+        (void) pthread_cond_timedwait( (pthread_cond_t *) cond,

+                   (pthread_mutex_t *) mutex, &wait );

+    }

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformSignalCond() - Signal a condition to one waiting thread

+//========================================================================

+

+void _glfwPlatformSignalCond( GLFWcond cond )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    // Signal condition

+    (void) pthread_cond_signal( (pthread_cond_t *) cond );

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformBroadcastCond() - Broadcast a condition to all waiting

+// threads

+//========================================================================

+

+void _glfwPlatformBroadcastCond( GLFWcond cond )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    // Broadcast condition

+    (void) pthread_cond_broadcast( (pthread_cond_t *) cond );

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

+

+//========================================================================

+// _glfwPlatformGetNumberOfProcessors() - Return the number of processors

+// in the system.

+//========================================================================

+

+int _glfwPlatformGetNumberOfProcessors( void )

+{

+    int n;

+

+    // Get number of processors online

+    _glfw_numprocessors( n );

+    return n;

+}

diff --git a/src/engine/external/glfw/lib/x11/x11_time.c b/src/engine/external/glfw/lib/x11/x11_time.c
new file mode 100644
index 00000000..32ae9d9d
--- /dev/null
+++ b/src/engine/external/glfw/lib/x11/x11_time.c
@@ -0,0 +1,154 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        x11_time.c

+// Platform:    X11 (Unix)

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#include "internal.h"

+

+

+//========================================================================

+// Initialise timer

+//========================================================================

+

+void _glfwInitTimer( void )

+{

+    struct timeval  tv;

+

+    // "Resolution" is 1 us

+    _glfwLibrary.Timer.Resolution = 1e-6;

+

+    // Set start-time for timer

+    gettimeofday( &tv, NULL );

+    _glfwLibrary.Timer.t0 = (long long) tv.tv_sec * (long long) 1000000 +

+		            (long long) tv.tv_usec;

+}

+

+

+//************************************************************************

+//****               Platform implementation functions                ****

+//************************************************************************

+

+//========================================================================

+// Return timer value in seconds

+//========================================================================

+

+double _glfwPlatformGetTime( void )

+{

+    long long t;

+    struct timeval  tv;

+

+    gettimeofday( &tv, NULL );

+    t = (long long) tv.tv_sec * (long long) 1000000 +

+	(long long) tv.tv_usec;

+

+    return (double)(t - _glfwLibrary.Timer.t0) * _glfwLibrary.Timer.Resolution;

+}

+

+

+//========================================================================

+// Set timer value in seconds

+//========================================================================

+

+void _glfwPlatformSetTime( double t )

+{

+    long long t0;

+    struct timeval  tv;

+

+    gettimeofday( &tv, NULL );

+    t0 = (long long) tv.tv_sec * (long long) 1000000 +

+	 (long long) tv.tv_usec;

+

+    // Calulate new starting time

+    _glfwLibrary.Timer.t0 = t0 - (long long)(t/_glfwLibrary.Timer.Resolution);

+}

+

+

+//========================================================================

+// Put a thread to sleep for a specified amount of time

+//========================================================================

+

+void _glfwPlatformSleep( double time )

+{

+#ifdef _GLFW_HAS_PTHREAD

+

+    if( time == 0.0 )

+    {

+#ifdef _GLFW_HAS_SCHED_YIELD

+	sched_yield();

+#endif

+	return;

+    }

+

+    struct timeval  currenttime;

+    struct timespec wait;

+    pthread_mutex_t mutex;

+    pthread_cond_t  cond;

+    long dt_sec, dt_usec;

+

+    // Not all pthread implementations have a pthread_sleep() function. We

+    // do it the portable way, using a timed wait for a condition that we

+    // will never signal. NOTE: The unistd functions sleep/usleep suspends

+    // the entire PROCESS, not a signle thread, which is why we can not

+    // use them to implement glfwSleep.

+

+    // Set timeout time, relatvie to current time

+    gettimeofday( &currenttime, NULL );

+    dt_sec  = (long) time;

+    dt_usec = (long) ((time - (double)dt_sec) * 1000000.0);

+    wait.tv_nsec = (currenttime.tv_usec + dt_usec) * 1000L;

+    if( wait.tv_nsec > 1000000000L )

+    {

+        wait.tv_nsec -= 1000000000L;

+        dt_sec++;

+    }

+    wait.tv_sec  = currenttime.tv_sec + dt_sec;

+

+    // Initialize condition and mutex objects

+    pthread_mutex_init( &mutex, NULL );

+    pthread_cond_init( &cond, NULL );

+

+    // Do a timed wait

+    pthread_mutex_lock( &mutex );

+    pthread_cond_timedwait( &cond, &mutex, &wait );

+    pthread_mutex_unlock( &mutex );

+

+    // Destroy condition and mutex objects

+    pthread_mutex_destroy( &mutex );

+    pthread_cond_destroy( &cond );

+

+#else

+

+    // For systems without PTHREAD, use unistd usleep

+    if( time > 0 )

+    {

+        usleep( (unsigned int) (time*1000000) );

+    }

+

+#endif // _GLFW_HAS_PTHREAD

+}

+

diff --git a/src/engine/external/glfw/lib/x11/x11_window.c b/src/engine/external/glfw/lib/x11/x11_window.c
new file mode 100644
index 00000000..d9d97be4
--- /dev/null
+++ b/src/engine/external/glfw/lib/x11/x11_window.c
@@ -0,0 +1,1746 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        x11_window.c

+// Platform:    X11 (Unix)

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#include "internal.h"

+

+

+/* Defines some GLX FSAA tokens if not yet defined */

+#ifndef GLX_SAMPLE_BUFFERS

+# define GLX_SAMPLE_BUFFERS  100000

+#endif 

+#ifndef GLX_SAMPLES 

+# define GLX_SAMPLES         100001

+#endif 

+

+

+/* KDE decoration values */

+enum {

+  KDE_noDecoration = 0,

+  KDE_normalDecoration = 1,

+  KDE_tinyDecoration = 2,

+  KDE_noFocus = 256,

+  KDE_standaloneMenuBar = 512,

+  KDE_desktopIcon = 1024 ,

+  KDE_staysOnTop = 2048

+};

+

+

+//************************************************************************

+//****                  GLFW internal functions                       ****

+//************************************************************************

+

+//========================================================================

+// _glfwWaitForMapNotify()

+//========================================================================

+

+Bool _glfwWaitForMapNotify( Display *d, XEvent *e, char *arg )

+{

+    return (e->type == MapNotify) && (e->xmap.window == (Window)arg);

+}

+

+

+//========================================================================

+// _glfwWaitForUnmapNotify()

+//========================================================================

+

+Bool _glfwWaitForUnmapNotify( Display *d, XEvent *e, char *arg )

+{

+    return (e->type == UnmapNotify) && (e->xmap.window == (Window)arg);

+}

+

+

+//========================================================================

+// _glfwDisableDecorations() - Turn off window decorations

+// Based on xawdecode: src/wmhooks.c

+//========================================================================

+

+#define MWM_HINTS_DECORATIONS (1L << 1)

+

+static void _glfwDisableDecorations( void )

+{

+    int                   RemovedDecorations;

+    Atom                  HintAtom;

+    XSetWindowAttributes  attributes;

+

+    RemovedDecorations = 0;

+

+    // First try to set MWM hints

+    HintAtom = XInternAtom( _glfwLibrary.Dpy, "_MOTIF_WM_HINTS", True );

+    if ( HintAtom != None )

+    {

+        struct {

+            unsigned long flags;

+            unsigned long functions;

+            unsigned long decorations;

+                     long input_mode;

+            unsigned long status;

+        } MWMHints = { MWM_HINTS_DECORATIONS, 0, 0, 0, 0 };

+

+        XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom, HintAtom,

+                         32, PropModeReplace, (unsigned char *)&MWMHints,

+                         sizeof(MWMHints)/4 );

+        RemovedDecorations = 1;

+    }

+

+    // Now try to set KWM hints

+    HintAtom = XInternAtom( _glfwLibrary.Dpy, "KWM_WIN_DECORATION", True );

+    if ( HintAtom != None )

+    {

+        long KWMHints = KDE_tinyDecoration;

+

+        XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom, HintAtom,

+                         32, PropModeReplace, (unsigned char *)&KWMHints,

+                         sizeof(KWMHints)/4 );

+        RemovedDecorations = 1;

+    }

+

+    // Now try to set GNOME hints

+    HintAtom = XInternAtom(_glfwLibrary.Dpy, "_WIN_HINTS", True );

+    if ( HintAtom != None )

+    {

+        long GNOMEHints = 0;

+

+        XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom, HintAtom,

+                         32, PropModeReplace, (unsigned char *)&GNOMEHints,

+                         sizeof(GNOMEHints)/4 );

+        RemovedDecorations = 1;

+    }

+

+    // Now try to set KDE NET_WM hints

+    HintAtom = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_WINDOW_TYPE", True );

+    if ( HintAtom != None )

+    {

+        Atom NET_WMHints[2];

+

+        NET_WMHints[0] = XInternAtom( _glfwLibrary.Dpy, "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", True );

+        /* define a fallback... */

+        NET_WMHints[1] = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_WINDOW_TYPE_NORMAL", True );

+

+        XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom, XA_ATOM,

+                         32, PropModeReplace, (unsigned char *)&NET_WMHints,

+                         2 );

+        RemovedDecorations = 1;

+    }

+

+    // Set ICCCM fullscreen WM hint

+    HintAtom = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_STATE", True );

+    if ( HintAtom != None )

+    {

+        Atom NET_WMHints[1];

+

+        NET_WMHints[0] = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_STATE_FULLSCREEN", True );

+

+        XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom, XA_ATOM,

+                         32, PropModeReplace, (unsigned char *)&NET_WMHints, 1 );

+    }

+

+

+    // Did we sucessfully remove the window decorations?

+    if( RemovedDecorations )

+    {

+        // Finally set the transient hints

+        XSetTransientForHint( _glfwLibrary.Dpy, _glfwWin.Win, RootWindow(_glfwLibrary.Dpy, _glfwWin.Scrn) );

+        XUnmapWindow( _glfwLibrary.Dpy, _glfwWin.Win );

+        XMapWindow( _glfwLibrary.Dpy, _glfwWin.Win );

+    }

+    else

+    {

+        // The Butcher way of removing window decorations

+        attributes.override_redirect = True;

+        XChangeWindowAttributes( _glfwLibrary.Dpy, _glfwWin.Win,

+                                 CWOverrideRedirect, &attributes );

+        _glfwWin.OverrideRedirect = GL_TRUE;

+    }

+}

+

+

+//========================================================================

+// _glfwEnableDecorations() - Turn on window decorations

+//========================================================================

+

+static void _glfwEnableDecorations( void )

+{

+    int                   ActivatedDecorations;

+    Atom                  HintAtom;

+

+    // If this is an override redirect window, skip it...

+    if( _glfwWin.OverrideRedirect )

+    {

+        return;

+    }

+

+    ActivatedDecorations = 0;

+

+    // First try to unset MWM hints

+    HintAtom = XInternAtom( _glfwLibrary.Dpy, "_MOTIF_WM_HINTS", True );

+    if ( HintAtom != None )

+    {

+        XDeleteProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom );

+        ActivatedDecorations = 1;

+    }

+

+    // Now try to unset KWM hints

+    HintAtom = XInternAtom( _glfwLibrary.Dpy, "KWM_WIN_DECORATION", True );

+    if ( HintAtom != None )

+    {

+        XDeleteProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom );

+        ActivatedDecorations = 1;

+    }

+

+    // Now try to unset GNOME hints

+    HintAtom = XInternAtom( _glfwLibrary.Dpy, "_WIN_HINTS", True );

+    if ( HintAtom != None )

+    {

+        XDeleteProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom );

+        ActivatedDecorations = 1;

+    }

+

+    // Now try to unset NET_WM hints

+    HintAtom = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_WINDOW_TYPE", True );

+    if ( HintAtom != None )

+    {

+        Atom NET_WMHints = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_WINDOW_TYPE_NORMAL", True);

+        if( NET_WMHints != None )

+        {

+            XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win,

+                            HintAtom, XA_ATOM, 32, PropModeReplace,

+                            (unsigned char *)&NET_WMHints, 1 );

+            ActivatedDecorations = 1;

+        }

+    }

+

+    // Finally unset the transient hints if necessary

+    if( ActivatedDecorations )

+    {

+        // NOTE: Does this work?

+        XSetTransientForHint( _glfwLibrary.Dpy, _glfwWin.Win, None);

+        XUnmapWindow( _glfwLibrary.Dpy, _glfwWin.Win );

+        XMapWindow( _glfwLibrary.Dpy, _glfwWin.Win );

+    }

+}

+

+

+//========================================================================

+// _glfwChooseVisual() - We do our own function here, since

+// glXChooseVisual does not behave as we want it to (not according to the

+// GLFW specs)

+//========================================================================

+

+XVisualInfo * _glfwChooseVisual( Display *Dpy, int Screen, int r, int g,

+    int b, int a, int d, int s, int ar, int ag, int ab, int aa, int aux,

+				 int fsaa, int stereo)

+{

+    XVisualInfo *VI, *VI_list, VI_tmp;

+    int  nitems_return, i;

+    int  vi_gl, vi_rgba, vi_double, vi_stereo;

+    int  vi_r, vi_g, vi_b, vi_a, vi_d, vi_s, vi_ar, vi_ag, vi_ab, vi_aa;

+    int  vi_aux;

+    int  color, accum, vi_accum;

+    int  missing, color_diff, extra_diff;

+    int  best_vis, best_missing, best_color_diff, best_extra_diff;

+    int  samples, samplebuffers, vi_samples, vi_samplebuffers;

+

+    // Get list of visuals for this screen & display

+    VI_tmp.screen = Screen;

+    VI_list = XGetVisualInfo( Dpy, VisualScreenMask, &VI_tmp,

+                              &nitems_return );

+    if( VI_list == NULL )

+    {

+        return NULL;

+    }

+

+    // Pick some prefered color depth if the user did not request a

+    // specific depth (note: if the user did not request a specific color

+    // depth, this will not be a driving demand, it's only here to avoid

+    // selection randomness)

+    color = (r > 0 || g > 0 || b > 0);

+    if( !color )

+    {

+        r = g = b = 8;

+    }

+

+    // Make sure that stereo is 1 or 0

+    stereo = stereo ? 1 : 0;

+

+    // Convenience pre-calculation

+    accum = (ar > 0 || ag > 0 || ab > 0 || aa > 0);

+    

+    samples = fsaa;

+    samplebuffers = (fsaa > 0) ? 1 : 0;

+    

+    

+

+    // Loop through list of visuals to find best match

+    best_vis        = -1;

+    best_missing    = 0x7fffffff;

+    best_color_diff = 0x7fffffff;

+    best_extra_diff = 0x7fffffff;

+    for( i = 0; i < nitems_return; i ++ )

+    {

+        // We want GL, RGBA & DOUBLEBUFFER, and NOT STEREO / STEREO

+        glXGetConfig( Dpy, &VI_list[i], GLX_USE_GL, &vi_gl );

+        glXGetConfig( Dpy, &VI_list[i], GLX_RGBA, &vi_rgba );

+        glXGetConfig( Dpy, &VI_list[i], GLX_DOUBLEBUFFER, &vi_double );

+        glXGetConfig( Dpy, &VI_list[i], GLX_STEREO, &vi_stereo );

+        vi_stereo = vi_stereo ? 1 : 0;

+        if( vi_gl && vi_rgba && vi_double && (vi_stereo == stereo) )

+        {

+            // Get visual color parameters

+            glXGetConfig( Dpy, &VI_list[i], GLX_RED_SIZE, &vi_r );

+            glXGetConfig( Dpy, &VI_list[i], GLX_GREEN_SIZE, &vi_g );

+            glXGetConfig( Dpy, &VI_list[i], GLX_BLUE_SIZE, &vi_b );

+

+            // Get visual "extra" parameters

+            glXGetConfig( Dpy, &VI_list[i], GLX_ALPHA_SIZE, &vi_a );

+            glXGetConfig( Dpy, &VI_list[i], GLX_DEPTH_SIZE, &vi_d );

+            glXGetConfig( Dpy, &VI_list[i], GLX_STENCIL_SIZE, &vi_s );

+            glXGetConfig( Dpy, &VI_list[i], GLX_ACCUM_RED_SIZE, &vi_ar );

+            glXGetConfig( Dpy, &VI_list[i], GLX_ACCUM_GREEN_SIZE, &vi_ag );

+            glXGetConfig( Dpy, &VI_list[i], GLX_ACCUM_BLUE_SIZE, &vi_ab );

+            glXGetConfig( Dpy, &VI_list[i], GLX_ACCUM_ALPHA_SIZE, &vi_aa );

+            glXGetConfig( Dpy, &VI_list[i], GLX_AUX_BUFFERS, &vi_aux );

+	    glXGetConfig( Dpy, &VI_list[i], GLX_SAMPLE_BUFFERS, &vi_samplebuffers );

+	    glXGetConfig( Dpy, &VI_list[i], GLX_SAMPLES, &vi_samples );

+	    

+            vi_accum = (vi_ar > 0 || vi_ag > 0 || vi_ab > 0 || vi_aa > 0);

+

+            // Check how many buffers are missing

+            missing = 0;

+            if( a > 0 && vi_a == 0 ) missing ++;

+            if( d > 0 && vi_d == 0 ) missing ++;

+            if( s > 0 && vi_s == 0 ) missing ++;

+            if( accum && !vi_accum ) missing ++;

+            if( aux > 0 && vi_aux == 0 ) missing ++;

+	    if( samplebuffers > 0 && vi_samplebuffers == 0 ) missing ++;

+	    

+

+            // Calculate color diff

+            color_diff = (r - vi_r) * (r - vi_r) +

+                         (g - vi_g) * (g - vi_g) +

+                         (b - vi_b) * (b - vi_b);

+

+            // Calculate "extra" diff

+            extra_diff = 0;

+            if( a > 0 )

+            {

+                extra_diff += (a - vi_a) * (a - vi_a);

+            }

+            if( d > 0 )

+            {

+                extra_diff += (d - vi_d) * (d - vi_d);

+            }

+            if( s > 0 )

+            {

+                extra_diff += (s - vi_s) * (s - vi_s);

+            }

+            if( accum )

+            {

+                extra_diff += (ar - vi_ar) * (ar - vi_ar) +

+                              (ag - vi_ag) * (ag - vi_ag) +

+                              (ab - vi_ab) * (ab - vi_ab) +

+                              (aa - vi_aa) * (aa - vi_aa);

+            }

+            if( aux > 0 )

+            {

+                extra_diff += (aux - vi_aux) * (aux - vi_aux);

+            }

+	    if( samples > 0 )

+	    {

+	      extra_diff += (samples - vi_samples) * (samples - vi_samples);

+	      

+	    }

+            // Check if this is a better match. We implement some

+            // complicated rules, by prioritizing in this order:

+            //  1) Visuals with the least number of missing buffers always

+            //     have priority

+            //  2a) If (r,g,b)!=(0,0,0), color depth has priority over

+            //      other buffers

+            //  2b) If (r,g,b)==(0,0,0), other buffers have priority over

+            //      color depth

+            if( missing < best_missing )

+            {

+                best_vis = i;

+            }

+            else if( missing == best_missing )

+            {

+                if( color )

+                {

+                    if( (color_diff < best_color_diff) ||

+                        (color_diff == best_color_diff &&

+                         extra_diff < best_extra_diff) )

+                    {

+                        best_vis = i;

+                    }

+                }

+                else

+                {

+                    if( (extra_diff < best_extra_diff) ||

+                        (extra_diff == best_extra_diff &&

+                         color_diff < best_color_diff) )

+                    {

+                        best_vis = i;

+                    }

+                }

+            }

+            if( best_vis == i )

+            {

+                best_missing    = missing;

+                best_color_diff = color_diff;

+                best_extra_diff = extra_diff;

+            }

+        }

+    }

+

+    // Copy best visual to a visual to return

+    if( best_vis >= 0 )

+    {

+        VI = XGetVisualInfo( Dpy, VisualIDMask, &VI_list[ best_vis ],

+                             &nitems_return );

+    }

+    else

+    {

+        VI = NULL;

+    }

+

+    // Free visuals list

+    XFree( VI_list );

+

+    return VI;

+}

+

+

+//========================================================================

+// _glfwTranslateKey() - Translates an X Window key to internal coding

+//========================================================================

+

+static int _glfwTranslateKey( int keycode )

+{

+    KeySym key, key_lc, key_uc;

+

+    // Try secondary keysym, for numeric keypad keys

+    // Note: This way we always force "NumLock = ON", which at least

+    // enables GLFW users to detect numeric keypad keys

+    key = XKeycodeToKeysym( _glfwLibrary.Dpy, keycode, 1 );

+    switch( key )

+    {

+        // Numeric keypad

+        case XK_KP_0:         return GLFW_KEY_KP_0;

+        case XK_KP_1:         return GLFW_KEY_KP_1;

+        case XK_KP_2:         return GLFW_KEY_KP_2;

+        case XK_KP_3:         return GLFW_KEY_KP_3;

+        case XK_KP_4:         return GLFW_KEY_KP_4;

+        case XK_KP_5:         return GLFW_KEY_KP_5;

+        case XK_KP_6:         return GLFW_KEY_KP_6;

+        case XK_KP_7:         return GLFW_KEY_KP_7;

+        case XK_KP_8:         return GLFW_KEY_KP_8;

+        case XK_KP_9:         return GLFW_KEY_KP_9;

+        case XK_KP_Separator:

+        case XK_KP_Decimal:   return GLFW_KEY_KP_DECIMAL;

+        case XK_KP_Equal:     return GLFW_KEY_KP_EQUAL;

+        case XK_KP_Enter:     return GLFW_KEY_KP_ENTER;

+        default:              break;

+    }

+

+    // Now try pimary keysym

+    key = XKeycodeToKeysym( _glfwLibrary.Dpy, keycode, 0 );

+    switch( key )

+    {

+        // Special keys (non character keys)

+        case XK_Escape:       return GLFW_KEY_ESC;

+        case XK_Tab:          return GLFW_KEY_TAB;

+        case XK_Shift_L:      return GLFW_KEY_LSHIFT;

+        case XK_Shift_R:      return GLFW_KEY_RSHIFT;

+        case XK_Control_L:    return GLFW_KEY_LCTRL;

+        case XK_Control_R:    return GLFW_KEY_RCTRL;

+        case XK_Meta_L:

+        case XK_Alt_L:        return GLFW_KEY_LALT;

+        case XK_Mode_switch:  // Mapped to Alt_R on many keyboards

+        case XK_Meta_R:

+        case XK_Alt_R:        return GLFW_KEY_RALT;

+        case XK_KP_Delete:

+        case XK_Delete:       return GLFW_KEY_DEL;

+        case XK_BackSpace:    return GLFW_KEY_BACKSPACE;

+        case XK_Return:       return GLFW_KEY_ENTER;

+        case XK_KP_Home:

+        case XK_Home:         return GLFW_KEY_HOME;

+        case XK_KP_End:

+        case XK_End:          return GLFW_KEY_END;

+        case XK_KP_Page_Up:

+        case XK_Page_Up:      return GLFW_KEY_PAGEUP;

+        case XK_KP_Page_Down:

+        case XK_Page_Down:    return GLFW_KEY_PAGEDOWN;

+        case XK_KP_Insert:

+        case XK_Insert:       return GLFW_KEY_INSERT;

+        case XK_KP_Left:

+        case XK_Left:         return GLFW_KEY_LEFT;

+        case XK_KP_Right:

+        case XK_Right:        return GLFW_KEY_RIGHT;

+        case XK_KP_Down:

+        case XK_Down:         return GLFW_KEY_DOWN;

+        case XK_KP_Up:

+        case XK_Up:           return GLFW_KEY_UP;

+        case XK_F1:           return GLFW_KEY_F1;

+        case XK_F2:           return GLFW_KEY_F2;

+        case XK_F3:           return GLFW_KEY_F3;

+        case XK_F4:           return GLFW_KEY_F4;

+        case XK_F5:           return GLFW_KEY_F5;

+        case XK_F6:           return GLFW_KEY_F6;

+        case XK_F7:           return GLFW_KEY_F7;

+        case XK_F8:           return GLFW_KEY_F8;

+        case XK_F9:           return GLFW_KEY_F9;

+        case XK_F10:          return GLFW_KEY_F10;

+        case XK_F11:          return GLFW_KEY_F11;

+        case XK_F12:          return GLFW_KEY_F12;

+        case XK_F13:          return GLFW_KEY_F13;

+        case XK_F14:          return GLFW_KEY_F14;

+        case XK_F15:          return GLFW_KEY_F15;

+        case XK_F16:          return GLFW_KEY_F16;

+        case XK_F17:          return GLFW_KEY_F17;

+        case XK_F18:          return GLFW_KEY_F18;

+        case XK_F19:          return GLFW_KEY_F19;

+        case XK_F20:          return GLFW_KEY_F20;

+        case XK_F21:          return GLFW_KEY_F21;

+        case XK_F22:          return GLFW_KEY_F22;

+        case XK_F23:          return GLFW_KEY_F23;

+        case XK_F24:          return GLFW_KEY_F24;

+        case XK_F25:          return GLFW_KEY_F25;

+

+        // Numeric keypad (should have been detected in secondary keysym!)

+        case XK_KP_Divide:    return GLFW_KEY_KP_DIVIDE;

+        case XK_KP_Multiply:  return GLFW_KEY_KP_MULTIPLY;

+        case XK_KP_Subtract:  return GLFW_KEY_KP_SUBTRACT;

+        case XK_KP_Add:       return GLFW_KEY_KP_ADD;

+        case XK_KP_Equal:     return GLFW_KEY_KP_EQUAL;

+        case XK_KP_Enter:     return GLFW_KEY_KP_ENTER;

+

+        // The rest (should be printable keys)

+        default:

+            // Make uppercase

+            XConvertCase( key, &key_lc, &key_uc );

+            key = key_uc;

+

+            // Valid ISO 8859-1 character?

+            if( (key >=  32 && key <= 126) ||

+                (key >= 160 && key <= 255) )

+            {

+                return (int) key;

+            }

+            return GLFW_KEY_UNKNOWN;

+    }

+}

+

+

+//========================================================================

+// _glfwTranslateChar() - Translates an X Window event to Unicode

+//========================================================================

+

+static int _glfwTranslateChar( XKeyEvent *event )

+{

+    KeySym keysym;

+

+    // Get X11 keysym

+    XLookupString( event, NULL, 0, &keysym, NULL );

+

+    // Convert to Unicode (see x11_keysym2unicode.c)

+    return (int) _glfwKeySym2Unicode( keysym );

+}

+

+

+

+//========================================================================

+// Get next X event (called by glfwPollEvents)

+//========================================================================

+

+static int _glfwGetNextEvent( void )

+{

+    XEvent event, next_event;

+

+    // Pull next event from event queue

+    XNextEvent( _glfwLibrary.Dpy, &event );

+

+    // Handle certain window messages

+    switch( event.type )

+    {

+        // Is a key being pressed?

+        case KeyPress:

+	{

+            // Translate and report key press

+            _glfwInputKey( _glfwTranslateKey( event.xkey.keycode ), GLFW_PRESS );

+

+            // Translate and report character input

+            if( _glfwWin.CharCallback )

+            {

+                _glfwInputChar( _glfwTranslateChar( &event.xkey ), GLFW_PRESS );

+            }

+            break;

+	}

+

+        // Is a key being released?

+        case KeyRelease:

+	{

+            // Do not report key releases for key repeats. For key repeats

+            // we will get KeyRelease/KeyPress pairs with identical time

+            // stamps. User selected key repeat filtering is handled in

+            // _glfwInputKey()/_glfwInputChar().

+            if( XEventsQueued( _glfwLibrary.Dpy, QueuedAfterReading ) )

+            {

+                XPeekEvent( _glfwLibrary.Dpy, &next_event );

+                if( next_event.type == KeyPress &&

+                    next_event.xkey.window == event.xkey.window &&

+                    next_event.xkey.keycode == event.xkey.keycode &&

+                    next_event.xkey.time == event.xkey.time )

+                {

+                    // Do not report anything for this event

+                    break;

+                }

+            }

+

+            // Translate and report key release

+            _glfwInputKey( _glfwTranslateKey( event.xkey.keycode ), GLFW_RELEASE );

+

+            // Translate and report character input

+            if( _glfwWin.CharCallback )

+            {

+                _glfwInputChar( _glfwTranslateChar( &event.xkey ), GLFW_RELEASE );

+            }

+            break;

+	}

+

+        // Were any of the mouse-buttons pressed?

+        case ButtonPress:

+	{

+            if( event.xbutton.button == Button1 )

+            {

+                _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS );

+            }

+            else if( event.xbutton.button == Button2 )

+            {

+                _glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS );

+            }

+            else if( event.xbutton.button == Button3 )

+            {

+                _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS );

+            }

+

+            // XFree86 3.3.2 and later translates mouse wheel up/down into

+            // mouse button 4 & 5 presses

+            else if( event.xbutton.button == Button4 )

+            {

+                _glfwInput.WheelPos++;  // To verify: is this up or down?

+                if( _glfwWin.MouseWheelCallback )

+                {

+                    _glfwWin.MouseWheelCallback( _glfwInput.WheelPos );

+                }

+            }

+            else if( event.xbutton.button == Button5 )

+            {

+                _glfwInput.WheelPos--;

+                if( _glfwWin.MouseWheelCallback )

+                {

+                    _glfwWin.MouseWheelCallback( _glfwInput.WheelPos );

+                }

+            }

+            break;

+	}

+

+        // Were any of the mouse-buttons released?

+        case ButtonRelease:

+	{

+            if( event.xbutton.button == Button1 )

+            {

+                _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT,

+                                      GLFW_RELEASE );

+            }

+            else if( event.xbutton.button == Button2 )

+            {

+                _glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE,

+                                      GLFW_RELEASE );

+            }

+            else if( event.xbutton.button == Button3 )

+            {

+                _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT,

+                                      GLFW_RELEASE );

+            }

+            break;

+	}

+

+        // Was the mouse moved?

+        case MotionNotify:

+	{

+            if( event.xmotion.x != _glfwInput.CursorPosX ||

+                event.xmotion.y != _glfwInput.CursorPosY )

+            {

+                if( _glfwWin.MouseLock )

+                {

+                    _glfwInput.MousePosX += event.xmotion.x -

+                                            _glfwInput.CursorPosX;

+                    _glfwInput.MousePosY += event.xmotion.y -

+                                            _glfwInput.CursorPosY;

+                }

+                else

+                {

+                    _glfwInput.MousePosX = event.xmotion.x;

+                    _glfwInput.MousePosY = event.xmotion.y;

+                }

+                _glfwInput.CursorPosX = event.xmotion.x;

+                _glfwInput.CursorPosY = event.xmotion.y;

+                _glfwInput.MouseMoved = GL_TRUE;

+

+                // Call user callback function

+                if( _glfwWin.MousePosCallback )

+                {

+                    _glfwWin.MousePosCallback( _glfwInput.MousePosX,

+                                               _glfwInput.MousePosY );

+                }

+            }

+            break;

+	}

+

+        // Was the window resized?

+        case ConfigureNotify:

+	{

+            if( event.xconfigure.width != _glfwWin.Width ||

+                event.xconfigure.height != _glfwWin.Height )

+            {

+                _glfwWin.Width = event.xconfigure.width;

+                _glfwWin.Height = event.xconfigure.height;

+                if( _glfwWin.WindowSizeCallback )

+                {

+                    _glfwWin.WindowSizeCallback( _glfwWin.Width,

+                                                 _glfwWin.Height );

+                }

+            }

+            break;

+	}

+

+        // Was the window closed by the window manager?

+        case ClientMessage:

+	{

+            if( (Atom) event.xclient.data.l[ 0 ] == _glfwWin.WMDeleteWindow )

+            {

+                return GL_TRUE;

+            }

+

+	    if( (Atom) event.xclient.data.l[ 0 ] == _glfwWin.WMPing )

+	    {

+		XSendEvent( _glfwLibrary.Dpy,

+			    RootWindow( _glfwLibrary.Dpy, _glfwWin.VI->screen ),

+			    False, SubstructureNotifyMask | SubstructureRedirectMask, &event );

+	    }

+            break;

+	}

+

+        // Was the window mapped (un-iconified)?

+        case MapNotify:

+            _glfwWin.MapNotifyCount++;

+            break;

+

+        // Was the window unmapped (iconified)?

+        case UnmapNotify:

+            _glfwWin.MapNotifyCount--;

+            break;

+

+        // Was the window activated?

+        case FocusIn:

+            _glfwWin.FocusInCount++;

+            break;

+

+        // Was the window de-activated?

+        case FocusOut:

+            _glfwWin.FocusInCount--;

+            break;

+

+        // Was the window contents damaged?

+        case Expose:

+	{

+            // Call user callback function

+            if( _glfwWin.WindowRefreshCallback )

+            {

+                _glfwWin.WindowRefreshCallback();

+            }

+            break;

+	}

+

+        // Was the window destroyed?

+        case DestroyNotify:

+            return GL_TRUE;

+

+        default:

+	{

+#if defined( _GLFW_HAS_XRANDR )

+	    switch( event.type - _glfwLibrary.XRandR.EventBase )

+	    {

+		case RRScreenChangeNotify:

+		{

+		    // Show XRandR that we really care

+		    XRRUpdateConfiguration( &event );

+		    break;

+		}

+	    }

+#endif

+            break;

+	}

+    }

+

+    // The window was not destroyed

+    return GL_FALSE;

+}

+

+

+//========================================================================

+// _glfwCreateNULLCursor() - Create a blank cursor (for locked mouse mode)

+//========================================================================

+

+Cursor _glfwCreateNULLCursor( Display *display, Window root )

+{

+    Pixmap    cursormask;

+    XGCValues xgc;

+    GC        gc;

+    XColor    col;

+    Cursor    cursor;

+

+    cursormask = XCreatePixmap( display, root, 1, 1, 1 );

+    xgc.function = GXclear;

+    gc = XCreateGC( display, cursormask, GCFunction, &xgc );

+    XFillRectangle( display, cursormask, gc, 0, 0, 1, 1 );

+    col.pixel = 0;

+    col.red = 0;

+    col.flags = 4;

+    cursor = XCreatePixmapCursor( display, cursormask, cursormask,

+                                  &col,&col, 0,0 );

+    XFreePixmap( display, cursormask );

+    XFreeGC( display, gc );

+

+    return cursor;

+}

+

+

+//========================================================================

+// _glfwInitGLXExtensions() - Initialize GLX-specific extensions

+//========================================================================

+

+static void _glfwInitGLXExtensions( void )

+{

+    int has_swap_control;

+

+    // Initialize OpenGL extension: GLX_SGI_swap_control

+    has_swap_control = _glfwPlatformExtensionSupported(

+                           "GLX_SGI_swap_control"

+                       );

+

+    if( has_swap_control )

+    {

+        _glfwWin.SwapInterval = (GLXSWAPINTERVALSGI_T)

+            _glfw_glXGetProcAddress( (GLubyte*) "glXSwapIntervalSGI" );

+    }

+    else

+    {

+        _glfwWin.SwapInterval = NULL;

+    }

+}

+

+

+

+//************************************************************************

+//****               Platform implementation functions                ****

+//************************************************************************

+

+//========================================================================

+// _glfwPlatformOpenWindow() - Here is where the window is created, and

+// the OpenGL rendering context is created

+//========================================================================

+

+int _glfwPlatformOpenWindow( int width, int height, int redbits,

+    int greenbits, int bluebits, int alphabits, int depthbits,

+    int stencilbits, int mode, _GLFWhints* hints )

+{

+    Colormap    cmap;

+    XSetWindowAttributes wa;

+    XEvent      event;

+    Atom protocols[2];

+

+    // Clear platform specific GLFW window state

+    _glfwWin.VI               = NULL;

+    _glfwWin.CX               = (GLXContext)0;

+    _glfwWin.Win              = (Window)0;

+    _glfwWin.Hints            = NULL;

+    _glfwWin.PointerGrabbed   = GL_FALSE;

+    _glfwWin.KeyboardGrabbed  = GL_FALSE;

+    _glfwWin.OverrideRedirect = GL_FALSE;

+    _glfwWin.FS.ModeChanged   = GL_FALSE;

+    _glfwWin.Saver.Changed    = GL_FALSE;

+    _glfwWin.RefreshRate      = hints->RefreshRate;

+

+    // Fullscreen & screen saver settings

+    // Check if GLX is supported on this display

+    if( !glXQueryExtension( _glfwLibrary.Dpy, NULL, NULL ) )

+    {

+        _glfwPlatformCloseWindow();

+        return GL_FALSE;

+    }

+

+    // Get screen ID for this window

+    _glfwWin.Scrn = _glfwLibrary.DefaultScreen;

+

+    // Get an appropriate visual

+    _glfwWin.VI = _glfwChooseVisual( _glfwLibrary.Dpy,

+                                     _glfwWin.Scrn,

+                                     redbits, greenbits, bluebits,

+                                     alphabits, depthbits, stencilbits,

+                                     hints->AccumRedBits, hints->AccumGreenBits,

+                                     hints->AccumBlueBits, hints->AccumAlphaBits,

+                                     hints->AuxBuffers, hints->Samples, hints->Stereo );

+    if( _glfwWin.VI == NULL )

+    {

+        _glfwPlatformCloseWindow();

+        return GL_FALSE;

+    }

+

+    // Create a GLX context

+    _glfwWin.CX = glXCreateContext( _glfwLibrary.Dpy, _glfwWin.VI, 0, GL_TRUE );

+    if( _glfwWin.CX == NULL )

+    {

+        _glfwPlatformCloseWindow();

+        return GL_FALSE;

+    }

+

+    // Create a colormap

+    cmap = XCreateColormap( _glfwLibrary.Dpy, RootWindow( _glfwLibrary.Dpy,

+               _glfwWin.VI->screen), _glfwWin.VI->visual, AllocNone );

+

+    // Do we want fullscreen?

+    if( mode == GLFW_FULLSCREEN )

+    {

+        // Change video mode

+        _glfwSetVideoMode( _glfwWin.Scrn, &_glfwWin.Width,

+                           &_glfwWin.Height, &_glfwWin.RefreshRate );

+

+        // Remember old screen saver settings

+        XGetScreenSaver( _glfwLibrary.Dpy, &_glfwWin.Saver.Timeout,

+                         &_glfwWin.Saver.Interval, &_glfwWin.Saver.Blanking,

+                         &_glfwWin.Saver.Exposure );

+

+        // Disable screen saver

+        XSetScreenSaver( _glfwLibrary.Dpy, 0, 0, DontPreferBlanking,

+                         DefaultExposures );

+    }

+

+    // Attributes for window

+    wa.colormap = cmap;

+    wa.border_pixel = 0;

+    wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |

+        PointerMotionMask | ButtonPressMask | ButtonReleaseMask |

+        ExposureMask | FocusChangeMask | VisibilityChangeMask;

+

+    // Create a window

+    _glfwWin.Win = XCreateWindow(

+        _glfwLibrary.Dpy,

+        RootWindow( _glfwLibrary.Dpy, _glfwWin.VI->screen ),

+        0, 0,                            // Upper left corner

+        _glfwWin.Width, _glfwWin.Height, // Width, height

+        0,                               // Borderwidth

+        _glfwWin.VI->depth,              // Depth

+        InputOutput,

+        _glfwWin.VI->visual,

+        CWBorderPixel | CWColormap | CWEventMask,

+        &wa

+    );

+    if( !_glfwWin.Win )

+    {

+        _glfwPlatformCloseWindow();

+        return GL_FALSE;

+    }

+

+    // Get the delete window WM protocol atom

+    _glfwWin.WMDeleteWindow = XInternAtom( _glfwLibrary.Dpy,

+                                           "WM_DELETE_WINDOW",

+                                           False );

+

+    // Get the ping WM protocol atom

+    _glfwWin.WMPing = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_PING", False );

+

+    protocols[0] = _glfwWin.WMDeleteWindow;

+    protocols[1] = _glfwWin.WMPing;

+

+    // Allow us to trap the Window Close protocol

+    XSetWMProtocols( _glfwLibrary.Dpy, _glfwWin.Win, protocols,

+                     sizeof(protocols) / sizeof(Atom) );

+

+    // Remove window decorations for fullscreen windows

+    if( mode == GLFW_FULLSCREEN )

+    {

+        _glfwDisableDecorations();

+    }

+

+    _glfwWin.Hints = XAllocSizeHints();

+

+    if( hints->WindowNoResize )

+    {

+	_glfwWin.Hints->flags |= (PMinSize | PMaxSize);

+        _glfwWin.Hints->min_width = _glfwWin.Hints->max_width = _glfwWin.Width;

+        _glfwWin.Hints->min_height = _glfwWin.Hints->max_height = _glfwWin.Height;

+    }

+

+    if( mode == GLFW_FULLSCREEN )

+    {

+	_glfwWin.Hints->flags |= PPosition;

+	_glfwWin.Hints->x = 0;

+	_glfwWin.Hints->y = 0;

+    }

+

+    XSetWMNormalHints( _glfwLibrary.Dpy, _glfwWin.Win, _glfwWin.Hints );

+

+    // Map window

+    XMapWindow( _glfwLibrary.Dpy, _glfwWin.Win );

+

+    // Wait for map notification

+    XIfEvent( _glfwLibrary.Dpy, &event, _glfwWaitForMapNotify,

+              (char*)_glfwWin.Win );

+

+    // Make sure that our window ends up on top of things

+    XRaiseWindow( _glfwLibrary.Dpy, _glfwWin.Win );

+

+    // Fullscreen mode "post processing"

+    if( mode == GLFW_FULLSCREEN )

+    {

+#if defined( _GLFW_HAS_XRANDR )

+	// Request screen change notifications

+	if( _glfwLibrary.XRandR.Available )

+	{

+	    XRRSelectInput( _glfwLibrary.Dpy,

+	                    _glfwWin.Win,

+			    RRScreenChangeNotifyMask );

+	}

+#endif

+

+        // Force window position/size (some WMs do their own window

+        // geometry, which we want to override)

+        XMoveWindow( _glfwLibrary.Dpy, _glfwWin.Win, 0, 0 );

+        XResizeWindow( _glfwLibrary.Dpy, _glfwWin.Win, _glfwWin.Width,

+                       _glfwWin.Height );

+

+        // Grab keyboard

+        if( XGrabKeyboard( _glfwLibrary.Dpy, _glfwWin.Win, True,

+                           GrabModeAsync, GrabModeAsync, CurrentTime ) ==

+            GrabSuccess )

+        {

+            _glfwWin.KeyboardGrabbed = GL_TRUE;

+        }

+

+        // Grab mouse cursor

+        if( XGrabPointer( _glfwLibrary.Dpy, _glfwWin.Win, True,

+                          ButtonPressMask | ButtonReleaseMask |

+                          PointerMotionMask, GrabModeAsync, GrabModeAsync,

+                          _glfwWin.Win, None, CurrentTime ) ==

+            GrabSuccess )

+        {

+            _glfwWin.PointerGrabbed = GL_TRUE;

+        }

+

+        // Try to get window inside viewport (for virtual displays) by

+        // moving the mouse cursor to the upper left corner (and then to

+        // the center) - this works for XFree86

+        XWarpPointer( _glfwLibrary.Dpy, None, _glfwWin.Win, 0,0,0,0, 0,0 );

+        XWarpPointer( _glfwLibrary.Dpy, None, _glfwWin.Win, 0,0,0,0,

+                      _glfwWin.Width/2, _glfwWin.Height/2 );

+    }

+

+    // Set window & icon name

+    _glfwPlatformSetWindowTitle( "GLFW Window" );

+

+    // Connect the context to the window

+    glXMakeCurrent( _glfwLibrary.Dpy, _glfwWin.Win, _glfwWin.CX );

+

+    // Start by clearing the front buffer to black (avoid ugly desktop

+    // remains in our OpenGL window)

+    glClear( GL_COLOR_BUFFER_BIT );

+    glXSwapBuffers( _glfwLibrary.Dpy, _glfwWin.Win );

+

+    // Initialize GLX-specific OpenGL extensions

+    _glfwInitGLXExtensions();

+

+    return GL_TRUE;

+}

+

+

+//========================================================================

+// Properly kill the window/video display

+//========================================================================

+

+void _glfwPlatformCloseWindow( void )

+{

+#if defined( _GLFW_HAS_XRANDR )

+    XRRScreenConfiguration *sc;

+    Window root;

+#endif

+

+    // Free WM size hints

+    if( _glfwWin.Hints )

+    {

+	XFree( _glfwWin.Hints );

+	_glfwWin.Hints = NULL;

+    }

+

+    // Do we have a rendering context?

+    if( _glfwWin.CX )

+    {

+        // Release the context

+        glXMakeCurrent( _glfwLibrary.Dpy, None, NULL );

+

+        // Delete the context

+        glXDestroyContext( _glfwLibrary.Dpy, _glfwWin.CX );

+        _glfwWin.CX = NULL;

+    }

+

+    // Ungrab pointer and/or keyboard?

+    if( _glfwWin.KeyboardGrabbed )

+    {

+        XUngrabKeyboard( _glfwLibrary.Dpy, CurrentTime );

+        _glfwWin.KeyboardGrabbed = GL_FALSE;

+    }

+    if( _glfwWin.PointerGrabbed )

+    {

+        XUngrabPointer( _glfwLibrary.Dpy, CurrentTime );

+        _glfwWin.PointerGrabbed = GL_FALSE;

+    }

+

+    // Do we have a window?

+    if( _glfwWin.Win )

+    {

+        // Unmap the window

+        XUnmapWindow( _glfwLibrary.Dpy, _glfwWin.Win );

+

+        // Destroy the window

+        XDestroyWindow( _glfwLibrary.Dpy, _glfwWin.Win );

+        _glfwWin.Win = (Window) 0;

+    }

+

+    // Did we change the fullscreen resolution?

+    if( _glfwWin.FS.ModeChanged )

+    {

+#if defined( _GLFW_HAS_XRANDR )

+	if( _glfwLibrary.XRandR.Available )

+	{

+	    root = RootWindow( _glfwLibrary.Dpy, _glfwWin.Scrn );

+	    sc = XRRGetScreenInfo( _glfwLibrary.Dpy, root );

+

+	    XRRSetScreenConfig( _glfwLibrary.Dpy,

+	                        sc,

+				root,

+			        _glfwWin.FS.OldSizeID,

+				_glfwWin.FS.OldRotation,

+				CurrentTime );

+

+	    XRRFreeScreenConfigInfo( sc );

+	}

+#elif defined( _GLFW_HAS_XF86VIDMODE )

+        if( _glfwLibrary.XF86VidMode.Available )

+        {

+            // Unlock mode switch

+            XF86VidModeLockModeSwitch( _glfwLibrary.Dpy,

+                                       _glfwWin.Scrn,

+                                       0 );

+

+            // Change the video mode back to the old mode

+            XF86VidModeSwitchToMode( _glfwLibrary.Dpy,

+                _glfwWin.Scrn, &_glfwWin.FS.OldMode );

+        }

+#endif

+        _glfwWin.FS.ModeChanged = GL_FALSE;

+    }

+

+    // Did we change the screen saver setting?

+    if( _glfwWin.Saver.Changed )

+    {

+        // Restore old screen saver settings

+        XSetScreenSaver( _glfwLibrary.Dpy, _glfwWin.Saver.Timeout,

+                         _glfwWin.Saver.Interval, _glfwWin.Saver.Blanking,

+                         _glfwWin.Saver.Exposure );

+        _glfwWin.Saver.Changed = GL_FALSE;

+    }

+

+    XSync( _glfwLibrary.Dpy, True );

+}

+

+

+//========================================================================

+// _glfwPlatformSetWindowTitle() - Set the window title.

+//========================================================================

+

+void _glfwPlatformSetWindowTitle( const char *title )

+{

+    // Set window & icon title

+    XStoreName( _glfwLibrary.Dpy, _glfwWin.Win, title );

+    XSetIconName( _glfwLibrary.Dpy, _glfwWin.Win, title );

+}

+

+

+//========================================================================

+// _glfwPlatformSetWindowSize() - Set the window size.

+//========================================================================

+

+void _glfwPlatformSetWindowSize( int width, int height )

+{

+    int     mode = 0, rate, sizechanged = GL_FALSE;

+    GLint   drawbuffer;

+    GLfloat clearcolor[4];

+

+    rate = _glfwWin.RefreshRate;

+

+    // If we are in fullscreen mode, get some info about the current mode

+    if( _glfwWin.Fullscreen )

+    {

+        // Get closest match for target video mode

+        mode = _glfwGetClosestVideoMode( _glfwWin.Scrn, &width, &height, &rate );

+    }

+

+    if( _glfwWin.WindowNoResize )

+    {

+        _glfwWin.Hints->min_width = _glfwWin.Hints->max_width = width;

+        _glfwWin.Hints->min_height = _glfwWin.Hints->max_height = height;

+    }

+

+    XSetWMNormalHints( _glfwLibrary.Dpy, _glfwWin.Win, _glfwWin.Hints );

+

+    // Change window size before changing fullscreen mode?

+    if( _glfwWin.Fullscreen && (width > _glfwWin.Width) )

+    {

+        XResizeWindow( _glfwLibrary.Dpy, _glfwWin.Win, width, height );

+        sizechanged = GL_TRUE;

+    }

+

+    // Change fullscreen video mode?

+    if( _glfwWin.Fullscreen )

+    {

+        // Change video mode (keeping current rate)

+        _glfwSetVideoModeMODE( _glfwWin.Scrn, mode, _glfwWin.RefreshRate );

+

+        // Clear the front buffer to black (avoid ugly desktop remains in

+        // our OpenGL window)

+        glGetIntegerv( GL_DRAW_BUFFER, &drawbuffer );

+        glGetFloatv( GL_COLOR_CLEAR_VALUE, clearcolor );

+        glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );

+        glClear( GL_COLOR_BUFFER_BIT );

+        if( drawbuffer == GL_BACK )

+        {

+            glXSwapBuffers( _glfwLibrary.Dpy, _glfwWin.Win );

+        }

+        glClearColor( clearcolor[0], clearcolor[1], clearcolor[2],

+                      clearcolor[3] );

+    }

+

+    // Set window size (if not already changed)

+    if( !sizechanged )

+    {

+        XResizeWindow( _glfwLibrary.Dpy, _glfwWin.Win, width, height );

+    }

+}

+

+

+//========================================================================

+// _glfwPlatformSetWindowPos() - Set the window position.

+//========================================================================

+

+void _glfwPlatformSetWindowPos( int x, int y )

+{

+    // Set window position

+    XMoveWindow( _glfwLibrary.Dpy, _glfwWin.Win, x, y );

+}

+

+

+//========================================================================

+// _glfwPlatformIconfyWindow() - Window iconification

+//========================================================================

+

+void _glfwPlatformIconifyWindow( void )

+{

+    // We can't do this for override redirect windows

+    if( _glfwWin.OverrideRedirect )

+    {

+        return;

+    }

+

+    // In fullscreen mode, we need to restore the desktop video mode

+    if( _glfwWin.Fullscreen )

+    {

+#if defined( _GLFW_HAS_XF86VIDMODE )

+        if( _glfwLibrary.XF86VidMode.Available )

+        {

+            // Unlock mode switch

+            XF86VidModeLockModeSwitch( _glfwLibrary.Dpy,

+                                       _glfwWin.Scrn,

+                                       0 );

+

+            // Change the video mode back to the old mode

+            XF86VidModeSwitchToMode( _glfwLibrary.Dpy,

+                _glfwWin.Scrn, &_glfwWin.FS.OldMode );

+        }

+#endif

+        _glfwWin.FS.ModeChanged = GL_FALSE;

+    }

+

+    // Show mouse pointer

+    if( _glfwWin.PointerHidden )

+    {

+        XUndefineCursor( _glfwLibrary.Dpy, _glfwWin.Win );

+        _glfwWin.PointerHidden = GL_FALSE;

+    }

+

+    // Un-grab mouse pointer

+    if( _glfwWin.PointerGrabbed )

+    {

+        XUngrabPointer( _glfwLibrary.Dpy, CurrentTime );

+        _glfwWin.PointerGrabbed = GL_FALSE;

+    }

+

+    // Iconify window

+    XIconifyWindow( _glfwLibrary.Dpy, _glfwWin.Win,

+                    _glfwWin.Scrn );

+

+    // Window is now iconified

+    _glfwWin.Iconified = GL_TRUE;

+}

+

+

+//========================================================================

+// Window un-iconification

+//========================================================================

+

+void _glfwPlatformRestoreWindow( void )

+{

+    // We can't do this for override redirect windows

+    if( _glfwWin.OverrideRedirect )

+    {

+        return;

+    }

+

+    // In fullscreen mode, change back video mode to user selected mode

+    if( _glfwWin.Fullscreen )

+    {

+        _glfwSetVideoMode( _glfwWin.Scrn,

+	                   &_glfwWin.Width, &_glfwWin.Height, &_glfwWin.RefreshRate );

+    }

+

+    // Un-iconify window

+    XMapWindow( _glfwLibrary.Dpy, _glfwWin.Win );

+

+    // In fullscreen mode...

+    if( _glfwWin.Fullscreen )

+    {

+        // Make sure window is in upper left corner

+        XMoveWindow( _glfwLibrary.Dpy, _glfwWin.Win, 0, 0 );

+

+        // Get input focus

+        XSetInputFocus( _glfwLibrary.Dpy, _glfwWin.Win, RevertToParent,

+                        CurrentTime );

+    }

+

+    // Lock mouse, if necessary

+    if( _glfwWin.MouseLock )

+    {

+        // Hide cursor

+        if( !_glfwWin.PointerHidden )

+        {

+            XDefineCursor( _glfwLibrary.Dpy, _glfwWin.Win,

+                           _glfwCreateNULLCursor( _glfwLibrary.Dpy,

+                                                  _glfwWin.Win ) );

+            _glfwWin.PointerHidden = GL_TRUE;

+        }

+

+        // Grab cursor

+        if( !_glfwWin.PointerGrabbed )

+        {

+            if( XGrabPointer( _glfwLibrary.Dpy, _glfwWin.Win, True,

+                              ButtonPressMask | ButtonReleaseMask |

+                              PointerMotionMask, GrabModeAsync,

+                              GrabModeAsync, _glfwWin.Win, None,

+                              CurrentTime ) == GrabSuccess )

+            {

+                _glfwWin.PointerGrabbed = GL_TRUE;

+            }

+        }

+    }

+

+    // Window is no longer iconified

+    _glfwWin.Iconified = GL_FALSE;

+}

+

+

+//========================================================================

+// _glfwPlatformSwapBuffers() - Swap buffers (double-buffering) and poll

+// any new events.

+//========================================================================

+

+void _glfwPlatformSwapBuffers( void )

+{

+    // Update display-buffer

+    glXSwapBuffers( _glfwLibrary.Dpy, _glfwWin.Win );

+}

+

+

+//========================================================================

+// _glfwPlatformSwapInterval() - Set double buffering swap interval

+//========================================================================

+

+void _glfwPlatformSwapInterval( int interval )

+{

+    if( _glfwWin.SwapInterval )

+    {

+        _glfwWin.SwapInterval( interval );

+    }

+}

+

+

+//========================================================================

+// _glfwPlatformRefreshWindowParams()

+//========================================================================

+

+void _glfwPlatformRefreshWindowParams( void )

+{

+#if defined( _GLFW_HAS_XRANDR )

+    XRRScreenConfiguration *sc;

+#elif defined( _GLFW_HAS_XF86VIDMODE )

+    XF86VidModeModeLine modeline;

+    int dotclock;

+    float pixels_per_second, pixels_per_frame;

+#endif

+    int sample_buffers;

+

+    // AFAIK, there is no easy/sure way of knowing if OpenGL is hardware

+    // accelerated

+    _glfwWin.Accelerated = GL_TRUE;

+

+    // "Standard" window parameters

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_RED_SIZE,

+                  &_glfwWin.RedBits );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_GREEN_SIZE,

+                  &_glfwWin.GreenBits );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_BLUE_SIZE,

+                  &_glfwWin.BlueBits );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_ALPHA_SIZE,

+                  &_glfwWin.AlphaBits );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_DEPTH_SIZE,

+                  &_glfwWin.DepthBits );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_STENCIL_SIZE,

+                  &_glfwWin.StencilBits );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_ACCUM_RED_SIZE,

+                  &_glfwWin.AccumRedBits );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_ACCUM_GREEN_SIZE,

+                  &_glfwWin.AccumGreenBits );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_ACCUM_BLUE_SIZE,

+                  &_glfwWin.AccumBlueBits );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_ACCUM_ALPHA_SIZE,

+                  &_glfwWin.AccumAlphaBits );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_AUX_BUFFERS,

+                  &_glfwWin.AuxBuffers );

+

+    // Get stereo rendering setting

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_STEREO,

+                  &_glfwWin.Stereo );

+    _glfwWin.Stereo = _glfwWin.Stereo ? 1 : 0;

+

+    // Get multisample buffer samples

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_SAMPLES,

+		  &_glfwWin.Samples );

+    glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_SAMPLE_BUFFERS, 

+		  &sample_buffers );

+    if( sample_buffers == 0 )

+      _glfwWin.Samples = 0;

+    

+    // Default to refresh rate unknown (=0 according to GLFW spec)

+    _glfwWin.RefreshRate = 0;

+		  

+    // Retrieve refresh rate, if possible

+#if defined( _GLFW_HAS_XRANDR )

+    if( _glfwLibrary.XRandR.Available )

+    {

+	sc = XRRGetScreenInfo( _glfwLibrary.Dpy,

+	                       RootWindow( _glfwLibrary.Dpy, _glfwWin.Scrn ) );

+	_glfwWin.RefreshRate = XRRConfigCurrentRate( sc );

+	XRRFreeScreenConfigInfo( sc );

+    }

+#elif defined( _GLFW_HAS_XF86VIDMODE )

+    if( _glfwLibrary.XF86VidMode.Available )

+    {

+        // Use the XF86VidMode extension to get current video mode

+        XF86VidModeGetModeLine( _glfwLibrary.Dpy, _glfwWin.Scrn,

+                                &dotclock, &modeline );

+        pixels_per_second = 1000.0f * (float) dotclock;

+        pixels_per_frame  = (float) modeline.htotal * modeline.vtotal;

+        _glfwWin.RefreshRate = (int)(pixels_per_second/pixels_per_frame+0.5);

+    }

+#endif

+}

+

+

+//========================================================================

+// _glfwPlatformPollEvents() - Poll for new window and input events

+//========================================================================

+

+void _glfwPlatformPollEvents( void )

+{

+    int winclosed = GL_FALSE;

+

+    // Flag that the cursor has not moved

+    _glfwInput.MouseMoved = GL_FALSE;

+

+    // Clear MapNotify and FocusIn counts

+    _glfwWin.MapNotifyCount = 0;

+    _glfwWin.FocusInCount = 0;

+

+    // Use XSync to synchronise events to the X display.

+    // I don't know if this can have a serious performance impact. My

+    // benchmarks with a GeForce card under Linux shows no difference with

+    // or without XSync, but when the GL window is rendered over a slow

+    // network I have noticed bad event syncronisation problems when XSync

+    // is not used, so I decided to use it.

+    XSync( _glfwLibrary.Dpy, False );

+

+    // Empty the window event queue

+    while( XPending( _glfwLibrary.Dpy ) )

+    {

+        if( _glfwGetNextEvent() )

+        {

+            winclosed = GL_TRUE;

+        }

+    }

+

+    // Did we get mouse movement in locked cursor mode?

+    if( _glfwInput.MouseMoved && _glfwWin.MouseLock )

+    {

+        int maxx, minx, maxy, miny;

+

+        // Calculate movement threshold

+        minx = _glfwWin.Width / 4;

+        maxx = (_glfwWin.Width * 3) / 4;

+        miny = _glfwWin.Height / 4;

+        maxy = (_glfwWin.Height * 3) / 4;

+

+        // Did the mouse cursor move beyond our movement threshold

+        if(_glfwInput.CursorPosX < minx || _glfwInput.CursorPosX > maxx ||

+           _glfwInput.CursorPosY < miny || _glfwInput.CursorPosY > maxy)

+        {

+            // Move the mouse pointer back to the window center so that it

+            // does not wander off...

+            _glfwPlatformSetMouseCursorPos( _glfwWin.Width/2,

+                                            _glfwWin.Height/2 );

+            XSync( _glfwLibrary.Dpy, False );

+        }

+    }

+

+    // Was the window (un)iconified?

+    if( _glfwWin.MapNotifyCount < 0 && !_glfwWin.Iconified )

+    {

+        // Show mouse pointer

+        if( _glfwWin.PointerHidden )

+        {

+            XUndefineCursor( _glfwLibrary.Dpy, _glfwWin.Win );

+            _glfwWin.PointerHidden = GL_FALSE;

+        }

+

+        // Un-grab mouse pointer

+        if( _glfwWin.PointerGrabbed )

+        {

+            XUngrabPointer( _glfwLibrary.Dpy, CurrentTime );

+            _glfwWin.PointerGrabbed = GL_FALSE;

+        }

+

+        _glfwWin.Iconified = GL_TRUE;

+    }

+    else if( _glfwWin.MapNotifyCount > 0 && _glfwWin.Iconified )

+    {

+        // Restore fullscreen mode properties

+        if( _glfwWin.Fullscreen )

+        {

+            // Change back video mode to user selected mode

+            _glfwSetVideoMode( _glfwWin.Scrn, &_glfwWin.Width,

+                               &_glfwWin.Height, &_glfwWin.RefreshRate );

+

+            // Disable window manager decorations

+            _glfwEnableDecorations();

+

+            // Make sure window is in upper left corner

+            XMoveWindow( _glfwLibrary.Dpy, _glfwWin.Win, 0, 0 );

+

+            // Get input focus

+            XSetInputFocus( _glfwLibrary.Dpy, _glfwWin.Win,

+                            RevertToParent, CurrentTime );

+        }

+

+        // Hide cursor if necessary

+        if( _glfwWin.MouseLock && !_glfwWin.PointerHidden )

+        {

+            if( !_glfwWin.PointerHidden )

+            {

+                XDefineCursor( _glfwLibrary.Dpy, _glfwWin.Win,

+                    _glfwCreateNULLCursor( _glfwLibrary.Dpy,

+                                           _glfwWin.Win ) );

+                _glfwWin.PointerHidden = GL_TRUE;

+            }

+        }

+

+        // Grab cursor if necessary

+        if( (_glfwWin.MouseLock || _glfwWin.Fullscreen) &&

+            !_glfwWin.PointerGrabbed )

+        {

+            if( XGrabPointer( _glfwLibrary.Dpy, _glfwWin.Win, True,

+                    ButtonPressMask | ButtonReleaseMask |

+                    PointerMotionMask, GrabModeAsync,

+                    GrabModeAsync, _glfwWin.Win, None,

+                    CurrentTime ) == GrabSuccess )

+            {

+                _glfwWin.PointerGrabbed = GL_TRUE;

+            }

+        }

+

+        _glfwWin.Iconified = GL_FALSE;

+    }

+

+    // Did the window get/lose focus

+    if( _glfwWin.FocusInCount > 0 && !_glfwWin.Active )

+    {

+        // If we are in fullscreen mode, restore window

+        if( _glfwWin.Fullscreen && _glfwWin.Iconified )

+        {

+            _glfwPlatformRestoreWindow();

+        }

+

+        // Window is now active

+        _glfwWin.Active = GL_TRUE;

+    }

+    else if( _glfwWin.FocusInCount < 0 && _glfwWin.Active )

+    {

+        // If we are in fullscreen mode, iconfify window

+        if( _glfwWin.Fullscreen )

+        {

+            _glfwPlatformIconifyWindow();

+        }

+

+        // Window is not active

+        _glfwWin.Active = GL_FALSE;

+	_glfwInputDeactivation();

+    }

+

+    // Was there a window close request?

+    if( winclosed && _glfwWin.WindowCloseCallback )

+    {

+        // Check if the program wants us to close the window

+        winclosed = _glfwWin.WindowCloseCallback();

+    }

+    if( winclosed )

+    {

+        glfwCloseWindow();

+    }

+}

+

+

+//========================================================================

+// _glfwPlatformWaitEvents() - Wait for new window and input events

+//========================================================================

+

+void _glfwPlatformWaitEvents( void )

+{

+    XEvent event;

+

+    // Wait for new events (blocking)

+    XNextEvent( _glfwLibrary.Dpy, &event );

+    XPutBackEvent( _glfwLibrary.Dpy, &event );

+

+    // Poll events from queue

+    _glfwPlatformPollEvents();

+}

+

+

+//========================================================================

+// _glfwPlatformHideMouseCursor() - Hide mouse cursor (lock it)

+//========================================================================

+

+void _glfwPlatformHideMouseCursor( void )

+{

+    // Hide cursor

+    if( !_glfwWin.PointerHidden )

+    {

+        XDefineCursor( _glfwLibrary.Dpy, _glfwWin.Win,

+                       _glfwCreateNULLCursor( _glfwLibrary.Dpy,

+                                              _glfwWin.Win ) );

+        _glfwWin.PointerHidden = GL_TRUE;

+    }

+

+    // Grab cursor to user window

+    if( !_glfwWin.PointerGrabbed )

+    {

+        if( XGrabPointer( _glfwLibrary.Dpy, _glfwWin.Win, True,

+                          ButtonPressMask | ButtonReleaseMask |

+                          PointerMotionMask, GrabModeAsync, GrabModeAsync,

+                          _glfwWin.Win, None, CurrentTime ) ==

+            GrabSuccess )

+        {

+            _glfwWin.PointerGrabbed = GL_TRUE;

+        }

+    }

+}

+

+

+//========================================================================

+// _glfwPlatformShowMouseCursor() - Show mouse cursor (unlock it)

+//========================================================================

+

+void _glfwPlatformShowMouseCursor( void )

+{

+    // Un-grab cursor (only in windowed mode: in fullscreen mode we still

+    // want the mouse grabbed in order to confine the cursor to the window

+    // area)

+    if( _glfwWin.PointerGrabbed && !_glfwWin.Fullscreen )

+    {

+        XUngrabPointer( _glfwLibrary.Dpy, CurrentTime );

+        _glfwWin.PointerGrabbed = GL_FALSE;

+    }

+

+    // Show cursor

+    if( _glfwWin.PointerHidden )

+    {

+        XUndefineCursor( _glfwLibrary.Dpy, _glfwWin.Win );

+        _glfwWin.PointerHidden = GL_FALSE;

+    }

+}

+

+

+//========================================================================

+// _glfwPlatformSetMouseCursorPos() - Set physical mouse cursor position

+//========================================================================

+

+void _glfwPlatformSetMouseCursorPos( int x, int y )

+{

+    // Change cursor position

+    _glfwInput.CursorPosX = x;

+    _glfwInput.CursorPosY = y;

+    XWarpPointer( _glfwLibrary.Dpy, None, _glfwWin.Win, 0,0,0,0, x, y );

+}

+