Browse Source

Moved from SDL to GLFW & PortAudio.

Lasse Öörni 14 years ago
parent
commit
0d29d818ad
100 changed files with 23789 additions and 984 deletions
  1. 9 12
      CMakeLists.txt
  2. 4 4
      Docs/GettingStarted.dox
  3. 2 4
      Docs/Reference.dox
  4. 2 1
      Docs/Urho3D.dox
  5. 59 327
      Engine/Audio/Audio.cpp
  6. 9 33
      Engine/Audio/Audio.h
  7. 2 7
      Engine/Audio/CMakeLists.txt
  8. 6 7
      Engine/Core/CMakeLists.txt
  9. 10 7
      Engine/Core/Mutex.cpp
  10. 2 6
      Engine/Core/ProcessUtils.cpp
  11. 21 11
      Engine/Core/Thread.cpp
  12. 31 18
      Engine/Core/Timer.cpp
  13. 3 0
      Engine/Core/Timer.h
  14. 1 3
      Engine/Engine/AudioAPI.cpp
  15. 6 24
      Engine/Engine/Engine.cpp
  16. 1 1
      Engine/Engine/Engine.h
  17. 0 18
      Engine/Engine/InputAPI.cpp
  18. 5 2
      Engine/Graphics/CMakeLists.txt
  19. 57 77
      Engine/Graphics/OpenGL/OGLGraphics.cpp
  20. 1 3
      Engine/Graphics/OpenGL/OGLGraphics.h
  21. 1 1
      Engine/Graphics/OpenGL/OGLGraphicsImpl.h
  22. 5 0
      Engine/Input/CMakeLists.txt
  23. 138 219
      Engine/Input/Input.cpp
  24. 19 21
      Engine/Input/Input.h
  25. 75 108
      Engine/Input/InputEvents.h
  26. 2 2
      Engine/Network/Network.cpp
  27. 2 2
      Engine/Physics/PhysicsWorld.cpp
  28. 7 32
      Engine/UI/UI.cpp
  29. 46 18
      License.txt
  30. 2 1
      Readme.txt
  31. 49 0
      ThirdParty/GLFW/CMakeLists.txt
  32. 13 10
      ThirdParty/GLFW/COPYING.txt
  33. 509 0
      ThirdParty/GLFW/include/GL/glfw.h
  34. 43 0
      ThirdParty/GLFW/lib/carbon/carbon_enable.c
  35. 127 0
      ThirdParty/GLFW/lib/carbon/carbon_fullscreen.c
  36. 53 0
      ThirdParty/GLFW/lib/carbon/carbon_glext.c
  37. 181 0
      ThirdParty/GLFW/lib/carbon/carbon_init.c
  38. 51 0
      ThirdParty/GLFW/lib/carbon/carbon_joystick.c
  39. 415 0
      ThirdParty/GLFW/lib/carbon/carbon_thread.c
  40. 113 0
      ThirdParty/GLFW/lib/carbon/carbon_time.c
  41. 1309 0
      ThirdParty/GLFW/lib/carbon/carbon_window.c
  42. 334 0
      ThirdParty/GLFW/lib/carbon/platform.h
  43. 51 0
      ThirdParty/GLFW/lib/cocoa/cocoa_enable.m
  44. 102 0
      ThirdParty/GLFW/lib/cocoa/cocoa_fullscreen.m
  45. 63 0
      ThirdParty/GLFW/lib/cocoa/cocoa_glext.m
  46. 275 0
      ThirdParty/GLFW/lib/cocoa/cocoa_init.m
  47. 65 0
      ThirdParty/GLFW/lib/cocoa/cocoa_joystick.m
  48. 415 0
      ThirdParty/GLFW/lib/cocoa/cocoa_thread.c
  49. 105 0
      ThirdParty/GLFW/lib/cocoa/cocoa_time.m
  50. 920 0
      ThirdParty/GLFW/lib/cocoa/cocoa_window.m
  51. 258 0
      ThirdParty/GLFW/lib/cocoa/platform.h
  52. 310 0
      ThirdParty/GLFW/lib/enable.c
  53. 95 0
      ThirdParty/GLFW/lib/fullscreen.c
  54. 235 0
      ThirdParty/GLFW/lib/glext.c
  55. 631 0
      ThirdParty/GLFW/lib/image.c
  56. 111 0
      ThirdParty/GLFW/lib/init.c
  57. 280 0
      ThirdParty/GLFW/lib/input.c
  58. 265 0
      ThirdParty/GLFW/lib/internal.h
  59. 102 0
      ThirdParty/GLFW/lib/joystick.c
  60. 194 0
      ThirdParty/GLFW/lib/stream.c
  61. 405 0
      ThirdParty/GLFW/lib/tga.c
  62. 340 0
      ThirdParty/GLFW/lib/thread.c
  63. 83 0
      ThirdParty/GLFW/lib/time.c
  64. 539 0
      ThirdParty/GLFW/lib/win32/platform.h
  65. 49 0
      ThirdParty/GLFW/lib/win32/win32_dllmain.c
  66. 155 0
      ThirdParty/GLFW/lib/win32/win32_enable.c
  67. 320 0
      ThirdParty/GLFW/lib/win32/win32_fullscreen.c
  68. 82 0
      ThirdParty/GLFW/lib/win32/win32_glext.c
  69. 356 0
      ThirdParty/GLFW/lib/win32/win32_init.c
  70. 234 0
      ThirdParty/GLFW/lib/win32/win32_joystick.c
  71. 511 0
      ThirdParty/GLFW/lib/win32/win32_thread.c
  72. 146 0
      ThirdParty/GLFW/lib/win32/win32_time.c
  73. 1819 0
      ThirdParty/GLFW/lib/win32/win32_window.c
  74. 1030 0
      ThirdParty/GLFW/lib/window.c
  75. 503 0
      ThirdParty/GLFW/lib/x11/platform.h
  76. 64 0
      ThirdParty/GLFW/lib/x11/x11_enable.c
  77. 572 0
      ThirdParty/GLFW/lib/x11/x11_fullscreen.c
  78. 90 0
      ThirdParty/GLFW/lib/x11/x11_glext.c
  79. 286 0
      ThirdParty/GLFW/lib/x11/x11_init.c
  80. 367 0
      ThirdParty/GLFW/lib/x11/x11_joystick.c
  81. 901 0
      ThirdParty/GLFW/lib/x11/x11_keysym2unicode.c
  82. 508 0
      ThirdParty/GLFW/lib/x11/x11_thread.c
  83. 154 0
      ThirdParty/GLFW/lib/x11/x11_time.c
  84. 1875 0
      ThirdParty/GLFW/lib/x11/x11_window.c
  85. 1149 0
      ThirdParty/GLFW/readme.html
  86. 2 2
      ThirdParty/GLee/CMakeLists.txt
  87. 3 3
      ThirdParty/GLee/GLee.c
  88. 117 0
      ThirdParty/PortAudio/CMakeLists.txt
  89. 81 0
      ThirdParty/PortAudio/LICENSE.txt
  90. 98 0
      ThirdParty/PortAudio/README.txt
  91. 143 0
      ThirdParty/PortAudio/include/pa_asio.h
  92. 76 0
      ThirdParty/PortAudio/include/pa_jack.h
  93. 99 0
      ThirdParty/PortAudio/include/pa_linux_alsa.h
  94. 176 0
      ThirdParty/PortAudio/include/pa_mac_core.h
  95. 101 0
      ThirdParty/PortAudio/include/pa_win_ds.h
  96. 391 0
      ThirdParty/PortAudio/include/pa_win_wasapi.h
  97. 199 0
      ThirdParty/PortAudio/include/pa_win_waveformat.h
  98. 186 0
      ThirdParty/PortAudio/include/pa_win_wmme.h
  99. 1134 0
      ThirdParty/PortAudio/include/portaudio.h
  100. 243 0
      ThirdParty/PortAudio/src/common/pa_allocation.c

+ 9 - 12
CMakeLists.txt

@@ -22,13 +22,11 @@ endif ()
 # instantiated.
 add_definitions (-DENABLE_PROFILING)
 
-# If not on Windows, enable use of SDL and OpenGL instead of Direct3D9 (so called "Turso3D" mode.)
-# Setting this on Windows is not recommended, as graphics card drivers are usually better optimized 
-# for Direct3D.
-if (UNIX)
-    set (USE_SDL 1)
+# If not on Windows, enable use of OpenGL instead of Direct3D9 (so called "Turso3D" mode.) Setting 
+# this on Windows is not recommended, as graphics card drivers are usually better optimized for 
+# Direct3D.
+if (NOT WIN32)
     set (USE_OPENGL 1)
-    add_definitions (-DUSE_SDL)
     add_definitions (-DUSE_OPENGL)
 endif ()
 
@@ -123,9 +121,9 @@ else()
     endmacro ()
 endif ()
 
-# If SDL used, add it as a global include directory
-if (USE_SDL)
-    include_directories (ThirdParty/SDL/include)
+# If GLFW used, add it as a global include directory
+if (USE_OPENGL)
+    include_directories (ThirdParty/GLFW/include)
 endif ()
 
 # Add projects
@@ -149,6 +147,7 @@ add_subdirectory (ThirdParty/Assimp)
 add_subdirectory (ThirdParty/ENet)
 add_subdirectory (ThirdParty/FreeType)
 add_subdirectory (ThirdParty/ODE)
+add_subdirectory (ThirdParty/PortAudio)
 add_subdirectory (ThirdParty/StanHull)
 add_subdirectory (ThirdParty/STB)
 add_subdirectory (ThirdParty/TinyXML)
@@ -162,12 +161,10 @@ add_subdirectory (Urho3D)
 if (USE_OPENGL)
     add_subdirectory (SourceAssets/GLSLShaders)
     add_subdirectory (ThirdParty/GLee)
+    add_subdirectory (ThirdParty/GLFW)
     add_subdirectory (Tools/GLShaderProcessor)
 else ()
     add_subdirectory (SourceAssets/HLSLShaders)
     add_subdirectory (Tools/ShaderCompiler)
 endif ()
 
-if (USE_SDL)
-    add_subdirectory (ThirdParty/SDL)
-endif ()

+ 4 - 4
Docs/GettingStarted.dox

@@ -20,7 +20,7 @@ Although all required third-party libraries are included as source code, there a
 
 - For Windows, the DirectX SDK needs to be installed. The HLSL compiler included in some SDK's may fail to compile those SM2.0 shaders that reach exactly the arithmetic instruction count limit; at least the February 2010 SDK is known to work.
 
-- For Linux, the following development packages need to be installed: libx11-dev, libxxf86vm-dev, libgl1-mesa-dev, libasound2-dev.
+- For Linux, the following development packages need to be installed: libx11-dev, libxrandr-dev, libgl1-mesa-dev, libasound2-dev.
 
 - For Mac OS X, the Xcode developer tools package should include everything necessary.
 
@@ -84,7 +84,6 @@ Urho3D.exe understands the following command line options:
 -headless   Headless mode. No application window will be created
 -forward    Use forward rendering (default)
 -deferred   Use deferred rendering
--b<length>  Mixing buffer length in milliseconds
 -r<freq>    Mixing frequency in Hz
 -nolimit    Disable frame limiter
 -noshadows  Disable rendering of shadows
@@ -127,9 +126,10 @@ The third-party libraries are used for the following functionality:
 - ENet: UDP networking
 - FreeType: font rendering
 - GLee: OpenGL extensions handling
+- GLFW: low-level windowing and input on Linux and Mac OS X, and on Windows when running in OpenGL mode
 - Open Asset Import Library: reading various 3D file formats
 - Open Dynamics %Engine: physics simulation implementation
-- SDL: low-level windowing, input, timing and audio functionality on Linux and Mac OS X, and on Windows when running in OpenGL mode
+- PortAudio: audio playback
 - StanHull: convex hull generation from triangle meshes, used for physics collision shapes
 - stb_image: image loading
 - stb_vorbis: Ogg Vorbis decoding
@@ -467,4 +467,4 @@ void HelloWorld::HandleUpdate(StringHash eventType, VariantMap& eventData)
 \endcode
 
 Now you should be ready to compile HelloWorld.cpp. The resulting executable will be placed in the Bin directory. It should be substantially smaller than Urho3D.exe, due to leaving out the scripting functionality.
-*/
+*/

+ 2 - 4
Docs/Reference.dox

@@ -634,15 +634,13 @@ Forward rendering also allows per-object control of which lights will influence
 
 \page Input %Input
 
-The Input subsystem provides keyboard and mouse input via both a polled interface and events. It is always instantiated, even in headless mode, but is active only once the application window has been created.
-
-Once active, the subsystem takes over the application mouse cursor. It will be hidden, so the UI should be used to render a software cursor if necessary. The cursor can be in either confined or non-confined mode. In confined mode (default) it is always forcibly centered to the window, so that mouse delta motion can be read "infinitely" in each direction. Non-confined mode is set by calling \ref Input::SetClipCursor "SetClipCursor(false)". In this case the cursor may freely travel out of the application window, which also means that infinite mouse delta motion can no longer be relied upon.
+The Input subsystem provides keyboard and mouse input via both a polled interface and events. It is always instantiated, even in headless mode, but is active only once the application window has been created. Once active, the subsystem takes over the application mouse cursor. It will be hidden, so the UI should be used to render a software cursor if necessary.
 
 The input events include:
 
 - E_MOUSEBUTTONUP: a mouse button has been released.
 - E_MOUSEBUTTONDOWN: a mouse button has been pressed.
-- E_MOUSEMOVE: the mouse has been moved. Both movement and cursor position will be sent, but the position is only useful in non-confined mode.
+- E_MOUSEMOVE: the mouse has been moved.
 - E_MOUSEWHEEL: the mouse wheel has been moved.
 - E_KEYUP: a key has been released.
 - E_KEYDOWN: a key has been pressed.

+ 2 - 1
Docs/Urho3D.dox

@@ -60,9 +60,10 @@ Urho3D uses the following third-party libraries:
 - ENet 1.3.1 (http://enet.bespin.org/)
 - FreeType 2.3.12 (http://www.freetype.org/)
 - GLee 5.4 (http://elf-stone.com/)
+- GLFW 2.7 (http://www.glfw.org/)
 - Open Asset Import Library 2.0.863 (http://assimp.sourceforge.net/)
 - Open Dynamics %Engine, svn rev 1806 (http://www.ode.org/)
-- SDL 1.3 (http://www.libsdl.org/)
+- PortAudio V19 (http://www.portaudio.com/)
 - StanHull (http://codesuppository.blogspot.com/2006/03/john-ratcliffs-code-suppository-blog.html)
 - stb_image 1.29 (http://nothings.org/)
 - stb_vorbis 0.99996 (http://nothings.org/)

+ 59 - 327
Engine/Audio/Audio.cpp

@@ -28,59 +28,28 @@
 #include "Graphics.h"
 #include "GraphicsEvents.h"
 #include "Log.h"
+#include "ProcessUtils.h"
 #include "Profiler.h"
 #include "Sound.h"
 #include "SoundSource3D.h"
 
-#ifndef USE_SDL
-#define DIRECTSOUND_VERSION 0x0800
-#include <Windows.h>
-#include <MMSystem.h>
-#include <dsound.h>
-#else
-#include <SDL.h>
-#endif
+#include "portaudio.h"
 
 #include "DebugNew.h"
 
-static const int AUDIO_FPS = 100;
+static unsigned numInstances = 0;
 
-#ifndef USE_SDL
-/// Audio implementation. Contains the DirectSound buffer
-class AudioImpl
-{
-    friend class Audio;
-    
-public:
-    /// Construct
-    AudioImpl() :
-        dsObject_(0),
-        dsBuffer_(0)
-    {
-    }
-    
-private:
-    /// DirectSound interface
-    IDirectSound* dsObject_;
-    /// DirectSound buffer
-    IDirectSoundBuffer* dsBuffer_;
-};
-#else
-static void SDLAudioCallback(void *userdata, Uint8 *stream, int len);
-#endif
+static int PortAudioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo*
+    timeInfo, PaStreamCallbackFlags statusFlags, void *userData);
 
 OBJECTTYPESTATIC(Audio);
 
 Audio::Audio(Context* context) :
     Object(context),
-    #ifndef USE_SDL
-    impl_(new AudioImpl()),
-    windowHandle_(0),
-    #endif
-    playing_(false),
-    bufferSamples_(0),
-    bufferSize_(0),
+    stream_(0),
+    clipBufferSize_(0),
     sampleSize_(0),
+    playing_(false),
     listenerPosition_(Vector3::ZERO),
     listenerRotation_(Quaternion::IDENTITY)
 {
@@ -89,163 +58,53 @@ Audio::Audio(Context* context) :
     for (unsigned i = 0; i < MAX_SOUND_TYPES; ++i)
         masterGain_[i] = 1.0f;
     
-    #ifndef USE_SDL
-    SubscribeToEvent(E_SCREENMODE, HANDLER(Audio, HandleScreenMode));
-    // Try to initialize right now, but skip if screen mode is not yet set
-    Initialize();
-    #else
-    SDL_InitSubSystem(SDL_INIT_AUDIO);
-    #endif
+    // Initialize PortAudio under static mutex in case this is the first instance
+    {
+        MutexLock lock(GetStaticMutex());
+        if (!numInstances)
+        {
+            if (Pa_Initialize() != paNoError)
+                LOGERROR("Could not initialize PortAudio");
+        }
+        ++numInstances;
+    }
 }
 
 Audio::~Audio()
 {
     Release();
     
-    #ifndef USE_SDL
-    if (impl_->dsObject_)
+    // Uninitialize PortAudio under static mutex in case this is the last instance
     {
-        impl_->dsObject_->Release();
-        impl_->dsObject_ = 0;
+        MutexLock lock(GetStaticMutex());
+        
+        --numInstances;
+        if (!numInstances)
+            Pa_Terminate();
     }
-    
-    delete impl_;
-    impl_ = 0;
-    #else
-    SDL_QuitSubSystem(SDL_INIT_AUDIO);
-    #endif
 }
 
-bool Audio::SetMode(int bufferLengthMSec, int mixRate, bool sixteenBit, bool stereo, bool interpolate)
+bool Audio::SetMode(int mixRate, bool sixteenBit, bool stereo, bool interpolate)
 {
     Release();
     
-    #ifndef USE_SDL
-    if (!impl_->dsObject_)
-    {
-        if (DirectSoundCreate(0, &impl_->dsObject_, 0) != DS_OK)
-        {
-            LOGERROR("Could not create DirectSound object");
-            return false;
-        }
-    }
-    
-    if (impl_->dsObject_->SetCooperativeLevel((HWND)windowHandle_, DSSCL_PRIORITY) != DS_OK)
-    {
-        LOGERROR("Could not set DirectSound cooperative level");
-        return false;
-    }
-    DSCAPS dsCaps;
-    dsCaps.dwSize = sizeof(dsCaps);
-    if (impl_->dsObject_->GetCaps(&dsCaps) != DS_OK)
+    if (Pa_OpenDefaultStream(&stream_, 0, stereo ? 2 : 1, sixteenBit ? paInt16 : paUInt8, mixRate, paFramesPerBufferUnspecified,
+        PortAudioCallback, this) != paNoError)
     {
-        LOGERROR("Could not get DirectSound capabilities");
-        return false;
-    }
-    
-    if (!(dsCaps.dwFlags & (DSCAPS_SECONDARY16BIT|DSCAPS_PRIMARY16BIT)))
-        sixteenBit = false;
-    if (!(dsCaps.dwFlags & (DSCAPS_SECONDARYSTEREO|DSCAPS_PRIMARYSTEREO)))
-        stereo = false;
-    
-    bufferLengthMSec = Max(bufferLengthMSec, 50);
-    mixRate = Clamp(mixRate, 11025, 48000);
-    
-    WAVEFORMATEX waveFormat;
-    waveFormat.wFormatTag = WAVE_FORMAT_PCM;
-    waveFormat.nSamplesPerSec = mixRate;
-    
-    if (sixteenBit)
-        waveFormat.wBitsPerSample = 16;
-    else
-        waveFormat.wBitsPerSample = 8;
-    
-    if (stereo)
-        waveFormat.nChannels = 2;
-    else
-        waveFormat.nChannels = 1;
-    
-    unsigned sampleSize = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
-    unsigned numSamples = (bufferLengthMSec * mixRate) / 1000;
-    
-    waveFormat.nAvgBytesPerSec = mixRate * sampleSize;
-    waveFormat.nBlockAlign = sampleSize;
-    waveFormat.cbSize = 0;
-    
-    DSBUFFERDESC bufferDesc;
-    memset(&bufferDesc, 0, sizeof(bufferDesc));
-    bufferDesc.dwSize = sizeof(bufferDesc);
-    bufferDesc.dwFlags = DSBCAPS_STICKYFOCUS;
-    bufferDesc.dwBufferBytes = numSamples * sampleSize;
-    bufferDesc.lpwfxFormat = &waveFormat;
-    
-    if (impl_->dsObject_->CreateSoundBuffer(&bufferDesc, &impl_->dsBuffer_, 0) != DS_OK)
-    {
-        LOGERROR("Could not create DirectSound buffer");
-        return false;
-    }
-    
-    clipBuffer_ = new int[numSamples * waveFormat.nChannels];
-    
-    bufferSamples_ = numSamples;
-    bufferSize_ = numSamples * sampleSize;
-    sampleSize_ = sampleSize;
-    mixRate_ = mixRate;
-    sixteenBit_ = sixteenBit;
-    stereo_ = stereo;
-    interpolate_ = interpolate;
-    #else
-    SDL_AudioSpec desired;
-    SDL_AudioSpec obtained;
-    
-    desired.freq = mixRate;
-    desired.format = AUDIO_U8;
-    if (sixteenBit)
-        desired.format = AUDIO_S16SYS;
-    desired.channels = 1;
-    if (stereo)
-        desired.channels = 2;
-    
-    // For SDL, do not actually use the buffer length, but calculate a suitable power-of-two size from the mixrate
-    if (desired.freq <= 11025)
-        desired.samples = 512;
-    else if (desired.freq <= 22050)
-        desired.samples = 1024;
-    else if (desired.freq <= 44100)
-        desired.samples = 2048;
-    else
-        desired.samples = 4096;
-    
-    desired.callback = SDLAudioCallback;
-    desired.userdata = this;
-    
-    SDL_PauseAudio(1);
-    playing_ = false;
-    if (SDL_OpenAudio(&desired, &obtained))
-    {
-        LOGERROR("Could not initialize audio output");
+        LOGERROR("Failed to open audio stream");
         return false;
     }
     
     sampleSize_ = 1;
-    if (obtained.channels == 2)
-    {
-        stereo_ = true;
+    if (stereo)
         sampleSize_ <<= 1;
-    }
-    if (obtained.format == AUDIO_S16SYS || obtained.format == AUDIO_S16LSB || obtained.format == AUDIO_S16MSB)
-    {
-        sixteenBit_ = true;
+    if (sixteenBit)
         sampleSize_ <<= 1;
-    }
-    
-    clipBuffer_ = new int[obtained.samples * obtained.channels];
     
-    bufferSamples_ = obtained.samples;
-    bufferSize_ = bufferSamples_ * sampleSize_;
-    mixRate_ = obtained.freq;
+    mixRate_ = mixRate;
+    stereo_ = stereo;
+    sixteenBit_ = sixteenBit;
     interpolate_ = interpolate;
-    #endif
     
     LOGINFO("Set audio mode " + String(mixRate_) + " Hz " + (stereo_ ? "stereo" : "mono") + " " +
         (sixteenBit_ ? "16-bit" : "8-bit") + " " + (interpolate_ ? "interpolated" : ""));
@@ -269,57 +128,28 @@ bool Audio::Play()
     if (playing_)
         return true;
     
-    #ifndef USE_SDL
-    if (!impl_->dsBuffer_)
+    if (!stream_)
     {
-        LOGERROR("No audio buffer, can not start playback");
+        LOGERROR("No audio mode set, can not start playback");
         return false;
     }
     
-    // Clear buffer before starting playback
-    DWORD bytes1, bytes2;
-    void *ptr1, *ptr2;
-    unsigned char value = sixteenBit_ ? 0 : 128;
-    if (impl_->dsBuffer_->Lock(0, bufferSize_, &ptr1, &bytes1, &ptr2, &bytes2, 0) == DS_OK)
+    if (Pa_StartStream(stream_) != paNoError)
     {
-        if (bytes1)
-            memset(ptr1, value, bytes1);
-        if (bytes2)
-            memset(ptr2, value, bytes2);
-        impl_->dsBuffer_->Unlock(ptr1, bytes1, ptr2, bytes2);
-    }
-    
-    // Create playback thread
-    if (!Start())
-    {
-        LOGERROR("Could not create audio thread");
+        LOGERROR("Failed to start playback");
         return false;
     }
     
-    // Adjust playback thread priority
-    SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
     playing_ = true;
-    #else
-    if (!clipBuffer_)
-    {
-        LOGERROR("No audio buffer, can not start playback");
-        return false;
-    }
-    SDL_PauseAudio(0);
-    playing_ = true;
-    #endif
-    
     return true;
 }
 
 void Audio::Stop()
 {
-    #ifndef USE_SDL
-    Thread::Stop();
-    #else
-    if (playing_)
-        SDL_PauseAudio(1);
-    #endif
+    if (!stream_ || !playing_)
+        return;
+    
+    Pa_StopStream(stream_);
     playing_ = false;
 }
 
@@ -356,15 +186,6 @@ void Audio::StopSound(Sound* soundClip)
     }
 }
 
-bool Audio::IsInitialized() const
-{
-    #ifndef USE_SDL
-    return impl_->dsBuffer_ != 0;
-    #else
-    return clipBuffer_.GetPtr() != 0;
-    #endif
-}
-
 float Audio::GetMasterGain(SoundType type) const
 {
     if (type >= MAX_SOUND_TYPES)
@@ -394,97 +215,30 @@ void Audio::RemoveSoundSource(SoundSource* channel)
     }
 }
 
-#ifndef USE_SDL
-void Audio::ThreadFunction()
-{
-    AudioImpl* impl = impl_;
-    
-    DWORD playCursor = 0;
-    DWORD writeCursor = 0;
-    
-    while (shouldRun_)
-    {
-        Timer audioUpdateTimer;
-        
-        // Restore buffer / restart playback if necessary
-        DWORD status;
-        impl->dsBuffer_->GetStatus(&status);
-        if (status == DSBSTATUS_BUFFERLOST)
-        {
-            impl->dsBuffer_->Restore();
-            impl->dsBuffer_->GetStatus(&status);
-        }
-        if (!(status & DSBSTATUS_PLAYING))
-        {
-            impl->dsBuffer_->Play(0, 0, DSBPLAY_LOOPING);
-            writeCursor = 0;
-        }
-        
-        // Get current buffer position
-        impl->dsBuffer_->GetCurrentPosition(&playCursor, 0);
-        playCursor %= bufferSize_;
-        playCursor &= -((int)sampleSize_);
-        
-        if (playCursor != writeCursor)
-        {
-            int writeBytes = playCursor - writeCursor;
-            if (writeBytes < 0)
-                writeBytes += bufferSize_;
-            
-            // Try to lock buffer
-            DWORD bytes1, bytes2;
-            void *ptr1, *ptr2;
-            if (impl->dsBuffer_->Lock(writeCursor, writeBytes, &ptr1, &bytes1, &ptr2, &bytes2, 0) == DS_OK)
-            {
-                // Mix sound to locked positions
-                {
-                    MutexLock Lock(audioMutex_);
-                    
-                    if (bytes1)
-                        MixOutput(ptr1, bytes1);
-                    if (bytes2)
-                        MixOutput(ptr2, bytes2);
-                }
-                
-                // Unlock buffer and update write cursor
-                impl->dsBuffer_->Unlock(ptr1, bytes1, ptr2, bytes2);
-                writeCursor += writeBytes;
-                if (writeCursor >= bufferSize_)
-                    writeCursor -= bufferSize_;
-            }
-        }
-        
-        // Sleep the remaining time of the audio update period
-        int audioSleepTime = Max(1000 / AUDIO_FPS - (int)audioUpdateTimer.GetMSec(false), 0);
-        Sleep(audioSleepTime);
-    }
-    
-    impl->dsBuffer_->Stop();
-}
-#else
-void SDLAudioCallback(void *userdata, Uint8* stream, int len)
+int PortAudioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo*
+    timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
 {
-    Audio* audio = static_cast<Audio*>(userdata);
+    Audio* audio = static_cast<Audio*>(userData);
     
     {
         MutexLock Lock(audio->GetMutex());
-        audio->MixOutput(stream, len);
+        audio->MixOutput(outputBuffer, framesPerBuffer);
     }
+    
+    return 0;
 }
-#endif
 
-void Audio::MixOutput(void *dest, unsigned bytes)
+void Audio::MixOutput(void *dest, unsigned mixSamples)
 {
-    unsigned mixSamples = bytes;
-    unsigned clipSamples = bytes;
-    
+    unsigned clipSamples = mixSamples;
     if (stereo_)
-        mixSamples >>= 1;
+        clipSamples <<= 1;
     
-    if (sixteenBit_)
+    // Make sure the clipbuffer is large enough, then clear it
+    if (clipBufferSize_ < clipSamples)
     {
-        clipSamples >>= 1;
-        mixSamples >>= 1;
+        clipBuffer_ = new int[clipSamples];
+        clipBufferSize_ = clipSamples;
     }
     
     // Clear clip buffer
@@ -531,40 +285,18 @@ void Audio::HandleRenderUpdate(StringHash eventType, VariantMap& eventData)
     Update(eventData[P_TIMESTEP].GetFloat());
 }
 
-#ifndef USE_SDL
-void Audio::HandleScreenMode(StringHash eventType, VariantMap& eventData)
-{
-    if (!windowHandle_)
-        Initialize();
-}
-
-void Audio::Initialize()
-{
-    Graphics* graphics = GetSubsystem<Graphics>();
-    if (!graphics || !graphics->IsInitialized())
-        return;
-    
-    windowHandle_ = graphics->GetWindowHandle();
-}
-#endif
-
 void Audio::Release()
 {
     Stop();
     
-    #ifndef USE_SDL
-    if (impl_->dsBuffer_)
+    if (stream_)
     {
-        impl_->dsBuffer_->Release();
-        impl_->dsBuffer_ = 0;
-    }
-    #else
-    if (clipBuffer_)
-    {
-        SDL_CloseAudio();
+        Pa_CloseStream(stream_);
+        
+        stream_ = 0;
         clipBuffer_.Reset();
+        clipBufferSize_ = 0;
     }
-    #endif
 }
 
 void RegisterAudioLibrary(Context* context)

+ 9 - 33
Engine/Audio/Audio.h

@@ -34,12 +34,8 @@ class AudioImpl;
 class Sound;
 class SoundSource;
 
-/// Audio subsystem. Uses either DirectSound or SDL for sound output
-#ifndef USE_SDL
-class Audio : public Object, public Thread
-#else
+/// Audio subsystem. Uses PortAudio for the actual sound output
 class Audio : public Object
-#endif
 {
     OBJECT(Audio);
     
@@ -50,7 +46,7 @@ public:
     virtual ~Audio();
     
     /// Initialize sound output with specified buffer length and output mode
-    bool SetMode(int bufferLengthMSec, int mixRate, bool sixteenBit, bool stereo, bool interpolate = true);
+    bool SetMode(int mixRate, bool sixteenBit, bool stereo, bool interpolate = true);
     /// Run update on sound sources. Not required for continued playback, but frees unused sound sources & sounds and updates 3D positions.
     void Update(float timeStep);
     /// Restart sound output
@@ -68,10 +64,6 @@ public:
     /// Stop any sound source playing a certain sound clip
     void StopSound(Sound* sound);
     
-    /// Return sound buffer size in samples
-    unsigned GetBufferSamples() const { return bufferSamples_; }
-    /// Return sound buffer size in bytes
-    unsigned GetBufferSize() const { return bufferSize_; }
     /// Return byte size of one sample
     unsigned GetSampleSize() const { return sampleSize_; }
     /// Return mixing rate
@@ -84,8 +76,8 @@ public:
     bool IsInterpolated() const { return interpolate_; }
     /// Return whether audio is being output
     bool IsPlaying() const { return playing_; }
-    /// Return whether an audio buffer has been reserved
-    bool IsInitialized() const;
+    /// Return whether an audio stream has been reserved
+    bool IsInitialized() const { return stream_ != 0; }
     /// Return master gain for a specific sound source type
     float GetMasterGain(SoundType type) const;
     /// Return listener position
@@ -104,39 +96,23 @@ public:
     /// Return sound type specific gain multiplied by master gain
     float GetSoundSourceMasterGain(SoundType type) const { return masterGain_[SOUND_MASTER] * masterGain_[type]; }
     
-    #ifndef USE_SDL
-    /// Mixing thread function
-    virtual void ThreadFunction();
-    #endif
     /// Mix sound sources into the buffer
-    void MixOutput(void* dest, unsigned bytes);
+    void MixOutput(void *dest, unsigned mixSamples);
     
 private:
-    #ifndef USE_SDL
-    /// Handle screen mode event
-    void HandleScreenMode(StringHash eventType, VariantMap& eventData);
-    /// Initialize when screen mode initially set
-    void Initialize();
-    #endif
     /// Handle render update event
     void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
     /// Stop sound output and release the sound buffer
     void Release();
     
-    #ifndef USE_SDL
-    /// Implementation
-    AudioImpl* impl_;
-    /// Window handle
-    unsigned windowHandle_;
-    #endif
+    /// PortAudio stream
+    void* stream_;
     /// Clipping buffer for mixing
     SharedArrayPtr<int> clipBuffer_;
     /// Audio thread mutex
     Mutex audioMutex_;
-    /// Sound buffer size in samples
-    unsigned bufferSamples_;
-    /// Sound buffer size in bytes
-    unsigned bufferSize_;
+    /// Clipping buffer size in samples
+    unsigned clipBufferSize_;
     /// Sample size
     unsigned sampleSize_;
     /// Mixing rate

+ 2 - 7
Engine/Audio/CMakeLists.txt

@@ -9,17 +9,12 @@ set (SOURCE_FILES ${CPP_FILES} ${H_FILES})
 # Include directories
 include_directories (
     ../Container ../Core ../Graphics ../IO ../Math ../Resource ../Scene ../../ThirdParty/STB
+    ../../ThirdParty/PortAudio/include
 )
 
 # Define target & libraries to link
 add_library (${TARGET_NAME} STATIC ${SOURCE_FILES})
-target_link_libraries (${TARGET_NAME} Container Core Graphics IO Math Resource Scene STB)
-
-if (USE_SDL)
-    target_link_libraries (${TARGET_NAME} SDL)
-else ()
-    target_link_libraries (${TARGET_NAME} dsound.lib)
-endif()
+target_link_libraries (${TARGET_NAME} Container Core Graphics IO Math PortAudio Resource Scene STB)
 
 enable_pch ()
 finalize_lib ()

+ 6 - 7
Engine/Core/CMakeLists.txt

@@ -15,14 +15,13 @@ include_directories (
 add_library (${TARGET_NAME} STATIC ${SOURCE_FILES})
 target_link_libraries (${TARGET_NAME} Container Math)
 
-if (USE_SDL)
-    target_link_libraries (${TARGET_NAME} SDL)
-else ()
+if (WIN32)
     target_link_libraries (${TARGET_NAME} winmm.lib)
-endif ()
-
-if (ENABLE_MINIDUMPS)
-    target_link_libraries (${TARGET_NAME} dbghelp.lib)
+    if (ENABLE_MINIDUMPS)
+        target_link_libraries (${TARGET_NAME} dbghelp.lib)
+    endif ()
+else ()
+    target_link_libraries (${TARGET_NAME} pthread)
 endif ()
 
 enable_pch ()

+ 10 - 7
Engine/Core/Mutex.cpp

@@ -24,15 +24,15 @@
 #include "Precompiled.h"
 #include "Mutex.h"
 
-#ifndef USE_SDL
+#ifdef _WIN32
 #include <Windows.h>
 #else
-#include <SDL.h>
+#include <pthread.h>
 #endif
 
 #include "DebugNew.h"
 
-#ifndef USE_SDL
+#ifdef _WIN32
 Mutex::Mutex() :
     criticalSection_(new CRITICAL_SECTION)
 {
@@ -58,24 +58,27 @@ void Mutex::Release()
 }
 #else
 Mutex::Mutex() :
-    criticalSection_(SDL_CreateMutex())
+    criticalSection_(new pthread_mutex_t)
 {
+    pthread_mutex_init((pthread_mutex_t*)criticalSection_);
 }
 
 Mutex::~Mutex()
 {
-    SDL_DestroyMutex((SDL_mutex*)criticalSection_);
+    pthread_mutex_t* mutex = (pthread_mutex_t*)criticalSection_;
+    pthread_mutex_destroy(mutex);
+    delete mutex;
     criticalSection_ = 0;
 }
 
 void Mutex::Acquire()
 {
-    SDL_mutexP((SDL_mutex*)criticalSection_);
+    pthread_mutex_lock((pthread_mutex_t*)criticalSection_);
 }
 
 void Mutex::Release()
 {
-    SDL_mutexV((SDL_mutex*)criticalSection_);
+    pthread_mutex_acquire((pthread_mutex_t*)criticalSection_);
 }
 #endif
 

+ 2 - 6
Engine/Core/ProcessUtils.cpp

@@ -35,10 +35,6 @@
 #include <unistd.h>
 #endif
 
-#ifdef USE_SDL
-#include <SDL.h>
-#endif
-
 #include "DebugNew.h"
 
 static bool consoleOpened = false;
@@ -216,11 +212,11 @@ String GetConsoleInput()
 
 unsigned GetNumCPUCores()
 {
-    #ifndef USE_SDL
+    #ifdef _WIN32
     SYSTEM_INFO info;
     GetSystemInfo(&info);
     return info.dwNumberOfProcessors;
     #else
-    return SDL_GetCPUCount();
+    return sysconf(_SC_NPROCESSORS_ONLN);
     #endif
 }

+ 21 - 11
Engine/Core/Thread.cpp

@@ -24,15 +24,15 @@
 #include "Precompiled.h"
 #include "Thread.h"
 
-#ifndef USE_SDL
+#ifdef _WIN32
 #include <Windows.h>
 #else
-#include <SDL.h>
+#include <pthread.h>
 #endif
 
 #include "DebugNew.h"
 
-#ifndef USE_SDL
+#ifdef _WIN32
 DWORD WINAPI ThreadFunctionStatic(void* data)
 {
     Thread* thread = static_cast<Thread*>(data);
@@ -40,10 +40,11 @@ DWORD WINAPI ThreadFunctionStatic(void* data)
     return 0;
 }
 #else
-int ThreadFunctionStatic(void* data)
+void* ThreadFunctionStatic(void* data)
 {
     Thread* thread = static_cast<Thread*>(data);
     thread->ThreadFunction();
+    pthread_exit((void*)0);
     return 0;
 }
 #endif
@@ -66,10 +67,14 @@ bool Thread::Start()
         return false;
     
     shouldRun_ = true;
-    #ifndef USE_SDL
+    #ifdef _WIN32
     handle_ = CreateThread(0, 0, ThreadFunctionStatic, this, 0, 0);
     #else
-    handle_ = SDL_CreateThread(ThreadFunctionStatic, this);
+    handle_ = new pthread_t;
+    pthread_attr_t type;
+    pthread_attr_init(&type);
+    pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
+    pthread_create((pthread_t*)handle_, &type, ThreadFunctionStatic, this);
     #endif
     return handle_ != 0;
 }
@@ -77,21 +82,26 @@ bool Thread::Start()
 void Thread::Stop()
 {
     shouldRun_ = false;
-    #ifndef USE_SDL
+    #ifdef _WIN32
     WaitForSingleObject((HANDLE)handle_, INFINITE);
     CloseHandle((HANDLE)handle_);
     #else
-    if (handle_)
-        SDL_WaitThread((SDL_Thread*)handle_, 0);
+    pthread_t* thread = (pthread_t*)handle_;
+    if (thread)
+    {
+        pthread_join(thread, 0);
+        pthread_destroy(thread);
+    }
+    delete thread;
     #endif
     handle_ = 0;
 }
 
 void Thread::SetPriority(int priority)
 {
-    #ifndef USE_SDL
+    #ifdef _WIN32
     if (handle_)
         SetThreadPriority((HANDLE)handle_, priority);
     #endif
-    /// \todo Implement on SDL
+    /// \todo Implement on pthreads
 }

+ 31 - 18
Engine/Core/Timer.cpp

@@ -25,11 +25,12 @@
 #include "CoreEvents.h"
 #include "Timer.h"
 
-#ifndef USE_SDL
+#ifdef _WIN32
 #include <Windows.h>
 #include <MMSystem.h>
 #else
-#include <SDL.h>
+#include <sys/time.h>
+#include <unistd.h>
 #endif
 
 #include "DebugNew.h"
@@ -47,7 +48,7 @@ Time::Time(Context* context) :
     totalMSec_(0),
     timerPeriod_(0)
 {
-    #ifndef USE_SDL
+    #ifdef _WIN32
     LARGE_INTEGER frequency;
     if (QueryPerformanceFrequency(&frequency))
     {
@@ -55,8 +56,7 @@ Time::Time(Context* context) :
         HiresTimer::supported = true;
     }
     #else
-    SDL_InitSubSystem(SDL_INIT_TIMER);
-    HiresTimer::frequency = SDL_GetPerformanceFrequency();
+    HiresTimer::frequency = 1000000;
     HiresTimer::supported = true;
     #endif
 }
@@ -64,9 +64,6 @@ Time::Time(Context* context) :
 Time::~Time()
 {
     SetTimerPeriod(0);
-    #ifdef USE_SDL
-    SDL_QuitSubSystem(SDL_INIT_TIMER);
-    #endif
 }
 
 void Time::BeginFrame(unsigned mSec)
@@ -117,7 +114,7 @@ void Time::EndFrame()
 
 void Time::SetTimerPeriod(unsigned mSec)
 {
-    #ifndef USE_SDL
+    #ifdef _WIN32
     if (timerPeriod_ > 0)
         timeEndPeriod(timerPeriod_);
     
@@ -128,6 +125,15 @@ void Time::SetTimerPeriod(unsigned mSec)
     #endif
 }
 
+void Time::Sleep(unsigned mSec)
+{
+    #ifdef _WIN32
+    ::Sleep(mSec);
+    #else
+    usleep(mSec * 1000);
+    #endif
+}
+
 Timer::Timer()
 {
     Reset();
@@ -135,10 +141,12 @@ Timer::Timer()
 
 unsigned Timer::GetMSec(bool reset)
 {
-    #ifndef USE_SDL
+    #ifdef _WIN32
     unsigned currentTime = timeGetTime();
     #else
-    unsigned currentTime = SDL_GetTicks();
+    struct timeval time;
+    gettimeofday(&time, NULL);
+    unsigned currentTime = time.tv_sec * 1000 + time.tv_usec / 1000;
     #endif
     
     unsigned elapsedTime = currentTime - startTime_;
@@ -150,10 +158,12 @@ unsigned Timer::GetMSec(bool reset)
 
 void Timer::Reset()
 {
-    #ifndef USE_SDL
+    #ifdef _WIN32
     startTime_ = timeGetTime();
     #else
-    startTime_ = SDL_GetTicks();
+    struct timeval time;
+    gettimeofday(&time, NULL);
+    startTime_ = time.tv_sec * 1000 + time.tv_usec / 1000;
     #endif
 }
 
@@ -166,7 +176,7 @@ long long HiresTimer::GetUSec(bool reset)
 {
     long long currentTime;
     
-    #ifndef USE_SDL
+    #ifdef _WIN32
     if (supported)
     {
         LARGE_INTEGER counter;
@@ -176,7 +186,9 @@ long long HiresTimer::GetUSec(bool reset)
     else
         currentTime = timeGetTime();
     #else
-    currentTime = SDL_GetPerformanceCounter();
+    struct timeval time;
+    gettimeofday(&time, NULL);
+    currentTime = time.tv_sec * 1000000LL + time.tv_usec;
     #endif
     
     long long elapsedTime = currentTime - startTime_;
@@ -193,7 +205,7 @@ long long HiresTimer::GetUSec(bool reset)
 
 void HiresTimer::Reset()
 {
-    #ifndef USE_SDL
+    #ifdef _WIN32
     if (supported)
     {
         LARGE_INTEGER counter;
@@ -203,7 +215,8 @@ void HiresTimer::Reset()
     else
         startTime_ = timeGetTime();
     #else
-    startTime_ = SDL_GetPerformanceCounter();
+    struct timeval time;
+    gettimeofday(&time, NULL);
+    startTime_ = time.tv_sec * 1000000LL + time.tv_usec;
     #endif
 }
-

+ 3 - 0
Engine/Core/Timer.h

@@ -54,6 +54,9 @@ public:
     /// Return current low-resolution timer period in milliseconds
     unsigned GetTimerPeriod() const { return timerPeriod_; }
     
+    /// Sleep for a number of milliseconds
+    static void Sleep(unsigned mSec);
+    
 private:
     /// Frame number
     unsigned frameNumber_;

+ 1 - 3
Engine/Engine/AudioAPI.cpp

@@ -69,7 +69,7 @@ static Audio* GetAudio()
 void RegisterAudio(asIScriptEngine* engine)
 {
     RegisterObject<Audio>(engine, "Audio");
-    engine->RegisterObjectMethod("Audio", "void SetMode(int, int, bool, bool, bool)", asMETHOD(Audio, SetMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Audio", "void SetMode(int, bool, bool, bool)", asMETHOD(Audio, SetMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Audio", "bool Play()", asMETHOD(Audio, Play), asCALL_THISCALL);
     engine->RegisterObjectMethod("Audio", "void Stop()", asMETHOD(Audio, Stop), asCALL_THISCALL);
     engine->RegisterObjectMethod("Audio", "void SetListenerTransform(const Vector3&in, const Quaternion&in)", asMETHOD(Audio, SetListenerTransform), asCALL_THISCALL);
@@ -79,8 +79,6 @@ void RegisterAudio(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Audio", "const Vector3& get_listenerPosition() const", asMETHOD(Audio, GetListenerPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("Audio", "void set_listenerRotation(const Quaternion&in)", asMETHOD(Audio, SetListenerRotation), asCALL_THISCALL);
     engine->RegisterObjectMethod("Audio", "const Quaternion& get_listenerRotation() const", asMETHOD(Audio, GetListenerRotation), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Audio", "uint get_bufferSamples() const", asMETHOD(Audio, GetBufferSamples), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Audio", "uint get_bufferSize() const", asMETHOD(Audio, GetBufferSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("Audio", "uint get_sampleSize() const", asMETHOD(Audio, GetSampleSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("Audio", "int get_mixRate() const", asMETHOD(Audio, GetMixRate), asCALL_THISCALL);
     engine->RegisterObjectMethod("Audio", "bool get_sixteenBit() const", asMETHOD(Audio, IsSixteenBit), asCALL_THISCALL);

+ 6 - 24
Engine/Engine/Engine.cpp

@@ -46,17 +46,12 @@
 #include "StringUtils.h"
 #include "UI.h"
 
-#ifndef USE_SDL
-#include <Windows.h>
-#endif
-
 #include "DebugNew.h"
 
 OBJECTTYPESTATIC(Engine);
 
 Engine::Engine(Context* context) :
     Object(context),
-    frameTimer_(0),
     minFps_(10),
     maxFps_(200),
     maxInactiveFps_(50),
@@ -69,8 +64,6 @@ Engine::Engine(Context* context) :
 
 Engine::~Engine()
 {
-    delete frameTimer_;
-    frameTimer_ = 0;
 }
 
 bool Engine::Initialize(const String& windowTitle, const String& logName, const Vector<String>& arguments)
@@ -87,7 +80,6 @@ bool Engine::Initialize(const String& windowTitle, const String& logName, const
     bool forceSM2 = false;
     bool shadows = true;
     int mixRate = 44100;
-    int buffer = 100;
     bool sound = true;
     bool stereo = true;
     bool sixteenBit = true;
@@ -136,11 +128,6 @@ bool Engine::Initialize(const String& windowTitle, const String& logName, const
                         multiSample = ToInt(argument.Substring(1));
                     break;
                     
-                case 'b':
-                    if (arguments[i].Length() > 1)
-                        buffer = ToInt(argument.Substring(1));
-                    break;
-                    
                 case 'r':
                     if (arguments[i].Length() > 1)
                         mixRate = ToInt(argument.Substring(1));
@@ -166,9 +153,6 @@ bool Engine::Initialize(const String& windowTitle, const String& logName, const
     RegisterObjects();
     RegisterSubsystems();
     
-    // Create the frame timer
-    frameTimer_ = new Timer();
-    
     // Start logging
     Log* log = GetSubsystem<Log>();
     log->Open(logName);
@@ -205,9 +189,11 @@ bool Engine::Initialize(const String& windowTitle, const String& logName, const
         if (!shadows)
             GetSubsystem<Renderer>()->SetDrawShadows(false);
         if (sound)
-            GetSubsystem<Audio>()->SetMode(buffer, mixRate, sixteenBit, stereo, interpolate);
+            GetSubsystem<Audio>()->SetMode(mixRate, sixteenBit, stereo, interpolate);
     }
     
+    frameTimer_.Reset();
+    
     initialized_ = true;
     return true;
 }
@@ -379,20 +365,16 @@ void Engine::GetNextTimeStep()
         int targetMax = 1000 / maxFps;
         for (;;)
         {
-            timeAcc += frameTimer_->GetMSec(true);
+            timeAcc += frameTimer_.GetMSec(true);
             if (timeAcc >= targetMax)
                 break;
             
             unsigned wait = (targetMax - timeAcc);
-            #ifndef USE_SDL
-            Sleep(wait / 2);
-            #else
-            SDL_Delay(wait / 2);
-            #endif
+            Time::Sleep(wait / 2);
         }
     }
     else
-        timeAcc = frameTimer_->GetMSec(true);
+        timeAcc = frameTimer_.GetMSec(true);
     
     // If FPS lower than minimum, clamp elapsed time
     if (minFps_)

+ 1 - 1
Engine/Engine/Engine.h

@@ -89,7 +89,7 @@ private:
     void RegisterSubsystems();
     
     /// Frame update timer
-    Timer* frameTimer_;
+    Timer frameTimer_;
     /// Next frame timestep in milliseconds
     unsigned timeStep_;
     /// Minimum frames per second

+ 0 - 18
Engine/Engine/InputAPI.cpp

@@ -51,7 +51,6 @@ static void RegisterInputConstants(asIScriptEngine* engine)
     engine->RegisterGlobalProperty("const int KEY_UP", (void*)&KEY_UP);
     engine->RegisterGlobalProperty("const int KEY_RIGHT", (void*)&KEY_RIGHT);
     engine->RegisterGlobalProperty("const int KEY_DOWN", (void*)&KEY_DOWN);
-    engine->RegisterGlobalProperty("const int KEY_PRINTSCREEN", (void*)&KEY_PRINTSCREEN);
     engine->RegisterGlobalProperty("const int KEY_INSERT", (void*)&KEY_INSERT);
     engine->RegisterGlobalProperty("const int KEY_DELETE", (void*)&KEY_DELETE);
     engine->RegisterGlobalProperty("const int KEY_LWIN", (void*)&KEY_LWIN);
@@ -104,18 +103,6 @@ static void RegisterInputConstants(asIScriptEngine* engine)
     engine->RegisterGlobalProperty("const int KEY_RCTRL", (void*)&KEY_RCTRL);
     engine->RegisterGlobalProperty("const int KEY_LALT", (void*)&KEY_LALT);
     engine->RegisterGlobalProperty("const int KEY_RALT", (void*)&KEY_RALT);
-    engine->RegisterGlobalProperty("const int KEY_OEM_1", (void*)&KEY_OEM_1);
-    engine->RegisterGlobalProperty("const int KEY_OEM_PLUS", (void*)&KEY_OEM_PLUS);
-    engine->RegisterGlobalProperty("const int KEY_OEM_COMMA", (void*)&KEY_OEM_COMMA);
-    engine->RegisterGlobalProperty("const int KEY_OEM_MINUS", (void*)&KEY_OEM_MINUS);
-    engine->RegisterGlobalProperty("const int KEY_OEM_PERIOD", (void*)&KEY_OEM_PERIOD);
-    engine->RegisterGlobalProperty("const int KEY_OEM_2", (void*)&KEY_OEM_2);
-    engine->RegisterGlobalProperty("const int KEY_OEM_3", (void*)&KEY_OEM_3);
-    engine->RegisterGlobalProperty("const int KEY_OEM_4", (void*)&KEY_OEM_4);
-    engine->RegisterGlobalProperty("const int KEY_OEM_5", (void*)&KEY_OEM_5);
-    engine->RegisterGlobalProperty("const int KEY_OEM_6", (void*)&KEY_OEM_6);
-    engine->RegisterGlobalProperty("const int KEY_OEM_7", (void*)&KEY_OEM_7);
-    engine->RegisterGlobalProperty("const int KEY_OEM_8", (void*)&KEY_OEM_8);
 }
 
 static Input* GetInput()
@@ -126,14 +113,9 @@ static Input* GetInput()
 static void RegisterInput(asIScriptEngine* engine)
 {
     RegisterObject<Input>(engine, "Input");
-    engine->RegisterObjectMethod("Input", "void SetMousePosition(int, int)", asMETHODPR(Input, SetMousePosition, (int, int), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "void SuppressNextChar()", asMETHOD(Input, SuppressNextChar), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Input", "void set_clipCursor(bool)", asMETHOD(Input, SetClipCursor), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Input", "bool get_clipCursor() const", asMETHOD(Input, GetClipCursor), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "void set_toggleFullscreen(bool)", asMETHOD(Input, SetToggleFullscreen), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_toggleFullscreen() const", asMETHOD(Input, GetToggleFullscreen), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Input", "void set_mousePosition(const IntVector2&in)", asMETHODPR(Input, SetMousePosition, (const IntVector2&), void), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Input", "IntVector2 get_mousePosition() const", asMETHOD(Input, GetMousePosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_keyDown(int) const", asMETHOD(Input, GetKeyDown), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_keyPress(int) const", asMETHOD(Input, GetKeyPress), asCALL_THISCALL);
     engine->RegisterObjectMethod("Input", "bool get_mouseButtonDown(int) const", asMETHOD(Input, GetMouseButtonDown), asCALL_THISCALL);

+ 5 - 2
Engine/Graphics/CMakeLists.txt

@@ -8,7 +8,6 @@ file (GLOB H_FILES *.h)
 if (USE_OPENGL)
     file (GLOB SYS_CPP_FILES OpenGL/*.cpp)
     file (GLOB SYS_H_FILES OpenGL/*.h)
-    include_directories (../../ThirdParty/GLee)
 else ()
     file (GLOB SYS_CPP_FILES Direct3D9/*.cpp)
     file (GLOB SYS_H_FILES Direct3D9/*.h)
@@ -21,12 +20,16 @@ include_directories (
     . ../Container ../Core ../IO ../Math ../Resource ../Scene
 )
 
+if (USE_OPENGL)
+    include_directories (../../ThirdParty/GLee)
+endif ()
+
 # Define target & libraries to link
 add_library (${TARGET_NAME} STATIC ${SOURCE_FILES})
 target_link_libraries (${TARGET_NAME} Container Core Math Resource Scene)
 	
 if (USE_OPENGL)
-    target_link_libraries (${TARGET_NAME} GLee)
+    target_link_libraries (${TARGET_NAME} GLee GLFW)
 else ()
     target_link_libraries (${TARGET_NAME} d3d9.lib)
 endif ()

+ 57 - 77
Engine/Graphics/OpenGL/OGLGraphics.cpp

@@ -151,6 +151,8 @@ Graphics::Graphics(Context* context_) :
 {
     ResetCachedState();
     InitializeShaderParameters();
+    
+    glfwInit();
 }
 
 Graphics::~Graphics()
@@ -159,11 +161,13 @@ Graphics::~Graphics()
     
     delete impl_;
     impl_ = 0;
+    
+    glfwTerminate();
 }
 
 void Graphics::SetWindowTitle(const String& windowTitle)
 {
-    SDL_WM_SetCaption(windowTitle.CString(), 0);
+    glfwSetWindowTitle(windowTitle.CString());
 }
 
 bool Graphics::SetMode(RenderMode mode, int width, int height, bool fullscreen, bool vsync, int multiSample)
@@ -180,7 +184,7 @@ bool Graphics::SetMode(RenderMode mode, int width, int height, bool fullscreen,
     if (initialized_ && mode == mode_ && width == width_ && height == height_ && fullscreen == fullscreen_ &&
         multiSample == multiSample_ && vsync != vsync_)
     {
-        SDL_GL_SetSwapInterval(vsync ? 1 : 0);
+        glfwSwapInterval(vsync ? 1 : 0);
         vsync_ = vsync;
         return true;
     }
@@ -195,61 +199,28 @@ bool Graphics::SetMode(RenderMode mode, int width, int height, bool fullscreen,
         }
         else
         {
-            width = 0;
-            height = 0;
-        }
-    }
-    
-    /// \todo Reimplement using SDL 1.3 functionality, which allows multiple windows
-    if (!initialized_)
-    {
-        if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
-        {
-            LOGERROR("SDL video subsystem initialization failed");
-            return false;
+            GLFWvidmode mode;
+            glfwGetDesktopMode(&mode);
+            width = mode.Width;
+            height = mode.Height;
         }
     }
     
-    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
-    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
-    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
-    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
-    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
-    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
-    
     if (multiSample > 1 && mode == RENDER_FORWARD)
-    {
-        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
-        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multiSample);
-    }
+        glfwOpenWindowHint(GLFW_FSAA_SAMPLES, multiSample);
     else
-    {
-        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
-        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
-    }
+       glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 0);
+    
+    // Disable resize
+    glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, GL_TRUE);
     
-    // Lose the existing OpenGL context now
+    // Close the existing window
     Release();
     
-    unsigned sdlFlags = SDL_OPENGL;
-    if (fullscreen)
-        sdlFlags |= SDL_FULLSCREEN;
-    SDL_Surface* surface = SDL_SetVideoMode(width, height, 0, sdlFlags);
-    if (!surface)
+    if (!glfwOpenWindow(width, height, 8, 8, 8, 0, 24, 8, fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOW))
     {
-        // If fullscreen mode fails, retry windowed
-        if (fullscreen)
-        {
-            fullscreen = false;
-            unsigned sdlFlags = SDL_OPENGL;
-            surface = SDL_SetVideoMode(width, height, 0, sdlFlags);
-        }
-        if (!surface)
-        {
-            LOGERROR("Could not set screen mode");
-            return false;
-        }
+        LOGERROR("Could not open window");
+        return false;
     }
     
     // Mimic Direct3D way of setting FPU into round-to-nearest, single precision mode
@@ -264,23 +235,21 @@ bool Graphics::SetMode(RenderMode mode, int width, int height, bool fullscreen,
     #endif
     
     // If OpenGL extensions not yet initialized, initialize now
-    // Query needs to happen under lock as the function pointers are static
-    {
-        MutexLock lock(GetStaticMutex());
-        
-        if (!GLeeInitialized())
-            GLeeInit();
-    }
+    if (!GLeeInitialized())
+        GLeeInit();
     
     if (!_GLEE_VERSION_2_0)
     {
         LOGERROR("OpenGL 2.0 is required");
-        SDL_Quit();
+        glfwCloseWindow();
         return false;
     }
     
+    // Disable auto polling of window events
+    glfwDisable(GLFW_AUTO_POLL_EVENTS);
+    
     // Set vsync
-    SDL_GL_SetSwapInterval(vsync ? 1 : 0);
+    glfwSwapInterval(vsync ? 1 : 0);
     
     // Query for system backbuffer depth
     glGetIntegerv(GL_DEPTH_BITS, &impl_->windowDepthBits_);
@@ -303,8 +272,7 @@ bool Graphics::SetMode(RenderMode mode, int width, int height, bool fullscreen,
     SetCullMode(CULL_CCW);
     SetDepthTest(CMP_LESSEQUAL);
     
-    width_ = surface->w;
-    height_ = surface->h;
+    glfwGetWindowSize(&width_, &height_);
     fullscreen_ = fullscreen;
     vsync_ = vsync;
     mode_ = mode;
@@ -317,7 +285,7 @@ bool Graphics::SetMode(RenderMode mode, int width, int height, bool fullscreen,
     
     // Clear the window to black now, because GPU object restore may take time
     Clear(CLEAR_COLOR);
-    SDL_GL_SwapBuffers();
+    glfwSwapBuffers();
     
     // Create deferred rendering buffers as necessary
     CreateRenderTargets();
@@ -368,9 +336,6 @@ void Graphics::Close()
         gpuObjects_.Clear();
         
         Release();
-        
-        SDL_QuitSubSystem(SDL_INIT_VIDEO);
-        initialized_ = false;
     }
 }
 
@@ -398,12 +363,8 @@ bool Graphics::BeginFrame()
         return false;
     
     // If we should be fullscreen, but are not currently active, do not render
-    if (fullscreen_)
-    {
-        unsigned state = SDL_GetAppState();
-        if (!(state & SDL_APPACTIVE))
-            return false;
-    }
+    if (fullscreen_ && (!glfwGetWindowParam(GLFW_ACTIVE) || glfwGetWindowParam(GLFW_ICONIFIED)))
+        return false;
     
     // Set default rendertarget and depth buffer
     ResetRenderTargets();
@@ -434,7 +395,7 @@ void Graphics::EndFrame()
     
     SendEvent(E_ENDRENDER);
     
-    SDL_GL_SwapBuffers();
+    glfwSwapBuffers();
 }
 
 void Graphics::Clear(unsigned flags, const Color& color, float depth, unsigned stencil)
@@ -1859,14 +1820,30 @@ unsigned char* Graphics::GetImmediateDataPtr() const
 
 PODVector<IntVector2> Graphics::GetResolutions() const
 {
-    PODVector<IntVector2> ret;
+    static const unsigned MAX_MODES = 256;
+    GLFWvidmode modes[MAX_MODES];
     
-    SDL_Rect** rects = SDL_ListModes(0, SDL_OPENGL | SDL_FULLSCREEN);
+    unsigned count = glfwGetVideoModes(modes, MAX_MODES);
+    PODVector<IntVector2> ret;
     
-    if (rects && rects != (SDL_Rect**)-1)
-    { 
-        for (unsigned i = 0; rects[i]; ++i)
-            ret.Push(IntVector2(rects[i]->w, rects[i]->h));
+    for (unsigned i = 0; i < count; ++i)
+    {
+        int width = modes[i].Width;
+        int height  = modes[i].Height;
+        
+        // Store mode if unique
+        bool unique = true;
+        for (unsigned j = 0; j < ret.Size(); ++i)
+        {
+            if (ret[j].x_ == width && ret[j].y_ == height)
+            {
+                unique = false;
+                break;
+            }
+        }
+        
+        if (unique)
+            ret.Push(IntVector2(width, height));
     }
     
     return ret;
@@ -1877,7 +1854,7 @@ PODVector<int> Graphics::GetMultiSampleLevels() const
     PODVector<int> ret;
     // No multisampling always supported
     ret.Push(1);
-    /// \todo Implement properly using SDL, if possible
+    /// \todo Implement properly, if possible
     
     return ret;
 }
@@ -2158,6 +2135,9 @@ void Graphics::Release()
     // When the new context is initialized, it will have default state again
     ResetCachedState();
     ClearParameterSources();
+    
+    glfwCloseWindow();
+    initialized_ = false;
 }
 
 void Graphics::InitializeShaderParameters()

+ 1 - 3
Engine/Graphics/OpenGL/OGLGraphics.h

@@ -373,8 +373,6 @@ private:
     void SetDrawBuffers();
     /// Destroy the OpenGL rendering context and the window
     void Release();
-    /// Initialize OpenGL extensions. Creates a dummy window and OpenGL context
-    void InitializeExtensions();
     /// Initialize shader parameter and texture unit mappings
     void InitializeShaderParameters();
     
@@ -390,7 +388,7 @@ private:
     int height_;
     /// Multisampling mode
     int multiSample_;
-    /// Initialized flag
+    /// Initialized flag (window open)
     bool initialized_;
     /// Fullscreen flag
     bool fullscreen_;

+ 1 - 1
Engine/Graphics/OpenGL/OGLGraphicsImpl.h

@@ -27,7 +27,7 @@
 #include "Map.h"
 
 #include <GLee.h>
-#include <SDL.h>
+#include <GL/glfw.h>
 
 /// Graphics implementation
 class GraphicsImpl

+ 5 - 0
Engine/Input/CMakeLists.txt

@@ -14,4 +14,9 @@ include_directories (
 # Define target & libraries to link
 add_library (${TARGET_NAME} STATIC ${SOURCE_FILES})
 target_link_libraries (${TARGET_NAME} Container Core Graphics IO Math Resource Scene)
+
+if (USE_OPENGL)
+    target_link_libraries (${TARGET_NAME} GLFW)
+endif ()
+
 finalize_lib ()

+ 138 - 219
Engine/Input/Input.cpp

@@ -31,10 +31,12 @@
 
 #include <cstring>
 
-#ifndef USE_SDL
+#ifndef USE_OPENGL
 #include <Windows.h>
 #else
-#include <SDL.h>
+#include <GL/glfw.h>
+
+static Input* inputInstance = 0;
 #endif
 
 #include "DebugNew.h"
@@ -43,7 +45,6 @@ OBJECTTYPESTATIC(Input);
 
 Input::Input(Context* context) :
     Object(context),
-    clipCursor_(true),
     showCursor_(true),
     toggleFullscreen_(true),
     active_(false),
@@ -55,10 +56,13 @@ Input::Input(Context* context) :
     // Zero the initial state
     mouseButtonDown_ = 0;
     mouseButtonPress_ = 0;
-    lastMousePosition_ = IntVector2::ZERO;
+    lastCursorPosition_ = IntVector2::ZERO;
     
-    #ifndef USE_SDL
+    #ifndef USE_OPENGL
     SubscribeToEvent(E_WINDOWMESSAGE, HANDLER(Input, HandleWindowMessage));
+    #else
+    // GLFW callbacks do not include userdata, so a static instance pointer is necessary
+    inputInstance = this;
     #endif
     
     SubscribeToEvent(E_SCREENMODE, HANDLER(Input, HandleScreenMode));
@@ -85,7 +89,7 @@ void Input::Update()
     mouseMove_ = IntVector2::ZERO;
     mouseMoveWheel_ = 0;
     
-    #ifndef USE_SDL
+    #ifndef USE_OPENGL
     // Pump Win32 events
     MSG msg;
     while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
@@ -94,15 +98,11 @@ void Input::Update()
         DispatchMessage(&msg);
     }
     #else
-    // Pump SDL events
-    SDL_Event evt;
-    SDL_PumpEvents();
-    while (SDL_PollEvent(&evt))
-        HandleSDLEvent(&evt);
-    
-    // Poll SDL activation state
-    unsigned state = SDL_GetAppState();
-    if ((state & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) == (SDL_APPINPUTFOCUS | SDL_APPACTIVE))
+    // Pump GLFW events
+    glfwPollEvents();
+    
+    // Check state
+    if (glfwGetWindowParam(GLFW_ACTIVE))
     {
         if (!active_)
             activated_ = true;
@@ -121,93 +121,44 @@ void Input::Update()
     // Finally send the mouse move event if motion has been accumulated
     if (active_)
     {
-        // In clipped mode, require the operating system cursor to be hidden first
-        IntVector2 mousePos = GetMousePosition();
-        mouseMove_ = !clipCursor_ || !showCursor_ ? mousePos - lastMousePosition_ : IntVector2::ZERO;
+        #ifndef USE_OPENGL
+        IntVector2 mousePos = GetCursorPosition();
+        mouseMove_ = mousePos - lastCursorPosition_;
         
-        // Recenter the mouse cursor manually if cursor clipping is in effect
-        if (clipCursor_ && mouseMove_ != IntVector2::ZERO)
+        // Recenter the mouse cursor manually if it moved
+        if (mouseMove_ != IntVector2::ZERO)
         {
             IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
-            SetMousePosition(center);
-            lastMousePosition_ = GetMousePosition();
+            SetCursorPosition(center);
+            lastCursorPosition_ = GetCursorPosition();
         }
         else
-            lastMousePosition_ = mousePos;
+            lastCursorPosition_ = mousePos;
+        #else
+        IntVector2 mousePos = GetCursorPosition();
+        mouseMove_ = mousePos - lastCursorPosition_;
+        lastCursorPosition_ = mousePos;
+        #endif
         
         if (mouseMove_ != IntVector2::ZERO)
         {
             using namespace MouseMove;
             
             VariantMap eventData;
-            eventData[P_X] = lastMousePosition_.x_;
-            eventData[P_Y] = lastMousePosition_.y_;
             eventData[P_DX] = mouseMove_.x_;
             eventData[P_DY] = mouseMove_.y_;
             eventData[P_BUTTONS] = mouseButtonDown_;
             eventData[P_QUALIFIERS] = GetQualifiers();
-            eventData[P_CLIPCURSOR] = clipCursor_;
             SendEvent(E_MOUSEMOVE, eventData);
         }
     }
 }
 
-void Input::SetClipCursor(bool enable)
-{
-    clipCursor_ = enable;
-    
-    if (!graphics_)
-        return;
-    
-    if (!graphics_->GetFullscreen() && active_ && clipCursor_)
-    {
-        SetMousePosition(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
-        lastMousePosition_ = GetMousePosition();
-        #ifndef USE_SDL
-        RECT clipRect;
-        GetWindowRect((HWND)graphics_->GetWindowHandle(), &clipRect);
-        ClipCursor(&clipRect);
-        #endif
-    }
-    else
-    {
-        if (graphics_->GetFullscreen() && active_ && clipCursor_)
-        {
-            SetMousePosition(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
-            lastMousePosition_ = GetMousePosition();
-        }
-        #ifndef USE_SDL
-        ClipCursor(0);
-        #endif
-    }
-}
-
 void Input::SetToggleFullscreen(bool enable)
 {
     toggleFullscreen_ = enable;
 }
 
-void Input::SetMousePosition(const IntVector2& position)
-{
-    if (!graphics_)
-        return;
-    
-    #ifndef USE_SDL
-    POINT point;
-    point.x = position.x_;
-    point.y = position.y_;
-    ClientToScreen((HWND)graphics_->GetWindowHandle(), &point);
-    SetCursorPos(point.x, point.y);
-    #else
-    SDL_WarpMouse(position.x_, position.y_);
-    #endif
-}
-
-void Input::SetMousePosition(int x, int y)
-{
-    SetMousePosition(IntVector2(x, y));
-}
-
 void Input::SuppressNextChar()
 {
     suppressNextChar_ = true;
@@ -223,26 +174,6 @@ bool Input::GetKeyPress(int key) const
     return keyPress_.Contains(key);
 }
 
-IntVector2 Input::GetMousePosition() const
-{
-    IntVector2 ret(0, 0);
-    
-    if (!graphics_)
-        return ret;
-    
-    #ifndef USE_SDL
-    POINT mouse;
-    GetCursorPos(&mouse);
-    ScreenToClient((HWND)graphics_->GetWindowHandle(), &mouse);
-    ret.x_ = mouse.x;
-    ret.y_ = mouse.y;
-    #else
-    SDL_GetMouseState(&ret.x_, &ret.y_);
-    #endif
-    
-    return ret;
-}
-
 bool Input::GetMouseButtonDown(int button) const
 {
     return (mouseButtonDown_ & button) != 0;
@@ -255,7 +186,7 @@ bool Input::GetMouseButtonPress(int button) const
 
 bool Input::GetQualifierDown(int qualifier) const
 {
-    #ifndef USE_SDL
+    #ifndef USE_OPENGL
     if (qualifier == QUAL_SHIFT)
         return GetKeyDown(KEY_SHIFT);
     if (qualifier == QUAL_CTRL)
@@ -275,7 +206,7 @@ bool Input::GetQualifierDown(int qualifier) const
 
 bool Input::GetQualifierPress(int qualifier) const
 {
-    #ifndef USE_SDL
+    #ifndef USE_OPENGL
     if (qualifier == QUAL_SHIFT)
         return GetKeyPress(KEY_SHIFT);
     if (qualifier == QUAL_CTRL)
@@ -313,14 +244,12 @@ void Input::Initialize()
     
     graphics_ = graphics;
     
-    #ifdef USE_SDL
-    // Enable translated keyboard input
-    SDL_EnableUNICODE(SDL_TRUE);
-    #endif
     // Set the initial activation
     MakeActive();
-    SetClipCursor(clipCursor_);
+    #ifndef USE_OPENGL
+    SetClipCursor(true);
     SetCursorVisible(false);
+    #endif
     
     initialized_ = true;
     
@@ -337,13 +266,14 @@ void Input::MakeActive()
     active_ = true;
     activated_ = false;
     
-    // Re-establish mouse cursor clipping immediately in fullscreen. In windowed mode, require a mouse click inside the window
-    // first to not confuse with title bar drag
-    if (!clipCursor_ || graphics_->GetFullscreen())
-    {
-        SetClipCursor(clipCursor_);
-        SetCursorVisible(false);
-    }
+    // Re-establish mouse cursor clipping as necessary
+    #ifndef USE_OPENGL
+    SetClipCursor(true);
+    SetCursorVisible(false);
+    #else
+    // Get the current mouse position as a base for movement calculations
+    lastCursorPosition_ = GetCursorPosition();
+    #endif
     
     using namespace Activation;
     
@@ -364,11 +294,11 @@ void Input::MakeInactive()
     activated_ = false;
     
     // Free and show the mouse cursor
-    #ifndef USE_SDL
+    #ifndef USE_OPENGL
     ReleaseCapture();
     ClipCursor(0);
-    #endif
     SetCursorVisible(true);
+    #endif
     
     using namespace Activation;
     
@@ -399,14 +329,6 @@ void Input::SetMouseButton(int button, bool newState)
     if (newState && !active_)
         return;
     
-    // If we are still showing the cursor (waiting for a click inside window), hide it now and disregard this click
-    if (newState && clipCursor_ && showCursor_)
-    {
-        SetClipCursor(clipCursor_);
-        SetCursorVisible(false);
-        return;
-    }
-    
     if (newState)
     {
         if (!(mouseButtonDown_ & button))
@@ -429,20 +351,9 @@ void Input::SetMouseButton(int button, bool newState)
     eventData[P_BUTTONS] = mouseButtonDown_;
     eventData[P_QUALIFIERS] = GetQualifiers();
     SendEvent(newState ? E_MOUSEBUTTONDOWN : E_MOUSEBUTTONUP, eventData);
-    
-    #ifndef USE_SDL
-    // In non-clipped mode, while any of the mouse buttons are down, capture the mouse so that we get the button release reliably
-    if (graphics_ && !clipCursor_)
-    {
-        if (mouseButtonDown_)
-            SetCapture((HWND)graphics_->GetWindowHandle());
-        else
-            ReleaseCapture();
-    }
-    #endif
 }
 
-void Input::SetKey(int key, int scanCode, bool newState)
+void Input::SetKey(int key, bool newState)
 {
     // If we are not active yet, do not react to the key down
     if (newState && !active_)
@@ -470,7 +381,6 @@ void Input::SetKey(int key, int scanCode, bool newState)
     
     VariantMap eventData;
     eventData[P_KEY] = key;
-    eventData[P_SCANCODE] = scanCode;
     eventData[P_BUTTONS] = mouseButtonDown_;
     eventData[P_QUALIFIERS] = GetQualifiers();
     if (newState)
@@ -498,12 +408,48 @@ void Input::SetMouseWheel(int delta)
     }
 }
 
+#ifndef USE_OPENGL
+void Input::SetClipCursor(bool enable)
+{
+    if (!graphics_)
+        return;
+    
+    if (!graphics_->GetFullscreen() && active_ && enable)
+    {
+        SetCursorPosition(IntVector2(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2));
+        lastCursorPosition_ = GetCursorPosition();
+        RECT clipRect;
+        GetWindowRect((HWND)graphics_->GetWindowHandle(), &clipRect);
+        ClipCursor(&clipRect);
+    }
+    else
+    {
+        if (graphics_->GetFullscreen() && active_ && enable)
+        {
+            SetCursorPosition(IntVector2(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2));
+            lastCursorPosition_ = GetCursorPosition();
+        }
+        ClipCursor(0);
+    }
+}
+
+void Input::SetCursorPosition(const IntVector2& position)
+{
+    if (!graphics_)
+        return;
+    
+    POINT point;
+    point.x = position.x_;
+    point.y = position.y_;
+    ClientToScreen((HWND)graphics_->GetWindowHandle(), &point);
+    SetCursorPos(point.x, point.y);
+}
+
 void Input::SetCursorVisible(bool enable)
 {
     if (!graphics_)
         return;
     
-    #ifndef USE_SDL
     // When inactive, always show the cursor
     if (!active_)
         enable = true;
@@ -512,13 +458,9 @@ void Input::SetCursorVisible(bool enable)
         return;
     
     ShowCursor(enable ? TRUE : FALSE);
-    #else
-    SDL_ShowCursor(enable ? SDL_TRUE : SDL_FALSE);
-    #endif
     showCursor_ = enable;
 }
 
-#ifndef USE_SDL
 void Input::HandleWindowMessage(StringHash eventType, VariantMap& eventData)
 {
     using namespace WindowMessage;
@@ -580,12 +522,12 @@ void Input::HandleWindowMessage(StringHash eventType, VariantMap& eventData)
         break;
         
     case WM_KEYDOWN:
-        SetKey(wParam, (lParam >> 16) & 255, true);
+        SetKey(wParam, true);
         eventData[P_HANDLED] = true;
         break;
         
     case WM_SYSKEYDOWN:
-        SetKey(wParam, (lParam >> 16) & 255, true);
+        SetKey(wParam, true);
         if (wParam == KEY_RETURN && toggleFullscreen_)
             graphics_->ToggleFullscreen();
         if (wParam != KEY_F4)
@@ -593,12 +535,12 @@ void Input::HandleWindowMessage(StringHash eventType, VariantMap& eventData)
         break;
         
     case WM_KEYUP:
-        SetKey(wParam, (lParam >> 16) & 255, false);
+        SetKey(wParam, false);
         eventData[P_HANDLED] = true;
         break;
         
     case WM_SYSKEYUP:
-        SetKey(wParam, (lParam >> 16) & 255, false);
+        SetKey(wParam, false);
         eventData[P_HANDLED] = true;
         break;
         
@@ -616,98 +558,75 @@ void Input::HandleWindowMessage(StringHash eventType, VariantMap& eventData)
         suppressNextChar_ = false;
         eventData[P_HANDLED] = true;
         break;
-        
-    case WM_SETCURSOR:
-        // When cursor is not clipped, switch to the operating system cursor outside the client area
-        if (!clipCursor_)
-        {
-            if ((lParam & 0xffff) == HTCLIENT)
-            {
-                SetCursorVisible(false);
-                eventData[P_HANDLED] = true;
-            }
-            else
-                SetCursorVisible(true);
-        }
-        break;
     }
 }
 #else
-void Input::HandleSDLEvent(void* sdlEvent)
+void KeyCallback(int key, int action)
 {
-    SDL_Event& evt = *static_cast<SDL_Event*>(sdlEvent);
-    switch (evt.type)
+    inputInstance->SetKey(key, action & GLFW_PRESS);
+}
+
+void CharCallback(int key, int action)
+{
+    if (key < 256 && action == GLFW_PRESS)
     {
-    case SDL_KEYDOWN:
-        // Convert to uppercase to match Win32 virtual key codes
-        SetKey(SDL_toupper(evt.key.keysym.sym), evt.key.keysym.scancode, true);
-        
-        // Check ALT-ENTER fullscreen toggle
-        if (evt.key.keysym.sym == KEY_RETURN && toggleFullscreen_ && (GetKeyDown(KEY_LALT) || GetKeyDown(KEY_RALT)))
-            graphics_->ToggleFullscreen();
-        break;
-        
-    case SDL_KEYUP:
-        SetKey(SDL_toupper(evt.key.keysym.sym), evt.key.keysym.scancode, false);
-        break;
-        
-    case SDL_TEXTINPUT:
-        // Convert back to Latin-1
-        if (!suppressNextChar_)
-        {
-            unsigned char x = evt.text.text[0];
-            unsigned char y = evt.text.text[1];
-            int latin1 = 0;
-            
-            if (x < 0x80)
-                latin1 = x;
-            else if (x < 0xe0)
-                latin1 = (y & 0x3f) | ((x & 0x1f) << 6);
-            
-            if (latin1 && latin1 < 256)
-            {
-                using namespace Char;
-                
-                VariantMap keyEventData;
-                
-                keyEventData[P_CHAR] = latin1;
-                keyEventData[P_BUTTONS] = mouseButtonDown_;
-                keyEventData[P_QUALIFIERS] = GetQualifiers();
-                SendEvent(E_CHAR, keyEventData);
-            }
-        }
-        else
-            suppressNextChar_ = false;
-        break;
-        
-    case SDL_MOUSEBUTTONDOWN:
-        SetMouseButton(1 << (evt.button.button - 1), true);
-        break;
-        
-    case SDL_MOUSEBUTTONUP:
-        SetMouseButton(1 << (evt.button.button - 1), false);
-        break;
-        
-    case SDL_MOUSEWHEEL:
-        SetMouseWheel(evt.wheel.y);
-        break;
+        using namespace Char;
         
-    case SDL_QUIT:
-        if (graphics_)
-            graphics_->Close();
-        break;
+        VariantMap keyEventData;
+        keyEventData[P_CHAR] = key;
+        keyEventData[P_BUTTONS] = inputInstance->mouseButtonDown_;
+        keyEventData[P_QUALIFIERS] = inputInstance->GetQualifiers();
+        inputInstance->SendEvent(E_CHAR, keyEventData);
     }
 }
+
+void MouseButtonCallback(int button, int action)
+{
+    inputInstance->SetMouseButton(1 << button, action == GLFW_PRESS);
+}
+
+void MouseWheelCallback(int wheel)
+{
+    /// \todo Implement
+}
 #endif
 
+IntVector2 Input::GetCursorPosition() const
+{
+    IntVector2 ret(0, 0);
+    
+    if (!graphics_)
+        return ret;
+    
+    #ifndef USE_OPENGL
+    POINT mouse;
+    GetCursorPos(&mouse);
+    ScreenToClient((HWND)graphics_->GetWindowHandle(), &mouse);
+    ret.x_ = mouse.x;
+    ret.y_ = mouse.y;
+    #else
+    glfwGetMousePos(&ret.x_, &ret.y_);
+    #endif
+    
+    return ret;
+}
+
 void Input::HandleScreenMode(StringHash eventType, VariantMap& eventData)
 {
     if (!initialized_)
         Initialize();
     // Screen mode change may affect the cursor clipping behaviour. Also re-center the cursor (if needed) to the new screen size,
     // so that there is no erroneous mouse move event
-    else
-        SetClipCursor(clipCursor_);
+    #ifndef USE_OPENGL
+    SetClipCursor(true);
+    #else
+    // Re-enable GLFW callbacks each time the window has been recreated
+    glfwDisable(GLFW_MOUSE_CURSOR);
+    glfwSetKeyCallback(&KeyCallback);
+    glfwSetCharCallback(&CharCallback);
+    glfwSetMouseButtonCallback(&MouseButtonCallback);
+    glfwSetMouseWheelCallback(&MouseWheelCallback);
+    #endif
 }
 
 void Input::HandleBeginFrame(StringHash eventType, VariantMap& eventData)

+ 19 - 21
Engine/Input/Input.h

@@ -32,6 +32,13 @@ class Graphics;
 /// Input subsystem. Converts operating system window messages to input state and events
 class Input : public Object
 {
+    #ifdef USE_OPENGL
+    friend void KeyCallback(int, int);
+    friend void CharCallback(int, int);
+    friend void MouseButtonCallback(int, int);
+    friend void MouseWheelCallback(int);
+    #endif
+    
     OBJECT(Input);
     
 public:
@@ -42,14 +49,8 @@ public:
     
     /// Poll for window messages. Called by HandleBeginFrame()
     void Update();
-    /// Set whether mouse cursor is confined inside the window. Mouse delta movement is sent only when enabled, which is default.
-    void SetClipCursor(bool enable);
-    /// Set whether ALT-ENTER fullscreen Toggle is enabled
+    /// Set whether ALT-ENTER fullscreen toggle is enabled
     void SetToggleFullscreen(bool enable);
-    /// Set absolute mouse cursor position within the window. Only useful when the cursor is not confined
-    void SetMousePosition(const IntVector2& position);
-    /// Set absolute mouse cursor position within the window. Only useful when the cursor is not confined
-    void SetMousePosition(int x, int y);
     /// Suppress the next char message
     void SuppressNextChar();
     
@@ -67,8 +68,6 @@ public:
     bool GetQualifierPress(int qualifier) const;
     /// Return the currently held down qualifiers
     int GetQualifiers() const;
-    /// Return absolute mouse cursor position within the window. Only useful when the cursor is not confined
-    IntVector2 GetMousePosition() const;
     /// Return mouse movement since last frame
     const IntVector2& GetMouseMove() const { return mouseMove_; }
     /// Return horizontal mouse movement since last frame
@@ -77,8 +76,6 @@ public:
     int GetMouseMoveY() const { return mouseMove_.y_; }
     /// Return mouse wheel movement since last frame
     int GetMouseMoveWheel() const { return mouseMoveWheel_; }
-    /// Return whether mouse cursor is confined inside the window
-    bool GetClipCursor() const { return clipCursor_; }
     /// Return whether fullscreen Toggle is enabled
     bool GetToggleFullscreen() const { return toggleFullscreen_; }
     /// Return whether application window is active
@@ -98,18 +95,21 @@ private:
     /// Handle a mouse button change
     void SetMouseButton(int button, bool newState);
     /// Handle a key change
-    void SetKey(int key, int scanCode, bool newState);
+    void SetKey(int key, bool newState);
     /// Handle mousewheel change
     void SetMouseWheel(int delta);
-    /// Internal function to show/hide the operating system mouse cursor
+    #ifndef USE_OPENGL
+    /// Internal function to clip the mouse cursor to the window
+    void SetClipCursor(bool enable);
+    /// Internal function to set the mouse cursor position
+    void SetCursorPosition(const IntVector2& position);
+    /// Internal function to show/hide the mouse cursor
     void SetCursorVisible(bool enable);
-    #ifndef USE_SDL
     /// Handle window message event
     void HandleWindowMessage(StringHash eventType, VariantMap& eventData);
-    #else
-    /// Handle SDL event
-    void HandleSDLEvent(void* sdlEvent);
     #endif
+    /// Internal function to get the mouse cursor position
+    IntVector2 GetCursorPosition() const;
     /// Handle screen mode event
     void HandleScreenMode(StringHash eventType, VariantMap& eventData);
     /// Handle frame start event
@@ -125,14 +125,12 @@ private:
     unsigned mouseButtonDown_;
     /// Mouse buttons' pressed state
     unsigned mouseButtonPress_;
-    /// Last mouse position for calculating deltas
-    IntVector2 lastMousePosition_;
+    /// Last mouse position for calculating movement
+    IntVector2 lastCursorPosition_;
     /// Mouse movement since last frame
     IntVector2 mouseMove_;
     /// Mouse wheel movement since last frame
     int mouseMoveWheel_;
-    /// Mouse cursor confine flag
-    bool clipCursor_;
     /// Mouse cursor show/hide flag
     bool showCursor_;
     /// Fullscreen Toggle flag

+ 75 - 108
Engine/Input/InputEvents.h

@@ -25,8 +25,8 @@
 
 #include "Object.h"
 
-#ifdef USE_SDL
-#include <SDL.h>
+#ifdef USE_OPENGL
+#include <GL/glfw.h>
 #endif
 
 /// Mouse button pressed
@@ -48,13 +48,10 @@ EVENT(E_MOUSEBUTTONUP, MouseButtonUp)
 /// Mouse moved
 EVENT(E_MOUSEMOVE, MouseMove)
 {
-    PARAM(P_X, X);                        // int
-    PARAM(P_Y, Y);                        // int
     PARAM(P_DX, DX);                      // int
     PARAM(P_DY, DY);                      // int
     PARAM(P_BUTTONS, Buttons);            // int
     PARAM(P_QUALIFIERS, Qualifiers);      // int
-    PARAM(P_CLIPCURSOR, ClipCursor);      // bool
 }
 
 /// Mouse wheel moved
@@ -69,7 +66,6 @@ EVENT(E_MOUSEWHEEL, MouseWheel)
 EVENT(E_KEYDOWN, KeyDown)
 {
     PARAM(P_KEY, Key);                    // int
-    PARAM(P_SCANCODE, ScanCode);          // int
     PARAM(P_BUTTONS, Buttons);            // int
     PARAM(P_QUALIFIERS, Qualifiers);      // int
     PARAM(P_REPEAT, Repeat);              // bool
@@ -79,7 +75,6 @@ EVENT(E_KEYDOWN, KeyDown)
 EVENT(E_KEYUP, KeyUp)
 {
     PARAM(P_KEY, Key);                    // int
-    PARAM(P_SCANCODE, ScanCode);          // int
     PARAM(P_BUTTONS, Buttons);            // int
     PARAM(P_QUALIFIERS, Qualifiers);      // int
 }
@@ -93,14 +88,14 @@ EVENT(E_CHAR, Char)
 }
 
 static const int MOUSEB_LEFT = 1;
-static const int MOUSEB_MIDDLE = 2;
-static const int MOUSEB_RIGHT = 4;
+static const int MOUSEB_RIGHT = 2;
+static const int MOUSEB_MIDDLE = 4;
 
 static const int QUAL_SHIFT = 1;
 static const int QUAL_CTRL = 2;
 static const int QUAL_ALT = 4;
 
-#ifndef USE_SDL
+#ifndef USE_OPENGL
 static const int KEY_BACKSPACE = 0x08;
 static const int KEY_TAB = 0x09;
 static const int KEY_RETURN = 0x0d;
@@ -119,8 +114,6 @@ static const int KEY_LEFT = 0x25;
 static const int KEY_UP = 0x26;
 static const int KEY_RIGHT = 0x27;
 static const int KEY_DOWN = 0x28;
-static const int KEY_SELECT = 0x29;
-static const int KEY_PRINTSCREEN = 0x2c;
 static const int KEY_INSERT = 0x2d;
 static const int KEY_DELETE = 0x2e;
 static const int KEY_LWIN = 0x5b;
@@ -173,101 +166,75 @@ static const int KEY_LCTRL = 0xa2;
 static const int KEY_RCTRL = 0xa3;
 static const int KEY_LALT = 0xa4;
 static const int KEY_RALT = 0xa5;
-static const int KEY_OEM_1 = 0xba;
-static const int KEY_OEM_PLUS = 0xbb;
-static const int KEY_OEM_COMMA = 0xbc;
-static const int KEY_OEM_MINUS = 0xbd;
-static const int KEY_OEM_PERIOD = 0xbe;
-static const int KEY_OEM_2 = 0xbf;
-static const int KEY_OEM_3 = 0xc0;
-static const int KEY_OEM_4 = 0xdb;
-static const int KEY_OEM_5 = 0xdc;
-static const int KEY_OEM_6 = 0xdd;
-static const int KEY_OEM_7 = 0xde;
-static const int KEY_OEM_8 = 0xdf;
 #else
-static const int KEY_BACKSPACE = SDLK_BACKSPACE;
-static const int KEY_TAB = SDLK_TAB;
-static const int KEY_RETURN = SDLK_RETURN;
-static const int KEY_SHIFT = SDLK_LSHIFT;
-static const int KEY_CTRL = SDLK_LCTRL;
-static const int KEY_ALT = SDLK_LALT;
-static const int KEY_PAUSE = SDLK_PAUSE;
-static const int KEY_CAPSLOCK = SDLK_CAPSLOCK;
-static const int KEY_ESC = SDLK_ESCAPE;
-static const int KEY_SPACE = SDLK_SPACE;
-static const int KEY_PAGEUP = SDLK_PAGEUP;
-static const int KEY_PAGEDOWN = SDLK_PAGEDOWN;
-static const int KEY_END = SDLK_END;
-static const int KEY_HOME = SDLK_HOME;
-static const int KEY_LEFT = SDLK_LEFT;
-static const int KEY_UP = SDLK_UP;
-static const int KEY_RIGHT = SDLK_RIGHT;
-static const int KEY_DOWN = SDLK_DOWN;
-static const int KEY_SELECT = SDLK_SELECT;
-static const int KEY_PRINTSCREEN = SDLK_PRINTSCREEN;
-static const int KEY_INSERT = SDLK_INSERT;
-static const int KEY_DELETE = SDLK_DELETE;
-static const int KEY_LWIN = SDLK_LGUI;
-static const int KEY_RWIN = SDLK_RGUI;
-static const int KEY_APPS = SDLK_APPLICATION;
-static const int KEY_NUMPAD0 = SDLK_KP_0;
-static const int KEY_NUMPAD1 = SDLK_KP_1;
-static const int KEY_NUMPAD2 = SDLK_KP_2;
-static const int KEY_NUMPAD3 = SDLK_KP_3;
-static const int KEY_NUMPAD4 = SDLK_KP_4;
-static const int KEY_NUMPAD5 = SDLK_KP_5;
-static const int KEY_NUMPAD6 = SDLK_KP_6;
-static const int KEY_NUMPAD7 = SDLK_KP_7;
-static const int KEY_NUMPAD8 = SDLK_KP_8;
-static const int KEY_NUMPAD9 = SDLK_KP_9;
-static const int KEY_MULTIPLY = SDLK_KP_MULTIPLY;
-static const int KEY_ADD = SDLK_KP_PLUS;
-static const int KEY_SUBTRACT = SDLK_KP_MINUS;
-static const int KEY_DECIMAL = SDLK_KP_PERIOD;
-static const int KEY_DIVIDE = SDLK_KP_DIVIDE;
-static const int KEY_F1 = SDLK_F1;
-static const int KEY_F2 = SDLK_F2;
-static const int KEY_F3 = SDLK_F3;
-static const int KEY_F4 = SDLK_F4;
-static const int KEY_F5 = SDLK_F5;
-static const int KEY_F6 = SDLK_F6;
-static const int KEY_F7 = SDLK_F7;
-static const int KEY_F8 = SDLK_F8;
-static const int KEY_F9 = SDLK_F9;
-static const int KEY_F10 = SDLK_F10;
-static const int KEY_F11 = SDLK_F11;
-static const int KEY_F12 = SDLK_F12;
-static const int KEY_F13 = SDLK_F13;
-static const int KEY_F14 = SDLK_F14;
-static const int KEY_F15 = SDLK_F15;
-static const int KEY_F16 = SDLK_F16;
-static const int KEY_F17 = SDLK_F17;
-static const int KEY_F18 = SDLK_F18;
-static const int KEY_F19 = SDLK_F19;
-static const int KEY_F20 = SDLK_F20;
-static const int KEY_F21 = SDLK_F21;
-static const int KEY_F22 = SDLK_F22;
-static const int KEY_F23 = SDLK_F23;
-static const int KEY_F24 = SDLK_F24;
-static const int KEY_NUMLOCK = SDLK_NUMLOCKCLEAR;
-static const int KEY_SCROLLLOCK = SDLK_SCROLLLOCK;
-static const int KEY_LSHIFT = SDLK_LSHIFT;
-static const int KEY_RSHIFT = SDLK_RSHIFT;
-static const int KEY_LCTRL = SDLK_LCTRL;
-static const int KEY_RCTRL = SDLK_RCTRL;
-static const int KEY_LALT = SDLK_LALT;
-static const int KEY_RALT = SDLK_RALT;
-static const int KEY_OEM_1 = 0;
-static const int KEY_OEM_PLUS = 0;
-static const int KEY_OEM_COMMA = 0;
-static const int KEY_OEM_MINUS = 0;
-static const int KEY_OEM_PERIOD = 0;
-static const int KEY_OEM_2 = 0;
-static const int KEY_OEM_3 = 0;
-static const int KEY_OEM_4 = 0;
-static const int KEY_OEM_5 = 0;
-static const int KEY_OEM_6 = 0;
-static const int KEY_OEM_7 = 0;
-static const int KEY_OEM_8 = 0;
+static const int KEY_BACKSPACE = GLFW_KEY_BACKSPACE;
+static const int KEY_TAB = GLFW_KEY_TAB;
+static const int KEY_RETURN = GLFW_KEY_ENTER;
+static const int KEY_SHIFT = GLFW_KEY_LSHIFT;
+static const int KEY_CTRL = GLFW_KEY_LCTRL;
+static const int KEY_ALT = GLFW_KEY_LALT;
+static const int KEY_PAUSE = GLFW_KEY_PAUSE;
+static const int KEY_CAPSLOCK = GLFW_KEY_CAPS_LOCK;
+static const int KEY_ESC = GLFW_KEY_ESC;
+static const int KEY_SPACE = GLFW_KEY_SPACE;
+static const int KEY_PAGEUP = GLFW_KEY_PAGEUP;
+static const int KEY_PAGEDOWN = GLFW_KEY_PAGEDOWN;
+static const int KEY_END = GLFW_KEY_END;
+static const int KEY_HOME = GLFW_KEY_HOME;
+static const int KEY_LEFT = GLFW_KEY_LEFT;
+static const int KEY_UP = GLFW_KEY_UP;
+static const int KEY_RIGHT = GLFW_KEY_RIGHT;
+static const int KEY_DOWN = GLFW_KEY_DOWN;
+static const int KEY_INSERT = GLFW_KEY_INSERT;
+static const int KEY_DELETE = GLFW_KEY_DEL;
+static const int KEY_LWIN = GLFW_KEY_LSUPER;
+static const int KEY_RWIN = GLFW_KEY_RSUPER;
+static const int KEY_APPS = GLFW_KEY_MENU;
+static const int KEY_NUMPAD0 = GLFW_KEY_KP_0;
+static const int KEY_NUMPAD1 = GLFW_KEY_KP_1;
+static const int KEY_NUMPAD2 = GLFW_KEY_KP_2;
+static const int KEY_NUMPAD3 = GLFW_KEY_KP_3;
+static const int KEY_NUMPAD4 = GLFW_KEY_KP_4;
+static const int KEY_NUMPAD5 = GLFW_KEY_KP_5;
+static const int KEY_NUMPAD6 = GLFW_KEY_KP_6;
+static const int KEY_NUMPAD7 = GLFW_KEY_KP_7;
+static const int KEY_NUMPAD8 = GLFW_KEY_KP_8;
+static const int KEY_NUMPAD9 = GLFW_KEY_KP_9;
+static const int KEY_MULTIPLY = GLFW_KEY_KP_MULTIPLY;
+static const int KEY_ADD = GLFW_KEY_KP_ADD;
+static const int KEY_SUBTRACT = GLFW_KEY_KP_SUBTRACT;
+static const int KEY_DECIMAL = GLFW_KEY_KP_DECIMAL;
+static const int KEY_DIVIDE = GLFW_KEY_KP_DIVIDE;
+static const int KEY_F1 = GLFW_KEY_F1;
+static const int KEY_F2 = GLFW_KEY_F2;
+static const int KEY_F3 = GLFW_KEY_F3;
+static const int KEY_F4 = GLFW_KEY_F4;
+static const int KEY_F5 = GLFW_KEY_F5;
+static const int KEY_F6 = GLFW_KEY_F6;
+static const int KEY_F7 = GLFW_KEY_F7;
+static const int KEY_F8 = GLFW_KEY_F8;
+static const int KEY_F9 = GLFW_KEY_F9;
+static const int KEY_F10 = GLFW_KEY_F10;
+static const int KEY_F11 = GLFW_KEY_F11;
+static const int KEY_F12 = GLFW_KEY_F12;
+static const int KEY_F13 = GLFW_KEY_F13;
+static const int KEY_F14 = GLFW_KEY_F14;
+static const int KEY_F15 = GLFW_KEY_F15;
+static const int KEY_F16 = GLFW_KEY_F16;
+static const int KEY_F17 = GLFW_KEY_F17;
+static const int KEY_F18 = GLFW_KEY_F18;
+static const int KEY_F19 = GLFW_KEY_F19;
+static const int KEY_F20 = GLFW_KEY_F20;
+static const int KEY_F21 = GLFW_KEY_F21;
+static const int KEY_F22 = GLFW_KEY_F22;
+static const int KEY_F23 = GLFW_KEY_F23;
+static const int KEY_F24 = GLFW_KEY_F24;
+static const int KEY_NUMLOCK = GLFW_KEY_KP_NUM_LOCK;
+static const int KEY_SCROLLLOCK = GLFW_KEY_SCROLL_LOCK;
+static const int KEY_LSHIFT = GLFW_KEY_LSHIFT;
+static const int KEY_RSHIFT = GLFW_KEY_RSHIFT;
+static const int KEY_LCTRL = GLFW_KEY_LCTRL;
+static const int KEY_RCTRL = GLFW_KEY_RCTRL;
+static const int KEY_LALT = GLFW_KEY_LALT;
+static const int KEY_RALT = GLFW_KEY_RALT;
 #endif

+ 2 - 2
Engine/Network/Network.cpp

@@ -51,7 +51,7 @@ Network::Network(Context* context) :
     dataOutBps_(0)
 {
     {
-        MutexLock Lock(GetStaticMutex());
+        MutexLock lock(GetStaticMutex());
         
         if (!numInstances)
         {
@@ -70,7 +70,7 @@ Network::~Network()
     StopClient();
     
     {
-        MutexLock Lock(GetStaticMutex());
+        MutexLock lock(GetStaticMutex());
         
         --numInstances;
         if (!numInstances)

+ 2 - 2
Engine/Physics/PhysicsWorld.cpp

@@ -68,7 +68,7 @@ PhysicsWorld::PhysicsWorld(Context* context) :
     randomSeed_(0)
 {
     {
-        MutexLock Lock(GetStaticMutex());
+        MutexLock lock(GetStaticMutex());
         
         if (!numInstances)
             dInitODE();
@@ -122,7 +122,7 @@ PhysicsWorld::~PhysicsWorld()
     }
     
     {
-        MutexLock Lock(GetStaticMutex());
+        MutexLock lock(GetStaticMutex());
         
         --numInstances;
         if (!numInstances)

+ 7 - 32
Engine/UI/UI.cpp

@@ -571,40 +571,15 @@ void UI::HandleMouseMove(StringHash eventType, VariantMap& eventData)
     {
         const IntVector2& rootSize = rootElement_->GetSize();
         
-        if (eventData[P_CLIPCURSOR].GetBool())
+        // Move cursor only when visible
+        if (cursor_->IsVisible())
         {
-            // When in confined cursor mode, move cursor only when visible
-            if (cursor_->IsVisible())
-            {
-                IntVector2 pos = cursor_->GetPosition();
-                pos.x_ += eventData[P_DX].GetInt();
-                pos.y_ += eventData[P_DY].GetInt();
-                pos.x_ = Clamp(pos.x_, 0, rootSize.x_ - 1);
-                pos.y_ = Clamp(pos.y_, 0, rootSize.y_ - 1);
-                cursor_->SetPosition(pos);
-            }
-        }
-        else
-        {
-            // When in non-confined mode, move cursor always to ensure accurate position
-            IntVector2 pos(eventData[P_X].GetInt(), eventData[P_Y].GetInt());
-            bool inside = pos.x_ >= 0 && pos.x_ < rootSize.x_ && pos.y_ >= 0 && pos.y_ < rootSize.y_;
-            
-            // Hide by moving completely outside if outside
-            // (do not use SetVisible(), so that actual visibility remains under application control)
-            if (pos.x_ < 0)
-                pos.x_ = -cursor_->GetWidth() * 2;
-            if (pos.x_ >= rootSize.x_)
-                pos.x_ = rootSize.x_ + cursor_->GetWidth() * 2;
-            if (pos.y_ < 0)
-                pos.y_ = -cursor_->GetHeight() * 2;
-            if (pos.y_ >= rootSize.y_)
-                pos.y_ = rootSize.y_ + cursor_->GetHeight() * 2;
+            IntVector2 pos = cursor_->GetPosition();
+            pos.x_ += eventData[P_DX].GetInt();
+            pos.y_ += eventData[P_DY].GetInt();
+            pos.x_ = Clamp(pos.x_, 0, rootSize.x_ - 1);
+            pos.y_ = Clamp(pos.y_, 0, rootSize.y_ - 1);
             cursor_->SetPosition(pos);
-            
-            // Do not drag when outside
-            if (!inside)
-                return;
         }
         
         if (dragElement_ && mouseButtons_)

+ 46 - 18
License.txt

@@ -113,7 +113,7 @@ all copies or substantial portions of the Software.
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 DEALINGS IN THE SOFTWARE.
@@ -153,6 +153,32 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
+GLFW license
+------------
+
+Copyright (c) 2002-2006 Marcus Geelnard
+Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+
+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.
+
+
 Open Dynamics Engine license
 ----------------------------
 
@@ -188,27 +214,29 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-SDL license
------------
+PortAudio license
+-----------------
 
-Simple DirectMedia Layer
-Copyright (C) 1997-2011 Sam Lantinga <[email protected]>
+PortAudio Portable Real-Time Audio Library
+Copyright (c) 1999-2011 Ross Bencina and Phil Burk
 
-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 hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+and/or sell copies of the Software, and to permit persons to whom the 
+Software is furnished to do so, subject to the following conditions:
 
-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:
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
 
-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.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND ON INFRINGEMENT. IN NO EVENT SHALL 
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+DEALINGS IN THE SOFTWARE.
 
 
 StanHull license

+ 2 - 1
Readme.txt

@@ -40,9 +40,10 @@ Urho3D uses the following third-party libraries:
 - ENet 1.3.1 (http://enet.bespin.org/)
 - FreeType 2.3.12 (http://www.freetype.org/)
 - GLee 5.4 (http://elf-stone.com/)
+- GLFW 2.7 (http://www.glfw.org/)
 - Open Asset Import Library 2.0.863 (http://assimp.sourceforge.net/)
 - Open Dynamics Engine, svn rev 1806 (http://www.ode.org/)
-- SDL 1.3 (http://www.libsdl.org/)
+- PortAudio V19 (http://www.portaudio.com/)
 - StanHull (http://codesuppository.blogspot.com/2006/03/
   john-ratcliffs-code-suppository-blog.html)
 - stb_image 1.29 (http://nothings.org/)

+ 49 - 0
ThirdParty/GLFW/CMakeLists.txt

@@ -0,0 +1,49 @@
+# Define target name
+set (TARGET_NAME GLFW)
+
+# Define source files
+file (GLOB C_FILES lib/*.c)
+
+if (WIN32)
+    file (GLOB SYS_C_FILES lib/win32/*.c)
+elseif (APPLE)
+    file (GLOB SYS_C_FILES lib/cocoa/*.m)
+else ()
+    file (GLOB SYS_C_FILES lib/x11/*.c)
+endif ()
+
+file (GLOB H_FILES include/GL/*.h)
+
+set_source_files_properties (${C_FILES} PROPERTIES LANGUAGE C)
+set_source_files_properties (${SYS_FILES} PROPERTIES LANGUAGE C)
+set (SOURCE_FILES ${C_FILES} ${SYS_C_FILES} ${H_FILES})
+
+# Include directories and definitions
+include_directories (include lib)
+if (WIN32)
+    include_directories (lib/win32)
+elseif (APPLE)
+    include_directories (lib/cocoa)
+else ()
+    include_directories (lib/x11)
+    add_definitions (-D_GLFW_HAS_XRANDR -D_GLFW_HAS_PTHREAD -D_GLFW_HAS_SCHED_YIELD -D_GLFW_HAS_GLXGETPROCADDRESS -D_GLFW_HAS_DLOPEN -D_GLFW_HAS_SYSCONF)
+endif ()
+
+# Define target & libraries to link
+add_library (${TARGET_NAME} STATIC ${SOURCE_FILES})
+
+if (WIN32)
+    include_directories (lib/win32)
+    target_link_libraries (${TARGET_NAME} winmm.lib opengl32.lib)
+elseif (APPLE)
+    include_directories (lib/cocoa)
+    find_library (CARBON_FW Carbon)
+    find_library (COCOA_FW Cocoa)
+    find_library (OPENGL_FW OpenGL)
+    target_link_libraries (${TARGET_NAME} dl pthread ${CARBON_FW} ${COCOA_FW} ${OPENGL_FW})
+else ()
+    include_directories (lib/x11)
+    target_link_libraries (${TARGET_NAME} GL X11 Xrandr pthread)
+endif ()
+
+finalize_lib ()

+ 13 - 10
ThirdParty/SDL/COPYING → ThirdParty/GLFW/COPYING.txt

@@ -1,19 +1,22 @@
+Copyright (c) 2002-2006 Marcus Geelnard
+Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
 
-Simple DirectMedia Layer
-Copyright (C) 1997-2011 Sam Lantinga <[email protected]>
-  
 This software is provided 'as-is', without any express or implied
-warranty.  In no event will the authors be held liable for any damages
+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.
+   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.
+

+ 509 - 0
ThirdParty/GLFW/include/GL/glfw.h

@@ -0,0 +1,509 @@
+/************************************************************************
+ * GLFW - An OpenGL framework
+ * API version: 2.7
+ * WWW:         http://www.glfw.org/
+ *------------------------------------------------------------------------
+ * Copyright (c) 2002-2006 Marcus Geelnard
+ * Copyright (c) 2006-2010 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 __glfw_h_
+#define __glfw_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************************************************************************
+ * Global definitions
+ *************************************************************************/
+
+/* We need a NULL pointer from time to time */
+#ifndef NULL
+ #ifdef __cplusplus
+  #define NULL 0
+ #else
+  #define NULL ((void *)0)
+ #endif
+#endif /* NULL */
+
+
+/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */
+
+/* Please report any probles that you find with your compiler, which may
+ * be solved in this section! There are several compilers that I have not
+ * been able to test this file with yet.
+ *
+ * First: If we are we on Windows, we want a single define for it (_WIN32)
+ * (Note: For Cygwin the compiler flag -mwin32 should be used, but to
+ * make sure that things run smoothly for Cygwin users, we add __CYGWIN__
+ * to the list of "valid Win32 identifiers", which removes the need for
+ * -mwin32)
+ */
+#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__))
+ #define _WIN32
+#endif /* _WIN32 */
+
+/* In order for extension support to be portable, we need to define an
+ * OpenGL function call method. We use the keyword APIENTRY, which is
+ * defined for Win32. (Note: Windows also needs this for <GL/gl.h>)
+ */
+#ifndef APIENTRY
+ #ifdef _WIN32
+  #define APIENTRY __stdcall
+ #else
+  #define APIENTRY
+ #endif
+ #define GL_APIENTRY_DEFINED
+#endif /* APIENTRY */
+
+
+/* The following three defines are here solely to make some Windows-based
+ * <GL/gl.h> files happy. Theoretically we could include <windows.h>, but
+ * it has the major drawback of severely polluting our namespace.
+ */
+
+/* Under Windows, we need WINGDIAPI defined */
+#if !defined(WINGDIAPI) && defined(_WIN32)
+ #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__)
+  /* Microsoft Visual C++, Borland C++ Builder and Pelles C */
+  #define WINGDIAPI __declspec(dllimport)
+ #elif defined(__LCC__)
+  /* LCC-Win32 */
+  #define WINGDIAPI __stdcall
+ #else
+  /* Others (e.g. MinGW, Cygwin) */
+  #define WINGDIAPI extern
+ #endif
+ #define GL_WINGDIAPI_DEFINED
+#endif /* WINGDIAPI */
+
+/* Some <GL/glu.h> files also need CALLBACK defined */
+#if !defined(CALLBACK) && defined(_WIN32)
+ #if defined(_MSC_VER)
+  /* Microsoft Visual C++ */
+  #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
+   #define CALLBACK __stdcall
+  #else
+   #define CALLBACK
+  #endif
+ #else
+  /* Other Windows compilers */
+  #define CALLBACK __stdcall
+ #endif
+ #define GLU_CALLBACK_DEFINED
+#endif /* CALLBACK */
+
+/* Microsoft Visual C++, Borland C++ and Pelles C <GL*glu.h> needs wchar_t */
+#if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__)) && !defined(_WCHAR_T_DEFINED)
+ typedef unsigned short wchar_t;
+ #define _WCHAR_T_DEFINED
+#endif /* _WCHAR_T_DEFINED */
+
+
+/* ---------------- GLFW related system specific defines ----------------- */
+
+#if defined(_WIN32) && defined(GLFW_BUILD_DLL)
+
+ /* We are building a Win32 DLL */
+ #define GLFWAPI      __declspec(dllexport)
+ #define GLFWAPIENTRY __stdcall
+ #define GLFWCALL     __stdcall
+
+#elif defined(_WIN32) && defined(GLFW_DLL)
+
+ /* We are calling a Win32 DLL */
+ #if defined(__LCC__)
+  #define GLFWAPI      extern
+ #else
+  #define GLFWAPI      __declspec(dllimport)
+ #endif
+ #define GLFWAPIENTRY __stdcall
+ #define GLFWCALL     __stdcall
+
+#else
+
+ /* We are either building/calling a static lib or we are non-win32 */
+ #define GLFWAPIENTRY
+ #define GLFWAPI
+ #define GLFWCALL
+
+#endif
+
+/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
+
+/* Include standard OpenGL headers: GLFW uses GL_FALSE/GL_TRUE, and it is
+ * convenient for the user to only have to include <GL/glfw.h>. This also
+ * solves the problem with Windows <GL/gl.h> and <GL/glu.h> needing some
+ * special defines which normally requires the user to include <windows.h>
+ * (which is not a nice solution for portable programs).
+ */
+#if defined(__APPLE_CC__)
+ #include <OpenGL/gl.h>
+ #ifndef GLFW_NO_GLU
+  #include <OpenGL/glu.h>
+ #endif
+#else
+ #include <GL/gl.h>
+ #ifndef GLFW_NO_GLU
+  #include <GL/glu.h>
+ #endif
+#endif
+
+
+/*************************************************************************
+ * GLFW version
+ *************************************************************************/
+
+#define GLFW_VERSION_MAJOR    2
+#define GLFW_VERSION_MINOR    7
+#define GLFW_VERSION_REVISION 0
+
+
+/*************************************************************************
+ * Input handling definitions
+ *************************************************************************/
+
+/* Key and button state/action definitions */
+#define GLFW_RELEASE            0
+#define GLFW_PRESS              1
+
+/* Keyboard key definitions: 8-bit ISO-8859-1 (Latin 1) encoding is used
+ * for printable keys (such as A-Z, 0-9 etc), and values above 256
+ * represent special (non-printable) keys (e.g. F1, Page Up etc).
+ */
+#define GLFW_KEY_UNKNOWN      -1
+#define GLFW_KEY_SPACE        32
+#define GLFW_KEY_SPECIAL      256
+#define GLFW_KEY_ESC          (GLFW_KEY_SPECIAL+1)
+#define GLFW_KEY_F1           (GLFW_KEY_SPECIAL+2)
+#define GLFW_KEY_F2           (GLFW_KEY_SPECIAL+3)
+#define GLFW_KEY_F3           (GLFW_KEY_SPECIAL+4)
+#define GLFW_KEY_F4           (GLFW_KEY_SPECIAL+5)
+#define GLFW_KEY_F5           (GLFW_KEY_SPECIAL+6)
+#define GLFW_KEY_F6           (GLFW_KEY_SPECIAL+7)
+#define GLFW_KEY_F7           (GLFW_KEY_SPECIAL+8)
+#define GLFW_KEY_F8           (GLFW_KEY_SPECIAL+9)
+#define GLFW_KEY_F9           (GLFW_KEY_SPECIAL+10)
+#define GLFW_KEY_F10          (GLFW_KEY_SPECIAL+11)
+#define GLFW_KEY_F11          (GLFW_KEY_SPECIAL+12)
+#define GLFW_KEY_F12          (GLFW_KEY_SPECIAL+13)
+#define GLFW_KEY_F13          (GLFW_KEY_SPECIAL+14)
+#define GLFW_KEY_F14          (GLFW_KEY_SPECIAL+15)
+#define GLFW_KEY_F15          (GLFW_KEY_SPECIAL+16)
+#define GLFW_KEY_F16          (GLFW_KEY_SPECIAL+17)
+#define GLFW_KEY_F17          (GLFW_KEY_SPECIAL+18)
+#define GLFW_KEY_F18          (GLFW_KEY_SPECIAL+19)
+#define GLFW_KEY_F19          (GLFW_KEY_SPECIAL+20)
+#define GLFW_KEY_F20          (GLFW_KEY_SPECIAL+21)
+#define GLFW_KEY_F21          (GLFW_KEY_SPECIAL+22)
+#define GLFW_KEY_F22          (GLFW_KEY_SPECIAL+23)
+#define GLFW_KEY_F23          (GLFW_KEY_SPECIAL+24)
+#define GLFW_KEY_F24          (GLFW_KEY_SPECIAL+25)
+#define GLFW_KEY_F25          (GLFW_KEY_SPECIAL+26)
+#define GLFW_KEY_UP           (GLFW_KEY_SPECIAL+27)
+#define GLFW_KEY_DOWN         (GLFW_KEY_SPECIAL+28)
+#define GLFW_KEY_LEFT         (GLFW_KEY_SPECIAL+29)
+#define GLFW_KEY_RIGHT        (GLFW_KEY_SPECIAL+30)
+#define GLFW_KEY_LSHIFT       (GLFW_KEY_SPECIAL+31)
+#define GLFW_KEY_RSHIFT       (GLFW_KEY_SPECIAL+32)
+#define GLFW_KEY_LCTRL        (GLFW_KEY_SPECIAL+33)
+#define GLFW_KEY_RCTRL        (GLFW_KEY_SPECIAL+34)
+#define GLFW_KEY_LALT         (GLFW_KEY_SPECIAL+35)
+#define GLFW_KEY_RALT         (GLFW_KEY_SPECIAL+36)
+#define GLFW_KEY_TAB          (GLFW_KEY_SPECIAL+37)
+#define GLFW_KEY_ENTER        (GLFW_KEY_SPECIAL+38)
+#define GLFW_KEY_BACKSPACE    (GLFW_KEY_SPECIAL+39)
+#define GLFW_KEY_INSERT       (GLFW_KEY_SPECIAL+40)
+#define GLFW_KEY_DEL          (GLFW_KEY_SPECIAL+41)
+#define GLFW_KEY_PAGEUP       (GLFW_KEY_SPECIAL+42)
+#define GLFW_KEY_PAGEDOWN     (GLFW_KEY_SPECIAL+43)
+#define GLFW_KEY_HOME         (GLFW_KEY_SPECIAL+44)
+#define GLFW_KEY_END          (GLFW_KEY_SPECIAL+45)
+#define GLFW_KEY_KP_0         (GLFW_KEY_SPECIAL+46)
+#define GLFW_KEY_KP_1         (GLFW_KEY_SPECIAL+47)
+#define GLFW_KEY_KP_2         (GLFW_KEY_SPECIAL+48)
+#define GLFW_KEY_KP_3         (GLFW_KEY_SPECIAL+49)
+#define GLFW_KEY_KP_4         (GLFW_KEY_SPECIAL+50)
+#define GLFW_KEY_KP_5         (GLFW_KEY_SPECIAL+51)
+#define GLFW_KEY_KP_6         (GLFW_KEY_SPECIAL+52)
+#define GLFW_KEY_KP_7         (GLFW_KEY_SPECIAL+53)
+#define GLFW_KEY_KP_8         (GLFW_KEY_SPECIAL+54)
+#define GLFW_KEY_KP_9         (GLFW_KEY_SPECIAL+55)
+#define GLFW_KEY_KP_DIVIDE    (GLFW_KEY_SPECIAL+56)
+#define GLFW_KEY_KP_MULTIPLY  (GLFW_KEY_SPECIAL+57)
+#define GLFW_KEY_KP_SUBTRACT  (GLFW_KEY_SPECIAL+58)
+#define GLFW_KEY_KP_ADD       (GLFW_KEY_SPECIAL+59)
+#define GLFW_KEY_KP_DECIMAL   (GLFW_KEY_SPECIAL+60)
+#define GLFW_KEY_KP_EQUAL     (GLFW_KEY_SPECIAL+61)
+#define GLFW_KEY_KP_ENTER     (GLFW_KEY_SPECIAL+62)
+#define GLFW_KEY_KP_NUM_LOCK  (GLFW_KEY_SPECIAL+63)
+#define GLFW_KEY_CAPS_LOCK    (GLFW_KEY_SPECIAL+64)
+#define GLFW_KEY_SCROLL_LOCK  (GLFW_KEY_SPECIAL+65)
+#define GLFW_KEY_PAUSE        (GLFW_KEY_SPECIAL+66)
+#define GLFW_KEY_LSUPER       (GLFW_KEY_SPECIAL+67)
+#define GLFW_KEY_RSUPER       (GLFW_KEY_SPECIAL+68)
+#define GLFW_KEY_MENU         (GLFW_KEY_SPECIAL+69)
+#define GLFW_KEY_LAST         GLFW_KEY_MENU
+
+/* Mouse button definitions */
+#define GLFW_MOUSE_BUTTON_1      0
+#define GLFW_MOUSE_BUTTON_2      1
+#define GLFW_MOUSE_BUTTON_3      2
+#define GLFW_MOUSE_BUTTON_4      3
+#define GLFW_MOUSE_BUTTON_5      4
+#define GLFW_MOUSE_BUTTON_6      5
+#define GLFW_MOUSE_BUTTON_7      6
+#define GLFW_MOUSE_BUTTON_8      7
+#define GLFW_MOUSE_BUTTON_LAST   GLFW_MOUSE_BUTTON_8
+
+/* Mouse button aliases */
+#define GLFW_MOUSE_BUTTON_LEFT   GLFW_MOUSE_BUTTON_1
+#define GLFW_MOUSE_BUTTON_RIGHT  GLFW_MOUSE_BUTTON_2
+#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3
+
+
+/* Joystick identifiers */
+#define GLFW_JOYSTICK_1          0
+#define GLFW_JOYSTICK_2          1
+#define GLFW_JOYSTICK_3          2
+#define GLFW_JOYSTICK_4          3
+#define GLFW_JOYSTICK_5          4
+#define GLFW_JOYSTICK_6          5
+#define GLFW_JOYSTICK_7          6
+#define GLFW_JOYSTICK_8          7
+#define GLFW_JOYSTICK_9          8
+#define GLFW_JOYSTICK_10         9
+#define GLFW_JOYSTICK_11         10
+#define GLFW_JOYSTICK_12         11
+#define GLFW_JOYSTICK_13         12
+#define GLFW_JOYSTICK_14         13
+#define GLFW_JOYSTICK_15         14
+#define GLFW_JOYSTICK_16         15
+#define GLFW_JOYSTICK_LAST       GLFW_JOYSTICK_16
+
+
+/*************************************************************************
+ * Other definitions
+ *************************************************************************/
+
+/* glfwOpenWindow modes */
+#define GLFW_WINDOW               0x00010001
+#define GLFW_FULLSCREEN           0x00010002
+
+/* glfwGetWindowParam tokens */
+#define GLFW_OPENED               0x00020001
+#define GLFW_ACTIVE               0x00020002
+#define GLFW_ICONIFIED            0x00020003
+#define GLFW_ACCELERATED          0x00020004
+#define GLFW_RED_BITS             0x00020005
+#define GLFW_GREEN_BITS           0x00020006
+#define GLFW_BLUE_BITS            0x00020007
+#define GLFW_ALPHA_BITS           0x00020008
+#define GLFW_DEPTH_BITS           0x00020009
+#define GLFW_STENCIL_BITS         0x0002000A
+
+/* The following constants are used for both glfwGetWindowParam
+ * and glfwOpenWindowHint
+ */
+#define GLFW_REFRESH_RATE         0x0002000B
+#define GLFW_ACCUM_RED_BITS       0x0002000C
+#define GLFW_ACCUM_GREEN_BITS     0x0002000D
+#define GLFW_ACCUM_BLUE_BITS      0x0002000E
+#define GLFW_ACCUM_ALPHA_BITS     0x0002000F
+#define GLFW_AUX_BUFFERS          0x00020010
+#define GLFW_STEREO               0x00020011
+#define GLFW_WINDOW_NO_RESIZE     0x00020012
+#define GLFW_FSAA_SAMPLES         0x00020013
+#define GLFW_OPENGL_VERSION_MAJOR 0x00020014
+#define GLFW_OPENGL_VERSION_MINOR 0x00020015
+#define GLFW_OPENGL_FORWARD_COMPAT 0x00020016
+#define GLFW_OPENGL_DEBUG_CONTEXT 0x00020017
+#define GLFW_OPENGL_PROFILE       0x00020018
+
+/* GLFW_OPENGL_PROFILE tokens */
+#define GLFW_OPENGL_CORE_PROFILE  0x00050001
+#define GLFW_OPENGL_COMPAT_PROFILE 0x00050002
+
+/* glfwEnable/glfwDisable tokens */
+#define GLFW_MOUSE_CURSOR         0x00030001
+#define GLFW_STICKY_KEYS          0x00030002
+#define GLFW_STICKY_MOUSE_BUTTONS 0x00030003
+#define GLFW_SYSTEM_KEYS          0x00030004
+#define GLFW_KEY_REPEAT           0x00030005
+#define GLFW_AUTO_POLL_EVENTS     0x00030006
+
+/* glfwWaitThread wait modes */
+#define GLFW_WAIT                 0x00040001
+#define GLFW_NOWAIT               0x00040002
+
+/* glfwGetJoystickParam tokens */
+#define GLFW_PRESENT              0x00050001
+#define GLFW_AXES                 0x00050002
+#define GLFW_BUTTONS              0x00050003
+
+/* glfwReadImage/glfwLoadTexture2D flags */
+#define GLFW_NO_RESCALE_BIT       0x00000001 /* Only for glfwReadImage */
+#define GLFW_ORIGIN_UL_BIT        0x00000002
+#define GLFW_BUILD_MIPMAPS_BIT    0x00000004 /* Only for glfwLoadTexture2D */
+#define GLFW_ALPHA_MAP_BIT        0x00000008
+
+/* Time spans longer than this (seconds) are considered to be infinity */
+#define GLFW_INFINITY 100000.0
+
+
+/*************************************************************************
+ * Typedefs
+ *************************************************************************/
+
+/* The video mode structure used by glfwGetVideoModes() */
+typedef struct {
+    int Width, Height;
+    int RedBits, BlueBits, GreenBits;
+} GLFWvidmode;
+
+/* Image/texture information */
+typedef struct {
+    int Width, Height;
+    int Format;
+    int BytesPerPixel;
+    unsigned char *Data;
+} GLFWimage;
+
+/* Thread ID */
+typedef int GLFWthread;
+
+/* Mutex object */
+typedef void * GLFWmutex;
+
+/* Condition variable object */
+typedef void * GLFWcond;
+
+/* Function pointer types */
+typedef void (GLFWCALL * GLFWwindowsizefun)(int,int);
+typedef int  (GLFWCALL * GLFWwindowclosefun)(void);
+typedef void (GLFWCALL * GLFWwindowrefreshfun)(void);
+typedef void (GLFWCALL * GLFWmousebuttonfun)(int,int);
+typedef void (GLFWCALL * GLFWmouseposfun)(int,int);
+typedef void (GLFWCALL * GLFWmousewheelfun)(int);
+typedef void (GLFWCALL * GLFWkeyfun)(int,int);
+typedef void (GLFWCALL * GLFWcharfun)(int,int);
+typedef void (GLFWCALL * GLFWthreadfun)(void *);
+
+
+/*************************************************************************
+ * Prototypes
+ *************************************************************************/
+
+/* GLFW initialization, termination and version querying */
+GLFWAPI int  GLFWAPIENTRY glfwInit( void );
+GLFWAPI void GLFWAPIENTRY glfwTerminate( void );
+GLFWAPI void GLFWAPIENTRY glfwGetVersion( int *major, int *minor, int *rev );
+
+/* Window handling */
+GLFWAPI int  GLFWAPIENTRY glfwOpenWindow( int width, int height, int redbits, int greenbits, int bluebits, int alphabits, int depthbits, int stencilbits, int mode );
+GLFWAPI void GLFWAPIENTRY glfwOpenWindowHint( int target, int hint );
+GLFWAPI void GLFWAPIENTRY glfwCloseWindow( void );
+GLFWAPI void GLFWAPIENTRY glfwSetWindowTitle( const char *title );
+GLFWAPI void GLFWAPIENTRY glfwGetWindowSize( int *width, int *height );
+GLFWAPI void GLFWAPIENTRY glfwSetWindowSize( int width, int height );
+GLFWAPI void GLFWAPIENTRY glfwSetWindowPos( int x, int y );
+GLFWAPI void GLFWAPIENTRY glfwIconifyWindow( void );
+GLFWAPI void GLFWAPIENTRY glfwRestoreWindow( void );
+GLFWAPI void GLFWAPIENTRY glfwSwapBuffers( void );
+GLFWAPI void GLFWAPIENTRY glfwSwapInterval( int interval );
+GLFWAPI int  GLFWAPIENTRY glfwGetWindowParam( int param );
+GLFWAPI void GLFWAPIENTRY glfwSetWindowSizeCallback( GLFWwindowsizefun cbfun );
+GLFWAPI void GLFWAPIENTRY glfwSetWindowCloseCallback( GLFWwindowclosefun cbfun );
+GLFWAPI void GLFWAPIENTRY glfwSetWindowRefreshCallback( GLFWwindowrefreshfun cbfun );
+
+/* Video mode functions */
+GLFWAPI int  GLFWAPIENTRY glfwGetVideoModes( GLFWvidmode *list, int maxcount );
+GLFWAPI void GLFWAPIENTRY glfwGetDesktopMode( GLFWvidmode *mode );
+
+/* Input handling */
+GLFWAPI void GLFWAPIENTRY glfwPollEvents( void );
+GLFWAPI void GLFWAPIENTRY glfwWaitEvents( void );
+GLFWAPI int  GLFWAPIENTRY glfwGetKey( int key );
+GLFWAPI int  GLFWAPIENTRY glfwGetMouseButton( int button );
+GLFWAPI void GLFWAPIENTRY glfwGetMousePos( int *xpos, int *ypos );
+GLFWAPI void GLFWAPIENTRY glfwSetMousePos( int xpos, int ypos );
+GLFWAPI int  GLFWAPIENTRY glfwGetMouseWheel( void );
+GLFWAPI void GLFWAPIENTRY glfwSetMouseWheel( int pos );
+GLFWAPI void GLFWAPIENTRY glfwSetKeyCallback( GLFWkeyfun cbfun );
+GLFWAPI void GLFWAPIENTRY glfwSetCharCallback( GLFWcharfun cbfun );
+GLFWAPI void GLFWAPIENTRY glfwSetMouseButtonCallback( GLFWmousebuttonfun cbfun );
+GLFWAPI void GLFWAPIENTRY glfwSetMousePosCallback( GLFWmouseposfun cbfun );
+GLFWAPI void GLFWAPIENTRY glfwSetMouseWheelCallback( GLFWmousewheelfun cbfun );
+
+/* Joystick input */
+GLFWAPI int GLFWAPIENTRY glfwGetJoystickParam( int joy, int param );
+GLFWAPI int GLFWAPIENTRY glfwGetJoystickPos( int joy, float *pos, int numaxes );
+GLFWAPI int GLFWAPIENTRY glfwGetJoystickButtons( int joy, unsigned char *buttons, int numbuttons );
+
+/* Time */
+GLFWAPI double GLFWAPIENTRY glfwGetTime( void );
+GLFWAPI void   GLFWAPIENTRY glfwSetTime( double time );
+GLFWAPI void   GLFWAPIENTRY glfwSleep( double time );
+
+/* Extension support */
+GLFWAPI int   GLFWAPIENTRY glfwExtensionSupported( const char *extension );
+GLFWAPI void* GLFWAPIENTRY glfwGetProcAddress( const char *procname );
+GLFWAPI void  GLFWAPIENTRY glfwGetGLVersion( int *major, int *minor, int *rev );
+
+/* Threading support */
+GLFWAPI GLFWthread GLFWAPIENTRY glfwCreateThread( GLFWthreadfun fun, void *arg );
+GLFWAPI void GLFWAPIENTRY glfwDestroyThread( GLFWthread ID );
+GLFWAPI int  GLFWAPIENTRY glfwWaitThread( GLFWthread ID, int waitmode );
+GLFWAPI GLFWthread GLFWAPIENTRY glfwGetThreadID( void );
+GLFWAPI GLFWmutex GLFWAPIENTRY glfwCreateMutex( void );
+GLFWAPI void GLFWAPIENTRY glfwDestroyMutex( GLFWmutex mutex );
+GLFWAPI void GLFWAPIENTRY glfwLockMutex( GLFWmutex mutex );
+GLFWAPI void GLFWAPIENTRY glfwUnlockMutex( GLFWmutex mutex );
+GLFWAPI GLFWcond GLFWAPIENTRY glfwCreateCond( void );
+GLFWAPI void GLFWAPIENTRY glfwDestroyCond( GLFWcond cond );
+GLFWAPI void GLFWAPIENTRY glfwWaitCond( GLFWcond cond, GLFWmutex mutex, double timeout );
+GLFWAPI void GLFWAPIENTRY glfwSignalCond( GLFWcond cond );
+GLFWAPI void GLFWAPIENTRY glfwBroadcastCond( GLFWcond cond );
+GLFWAPI int  GLFWAPIENTRY glfwGetNumberOfProcessors( void );
+
+/* Enable/disable functions */
+GLFWAPI void GLFWAPIENTRY glfwEnable( int token );
+GLFWAPI void GLFWAPIENTRY glfwDisable( int token );
+
+/* Image/texture I/O support */
+GLFWAPI int  GLFWAPIENTRY glfwReadImage( const char *name, GLFWimage *img, int flags );
+GLFWAPI int  GLFWAPIENTRY glfwReadMemoryImage( const void *data, long size, GLFWimage *img, int flags );
+GLFWAPI void GLFWAPIENTRY glfwFreeImage( GLFWimage *img );
+GLFWAPI int  GLFWAPIENTRY glfwLoadTexture2D( const char *name, int flags );
+GLFWAPI int  GLFWAPIENTRY glfwLoadMemoryTexture2D( const void *data, long size, int flags );
+GLFWAPI int  GLFWAPIENTRY glfwLoadTextureImage2D( GLFWimage *img, int flags );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __glfw_h_ */
+

+ 43 - 0
ThirdParty/GLFW/lib/carbon/carbon_enable.c

@@ -0,0 +1,43 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Carbon/AGL/CGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003      Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund <[email protected]>
+//
+// 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.
+//
+//========================================================================
+
+void _glfwPlatformEnableSystemKeys( void )
+{
+    // Nothing to do; event handling code checks the status of
+    // _glfwWin.sysKeysDisabled to ensure this behavior.
+}
+
+void _glfwPlatformDisableSystemKeys( void )
+{
+    // Nothing to do; event handling code checks the status of
+    // _glfwWin.sysKeysDisabled to ensure this behavior.
+}
+

+ 127 - 0
ThirdParty/GLFW/lib/carbon/carbon_fullscreen.c

@@ -0,0 +1,127 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Carbon/AGL/CGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003      Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+//========================================================================
+// _glfwVideoModesEqual() - Compares two video modes
+//========================================================================
+
+static int _glfwVideoModesEqual( GLFWvidmode* first,
+                                 GLFWvidmode* second )
+{
+    if( first->Width != second->Width )
+	return 0;
+		
+    if( first->Height != second->Height )
+	return 0;
+		
+    if( first->RedBits + first->GreenBits + first->BlueBits !=
+      second->RedBits + second->GreenBits + second->BlueBits )
+	return 0;
+	
+    return 1;
+}
+                            
+//========================================================================
+// _glfwCGToGLFWVideoMode() - Converts a CG mode to a GLFW mode
+//========================================================================
+
+static void _glfwCGToGLFWVideoMode( CFDictionaryRef cgMode,
+                                    GLFWvidmode* glfwMode )
+{
+    int bitsPerSample;
+
+    CFNumberGetValue( CFDictionaryGetValue( cgMode, kCGDisplayWidth ),
+                     kCFNumberIntType,
+                     &(glfwMode->Width) );
+    CFNumberGetValue( CFDictionaryGetValue( cgMode, kCGDisplayHeight ),
+                     kCFNumberIntType,
+                     &(glfwMode->Height) );
+
+    CFNumberGetValue( CFDictionaryGetValue( cgMode, kCGDisplayBitsPerSample ),
+                     kCFNumberIntType,
+                     &bitsPerSample );
+
+    glfwMode->RedBits = bitsPerSample;
+    glfwMode->GreenBits = bitsPerSample;
+    glfwMode->BlueBits = bitsPerSample;
+}
+
+//========================================================================
+// _glfwPlatformGetVideoModes() - Get a list of available video modes
+//========================================================================
+
+int _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount )
+{
+    int i, j, maxModes, numModes;
+    GLFWvidmode mode;
+    CFArrayRef availableModes = CGDisplayAvailableModes( kCGDirectMainDisplay );
+    CFIndex numberOfAvailableModes = CFArrayGetCount( availableModes );
+
+    numModes = 0;
+    maxModes = ( numberOfAvailableModes < maxcount ?
+                 numberOfAvailableModes :
+                 maxcount );
+
+    for( i = 0; i < maxModes; ++i )
+    {
+        _glfwCGToGLFWVideoMode( CFArrayGetValueAtIndex( availableModes, i ),
+                                &mode );
+
+        // Is it a valid mode? (only list depths >= 15 bpp)
+	if( mode.RedBits + mode.GreenBits + mode.BlueBits < 15 )
+	    continue;
+			
+        // Check for duplicate of current mode in target list
+      	for( j = 0; j < numModes; ++j )
+      	{
+      	    if( _glfwVideoModesEqual( &mode, &(list[j]) ) )
+      		break;
+      	}
+      	
+      	// If empty list or no match found
+      	if( numModes == 0 || j == numModes )
+      	    list[numModes++] = mode;
+    }
+
+    return numModes;
+}
+
+//========================================================================
+// glfwGetDesktopMode() - Get the desktop video mode
+//========================================================================
+
+void _glfwPlatformGetDesktopMode( GLFWvidmode *mode )
+{
+    _glfwCGToGLFWVideoMode( _glfwDesktopVideoMode, mode );
+}
+

+ 53 - 0
ThirdParty/GLFW/lib/carbon/carbon_glext.c

@@ -0,0 +1,53 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Carbon/AGL/CGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003      Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+int _glfwPlatformExtensionSupported( const char *extension )
+{
+    // There are no AGL, CGL or NSGL extensions.
+    return GL_FALSE;
+}
+
+void * _glfwPlatformGetProcAddress( const char *procname )
+{
+    CFStringRef symbolName = CFStringCreateWithCString( kCFAllocatorDefault,
+                                                        procname,
+                                                        kCFStringEncodingASCII );
+
+    void *symbol = CFBundleGetFunctionPointerForName( _glfwLibrary.Libs.OpenGLFramework,
+                                                      symbolName );
+
+    CFRelease( symbolName );
+
+    return symbol;
+}
+

+ 181 - 0
ThirdParty/GLFW/lib/carbon/carbon_init.c

@@ -0,0 +1,181 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Carbon/AGL/CGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003      Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund <[email protected]>
+// Copyright (c) 2006-2007 Robin Leffmann
+//
+// 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"
+
+#include <unistd.h>
+
+//========================================================================
+// Global variables
+//========================================================================
+
+// KCHR resource pointer for keycode translation
+void *KCHRPtr;
+
+
+//========================================================================
+// Terminate GLFW when exiting application
+//========================================================================
+
+static void glfw_atexit( void )
+{
+    glfwTerminate();
+}
+
+
+//========================================================================
+// _glfwInitThreads() - Initialize GLFW thread package
+//========================================================================
+
+static void _glfwInitThreads( void )
+{
+    // Initialize critical section handle
+    (void) pthread_mutex_init( &_glfwThrd.CriticalSection, NULL );
+
+    // 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.PosixID  = pthread_self();
+    _glfwThrd.First.Previous = NULL;
+    _glfwThrd.First.Next     = NULL;
+}
+
+#define NO_BUNDLE_MESSAGE \
+    "Working in unbundled mode.  " \
+    "You should build a .app wrapper for your Mac OS X applications.\n"
+
+#define UNBUNDLED \
+    fprintf(stderr, NO_BUNDLE_MESSAGE); \
+    _glfwLibrary.Unbundled = 1; \
+    return
+
+void _glfwChangeToResourcesDirectory( void )
+{
+    CFBundleRef mainBundle = CFBundleGetMainBundle();
+    if( mainBundle == NULL )
+    {
+        UNBUNDLED;
+    }
+
+    CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL( mainBundle );
+    char resourcesPath[ _GLFW_MAX_PATH_LENGTH ];
+
+    CFStringRef lastComponent = CFURLCopyLastPathComponent( resourcesURL );
+    if( kCFCompareEqualTo != CFStringCompare(
+            CFSTR( "Resources" ),
+            lastComponent,
+            0 ) )
+    {
+        UNBUNDLED;
+    }
+
+    CFRelease( lastComponent );
+
+    if( !CFURLGetFileSystemRepresentation( resourcesURL,
+                                           TRUE,
+                                           (UInt8*)resourcesPath,
+                                           _GLFW_MAX_PATH_LENGTH ) )
+    {
+        CFRelease( resourcesURL );
+        UNBUNDLED;
+    }
+
+    CFRelease( resourcesURL );
+
+    if( chdir( resourcesPath ) != 0 )
+    {
+        UNBUNDLED;
+    }
+}
+
+int _glfwPlatformInit( void )
+{
+    struct timeval tv;
+    UInt32 nullDummy = 0;
+
+    _glfwWin.window = NULL;
+    _glfwWin.aglContext = NULL;
+    _glfwWin.cglContext = NULL;
+    _glfwWin.windowUPP = NULL;
+
+    _glfwInput.Modifiers = 0;
+
+    _glfwLibrary.Unbundled = 0;
+
+    _glfwLibrary.Libs.OpenGLFramework =
+        CFBundleGetBundleWithIdentifier( CFSTR( "com.apple.opengl" ) );
+    if( _glfwLibrary.Libs.OpenGLFramework == NULL )
+    {
+        fprintf( stderr, "glfwInit failing because you aren't linked to OpenGL\n" );
+        return GL_FALSE;
+    }
+
+    _glfwDesktopVideoMode = CGDisplayCurrentMode( kCGDirectMainDisplay );
+    if( _glfwDesktopVideoMode == NULL )
+    {
+        fprintf( stderr, "glfwInit failing because it kind find the desktop display mode\n" );
+        return GL_FALSE;
+    }
+
+    // Install atexit routine
+    atexit( glfw_atexit );
+
+    _glfwInitThreads();
+
+    _glfwChangeToResourcesDirectory();
+
+    // Ugly hack to reduce the nasty jump that occurs at the first non-
+    // sys keypress, caused by OS X loading certain meta scripts used
+    // for lexical- and raw keycode translation - instead of letting
+    // this happen while our application is running, we do some blunt
+    // function calls in advance just to get the script caching out of
+    // the way BEFORE our window/screen is opened. These calls might
+    // generate err return codes, but we don't care in this case.
+    // NOTE: KCHRPtr is declared globally, because we need it later on.
+    KCHRPtr = (void *)GetScriptVariable( smCurrentScript, smKCHRCache );
+    KeyTranslate( KCHRPtr, 0, &nullDummy );
+    UppercaseText( (char *)&nullDummy, 0, smSystemScript );
+
+    gettimeofday( &tv, NULL );
+    _glfwLibrary.Timer.t0 = tv.tv_sec + (double) tv.tv_usec / 1000000.0;
+
+    return GL_TRUE;
+}
+
+int _glfwPlatformTerminate( void )
+{
+    return GL_TRUE;
+}
+

+ 51 - 0
ThirdParty/GLFW/lib/carbon/carbon_joystick.c

@@ -0,0 +1,51 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Carbon/AGL/CGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003      Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+// TO DO: use HID manager to implement joystick support.
+
+int _glfwPlatformGetJoystickParam( int joy, int param )
+{
+    // GL_FALSE == 0
+    return 0;
+}
+
+int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes )
+{
+    return 0;
+}
+
+int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons, int numbuttons )
+{
+    return 0;
+}
+

+ 415 - 0
ThirdParty/GLFW/lib/carbon/carbon_thread.c

@@ -0,0 +1,415 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Carbon/AGL/CGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003      Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund <[email protected]>
+//
+// 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                       ****
+//************************************************************************
+
+//========================================================================
+// _glfwNewThread() - This is simply a "wrapper" for calling the user
+// thread function.
+//========================================================================
+
+void * _glfwNewThread( void * arg )
+{
+    GLFWthreadfun threadfun;
+    _GLFWthread   *t;
+
+    // Get pointer to thread information for current thread
+    t = _glfwGetThreadPointer( glfwGetThreadID() );
+    if( t == NULL )
+    {
+        return 0;
+    }
+
+    // Get user thread function pointer
+    threadfun = t->Function;
+
+    // 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;
+}
+
+
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// _glfwPlatformCreateThread() - Create a new thread
+//========================================================================
+
+GLFWthread _glfwPlatformCreateThread( GLFWthreadfun fun, void *arg )
+{
+    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;
+}
+
+
+//========================================================================
+// _glfwPlatformDestroyThread() - Kill a thread. NOTE: THIS IS A VERY
+// DANGEROUS OPERATION, AND SHOULD NOT BE USED EXCEPT IN EXTREME
+// SITUATIONS!
+//========================================================================
+
+void _glfwPlatformDestroyThread( GLFWthread ID )
+{
+    _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
+}
+
+
+//========================================================================
+// _glfwPlatformWaitThread() - Wait for a thread to die
+//========================================================================
+
+int _glfwPlatformWaitThread( GLFWthread ID, int waitmode )
+{
+    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;
+}
+
+
+//========================================================================
+// _glfwPlatformGetThreadID() - Return the thread ID for the current
+// thread
+//========================================================================
+
+GLFWthread _glfwPlatformGetThreadID( void )
+{
+    _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;
+}
+
+
+//========================================================================
+// _glfwPlatformCreateMutex() - Create a mutual exclusion object
+//========================================================================
+
+GLFWmutex _glfwPlatformCreateMutex( void )
+{
+    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;
+}
+
+
+//========================================================================
+// _glfwPlatformDestroyMutex() - Destroy a mutual exclusion object
+//========================================================================
+
+void _glfwPlatformDestroyMutex( GLFWmutex mutex )
+{
+    // Destroy the mutex object
+    pthread_mutex_destroy( (pthread_mutex_t *) mutex );
+
+    // Free memory for mutex object
+    free( (void *) mutex );
+}
+
+
+//========================================================================
+// _glfwPlatformLockMutex() - Request access to a mutex
+//========================================================================
+
+void _glfwPlatformLockMutex( GLFWmutex mutex )
+{
+    // Wait for mutex to be released
+    (void) pthread_mutex_lock( (pthread_mutex_t *) mutex );
+}
+
+
+//========================================================================
+// _glfwPlatformUnlockMutex() - Release a mutex
+//========================================================================
+
+void _glfwPlatformUnlockMutex( GLFWmutex mutex )
+{
+    // Release mutex
+    pthread_mutex_unlock( (pthread_mutex_t *) mutex );
+}
+
+
+//========================================================================
+// _glfwPlatformCreateCond() - Create a new condition variable object
+//========================================================================
+
+GLFWcond _glfwPlatformCreateCond( void )
+{
+    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;
+}
+
+
+//========================================================================
+// _glfwPlatformDestroyCond() - Destroy a condition variable object
+//========================================================================
+
+void _glfwPlatformDestroyCond( GLFWcond cond )
+{
+    // Destroy the condition variable object
+    (void) pthread_cond_destroy( (pthread_cond_t *) cond );
+
+    // Free memory for condition variable object
+    free( (void *) cond );
+}
+
+
+//========================================================================
+// _glfwPlatformWaitCond() - Wait for a condition to be raised
+//========================================================================
+
+void _glfwPlatformWaitCond( GLFWcond cond, GLFWmutex mutex,
+                            double timeout )
+{
+    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 );
+    }
+}
+
+
+//========================================================================
+// _glfwPlatformSignalCond() - Signal a condition to one waiting thread
+//========================================================================
+
+void _glfwPlatformSignalCond( GLFWcond cond )
+{
+    // Signal condition
+    (void) pthread_cond_signal( (pthread_cond_t *) cond );
+}
+
+
+//========================================================================
+// _glfwPlatformBroadcastCond() - Broadcast a condition to all waiting
+// threads
+//========================================================================
+
+void _glfwPlatformBroadcastCond( GLFWcond cond )
+{
+    // Broadcast condition
+    (void) pthread_cond_broadcast( (pthread_cond_t *) cond );
+}
+
+
+//========================================================================
+// _glfwPlatformGetNumberOfProcessors() - Return the number of processors
+// in the system.
+//========================================================================
+
+int _glfwPlatformGetNumberOfProcessors( void )
+{
+    int n;
+
+    // Get number of processors online
+    _glfw_numprocessors( n );
+    return n;
+}
+

+ 113 - 0
ThirdParty/GLFW/lib/carbon/carbon_time.c

@@ -0,0 +1,113 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Carbon/AGL/CGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003      Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund <[email protected]>
+//
+// 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                ****
+//************************************************************************
+
+//========================================================================
+// Return timer value in seconds
+//========================================================================
+
+double _glfwPlatformGetTime( void )
+{
+    struct timeval  tv;
+
+    gettimeofday( &tv, NULL );
+    return tv.tv_sec + (double) tv.tv_usec / 1000000.0 - _glfwLibrary.Timer.t0;
+}
+
+
+//========================================================================
+// Set timer value in seconds
+//========================================================================
+
+void _glfwPlatformSetTime( double time )
+{
+    struct timeval  tv;
+
+    gettimeofday( &tv, NULL );
+    _glfwLibrary.Timer.t0 = tv.tv_sec + (double) tv.tv_usec / 1000000.0 - time;
+}
+
+
+//========================================================================
+// Put a thread to sleep for a specified amount of time
+//========================================================================
+
+void _glfwPlatformSleep( double time )
+{
+    if( time == 0.0 )
+    {
+	sched_yield();
+	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 );
+}
+

+ 1309 - 0
ThirdParty/GLFW/lib/carbon/carbon_window.c

@@ -0,0 +1,1309 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Carbon/AGL/CGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003      Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund <[email protected]>
+// Copyright (c) 2006-2007 Robin Leffmann
+//
+// 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"
+
+#define _glfwTestModifier( modifierMask, glfwKey ) \
+if ( changed & modifierMask ) \
+{ \
+    _glfwInputKey( glfwKey, (modifiers & modifierMask ? GLFW_PRESS : GLFW_RELEASE) ); \
+}
+
+//************************************************************************
+//****                  GLFW internal functions                       ****
+//************************************************************************
+
+static void handleMacModifierChange( UInt32 modifiers )
+{
+    UInt32 changed = modifiers ^ _glfwInput.Modifiers;
+
+    // The right *key variants below never actually occur
+    // There also isn't even a broken right command key constant
+    _glfwTestModifier( shiftKey,        GLFW_KEY_LSHIFT );
+    _glfwTestModifier( rightShiftKey,   GLFW_KEY_RSHIFT );
+    _glfwTestModifier( controlKey,      GLFW_KEY_LCTRL );
+    _glfwTestModifier( rightControlKey, GLFW_KEY_RCTRL );
+    _glfwTestModifier( optionKey,       GLFW_KEY_LALT );
+    _glfwTestModifier( rightOptionKey,  GLFW_KEY_RALT );
+    _glfwTestModifier( cmdKey,          GLFW_KEY_LSUPER );
+
+    _glfwInput.Modifiers = modifiers;
+}
+
+static void handleMacKeyChange( UInt32 keyCode, int action )
+{
+    switch ( keyCode )
+    {
+        case MAC_KEY_ENTER:       _glfwInputKey( GLFW_KEY_ENTER,       action); break;
+        case MAC_KEY_RETURN:      _glfwInputKey( GLFW_KEY_KP_ENTER,    action); break;
+        case MAC_KEY_ESC:         _glfwInputKey( GLFW_KEY_ESC,         action); break;
+        case MAC_KEY_F1:          _glfwInputKey( GLFW_KEY_F1,          action); break;
+        case MAC_KEY_F2:          _glfwInputKey( GLFW_KEY_F2,          action); break;
+        case MAC_KEY_F3:          _glfwInputKey( GLFW_KEY_F3,          action); break;
+        case MAC_KEY_F4:          _glfwInputKey( GLFW_KEY_F4,          action); break;
+        case MAC_KEY_F5:          _glfwInputKey( GLFW_KEY_F5,          action); break;
+        case MAC_KEY_F6:          _glfwInputKey( GLFW_KEY_F6,          action); break;
+        case MAC_KEY_F7:          _glfwInputKey( GLFW_KEY_F7,          action); break;
+        case MAC_KEY_F8:          _glfwInputKey( GLFW_KEY_F8,          action); break;
+        case MAC_KEY_F9:          _glfwInputKey( GLFW_KEY_F9,          action); break;
+        case MAC_KEY_F10:         _glfwInputKey( GLFW_KEY_F10,         action); break;
+        case MAC_KEY_F11:         _glfwInputKey( GLFW_KEY_F11,         action); break;
+        case MAC_KEY_F12:         _glfwInputKey( GLFW_KEY_F12,         action); break;
+        case MAC_KEY_F13:         _glfwInputKey( GLFW_KEY_F13,         action); break;
+        case MAC_KEY_F14:         _glfwInputKey( GLFW_KEY_F14,         action); break;
+        case MAC_KEY_F15:         _glfwInputKey( GLFW_KEY_F15,         action); break;
+        case MAC_KEY_UP:          _glfwInputKey( GLFW_KEY_UP,          action); break;
+        case MAC_KEY_DOWN:        _glfwInputKey( GLFW_KEY_DOWN,        action); break;
+        case MAC_KEY_LEFT:        _glfwInputKey( GLFW_KEY_LEFT,        action); break;
+        case MAC_KEY_RIGHT:       _glfwInputKey( GLFW_KEY_RIGHT,       action); break;
+        case MAC_KEY_TAB:         _glfwInputKey( GLFW_KEY_TAB,         action); break;
+        case MAC_KEY_BACKSPACE:   _glfwInputKey( GLFW_KEY_BACKSPACE,   action); break;
+        case MAC_KEY_HELP:        _glfwInputKey( GLFW_KEY_INSERT,      action); break;
+        case MAC_KEY_DEL:         _glfwInputKey( GLFW_KEY_DEL,         action); break;
+        case MAC_KEY_PAGEUP:      _glfwInputKey( GLFW_KEY_PAGEUP,      action); break;
+        case MAC_KEY_PAGEDOWN:    _glfwInputKey( GLFW_KEY_PAGEDOWN,    action); break;
+        case MAC_KEY_HOME:        _glfwInputKey( GLFW_KEY_HOME,        action); break;
+        case MAC_KEY_END:         _glfwInputKey( GLFW_KEY_END,         action); break;
+        case MAC_KEY_KP_0:        _glfwInputKey( GLFW_KEY_KP_0,        action); break;
+        case MAC_KEY_KP_1:        _glfwInputKey( GLFW_KEY_KP_1,        action); break;
+        case MAC_KEY_KP_2:        _glfwInputKey( GLFW_KEY_KP_2,        action); break;
+        case MAC_KEY_KP_3:        _glfwInputKey( GLFW_KEY_KP_3,        action); break;
+        case MAC_KEY_KP_4:        _glfwInputKey( GLFW_KEY_KP_4,        action); break;
+        case MAC_KEY_KP_5:        _glfwInputKey( GLFW_KEY_KP_5,        action); break;
+        case MAC_KEY_KP_6:        _glfwInputKey( GLFW_KEY_KP_6,        action); break;
+        case MAC_KEY_KP_7:        _glfwInputKey( GLFW_KEY_KP_7,        action); break;
+        case MAC_KEY_KP_8:        _glfwInputKey( GLFW_KEY_KP_8,        action); break;
+        case MAC_KEY_KP_9:        _glfwInputKey( GLFW_KEY_KP_9,        action); break;
+        case MAC_KEY_KP_DIVIDE:   _glfwInputKey( GLFW_KEY_KP_DIVIDE,   action); break;
+        case MAC_KEY_KP_MULTIPLY: _glfwInputKey( GLFW_KEY_KP_MULTIPLY, action); break;
+        case MAC_KEY_KP_SUBTRACT: _glfwInputKey( GLFW_KEY_KP_SUBTRACT, action); break;
+        case MAC_KEY_KP_ADD:      _glfwInputKey( GLFW_KEY_KP_ADD,      action); break;
+        case MAC_KEY_KP_DECIMAL:  _glfwInputKey( GLFW_KEY_KP_DECIMAL,  action); break;
+        case MAC_KEY_KP_EQUAL:    _glfwInputKey( GLFW_KEY_KP_EQUAL,    action); break;
+        case MAC_KEY_KP_ENTER:    _glfwInputKey( GLFW_KEY_KP_ENTER,    action); break;
+        case MAC_KEY_NUMLOCK:     _glfwInputKey( GLFW_KEY_KP_NUM_LOCK, action); break;
+        default:
+        {
+            extern void *KCHRPtr;
+            UInt32 state = 0;
+            char charCode = (char)KeyTranslate( KCHRPtr, keyCode, &state );
+            UppercaseText( &charCode, 1, smSystemScript );
+            _glfwInputKey( (unsigned char)charCode, action );
+        }
+        break;
+    }
+}
+
+// The set of event class/kind combinations supported by keyEventHandler
+// This is used by installEventHandlers below
+static const EventTypeSpec GLFW_KEY_EVENT_TYPES[] =
+{
+    { kEventClassKeyboard, kEventRawKeyDown },
+    { kEventClassKeyboard, kEventRawKeyUp },
+    { kEventClassKeyboard, kEventRawKeyRepeat },
+    { kEventClassKeyboard, kEventRawKeyModifiersChanged }
+};
+
+static OSStatus keyEventHandler( EventHandlerCallRef handlerCallRef,
+                                 EventRef event,
+                                 void *userData )
+{
+    UInt32 keyCode;
+    short int keyChar;
+    UInt32 modifiers;
+
+    switch( GetEventKind( event ) )
+    {
+        case kEventRawKeyRepeat:
+        case kEventRawKeyDown:
+        {
+            if( GetEventParameter( event,
+                                   kEventParamKeyCode,
+                                   typeUInt32,
+                                   NULL,
+                                   sizeof( UInt32 ),
+                                   NULL,
+                                   &keyCode ) == noErr )
+            {
+                handleMacKeyChange( keyCode, GLFW_PRESS );
+            }
+            if( GetEventParameter( event,
+                                   kEventParamKeyUnicodes,
+                                   typeUnicodeText,
+                                   NULL,
+                                   sizeof(keyChar),
+                                   NULL,
+                                   &keyChar) == noErr )
+            {
+                _glfwInputChar( keyChar, GLFW_PRESS );
+            }
+            return noErr;
+        }
+
+        case kEventRawKeyUp:
+        {
+            if( GetEventParameter( event,
+                                   kEventParamKeyCode,
+                                   typeUInt32,
+                                   NULL,
+                                   sizeof( UInt32 ),
+                                   NULL,
+                                   &keyCode ) == noErr )
+            {
+                handleMacKeyChange( keyCode, GLFW_RELEASE );
+            }
+            if( GetEventParameter( event,
+                                   kEventParamKeyUnicodes,
+                                   typeUnicodeText,
+                                   NULL,
+                                   sizeof(keyChar),
+                                   NULL,
+                                   &keyChar) == noErr )
+            {
+                _glfwInputChar( keyChar, GLFW_RELEASE );
+            }
+            return noErr;
+        }
+
+        case kEventRawKeyModifiersChanged:
+        {
+            if( GetEventParameter( event,
+                                   kEventParamKeyModifiers,
+                                   typeUInt32,
+                                   NULL,
+                                   sizeof( UInt32 ),
+                                   NULL,
+                                   &modifiers ) == noErr )
+            {
+                handleMacModifierChange( modifiers );
+                return noErr;
+            }
+        }
+        break;
+    }
+
+    return eventNotHandledErr;
+}
+
+// The set of event class/kind combinations supported by mouseEventHandler
+// This is used by installEventHandlers below
+static const EventTypeSpec GLFW_MOUSE_EVENT_TYPES[] =
+{
+    { kEventClassMouse, kEventMouseDown },
+    { kEventClassMouse, kEventMouseUp },
+    { kEventClassMouse, kEventMouseMoved },
+    { kEventClassMouse, kEventMouseDragged },
+    { kEventClassMouse, kEventMouseWheelMoved },
+};
+
+static OSStatus mouseEventHandler( EventHandlerCallRef handlerCallRef,
+                                   EventRef event,
+                                   void *userData )
+{
+    switch( GetEventKind( event ) )
+    {
+        case kEventMouseDown:
+        {
+            WindowRef window;
+            EventRecord oldStyleMacEvent;
+            ConvertEventRefToEventRecord( event, &oldStyleMacEvent );
+            if( FindWindow ( oldStyleMacEvent.where, &window ) == inMenuBar )
+            {
+                MenuSelect( oldStyleMacEvent.where );
+                HiliteMenu(0);
+                return noErr;
+            }
+            else
+            {
+                EventMouseButton button;
+                if( GetEventParameter( event,
+                                       kEventParamMouseButton,
+                                       typeMouseButton,
+                                       NULL,
+                                       sizeof( EventMouseButton ),
+                                       NULL,
+                                       &button ) == noErr )
+                {
+                    button -= kEventMouseButtonPrimary;
+                    if( button <= GLFW_MOUSE_BUTTON_LAST )
+                    {
+                        _glfwInputMouseClick( button + GLFW_MOUSE_BUTTON_LEFT,
+                                              GLFW_PRESS );
+                    }
+                    return noErr;
+                }
+            }
+            break;
+        }
+
+        case kEventMouseUp:
+        {
+            EventMouseButton button;
+            if( GetEventParameter( event,
+                                   kEventParamMouseButton,
+                                   typeMouseButton,
+                                   NULL,
+                                   sizeof( EventMouseButton ),
+                                   NULL,
+                                   &button ) == noErr )
+            {
+                button -= kEventMouseButtonPrimary;
+                if( button <= GLFW_MOUSE_BUTTON_LAST )
+                {
+                    _glfwInputMouseClick( button + GLFW_MOUSE_BUTTON_LEFT,
+                                          GLFW_RELEASE );
+                }
+                return noErr;
+            }
+            break;
+        }
+
+        case kEventMouseMoved:
+        case kEventMouseDragged:
+        {
+            HIPoint mouseLocation;
+            if( _glfwWin.mouseLock )
+            {
+                if( GetEventParameter( event,
+                                       kEventParamMouseDelta,
+                                       typeHIPoint,
+                                       NULL,
+                                       sizeof( HIPoint ),
+                                       NULL,
+                                       &mouseLocation ) != noErr )
+                {
+                    break;
+                }
+
+                _glfwInput.MousePosX += mouseLocation.x;
+                _glfwInput.MousePosY += mouseLocation.y;
+            }
+            else
+            {
+                if( GetEventParameter( event,
+                                       kEventParamMouseLocation,
+                                       typeHIPoint,
+                                       NULL,
+                                       sizeof( HIPoint ),
+                                       NULL,
+                                       &mouseLocation ) != noErr )
+                {
+                    break;
+                }
+
+                _glfwInput.MousePosX = mouseLocation.x;
+                _glfwInput.MousePosY = mouseLocation.y;
+
+                if( !_glfwWin.fullscreen )
+                {
+                    Rect content;
+                    GetWindowBounds( _glfwWin.window,
+                                     kWindowContentRgn,
+                                     &content );
+
+                    _glfwInput.MousePosX -= content.left;
+                    _glfwInput.MousePosY -= content.top;
+                }
+            }
+
+            if( _glfwWin.mousePosCallback )
+            {
+                _glfwWin.mousePosCallback( _glfwInput.MousePosX,
+                                           _glfwInput.MousePosY );
+            }
+
+            break;
+        }
+
+        case kEventMouseWheelMoved:
+        {
+            EventMouseWheelAxis axis;
+            if( GetEventParameter( event,
+                                   kEventParamMouseWheelAxis,
+                                   typeMouseWheelAxis,
+                                   NULL,
+                                   sizeof( EventMouseWheelAxis ),
+                                   NULL,
+                                   &axis) == noErr )
+            {
+                long wheelDelta;
+                if( axis == kEventMouseWheelAxisY &&
+                    GetEventParameter( event,
+                                       kEventParamMouseWheelDelta,
+                                       typeLongInteger,
+                                       NULL,
+                                       sizeof( long ),
+                                       NULL,
+                                       &wheelDelta ) == noErr )
+                {
+                    _glfwInput.WheelPos += wheelDelta;
+                    if( _glfwWin.mouseWheelCallback )
+                    {
+                        _glfwWin.mouseWheelCallback( _glfwInput.WheelPos );
+                    }
+                    return noErr;
+                }
+            }
+            break;
+        }
+    }
+
+    return eventNotHandledErr;
+}
+
+// The set of event class/kind combinations supported by commandHandler
+// This is used by installEventHandlers below
+static const EventTypeSpec GLFW_COMMAND_EVENT_TYPES[] =
+{
+    { kEventClassCommand, kEventCommandProcess }
+};
+
+static OSStatus commandHandler( EventHandlerCallRef handlerCallRef,
+                                EventRef event,
+                                void *userData )
+{
+    if( _glfwWin.sysKeysDisabled )
+    {
+        // TODO: Give adequate UI feedback that this is the case
+        return eventNotHandledErr;
+    }
+
+    HICommand command;
+    if( GetEventParameter( event,
+                           kEventParamDirectObject,
+                           typeHICommand,
+                           NULL,
+                           sizeof( HICommand ),
+                           NULL,
+                           &command ) == noErr )
+    {
+        switch( command.commandID )
+        {
+            case kHICommandClose:
+            case kHICommandQuit:
+            {
+                // Check if the program wants us to close the window
+                if( _glfwWin.windowCloseCallback )
+                {
+                    if( _glfwWin.windowCloseCallback() )
+                    {
+                        glfwCloseWindow();
+                    }
+                }
+                else
+                {
+                    glfwCloseWindow();
+                }
+                return noErr;
+            }
+        }
+    }
+
+    return eventNotHandledErr;
+}
+
+// The set of event class/kind combinations supported by windowEventHandler
+// This is used by installEventHandlers below
+static const EventTypeSpec GLFW_WINDOW_EVENT_TYPES[] =
+{
+  { kEventClassWindow, kEventWindowBoundsChanged },
+  { kEventClassWindow, kEventWindowClose },
+  { kEventClassWindow, kEventWindowDrawContent },
+  { kEventClassWindow, kEventWindowActivated },
+  { kEventClassWindow, kEventWindowDeactivated },
+};
+
+static OSStatus windowEventHandler( EventHandlerCallRef handlerCallRef,
+                                    EventRef event,
+                                    void *userData )
+{
+    switch( GetEventKind(event) )
+    {
+        case kEventWindowBoundsChanged:
+        {
+            WindowRef window;
+            GetEventParameter( event,
+                               kEventParamDirectObject,
+                               typeWindowRef,
+                               NULL,
+                               sizeof(WindowRef),
+                               NULL,
+                               &window );
+
+            Rect rect;
+            GetWindowPortBounds( window, &rect );
+
+            if( _glfwWin.width != rect.right ||
+                _glfwWin.height != rect.bottom )
+            {
+                aglUpdateContext( _glfwWin.aglContext );
+
+                _glfwWin.width  = rect.right;
+                _glfwWin.height = rect.bottom;
+                if( _glfwWin.windowSizeCallback )
+                {
+                    _glfwWin.windowSizeCallback( _glfwWin.width, _glfwWin.height );
+                }
+                // Emulate (force) content invalidation
+                if( _glfwWin.windowRefreshCallback )
+                {
+                    _glfwWin.windowRefreshCallback();
+                }
+            }
+            break;
+        }
+
+        case kEventWindowClose:
+        {
+            // Check if the client wants us to close the window
+            if( _glfwWin.windowCloseCallback )
+            {
+                if( _glfwWin.windowCloseCallback() )
+                {
+                        glfwCloseWindow();
+                }
+            }
+            else
+            {
+                glfwCloseWindow();
+            }
+            return noErr;
+        }
+
+        case kEventWindowDrawContent:
+        {
+            if( _glfwWin.windowRefreshCallback )
+            {
+                _glfwWin.windowRefreshCallback();
+            }
+            break;
+        }
+
+        case kEventWindowActivated:
+        {
+            _glfwWin.active = GL_TRUE;
+            break;
+        }
+
+        case kEventWindowDeactivated:
+        {
+            _glfwWin.active = GL_FALSE;
+            _glfwInputDeactivation();
+            break;
+        }
+    }
+
+    return eventNotHandledErr;
+}
+
+static int installEventHandlers( void )
+{
+    OSStatus error;
+
+    _glfwWin.mouseUPP = NewEventHandlerUPP( mouseEventHandler );
+
+    error = InstallEventHandler( GetApplicationEventTarget(),
+                                 _glfwWin.mouseUPP,
+                                 GetEventTypeCount( GLFW_MOUSE_EVENT_TYPES ),
+                                 GLFW_MOUSE_EVENT_TYPES,
+                                 NULL,
+                                 NULL );
+    if( error != noErr )
+    {
+        fprintf( stderr, "Failed to install Carbon application mouse event handler\n" );
+        return GL_FALSE;
+    }
+
+    _glfwWin.commandUPP = NewEventHandlerUPP( commandHandler );
+
+    error = InstallEventHandler( GetApplicationEventTarget(),
+                                 _glfwWin.commandUPP,
+                                 GetEventTypeCount( GLFW_COMMAND_EVENT_TYPES ),
+                                 GLFW_COMMAND_EVENT_TYPES,
+                                 NULL,
+                                 NULL );
+    if( error != noErr )
+    {
+        fprintf( stderr, "Failed to install Carbon application command event handler\n" );
+        return GL_FALSE;
+    }
+
+    _glfwWin.keyboardUPP = NewEventHandlerUPP( keyEventHandler );
+
+    error = InstallEventHandler( GetApplicationEventTarget(),
+                                 _glfwWin.keyboardUPP,
+                                 GetEventTypeCount( GLFW_KEY_EVENT_TYPES ),
+                                 GLFW_KEY_EVENT_TYPES,
+                                 NULL,
+                                 NULL );
+    if( error != noErr )
+    {
+        fprintf( stderr, "Failed to install Carbon application key event handler\n" );
+        return GL_FALSE;
+    }
+
+    return GL_TRUE;
+}
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+#define _setAGLAttribute( aglAttributeName, AGLparameter ) \
+if ( AGLparameter != 0 ) \
+{ \
+    AGLpixelFormatAttributes[numAGLAttrs++] = aglAttributeName; \
+    AGLpixelFormatAttributes[numAGLAttrs++] = AGLparameter; \
+}
+
+#define _setCGLAttribute( cglAttributeName, CGLparameter ) \
+if ( CGLparameter != 0 ) \
+{ \
+    CGLpixelFormatAttributes[ numCGLAttrs++ ] = cglAttributeName; \
+    CGLpixelFormatAttributes[ numCGLAttrs++ ] = CGLparameter; \
+}
+
+//========================================================================
+// Here is where the window is created, and
+// the OpenGL rendering context is created
+//========================================================================
+
+int  _glfwPlatformOpenWindow( int width, int height,
+                              const _GLFWwndconfig *wndconfig,
+                              const _GLFWfbconfig *fbconfig )
+{
+    OSStatus error;
+    unsigned int windowAttributes;
+    ProcessSerialNumber psn;
+
+    // TODO: Break up this function!
+
+    _glfwWin.windowUPP      = NULL;
+    _glfwWin.mouseUPP       = NULL;
+    _glfwWin.keyboardUPP    = NULL;
+    _glfwWin.commandUPP     = NULL;
+    _glfwWin.window         = NULL;
+    _glfwWin.aglContext     = NULL;
+    _glfwWin.aglPixelFormat = NULL;
+    _glfwWin.cglContext     = NULL;
+    _glfwWin.cglPixelFormat = NULL;
+
+    _glfwWin.refreshRate = wndconfig->refreshRate;
+
+    // Fail if OpenGL 3.0 or above was requested
+    if( wndconfig->glMajor > 2 )
+    {
+        fprintf( stderr, "OpenGL 3.0+ is not yet supported on Mac OS X\n" );
+
+        _glfwPlatformCloseWindow();
+        return GL_FALSE;
+    }
+
+    if( _glfwLibrary.Unbundled )
+    {
+        if( GetCurrentProcess( &psn ) != noErr )
+        {
+            fprintf( stderr, "Failed to get the process serial number\n" );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        if( TransformProcessType( &psn, kProcessTransformToForegroundApplication ) != noErr )
+        {
+            fprintf( stderr, "Failed to become a foreground application\n" );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        if( wndconfig->mode == GLFW_FULLSCREEN )
+        {
+            if( SetFrontProcess( &psn ) != noErr )
+            {
+                fprintf( stderr, "Failed to become the front process\n" );
+
+                _glfwPlatformCloseWindow();
+                return GL_FALSE;
+            }
+        }
+    }
+
+    if( !installEventHandlers() )
+    {
+        fprintf( stderr,
+                 "Failed to install Carbon application event handlers\n" );
+
+        _glfwPlatformTerminate();
+        return GL_FALSE;
+    }
+
+    // Windowed or fullscreen; AGL or CGL? Quite the mess...
+    // AGL appears to be the only choice for attaching OpenGL contexts to
+    // Carbon windows, but it leaves the user no control over fullscreen
+    // mode stretching. Solution: AGL for windowed, CGL for fullscreen.
+    if( wndconfig->mode == GLFW_WINDOW )
+    {
+        // create AGL pixel format attribute list
+        GLint AGLpixelFormatAttributes[256];
+        int numAGLAttrs = 0;
+
+        AGLpixelFormatAttributes[numAGLAttrs++] = AGL_RGBA;
+        AGLpixelFormatAttributes[numAGLAttrs++] = AGL_DOUBLEBUFFER;
+        AGLpixelFormatAttributes[numAGLAttrs++] = AGL_CLOSEST_POLICY;
+
+        if( fbconfig->stereo )
+        {
+            AGLpixelFormatAttributes[numAGLAttrs++] = AGL_STEREO;
+        }
+
+        _setAGLAttribute( AGL_AUX_BUFFERS,      fbconfig->auxBuffers);
+        _setAGLAttribute( AGL_RED_SIZE,         fbconfig->redBits );
+        _setAGLAttribute( AGL_GREEN_SIZE,       fbconfig->greenBits );
+        _setAGLAttribute( AGL_BLUE_SIZE,        fbconfig->blueBits );
+        _setAGLAttribute( AGL_ALPHA_SIZE,       fbconfig->alphaBits );
+        _setAGLAttribute( AGL_DEPTH_SIZE,       fbconfig->depthBits );
+        _setAGLAttribute( AGL_STENCIL_SIZE,     fbconfig->stencilBits );
+        _setAGLAttribute( AGL_ACCUM_RED_SIZE,   fbconfig->accumRedBits );
+        _setAGLAttribute( AGL_ACCUM_GREEN_SIZE, fbconfig->accumGreenBits );
+        _setAGLAttribute( AGL_ACCUM_BLUE_SIZE,  fbconfig->accumBlueBits );
+        _setAGLAttribute( AGL_ACCUM_ALPHA_SIZE, fbconfig->accumAlphaBits );
+
+        if( fbconfig->samples > 1 )
+        {
+            _setAGLAttribute( AGL_SAMPLE_BUFFERS_ARB, 1 );
+            _setAGLAttribute( AGL_SAMPLES_ARB, fbconfig->samples );
+            AGLpixelFormatAttributes[numAGLAttrs++] = AGL_NO_RECOVERY;
+        }
+
+        AGLpixelFormatAttributes[numAGLAttrs++] = AGL_NONE;
+
+        // create pixel format descriptor
+        AGLDevice mainMonitor = GetMainDevice();
+        _glfwWin.aglPixelFormat = aglChoosePixelFormat( &mainMonitor,
+                                                        1,
+                                                        AGLpixelFormatAttributes );
+        if( _glfwWin.aglPixelFormat == NULL )
+        {
+            fprintf( stderr,
+                     "Failed to choose AGL pixel format: %s\n",
+                     aglErrorString( aglGetError() ) );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        // create AGL context
+        _glfwWin.aglContext = aglCreateContext( _glfwWin.aglPixelFormat, NULL );
+
+        if( _glfwWin.aglContext == NULL )
+        {
+            fprintf( stderr,
+                     "Failed to create AGL context: %s\n",
+                     aglErrorString( aglGetError() ) );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        // create window
+        Rect windowContentBounds;
+        windowContentBounds.left = 0;
+        windowContentBounds.top = 0;
+        windowContentBounds.right = width;
+        windowContentBounds.bottom = height;
+
+        windowAttributes = ( kWindowCloseBoxAttribute |
+                             kWindowCollapseBoxAttribute |
+                             kWindowStandardHandlerAttribute );
+
+        if( wndconfig->windowNoResize )
+        {
+            windowAttributes |= kWindowLiveResizeAttribute;
+        }
+        else
+        {
+            windowAttributes |= ( kWindowFullZoomAttribute |
+                                  kWindowResizableAttribute );
+        }
+
+        error = CreateNewWindow( kDocumentWindowClass,
+                                 windowAttributes,
+                                 &windowContentBounds,
+                                 &( _glfwWin.window ) );
+        if( ( error != noErr ) || ( _glfwWin.window == NULL ) )
+        {
+            fprintf( stderr, "Failed to create Carbon window\n" );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        _glfwWin.windowUPP = NewEventHandlerUPP( windowEventHandler );
+
+        error = InstallWindowEventHandler( _glfwWin.window,
+                                           _glfwWin.windowUPP,
+                                           GetEventTypeCount( GLFW_WINDOW_EVENT_TYPES ),
+                                           GLFW_WINDOW_EVENT_TYPES,
+                                           NULL,
+                                           NULL );
+        if( error != noErr )
+        {
+            fprintf( stderr, "Failed to install Carbon window event handler\n" );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        // Don't care if we fail here
+        (void)SetWindowTitleWithCFString( _glfwWin.window, CFSTR( "GLFW Window" ) );
+        (void)RepositionWindow( _glfwWin.window,
+                                NULL,
+                                kWindowCenterOnMainScreen );
+
+        if( !aglSetDrawable( _glfwWin.aglContext,
+                             GetWindowPort( _glfwWin.window ) ) )
+        {
+            fprintf( stderr,
+                     "Failed to set the AGL context as the Carbon window drawable: %s\n",
+                     aglErrorString( aglGetError() ) );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        // Make OpenGL context current
+        if( !aglSetCurrentContext( _glfwWin.aglContext ) )
+        {
+            fprintf( stderr,
+                     "Failed to make AGL context current: %s\n",
+                     aglErrorString( aglGetError() ) );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        ShowWindow( _glfwWin.window );
+    }
+    else
+    {
+        CGDisplayErr cgErr;
+        CGLError cglErr;
+
+        CFDictionaryRef optimalMode;
+
+        GLint numCGLvs = 0;
+
+        CGLPixelFormatAttribute CGLpixelFormatAttributes[64];
+        int numCGLAttrs = 0;
+
+        // variables for enumerating color depths
+        GLint rgbColorDepth;
+
+        // CGL pixel format attributes
+        _setCGLAttribute( kCGLPFADisplayMask,
+                          CGDisplayIDToOpenGLDisplayMask( kCGDirectMainDisplay ) );
+
+        if( fbconfig->stereo )
+        {
+            CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAStereo;
+        }
+
+        if( fbconfig->samples > 1 )
+        {
+            _setCGLAttribute( kCGLPFASamples,       (CGLPixelFormatAttribute)fbconfig->samples );
+            _setCGLAttribute( kCGLPFASampleBuffers, (CGLPixelFormatAttribute)1 );
+            CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFANoRecovery;
+        }
+
+        CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAFullScreen;
+        CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFADoubleBuffer;
+        CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAAccelerated;
+        CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFANoRecovery;
+        CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAMinimumPolicy;
+
+        _setCGLAttribute( kCGLPFAAccumSize,
+                          (CGLPixelFormatAttribute)( fbconfig->accumRedBits \
+                                                   + fbconfig->accumGreenBits \
+                                                   + fbconfig->accumBlueBits \
+                                                   + fbconfig->accumAlphaBits ) );
+
+        _setCGLAttribute( kCGLPFAAlphaSize,   (CGLPixelFormatAttribute)fbconfig->alphaBits );
+        _setCGLAttribute( kCGLPFADepthSize,   (CGLPixelFormatAttribute)fbconfig->depthBits );
+        _setCGLAttribute( kCGLPFAStencilSize, (CGLPixelFormatAttribute)fbconfig->stencilBits );
+        _setCGLAttribute( kCGLPFAAuxBuffers,  (CGLPixelFormatAttribute)fbconfig->auxBuffers );
+
+        CGLpixelFormatAttributes[ numCGLAttrs++ ] = (CGLPixelFormatAttribute)NULL;
+
+        // create a suitable pixel format with above attributes..
+        cglErr = CGLChoosePixelFormat( CGLpixelFormatAttributes,
+                                       &_glfwWin.cglPixelFormat,
+                                       &numCGLvs );
+        if( cglErr != kCGLNoError )
+        {
+            fprintf( stderr,
+                     "Failed to choose CGL pixel format: %s\n",
+                     CGLErrorString( cglErr ) );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        // ..and create a rendering context using that pixel format
+        cglErr = CGLCreateContext( _glfwWin.cglPixelFormat, NULL, &_glfwWin.cglContext );
+        if( cglErr != kCGLNoError )
+        {
+            fprintf( stderr,
+                     "Failed to create CGL context: %s\n",
+                     CGLErrorString( cglErr ) );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        // enumerate depth of RGB channels - unlike AGL, CGL works with
+        // a single parameter reflecting the full depth of the frame buffer
+        (void)CGLDescribePixelFormat( _glfwWin.cglPixelFormat,
+                                      0,
+                                      kCGLPFAColorSize,
+                                      &rgbColorDepth );
+
+        // capture the display for our application
+        cgErr = CGCaptureAllDisplays();
+        if( cgErr != kCGErrorSuccess )
+        {
+            fprintf( stderr,
+                     "Failed to capture Core Graphics displays\n");
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        // find closest matching NON-STRETCHED display mode..
+        optimalMode = CGDisplayBestModeForParametersAndRefreshRateWithProperty(
+                            kCGDirectMainDisplay,
+                            rgbColorDepth,
+                            width,
+                            height,
+                            wndconfig->refreshRate,
+                            NULL,
+                            NULL );
+        if( optimalMode == NULL )
+        {
+            fprintf( stderr,
+                     "Failed to retrieve Core Graphics display mode\n");
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        // ..and switch to that mode
+        cgErr = CGDisplaySwitchToMode( kCGDirectMainDisplay, optimalMode );
+        if( cgErr != kCGErrorSuccess )
+        {
+            fprintf( stderr,
+                     "Failed to switch to Core Graphics display mode\n");
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        // switch to our OpenGL context, and bring it up fullscreen
+        cglErr = CGLSetCurrentContext( _glfwWin.cglContext );
+        if( cglErr != kCGLNoError )
+        {
+            fprintf( stderr,
+                     "Failed to make CGL context current: %s\n",
+                     CGLErrorString( cglErr ) );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        cglErr = CGLSetFullScreen( _glfwWin.cglContext );
+        if( cglErr != kCGLNoError )
+        {
+            fprintf( stderr,
+                     "Failed to set CGL fullscreen mode: %s\n",
+                     CGLErrorString( cglErr ) );
+
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+    }
+
+    return GL_TRUE;
+}
+
+//========================================================================
+// Properly kill the window/video display
+//========================================================================
+
+void _glfwPlatformCloseWindow( void )
+{
+    if( _glfwWin.mouseUPP != NULL )
+    {
+        DisposeEventHandlerUPP( _glfwWin.mouseUPP );
+        _glfwWin.mouseUPP = NULL;
+    }
+    if( _glfwWin.commandUPP != NULL )
+    {
+        DisposeEventHandlerUPP( _glfwWin.commandUPP );
+        _glfwWin.commandUPP = NULL;
+    }
+    if( _glfwWin.keyboardUPP != NULL )
+    {
+        DisposeEventHandlerUPP( _glfwWin.keyboardUPP );
+        _glfwWin.keyboardUPP = NULL;
+    }
+    if( _glfwWin.windowUPP != NULL )
+    {
+        DisposeEventHandlerUPP( _glfwWin.windowUPP );
+        _glfwWin.windowUPP = NULL;
+    }
+
+    if( _glfwWin.fullscreen )
+    {
+        if( _glfwWin.cglContext != NULL )
+        {
+            CGLSetCurrentContext( NULL );
+            CGLClearDrawable( _glfwWin.cglContext );
+            CGLDestroyContext( _glfwWin.cglContext );
+            CGReleaseAllDisplays();
+            _glfwWin.cglContext = NULL;
+        }
+
+        if( _glfwWin.cglPixelFormat != NULL )
+        {
+            CGLDestroyPixelFormat( _glfwWin.cglPixelFormat );
+            _glfwWin.cglPixelFormat = NULL;
+        }
+    }
+    else
+    {
+        if( _glfwWin.aglContext != NULL )
+        {
+            aglSetCurrentContext( NULL );
+            aglSetDrawable( _glfwWin.aglContext, NULL );
+            aglDestroyContext( _glfwWin.aglContext );
+            _glfwWin.aglContext = NULL;
+        }
+
+        if( _glfwWin.aglPixelFormat != NULL )
+        {
+            aglDestroyPixelFormat( _glfwWin.aglPixelFormat );
+            _glfwWin.aglPixelFormat = NULL;
+        }
+    }
+
+    if( _glfwWin.window != NULL )
+    {
+        ReleaseWindow( _glfwWin.window );
+        _glfwWin.window = NULL;
+    }
+}
+
+//========================================================================
+// Set the window title
+//========================================================================
+
+void _glfwPlatformSetWindowTitle( const char *title )
+{
+    CFStringRef windowTitle;
+
+    if( !_glfwWin.fullscreen )
+    {
+        windowTitle = CFStringCreateWithCString( kCFAllocatorDefault,
+                                                 title,
+                                                 kCFStringEncodingISOLatin1 );
+
+        (void)SetWindowTitleWithCFString( _glfwWin.window, windowTitle );
+
+        CFRelease( windowTitle );
+    }
+}
+
+//========================================================================
+// Set the window size
+//========================================================================
+
+void _glfwPlatformSetWindowSize( int width, int height )
+{
+    if( !_glfwWin.fullscreen )
+    {
+        SizeWindow( _glfwWin.window, width, height, TRUE );
+    }
+}
+
+//========================================================================
+// Set the window position
+//========================================================================
+
+void _glfwPlatformSetWindowPos( int x, int y )
+{
+    if( !_glfwWin.fullscreen )
+    {
+        MoveWindow( _glfwWin.window, x, y, FALSE );
+    }
+}
+
+//========================================================================
+// Window iconification
+//========================================================================
+
+void _glfwPlatformIconifyWindow( void )
+{
+    if( !_glfwWin.fullscreen )
+    {
+        (void)CollapseWindow( _glfwWin.window, TRUE );
+    }
+}
+
+//========================================================================
+// Window un-iconification
+//========================================================================
+
+void _glfwPlatformRestoreWindow( void )
+{
+    if( !_glfwWin.fullscreen )
+    {
+        (void)CollapseWindow( _glfwWin.window, FALSE );
+    }
+}
+
+//========================================================================
+// Swap buffers (double-buffering) and poll any new events
+//========================================================================
+
+void _glfwPlatformSwapBuffers( void )
+{
+    if( _glfwWin.fullscreen )
+    {
+        CGLFlushDrawable( _glfwWin.cglContext );
+    }
+    else
+    {
+        aglSwapBuffers( _glfwWin.aglContext );
+    }
+}
+
+//========================================================================
+// Set double buffering swap interval
+//========================================================================
+
+void _glfwPlatformSwapInterval( int interval )
+{
+    GLint AGLparameter = interval;
+
+    // CGL doesn't seem to like intervals other than 0 (vsync off) or 1 (vsync on)
+    long CGLparameter = ( interval ? 1 : 0 );
+
+    if( _glfwWin.fullscreen )
+    {
+        // Don't care if we fail here..
+        (void)CGLSetParameter( _glfwWin.cglContext,
+                               kCGLCPSwapInterval,
+                               (GLint*) &CGLparameter );
+    }
+    else
+    {
+        // ..or here
+        (void)aglSetInteger( _glfwWin.aglContext,
+                             AGL_SWAP_INTERVAL,
+                             &AGLparameter );
+    }
+}
+
+//========================================================================
+// Read back framebuffer parameters from the context
+//========================================================================
+
+#define _getAGLAttribute( aglAttributeName, variableName ) \
+{ \
+    GLint aglValue; \
+    (void)aglDescribePixelFormat( _glfwWin.aglPixelFormat, aglAttributeName, &aglValue ); \
+    variableName = aglValue; \
+}
+
+#define _getCGLAttribute( cglAttributeName, variableName ) \
+{ \
+    GLint cglValue; \
+    (void)CGLDescribePixelFormat( _glfwWin.cglPixelFormat, 0, cglAttributeName, &cglValue ); \
+    variableName = cglValue; \
+}
+
+void _glfwPlatformRefreshWindowParams( void )
+{
+    GLint rgbColorDepth;
+    GLint rgbaAccumDepth = 0;
+    GLint rgbChannelDepth = 0;
+
+    if( _glfwWin.fullscreen )
+    {
+        _getCGLAttribute( kCGLPFAAccelerated, _glfwWin.accelerated );
+        _getCGLAttribute( kCGLPFAAlphaSize,   _glfwWin.alphaBits );
+        _getCGLAttribute( kCGLPFADepthSize,   _glfwWin.depthBits );
+        _getCGLAttribute( kCGLPFAStencilSize, _glfwWin.stencilBits );
+        _getCGLAttribute( kCGLPFAAuxBuffers,  _glfwWin.auxBuffers );
+        _getCGLAttribute( kCGLPFAStereo,      _glfwWin.stereo );
+        _getCGLAttribute( kCGLPFASamples,     _glfwWin.samples );
+
+        // Enumerate depth of RGB channels - unlike AGL, CGL works with
+        // a single parameter reflecting the full depth of the frame buffer
+        (void)CGLDescribePixelFormat( _glfwWin.cglPixelFormat,
+                                      0,
+                                      kCGLPFAColorSize,
+                                      &rgbColorDepth );
+
+        if( rgbColorDepth == 24 || rgbColorDepth == 32 )
+        {
+            rgbChannelDepth = 8;
+        }
+        if( rgbColorDepth == 16 )
+        {
+            rgbChannelDepth = 5;
+        }
+
+        _glfwWin.redBits   = rgbChannelDepth;
+        _glfwWin.greenBits = rgbChannelDepth;
+        _glfwWin.blueBits  = rgbChannelDepth;
+
+        // Get pixel depth of accumulator - I haven't got the slightest idea
+        // how this number conforms to any other channel depth than 8 bits,
+        // so this might end up giving completely knackered results...
+        _getCGLAttribute( kCGLPFAColorSize, rgbaAccumDepth );
+        if( rgbaAccumDepth == 32 )
+        {
+            rgbaAccumDepth = 8;
+        }
+
+        _glfwWin.accumRedBits   = rgbaAccumDepth;
+        _glfwWin.accumGreenBits = rgbaAccumDepth;
+        _glfwWin.accumBlueBits  = rgbaAccumDepth;
+        _glfwWin.accumAlphaBits = rgbaAccumDepth;
+    }
+    else
+    {
+        _getAGLAttribute( AGL_ACCELERATED,      _glfwWin.accelerated );
+        _getAGLAttribute( AGL_RED_SIZE,         _glfwWin.redBits );
+        _getAGLAttribute( AGL_GREEN_SIZE,       _glfwWin.greenBits );
+        _getAGLAttribute( AGL_BLUE_SIZE,        _glfwWin.blueBits );
+        _getAGLAttribute( AGL_ALPHA_SIZE,       _glfwWin.alphaBits );
+        _getAGLAttribute( AGL_DEPTH_SIZE,       _glfwWin.depthBits );
+        _getAGLAttribute( AGL_STENCIL_SIZE,     _glfwWin.stencilBits );
+        _getAGLAttribute( AGL_ACCUM_RED_SIZE,   _glfwWin.accumRedBits );
+        _getAGLAttribute( AGL_ACCUM_GREEN_SIZE, _glfwWin.accumGreenBits );
+        _getAGLAttribute( AGL_ACCUM_BLUE_SIZE,  _glfwWin.accumBlueBits );
+        _getAGLAttribute( AGL_ACCUM_ALPHA_SIZE, _glfwWin.accumAlphaBits );
+        _getAGLAttribute( AGL_AUX_BUFFERS,      _glfwWin.auxBuffers );
+        _getAGLAttribute( AGL_STEREO,           _glfwWin.stereo );
+        _getAGLAttribute( AGL_SAMPLES_ARB,      _glfwWin.samples );
+    }
+}
+
+//========================================================================
+// Poll for new window and input events
+//========================================================================
+
+void _glfwPlatformPollEvents( void )
+{
+    EventRef event;
+    EventTargetRef eventDispatcher = GetEventDispatcherTarget();
+
+    while ( ReceiveNextEvent( 0, NULL, 0.0, TRUE, &event ) == noErr )
+    {
+        SendEventToEventTarget( event, eventDispatcher );
+        ReleaseEvent( event );
+    }
+}
+
+//========================================================================
+// Wait for new window and input events
+//========================================================================
+
+void _glfwPlatformWaitEvents( void )
+{
+    EventRef event;
+
+    // Wait for new events
+    ReceiveNextEvent( 0, NULL, kEventDurationForever, FALSE, &event );
+
+    // Process the new events
+    _glfwPlatformPollEvents();
+}
+
+//========================================================================
+// Hide mouse cursor (lock it)
+//========================================================================
+
+void _glfwPlatformHideMouseCursor( void )
+{
+    CGDisplayHideCursor( kCGDirectMainDisplay );
+    CGAssociateMouseAndMouseCursorPosition( false );
+}
+
+//========================================================================
+// Show mouse cursor (unlock it)
+//========================================================================
+
+void _glfwPlatformShowMouseCursor( void )
+{
+    CGDisplayShowCursor( kCGDirectMainDisplay );
+    CGAssociateMouseAndMouseCursorPosition( true );
+}
+
+//========================================================================
+// Set physical mouse cursor position
+//========================================================================
+
+void _glfwPlatformSetMouseCursorPos( int x, int y )
+{
+    Rect content;
+
+    if( _glfwWin.fullscreen )
+    {
+        CGDisplayMoveCursorToPoint( kCGDirectMainDisplay,
+                                    CGPointMake( x, y ) );
+    }
+    else
+    {
+        GetWindowBounds(_glfwWin.window, kWindowContentRgn, &content);
+
+        _glfwInput.MousePosX = x + content.left;
+        _glfwInput.MousePosY = y + content.top;
+
+        CGDisplayMoveCursorToPoint( kCGDirectMainDisplay,
+                                    CGPointMake( _glfwInput.MousePosX,
+                                                _glfwInput.MousePosY ) );
+    }
+}
+

+ 334 - 0
ThirdParty/GLFW/lib/carbon/platform.h

@@ -0,0 +1,334 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Carbon/AGL/CGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003      Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund <[email protected]>
+// Copyright (c) 2006-2007 Robin Leffmann
+//
+// 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 Mac OS X version of GLFW
+#define _GLFW_MAC_OS_X
+
+#include <Carbon/Carbon.h>
+#include <OpenGL/OpenGL.h>
+#include <AGL/agl.h>
+#include <sched.h>
+#include <pthread.h>
+#include <sys/sysctl.h>
+
+#include "../../include/GL/glfw.h"
+
+#if MACOSX_DEPLOYMENT_TARGET < MAC_OS_X_VERSION_10_3
+
+#ifndef kCGLNoError
+#define kCGLNoError 0
+#endif
+
+#endif
+
+
+#ifndef GL_VERSION_3_0
+
+typedef const GLubyte * (APIENTRY *PFNGLGETSTRINGIPROC) (GLenum, GLuint);
+
+#endif /*GL_VERSION_3_0*/
+
+
+//========================================================================
+// Defines
+//========================================================================
+
+#define _GLFW_MAX_PATH_LENGTH (8192)
+
+#define MAC_KEY_ENTER       0x24
+#define MAC_KEY_RETURN      0x34
+#define MAC_KEY_ESC         0x35
+#define MAC_KEY_F1          0x7A
+#define MAC_KEY_F2          0x78
+#define MAC_KEY_F3          0x63
+#define MAC_KEY_F4          0x76
+#define MAC_KEY_F5          0x60
+#define MAC_KEY_F6          0x61
+#define MAC_KEY_F7          0x62
+#define MAC_KEY_F8          0x64
+#define MAC_KEY_F9          0x65
+#define MAC_KEY_F10         0x6D
+#define MAC_KEY_F11         0x67
+#define MAC_KEY_F12         0x6F
+#define MAC_KEY_F13         0x69
+#define MAC_KEY_F14         0x6B
+#define MAC_KEY_F15         0x71
+#define MAC_KEY_UP          0x7E
+#define MAC_KEY_DOWN        0x7D
+#define MAC_KEY_LEFT        0x7B
+#define MAC_KEY_RIGHT       0x7C
+#define MAC_KEY_TAB         0x30
+#define MAC_KEY_BACKSPACE   0x33
+#define MAC_KEY_HELP        0x72
+#define MAC_KEY_DEL         0x75
+#define MAC_KEY_PAGEUP      0x74
+#define MAC_KEY_PAGEDOWN    0x79
+#define MAC_KEY_HOME        0x73
+#define MAC_KEY_END         0x77
+#define MAC_KEY_KP_0        0x52
+#define MAC_KEY_KP_1        0x53
+#define MAC_KEY_KP_2        0x54
+#define MAC_KEY_KP_3        0x55
+#define MAC_KEY_KP_4        0x56
+#define MAC_KEY_KP_5        0x57
+#define MAC_KEY_KP_6        0x58
+#define MAC_KEY_KP_7        0x59
+#define MAC_KEY_KP_8        0x5B
+#define MAC_KEY_KP_9        0x5C
+#define MAC_KEY_KP_DIVIDE   0x4B
+#define MAC_KEY_KP_MULTIPLY 0x43
+#define MAC_KEY_KP_SUBTRACT 0x4E
+#define MAC_KEY_KP_ADD      0x45
+#define MAC_KEY_KP_DECIMAL  0x41
+#define MAC_KEY_KP_EQUAL    0x51
+#define MAC_KEY_KP_ENTER    0x4C
+#define MAC_KEY_NUMLOCK     0x47
+
+
+//========================================================================
+// GLFW platform specific types
+//========================================================================
+
+//------------------------------------------------------------------------
+// Pointer length integer
+//------------------------------------------------------------------------
+typedef intptr_t GLFWintptr;
+
+
+GLFWGLOBAL CFDictionaryRef _glfwDesktopVideoMode;
+
+//------------------------------------------------------------------------
+// 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
+    int       refreshRate;     // Vertical monitor refresh rate
+
+    // 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
+
+    // Framebuffer attributes
+    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       samples;
+
+    // OpenGL extensions and context attributes
+    int       has_GL_SGIS_generate_mipmap;
+    int       has_GL_ARB_texture_non_power_of_two;
+    int       glMajor, glMinor, glRevision;
+    int       glForward, glDebug, glProfile;
+
+    PFNGLGETSTRINGIPROC GetStringi;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+    WindowRef          window;
+
+    AGLContext         aglContext;
+    AGLPixelFormat     aglPixelFormat;
+
+    CGLContextObj      cglContext;
+    CGLPixelFormatObj  cglPixelFormat;
+
+    EventHandlerUPP    windowUPP;
+    EventHandlerUPP    mouseUPP;
+    EventHandlerUPP    commandUPP;
+    EventHandlerUPP    keyboardUPP;
+};
+
+GLFWGLOBAL _GLFWwin _glfwWin;
+
+
+//------------------------------------------------------------------------
+// User input status (some 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 ======================================
+
+    UInt32 Modifiers;
+
+} _glfwInput;
+
+
+
+//------------------------------------------------------------------------
+// Thread information
+//------------------------------------------------------------------------
+typedef struct _GLFWthread_struct _GLFWthread;
+
+// Thread record (one for each thread)
+struct _GLFWthread_struct {
+
+    // Pointer to previous and next threads in linked list
+    _GLFWthread   *Previous, *Next;
+
+    // GLFW user side thread information
+    GLFWthread    ID;
+    GLFWthreadfun Function;
+
+    // System side thread information
+    pthread_t     PosixID;
+};
+
+// General thread information
+GLFWGLOBAL struct {
+
+    // Critical section lock
+    pthread_mutex_t  CriticalSection;
+
+    // Next thread ID to use (increments for every created thread)
+    GLFWthread       NextID;
+
+    // First thread in linked list (always the main thread)
+    _GLFWthread      First;
+
+} _glfwThrd;
+
+
+//------------------------------------------------------------------------
+// Library global data
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+    // Window opening hints
+    _GLFWhints      hints;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+    // Timer data
+    struct {
+	double       t0;
+    } Timer;
+
+    struct {
+	    // Bundle for dynamically-loading extension function pointers
+        CFBundleRef OpenGLFramework;
+    } Libs;
+
+    int Unbundled;
+
+} _glfwLibrary;
+
+
+
+//========================================================================
+// Macros for encapsulating critical code sections (i.e. making parts
+// of GLFW thread safe)
+//========================================================================
+
+// Define so we can use the same thread code as X11
+#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; \
+        } \
+    } \
+}
+
+// Thread list management
+#define ENTER_THREAD_CRITICAL_SECTION \
+pthread_mutex_lock( &_glfwThrd.CriticalSection );
+#define LEAVE_THREAD_CRITICAL_SECTION \
+pthread_mutex_unlock( &_glfwThrd.CriticalSection );
+
+
+//========================================================================
+// Prototypes for platform specific internal functions
+//========================================================================
+
+void  _glfwChangeToResourcesDirectory( void );
+
+#endif // _platform_h_

+ 51 - 0
ThirdParty/GLFW/lib/cocoa/cocoa_enable.m

@@ -0,0 +1,51 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund <[email protected]>
+//
+// 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                ****
+//************************************************************************
+
+//========================================================================
+// Enable and disable system keys
+//========================================================================
+
+void _glfwPlatformEnableSystemKeys( void )
+{
+    // This is checked in macosx_window.m; we take no action here
+}
+
+void _glfwPlatformDisableSystemKeys( void )
+{
+    // This is checked in macosx_window.m; we take no action here
+    // I don't think it's really possible to disable stuff like Exposé
+    // except in full-screen mode.
+}
+

+ 102 - 0
ThirdParty/GLFW/lib/cocoa/cocoa_fullscreen.m

@@ -0,0 +1,102 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+//========================================================================
+// Check whether the display mode should be included in enumeration
+//========================================================================
+
+static BOOL modeIsGood( NSDictionary *mode )
+{
+    // This is a bit controversial, if you've got something other than an
+    // LCD computer monitor as an output device you might not want these
+    // checks.  You might also want to reject modes which are interlaced,
+    // or TV out.  There is no one-size-fits-all policy that can work here.
+    // This seems like a decent compromise, but certain applications may
+    // wish to patch this...
+    return [[mode objectForKey:(id)kCGDisplayBitsPerPixel] intValue] >= 15 &&
+           [mode objectForKey:(id)kCGDisplayModeIsSafeForHardware] != nil &&
+           [mode objectForKey:(id)kCGDisplayModeIsStretched] == nil;
+}
+
+//========================================================================
+// Convert Core Graphics display mode to GLFW video mode
+//========================================================================
+
+static GLFWvidmode vidmodeFromCGDisplayMode( NSDictionary *mode )
+{
+    unsigned int width = [[mode objectForKey:(id)kCGDisplayWidth] unsignedIntValue];
+    unsigned int height = [[mode objectForKey:(id)kCGDisplayHeight] unsignedIntValue];
+    unsigned int bps = [[mode objectForKey:(id)kCGDisplayBitsPerSample] unsignedIntValue];
+
+    GLFWvidmode result;
+    result.Width = width;
+    result.Height = height;
+    result.RedBits = bps;
+    result.GreenBits = bps;
+    result.BlueBits = bps;
+    return result;
+}
+
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// Get a list of available video modes
+//========================================================================
+
+int _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount )
+{
+    NSArray *modes = (NSArray *)CGDisplayAvailableModes( CGMainDisplayID() );
+
+    unsigned int i, j = 0, n = [modes count];
+    for( i = 0; i < n && i < (unsigned)maxcount; i++ )
+    {
+        NSDictionary *mode = [modes objectAtIndex:i];
+        if( modeIsGood( mode ) )
+        {
+            list[j++] = vidmodeFromCGDisplayMode( mode );
+        }
+    }
+
+    return j;
+}
+
+//========================================================================
+// Get the desktop video mode
+//========================================================================
+
+void _glfwPlatformGetDesktopMode( GLFWvidmode *mode )
+{
+    *mode = vidmodeFromCGDisplayMode( _glfwLibrary.DesktopMode );
+}
+

+ 63 - 0
ThirdParty/GLFW/lib/cocoa/cocoa_glext.m

@@ -0,0 +1,63 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund <[email protected]>
+//
+// 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 )
+{
+    // There are no AGL, CGL or NSGL extensions.
+    return GL_FALSE;
+}
+
+//========================================================================
+// Get the function pointer to an OpenGL function
+//========================================================================
+
+void * _glfwPlatformGetProcAddress( const char *procname )
+{
+    CFStringRef symbolName = CFStringCreateWithCString( kCFAllocatorDefault,
+                                                        procname,
+                                                        kCFStringEncodingASCII );
+
+    void *symbol = CFBundleGetFunctionPointerForName( _glfwLibrary.OpenGLFramework,
+                                                      symbolName );
+
+    CFRelease( symbolName );
+
+    return symbol;
+}
+

+ 275 - 0
ThirdParty/GLFW/lib/cocoa/cocoa_init.m

@@ -0,0 +1,275 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund <[email protected]>
+//
+// 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.
+//
+//========================================================================
+
+// Needed for _NSGetProgname
+#include <crt_externs.h>
+
+#include "internal.h"
+
+@interface GLFWApplication : NSApplication
+@end
+
+@implementation GLFWApplication
+
+// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
+// This works around an AppKit bug, where key up events while holding
+// down the command key don't get sent to the key window.
+- (void)sendEvent:(NSEvent *)event
+{
+    if( [event type] == NSKeyUp && ( [event modifierFlags] & NSCommandKeyMask ) )
+    {
+        [[self keyWindow] sendEvent:event];
+    }
+    else
+    {
+        [super sendEvent:event];
+    }
+}
+
+@end
+
+// Prior to Snow Leopard, we need to use this oddly-named semi-private API
+// to get the application menu working properly.  Need to be careful in
+// case it goes away in a future OS update.
+@interface NSApplication (NSAppleMenu)
+- (void)setAppleMenu:(NSMenu *)m;
+@end
+
+// Keys to search for as potential application names
+NSString *GLFWNameKeys[] =
+{
+    @"CFBundleDisplayName",
+    @"CFBundleName",
+    @"CFBundleExecutable",
+};
+
+//========================================================================
+// Try to figure out what the calling application is called
+//========================================================================
+static NSString *findAppName( void )
+{
+    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
+
+    unsigned int i;
+    for( i = 0; i < sizeof(GLFWNameKeys) / sizeof(GLFWNameKeys[0]); i++ )
+    {
+        id name = [infoDictionary objectForKey:GLFWNameKeys[i]];
+        if (name &&
+            [name isKindOfClass:[NSString class]] &&
+            ![@"" isEqualToString:name])
+        {
+            return name;
+        }
+    }
+
+    // If we get here, we're unbundled
+    if( !_glfwLibrary.Unbundled )
+    {
+        // Could do this only if we discover we're unbundled, but it should
+        // do no harm...
+        ProcessSerialNumber psn = { 0, kCurrentProcess };
+        TransformProcessType( &psn, kProcessTransformToForegroundApplication );
+
+        // Having the app in front of the terminal window is also generally
+        // handy.  There is an NSApplication API to do this, but...
+        SetFrontProcess( &psn );
+
+        _glfwLibrary.Unbundled = GL_TRUE;
+    }
+
+    char **progname = _NSGetProgname();
+    if( progname && *progname )
+    {
+        // TODO: UTF8?
+        return [NSString stringWithUTF8String:*progname];
+    }
+
+    // Really shouldn't get here
+    return @"GLFW Application";
+}
+
+//========================================================================
+// Set up the menu bar (manually)
+// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
+// could go away at any moment, lots of stuff that really should be
+// localize(d|able), etc.  Loading a nib would save us this horror, but that
+// doesn't seem like a good thing to require of GLFW's clients.
+//========================================================================
+static void setUpMenuBar( void )
+{
+    NSString *appName = findAppName();
+
+    NSMenu *bar = [[NSMenu alloc] init];
+    [NSApp setMainMenu:bar];
+
+    NSMenuItem *appMenuItem =
+        [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+    NSMenu *appMenu = [[NSMenu alloc] init];
+    [appMenuItem setSubmenu:appMenu];
+
+    [appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
+                       action:@selector(orderFrontStandardAboutPanel:)
+                keyEquivalent:@""];
+    [appMenu addItem:[NSMenuItem separatorItem]];
+    NSMenu *servicesMenu = [[NSMenu alloc] init];
+    [NSApp setServicesMenu:servicesMenu];
+    [[appMenu addItemWithTitle:@"Services"
+                       action:NULL
+                keyEquivalent:@""] setSubmenu:servicesMenu];
+    [appMenu addItem:[NSMenuItem separatorItem]];
+    [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
+                       action:@selector(hide:)
+                keyEquivalent:@"h"];
+    [[appMenu addItemWithTitle:@"Hide Others"
+                       action:@selector(hideOtherApplications:)
+                keyEquivalent:@"h"]
+        setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask];
+    [appMenu addItemWithTitle:@"Show All"
+                       action:@selector(unhideAllApplications:)
+                keyEquivalent:@""];
+    [appMenu addItem:[NSMenuItem separatorItem]];
+    [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
+                       action:@selector(terminate:)
+                keyEquivalent:@"q"];
+
+    NSMenuItem *windowMenuItem =
+        [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+    NSMenu *windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+    [NSApp setWindowsMenu:windowMenu];
+    [windowMenuItem setSubmenu:windowMenu];
+
+    [windowMenu addItemWithTitle:@"Miniaturize"
+                          action:@selector(performMiniaturize:)
+                   keyEquivalent:@"m"];
+    [windowMenu addItemWithTitle:@"Zoom"
+                          action:@selector(performZoom:)
+                   keyEquivalent:@""];
+    [windowMenu addItem:[NSMenuItem separatorItem]];
+    [windowMenu addItemWithTitle:@"Bring All to Front"
+                          action:@selector(arrangeInFront:)
+                   keyEquivalent:@""];
+
+    // At least guard the call to private API to avoid an exception if it
+    // goes away.  Hopefully that means the worst we'll break in future is to
+    // look ugly...
+    if( [NSApp respondsToSelector:@selector(setAppleMenu:)] )
+    {
+        [NSApp setAppleMenu:appMenu];
+    }
+}
+
+//========================================================================
+// Terminate GLFW when exiting application
+//========================================================================
+
+static void glfw_atexit( void )
+{
+    glfwTerminate();
+}
+
+
+//========================================================================
+// Initialize GLFW thread package
+//========================================================================
+
+static void initThreads( void )
+{
+    // Initialize critical section handle
+    (void) pthread_mutex_init( &_glfwThrd.CriticalSection, NULL );
+
+    // 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.PosixID  = pthread_self();
+    _glfwThrd.First.Previous = NULL;
+    _glfwThrd.First.Next     = NULL;
+}
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// Initialize the GLFW library
+//========================================================================
+
+int _glfwPlatformInit( void )
+{
+    _glfwLibrary.AutoreleasePool = [[NSAutoreleasePool alloc] init];
+
+    // Implicitly create shared NSApplication instance
+    [GLFWApplication sharedApplication];
+
+    NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
+
+    if( access( [resourcePath cStringUsingEncoding:NSUTF8StringEncoding], R_OK ) == 0 )
+    {
+        chdir( [resourcePath cStringUsingEncoding:NSUTF8StringEncoding] );
+    }
+
+    // Setting up menu bar must go exactly here else weirdness ensues
+    setUpMenuBar();
+
+    [NSApp finishLaunching];
+
+    // Install atexit routine
+    atexit( glfw_atexit );
+
+    initThreads();
+
+    _glfwPlatformSetTime( 0.0 );
+
+    _glfwLibrary.DesktopMode =
+	(NSDictionary *)CGDisplayCurrentMode( CGMainDisplayID() );
+
+    return GL_TRUE;
+}
+
+//========================================================================
+// Close window, if open, and shut down GLFW
+//========================================================================
+
+int _glfwPlatformTerminate( void )
+{
+    // TODO: Fail unless this is the main thread
+
+    glfwCloseWindow();
+
+    // TODO: Kill all non-main threads?
+    // TODO: Probably other cleanup
+
+    [_glfwLibrary.AutoreleasePool release];
+    _glfwLibrary.AutoreleasePool = nil;
+
+    return GL_TRUE;
+}
+

+ 65 - 0
ThirdParty/GLFW/lib/cocoa/cocoa_joystick.m

@@ -0,0 +1,65 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund <[email protected]>
+//
+// 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                ****
+//************************************************************************
+
+//========================================================================
+// Determine joystick capabilities
+//========================================================================
+
+int _glfwPlatformGetJoystickParam( int joy, int param )
+{
+    // TODO: Implement this.
+    return 0;
+}
+
+//========================================================================
+// Get joystick axis positions
+//========================================================================
+
+int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes )
+{
+    // TODO: Implement this.
+    return 0;
+}
+
+//========================================================================
+// Get joystick button states
+//========================================================================
+
+int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons, int numbuttons )
+{
+    // TODO: Implement this.
+    return 0;
+}
+

+ 415 - 0
ThirdParty/GLFW/lib/cocoa/cocoa_thread.c

@@ -0,0 +1,415 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+#include <sys/time.h>
+#include <sys/sysctl.h>
+
+
+//************************************************************************
+//****                  GLFW internal functions                       ****
+//************************************************************************
+
+//========================================================================
+// _glfwNewThread() - This is simply a "wrapper" for calling the user
+// thread function.
+//========================================================================
+
+void * _glfwNewThread( void * arg )
+{
+    GLFWthreadfun threadfun;
+    _GLFWthread   *t;
+
+    // Get pointer to thread information for current thread
+    t = _glfwGetThreadPointer( glfwGetThreadID() );
+    if( t == NULL )
+    {
+        return 0;
+    }
+
+    // Get user thread function pointer
+    threadfun = t->Function;
+
+    // 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;
+}
+
+
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// _glfwPlatformCreateThread() - Create a new thread
+//========================================================================
+
+GLFWthread _glfwPlatformCreateThread( GLFWthreadfun fun, void *arg )
+{
+    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;
+}
+
+
+//========================================================================
+// _glfwPlatformDestroyThread() - Kill a thread. NOTE: THIS IS A VERY
+// DANGEROUS OPERATION, AND SHOULD NOT BE USED EXCEPT IN EXTREME
+// SITUATIONS!
+//========================================================================
+
+void _glfwPlatformDestroyThread( GLFWthread ID )
+{
+    _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
+}
+
+
+//========================================================================
+// _glfwPlatformWaitThread() - Wait for a thread to die
+//========================================================================
+
+int _glfwPlatformWaitThread( GLFWthread ID, int waitmode )
+{
+    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;
+}
+
+
+//========================================================================
+// _glfwPlatformGetThreadID() - Return the thread ID for the current
+// thread
+//========================================================================
+
+GLFWthread _glfwPlatformGetThreadID( void )
+{
+    _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;
+}
+
+
+//========================================================================
+// _glfwPlatformCreateMutex() - Create a mutual exclusion object
+//========================================================================
+
+GLFWmutex _glfwPlatformCreateMutex( void )
+{
+    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;
+}
+
+
+//========================================================================
+// _glfwPlatformDestroyMutex() - Destroy a mutual exclusion object
+//========================================================================
+
+void _glfwPlatformDestroyMutex( GLFWmutex mutex )
+{
+    // Destroy the mutex object
+    pthread_mutex_destroy( (pthread_mutex_t *) mutex );
+
+    // Free memory for mutex object
+    free( (void *) mutex );
+}
+
+
+//========================================================================
+// _glfwPlatformLockMutex() - Request access to a mutex
+//========================================================================
+
+void _glfwPlatformLockMutex( GLFWmutex mutex )
+{
+    // Wait for mutex to be released
+    (void) pthread_mutex_lock( (pthread_mutex_t *) mutex );
+}
+
+
+//========================================================================
+// _glfwPlatformUnlockMutex() - Release a mutex
+//========================================================================
+
+void _glfwPlatformUnlockMutex( GLFWmutex mutex )
+{
+    // Release mutex
+    pthread_mutex_unlock( (pthread_mutex_t *) mutex );
+}
+
+
+//========================================================================
+// _glfwPlatformCreateCond() - Create a new condition variable object
+//========================================================================
+
+GLFWcond _glfwPlatformCreateCond( void )
+{
+    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;
+}
+
+
+//========================================================================
+// _glfwPlatformDestroyCond() - Destroy a condition variable object
+//========================================================================
+
+void _glfwPlatformDestroyCond( GLFWcond cond )
+{
+    // Destroy the condition variable object
+    (void) pthread_cond_destroy( (pthread_cond_t *) cond );
+
+    // Free memory for condition variable object
+    free( (void *) cond );
+}
+
+
+//========================================================================
+// _glfwPlatformWaitCond() - Wait for a condition to be raised
+//========================================================================
+
+void _glfwPlatformWaitCond( GLFWcond cond, GLFWmutex mutex,
+                            double timeout )
+{
+    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 );
+    }
+}
+
+
+//========================================================================
+// _glfwPlatformSignalCond() - Signal a condition to one waiting thread
+//========================================================================
+
+void _glfwPlatformSignalCond( GLFWcond cond )
+{
+    // Signal condition
+    (void) pthread_cond_signal( (pthread_cond_t *) cond );
+}
+
+
+//========================================================================
+// _glfwPlatformBroadcastCond() - Broadcast a condition to all waiting
+// threads
+//========================================================================
+
+void _glfwPlatformBroadcastCond( GLFWcond cond )
+{
+    // Broadcast condition
+    (void) pthread_cond_broadcast( (pthread_cond_t *) cond );
+}
+
+
+//========================================================================
+// _glfwPlatformGetNumberOfProcessors() - Return the number of processors
+// in the system.
+//========================================================================
+
+int _glfwPlatformGetNumberOfProcessors( void )
+{
+    int n;
+
+    // Get number of processors online
+    _glfw_numprocessors( n );
+    return n;
+}
+

+ 105 - 0
ThirdParty/GLFW/lib/cocoa/cocoa_time.m

@@ -0,0 +1,105 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+#include <sys/time.h>
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// Return timer value in seconds
+//========================================================================
+
+double _glfwPlatformGetTime( void )
+{
+    return [NSDate timeIntervalSinceReferenceDate] - _glfwLibrary.Timer.t0;
+}
+
+//========================================================================
+// Set timer value in seconds
+//========================================================================
+
+void _glfwPlatformSetTime( double time )
+{
+    _glfwLibrary.Timer.t0 = [NSDate timeIntervalSinceReferenceDate] - time;
+}
+
+//========================================================================
+// Put a thread to sleep for a specified amount of time
+//========================================================================
+
+void _glfwPlatformSleep( double time )
+{
+    if( time == 0.0 )
+    {
+	sched_yield();
+	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 );
+}
+

+ 920 - 0
ThirdParty/GLFW/lib/cocoa/cocoa_window.m

@@ -0,0 +1,920 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund <[email protected]>
+//
+// 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.
+//
+//========================================================================
+
+// Modified by Lasse Öörni for Urho3D
+
+#include "internal.h"
+
+//========================================================================
+// Delegate for window related notifications
+// (but also used as an application delegate)
+//========================================================================
+
+@interface GLFWWindowDelegate : NSObject
+@end
+
+@implementation GLFWWindowDelegate
+
+- (BOOL)windowShouldClose:(id)window
+{
+    if( _glfwWin.windowCloseCallback )
+    {
+        if( !_glfwWin.windowCloseCallback() )
+        {
+            return NO;
+        }
+    }
+
+    // This is horribly ugly, but it works
+    glfwCloseWindow();
+    return NO;
+}
+
+- (void)windowDidResize:(NSNotification *)notification
+{
+    [_glfwWin.context update];
+
+    NSRect contentRect =
+        [_glfwWin.window contentRectForFrameRect:[_glfwWin.window frame]];
+    _glfwWin.width = contentRect.size.width;
+    _glfwWin.height = contentRect.size.height;
+
+    if( _glfwWin.windowSizeCallback )
+    {
+        _glfwWin.windowSizeCallback( _glfwWin.width, _glfwWin.height );
+    }
+}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+    if( _glfwWin.windowCloseCallback )
+    {
+        if( !_glfwWin.windowCloseCallback() )
+        {
+            return NSTerminateCancel;
+        }
+    }
+
+    // This is horribly ugly, but it works
+    glfwCloseWindow();
+    return NSTerminateCancel;
+}
+
+@end
+
+// TODO: Need to find mappings for F13-F15, volume down/up/mute, and eject.
+static const unsigned int MAC_TO_GLFW_KEYCODE_MAPPING[128] =
+{
+    /* 00 */ 'A',
+    /* 01 */ 'S',
+    /* 02 */ 'D',
+    /* 03 */ 'F',
+    /* 04 */ 'H',
+    /* 05 */ 'G',
+    /* 06 */ 'Z',
+    /* 07 */ 'X',
+    /* 08 */ 'C',
+    /* 09 */ 'V',
+    /* 0a */ -1,
+    /* 0b */ 'B',
+    /* 0c */ 'Q',
+    /* 0d */ 'W',
+    /* 0e */ 'E',
+    /* 0f */ 'R',
+    /* 10 */ 'Y',
+    /* 11 */ 'T',
+    /* 12 */ '1',
+    /* 13 */ '2',
+    /* 14 */ '3',
+    /* 15 */ '4',
+    /* 16 */ '6',
+    /* 17 */ '5',
+    /* 18 */ '=',
+    /* 19 */ '9',
+    /* 1a */ '7',
+    /* 1b */ '-',
+    /* 1c */ '8',
+    /* 1d */ '0',
+    /* 1e */ ']',
+    /* 1f */ 'O',
+    /* 20 */ 'U',
+    /* 21 */ '[',
+    /* 22 */ 'I',
+    /* 23 */ 'P',
+    /* 24 */ GLFW_KEY_ENTER,
+    /* 25 */ 'L',
+    /* 26 */ 'J',
+    /* 27 */ '\'',
+    /* 28 */ 'K',
+    /* 29 */ ';',
+    /* 2a */ '\\',
+    /* 2b */ ',',
+    /* 2c */ '/',
+    /* 2d */ 'N',
+    /* 2e */ 'M',
+    /* 2f */ '.',
+    /* 30 */ GLFW_KEY_TAB,
+    /* 31 */ GLFW_KEY_SPACE,
+    /* 32 */ '`',
+    /* 33 */ GLFW_KEY_BACKSPACE,
+    /* 34 */ -1,
+    /* 35 */ GLFW_KEY_ESC,
+    /* 36 */ GLFW_KEY_RSUPER,
+    /* 37 */ GLFW_KEY_LSUPER,
+    /* 38 */ GLFW_KEY_LSHIFT,
+    /* 39 */ GLFW_KEY_CAPS_LOCK,
+    /* 3a */ GLFW_KEY_LALT,
+    /* 3b */ GLFW_KEY_LCTRL,
+    /* 3c */ GLFW_KEY_RSHIFT,
+    /* 3d */ GLFW_KEY_RALT,
+    /* 3e */ GLFW_KEY_RCTRL,
+    /* 3f */ -1, /*Function*/
+    /* 40 */ GLFW_KEY_F17,
+    /* 41 */ GLFW_KEY_KP_DECIMAL,
+    /* 42 */ -1,
+    /* 43 */ GLFW_KEY_KP_MULTIPLY,
+    /* 44 */ -1,
+    /* 45 */ GLFW_KEY_KP_ADD,
+    /* 46 */ -1,
+    /* 47 */ -1, /*KeypadClear*/
+    /* 48 */ -1, /*VolumeUp*/
+    /* 49 */ -1, /*VolumeDown*/
+    /* 4a */ -1, /*Mute*/
+    /* 4b */ GLFW_KEY_KP_DIVIDE,
+    /* 4c */ GLFW_KEY_KP_ENTER,
+    /* 4d */ -1,
+    /* 4e */ GLFW_KEY_KP_SUBTRACT,
+    /* 4f */ GLFW_KEY_F18,
+    /* 50 */ GLFW_KEY_F19,
+    /* 51 */ GLFW_KEY_KP_EQUAL,
+    /* 52 */ GLFW_KEY_KP_0,
+    /* 53 */ GLFW_KEY_KP_1,
+    /* 54 */ GLFW_KEY_KP_2,
+    /* 55 */ GLFW_KEY_KP_3,
+    /* 56 */ GLFW_KEY_KP_4,
+    /* 57 */ GLFW_KEY_KP_5,
+    /* 58 */ GLFW_KEY_KP_6,
+    /* 59 */ GLFW_KEY_KP_7,
+    /* 5a */ GLFW_KEY_F20,
+    /* 5b */ GLFW_KEY_KP_8,
+    /* 5c */ GLFW_KEY_KP_9,
+    /* 5d */ -1,
+    /* 5e */ -1,
+    /* 5f */ -1,
+    /* 60 */ GLFW_KEY_F5,
+    /* 61 */ GLFW_KEY_F6,
+    /* 62 */ GLFW_KEY_F7,
+    /* 63 */ GLFW_KEY_F3,
+    /* 64 */ GLFW_KEY_F8,
+    /* 65 */ GLFW_KEY_F9,
+    /* 66 */ -1,
+    /* 67 */ GLFW_KEY_F11,
+    /* 68 */ -1,
+    /* 69 */ GLFW_KEY_F13,
+    /* 6a */ GLFW_KEY_F16,
+    /* 6b */ GLFW_KEY_F14,
+    /* 6c */ -1,
+    /* 6d */ GLFW_KEY_F10,
+    /* 6e */ -1,
+    /* 6f */ GLFW_KEY_F12,
+    /* 70 */ -1,
+    /* 71 */ GLFW_KEY_F15,
+    /* 72 */ GLFW_KEY_INSERT, /*Help*/
+    /* 73 */ GLFW_KEY_HOME,
+    /* 74 */ GLFW_KEY_PAGEUP,
+    /* 75 */ GLFW_KEY_DEL,
+    /* 76 */ GLFW_KEY_F4,
+    /* 77 */ GLFW_KEY_END,
+    /* 78 */ GLFW_KEY_F2,
+    /* 79 */ GLFW_KEY_PAGEDOWN,
+    /* 7a */ GLFW_KEY_F1,
+    /* 7b */ GLFW_KEY_LEFT,
+    /* 7c */ GLFW_KEY_RIGHT,
+    /* 7d */ GLFW_KEY_DOWN,
+    /* 7e */ GLFW_KEY_UP,
+    /* 7f */ -1,
+};
+
+//========================================================================
+// Converts a Mac OS X keycode to a GLFW keycode
+//========================================================================
+
+static int convertMacKeyCode( unsigned int macKeyCode )
+{
+    if( macKeyCode >= 128 )
+    {
+        return -1;
+    }
+
+    // This treats keycodes as *positional*; that is, we'll return 'a'
+    // for the key left of 's', even on an AZERTY keyboard.  The charInput
+    // function should still get 'q' though.
+    return MAC_TO_GLFW_KEYCODE_MAPPING[macKeyCode];
+}
+
+//========================================================================
+// Content view class for the GLFW window
+//========================================================================
+
+@interface GLFWContentView : NSView
+@end
+
+@implementation GLFWContentView
+
+- (BOOL)isOpaque
+{
+    return YES;
+}
+
+- (BOOL)canBecomeKeyView
+{
+    return YES;
+}
+
+- (BOOL)acceptsFirstResponder
+{
+    return YES;
+}
+
+- (void)mouseDown:(NSEvent *)event
+{
+    _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS );
+}
+
+- (void)mouseDragged:(NSEvent *)event
+{
+    [self mouseMoved:event];
+}
+
+- (void)mouseUp:(NSEvent *)event
+{
+    _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE );
+    // Urho3D: the mouse was clicked inside the window. It is OK to enter mouselock mode again
+    _glfwWin.leftMouseDown = GL_FALSE;
+}
+
+- (void)mouseMoved:(NSEvent *)event
+{
+    if( _glfwWin.mouseLock )
+    {
+        _glfwInput.MousePosX += [event deltaX];
+        _glfwInput.MousePosY += [event deltaY];
+    }
+    else
+    {
+        NSPoint p = [event locationInWindow];
+
+        // Cocoa coordinate system has origin at lower left
+        _glfwInput.MousePosX = p.x;
+        _glfwInput.MousePosY = [[_glfwWin.window contentView] bounds].size.height - p.y;
+    }
+
+    if( _glfwWin.mousePosCallback )
+    {
+        _glfwWin.mousePosCallback( _glfwInput.MousePosX, _glfwInput.MousePosY );
+    }
+}
+
+- (void)rightMouseDown:(NSEvent *)event
+{
+    _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS );
+}
+
+- (void)rightMouseDragged:(NSEvent *)event
+{
+    [self mouseMoved:event];
+}
+
+- (void)rightMouseUp:(NSEvent *)event
+{
+    _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE );
+}
+
+- (void)otherMouseDown:(NSEvent *)event
+{
+    _glfwInputMouseClick( [event buttonNumber], GLFW_PRESS );
+}
+
+- (void)otherMouseDragged:(NSEvent *)event
+{
+    [self mouseMoved:event];
+}
+
+- (void)otherMouseUp:(NSEvent *)event
+{
+    _glfwInputMouseClick( [event buttonNumber], GLFW_RELEASE );
+}
+
+- (void)keyDown:(NSEvent *)event
+{
+    NSUInteger length;
+    NSString* characters;
+    int i, code = convertMacKeyCode( [event keyCode] );
+
+    if( code != -1 )
+    {
+        _glfwInputKey( code, GLFW_PRESS );
+
+        if( [event modifierFlags] & NSCommandKeyMask )
+        {
+            if( !_glfwWin.sysKeysDisabled )
+            {
+                [super keyDown:event];
+            }
+        }
+        else
+        {
+            characters = [event characters];
+            length = [characters length];
+
+            for( i = 0;  i < length;  i++ )
+            {
+                _glfwInputChar( [characters characterAtIndex:i], GLFW_PRESS );
+            }
+        }
+    }
+}
+
+- (void)flagsChanged:(NSEvent *)event
+{
+    unsigned int newModifierFlags = [event modifierFlags] | NSDeviceIndependentModifierFlagsMask;
+    int mode;
+
+    if( newModifierFlags > _glfwWin.modifierFlags )
+    {
+        mode = GLFW_PRESS;
+    }
+    else
+    {
+        mode = GLFW_RELEASE;
+    }
+
+    _glfwWin.modifierFlags = newModifierFlags;
+    _glfwInputKey( MAC_TO_GLFW_KEYCODE_MAPPING[[event keyCode]], mode );
+}
+
+- (void)keyUp:(NSEvent *)event
+{
+    NSUInteger length;
+    NSString* characters;
+    int i, code = convertMacKeyCode( [event keyCode] );
+
+    if( code != -1 )
+    {
+        _glfwInputKey( code, GLFW_RELEASE );
+
+        characters = [event characters];
+        length = [characters length];
+
+        for( i = 0;  i < length;  i++ )
+        {
+            _glfwInputChar( [characters characterAtIndex:i], GLFW_RELEASE );
+        }
+    }
+}
+
+- (void)scrollWheel:(NSEvent *)event
+{
+    _glfwInput.WheelPosFloating += [event deltaY];
+    _glfwInput.WheelPos = lrint(_glfwInput.WheelPosFloating);
+
+    if( _glfwWin.mouseWheelCallback )
+    {
+        _glfwWin.mouseWheelCallback( _glfwInput.WheelPos );
+    }
+}
+
+@end
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// Here is where the window is created, and the OpenGL rendering context is
+// created
+//========================================================================
+
+int  _glfwPlatformOpenWindow( int width, int height,
+                              const _GLFWwndconfig *wndconfig,
+                              const _GLFWfbconfig *fbconfig )
+{
+    int colorBits;
+
+    _glfwWin.pixelFormat = nil;
+    _glfwWin.window = nil;
+    _glfwWin.context = nil;
+    _glfwWin.delegate = nil;
+    
+    // Urho3D: initialize the added variables
+    _glfwWin.active = GL_FALSE;
+    _glfwWin.lastActive = GL_FALSE;
+    _glfwWin.leftMouseDown = GL_FALSE;
+
+    // Fail if OpenGL 3.0 or above was requested
+    if( wndconfig->glMajor > 2 )
+    {
+        _glfwPlatformCloseWindow();
+        return GL_FALSE;
+    }
+
+    _glfwWin.delegate = [[GLFWWindowDelegate alloc] init];
+    if( _glfwWin.delegate == nil )
+    {
+        _glfwPlatformCloseWindow();
+        return GL_FALSE;
+    }
+
+    [NSApp setDelegate:_glfwWin.delegate];
+
+    // Mac OS X needs non-zero color size, so set resonable values
+    colorBits = fbconfig->redBits + fbconfig->greenBits + fbconfig->blueBits;
+    if( colorBits == 0 )
+    {
+        colorBits = 24;
+    }
+    else if( colorBits < 15 )
+    {
+        colorBits = 15;
+    }
+
+    // Ignored hints:
+    // OpenGLMajor, OpenGLMinor, OpenGLForward:
+    //     pending Mac OS X support for OpenGL 3.x
+    // OpenGLDebug
+    //     pending it meaning anything on Mac OS X
+
+    // Don't use accumulation buffer support; it's not accelerated
+    // Aux buffers probably aren't accelerated either
+
+    CFDictionaryRef fullscreenMode = NULL;
+    if( wndconfig->mode == GLFW_FULLSCREEN )
+    {
+        fullscreenMode =
+            // I think it's safe to pass 0 to the refresh rate for this function
+            // rather than conditionalizing the code to call the version which
+            // doesn't specify refresh...
+            CGDisplayBestModeForParametersAndRefreshRateWithProperty(
+            CGMainDisplayID(),
+            colorBits + fbconfig->alphaBits,
+            width,
+            height,
+            wndconfig->refreshRate,
+            // Controversial, see macosx_fullscreen.m for discussion
+            kCGDisplayModeIsSafeForHardware,
+            NULL);
+
+        width = [[(id)fullscreenMode objectForKey:(id)kCGDisplayWidth] intValue];
+        height = [[(id)fullscreenMode objectForKey:(id)kCGDisplayHeight] intValue];
+    }
+
+    unsigned int styleMask = 0;
+    if( wndconfig->mode == GLFW_WINDOW )
+    {
+        styleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask;
+
+        if( !wndconfig->windowNoResize )
+        {
+            styleMask |= NSResizableWindowMask;
+        }
+    }
+    else
+    {
+        styleMask = NSBorderlessWindowMask;
+    }
+
+    _glfwWin.window = [[NSWindow alloc]
+        initWithContentRect:NSMakeRect(0, 0, width, height)
+                  styleMask:styleMask
+                    backing:NSBackingStoreBuffered
+                      defer:NO];
+    [_glfwWin.window setContentView:[[GLFWContentView alloc] init]];
+    [_glfwWin.window setDelegate:_glfwWin.delegate];
+    [_glfwWin.window setAcceptsMouseMovedEvents:YES];
+    [_glfwWin.window center];
+
+    if( wndconfig->mode == GLFW_FULLSCREEN )
+    {
+        CGCaptureAllDisplays();
+        CGDisplaySwitchToMode( CGMainDisplayID(), fullscreenMode );
+    }
+
+    unsigned int attribute_count = 0;
+#define ADD_ATTR(x) attributes[attribute_count++] = x
+#define ADD_ATTR2(x, y) (void)({ ADD_ATTR(x); ADD_ATTR(y); })
+#define MAX_ATTRS 24 // urgh
+    NSOpenGLPixelFormatAttribute attributes[MAX_ATTRS];
+
+    ADD_ATTR( NSOpenGLPFADoubleBuffer );
+
+    if( wndconfig->mode == GLFW_FULLSCREEN )
+    {
+        ADD_ATTR( NSOpenGLPFAFullScreen );
+        ADD_ATTR( NSOpenGLPFANoRecovery );
+        ADD_ATTR2( NSOpenGLPFAScreenMask,
+                   CGDisplayIDToOpenGLDisplayMask( CGMainDisplayID() ) );
+    }
+
+    ADD_ATTR2( NSOpenGLPFAColorSize, colorBits );
+
+    if( fbconfig->alphaBits > 0)
+    {
+        ADD_ATTR2( NSOpenGLPFAAlphaSize, fbconfig->alphaBits );
+    }
+
+    if( fbconfig->depthBits > 0)
+    {
+        ADD_ATTR2( NSOpenGLPFADepthSize, fbconfig->depthBits );
+    }
+
+    if( fbconfig->stencilBits > 0)
+    {
+        ADD_ATTR2( NSOpenGLPFAStencilSize, fbconfig->stencilBits );
+    }
+
+    int accumBits = fbconfig->accumRedBits + fbconfig->accumGreenBits +
+                    fbconfig->accumBlueBits + fbconfig->accumAlphaBits;
+
+    if( accumBits > 0)
+    {
+        ADD_ATTR2( NSOpenGLPFAAccumSize, accumBits );
+    }
+
+    if( fbconfig->auxBuffers > 0)
+    {
+        ADD_ATTR2( NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers );
+    }
+
+    if( fbconfig->stereo)
+    {
+        ADD_ATTR( NSOpenGLPFAStereo );
+    }
+
+    if( fbconfig->samples > 0)
+    {
+        ADD_ATTR2( NSOpenGLPFASampleBuffers, 1 );
+        ADD_ATTR2( NSOpenGLPFASamples, fbconfig->samples );
+    }
+
+    ADD_ATTR(0);
+
+    _glfwWin.pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+    if( _glfwWin.pixelFormat == nil )
+    {
+        _glfwPlatformCloseWindow();
+        return GL_FALSE;
+    }
+
+    _glfwWin.context = [[NSOpenGLContext alloc] initWithFormat:_glfwWin.pixelFormat
+                                                  shareContext:nil];
+    if( _glfwWin.context == nil )
+    {
+        _glfwPlatformCloseWindow();
+        return GL_FALSE;
+    }
+
+    [_glfwWin.window makeKeyAndOrderFront:nil];
+    [_glfwWin.context setView:[_glfwWin.window contentView]];
+
+    if( wndconfig->mode == GLFW_FULLSCREEN )
+    {
+        // TODO: Make this work on pre-Leopard systems
+        [[_glfwWin.window contentView] enterFullScreenMode:[NSScreen mainScreen]
+                                               withOptions:nil];
+    }
+
+    [_glfwWin.context makeCurrentContext];
+
+    NSPoint point = [[NSCursor currentCursor] hotSpot];
+    _glfwInput.MousePosX = point.x;
+    _glfwInput.MousePosY = point.y;
+
+    return GL_TRUE;
+}
+
+//========================================================================
+// Properly kill the window / video display
+//========================================================================
+
+void _glfwPlatformCloseWindow( void )
+{
+    [_glfwWin.window orderOut:nil];
+
+    if( _glfwWin.fullscreen )
+    {
+        [[_glfwWin.window contentView] exitFullScreenModeWithOptions:nil];
+        CGDisplaySwitchToMode( CGMainDisplayID(),
+                               (CFDictionaryRef)_glfwLibrary.DesktopMode );
+        CGReleaseAllDisplays();
+    }
+
+    [_glfwWin.pixelFormat release];
+    _glfwWin.pixelFormat = nil;
+
+    [NSOpenGLContext clearCurrentContext];
+    [_glfwWin.context release];
+    _glfwWin.context = nil;
+
+    [_glfwWin.window setDelegate:nil];
+    [NSApp setDelegate:nil];
+    [_glfwWin.delegate release];
+    _glfwWin.delegate = nil;
+
+    [_glfwWin.window close];
+    _glfwWin.window = nil;
+
+    // TODO: Probably more cleanup
+}
+
+//========================================================================
+// Set the window title
+//========================================================================
+
+void _glfwPlatformSetWindowTitle( const char *title )
+{
+    [_glfwWin.window setTitle:[NSString stringWithCString:title
+                     encoding:NSISOLatin1StringEncoding]];
+}
+
+//========================================================================
+// Set the window size
+//========================================================================
+
+void _glfwPlatformSetWindowSize( int width, int height )
+{
+    [_glfwWin.window setContentSize:NSMakeSize(width, height)];
+}
+
+//========================================================================
+// Set the window position
+//========================================================================
+
+void _glfwPlatformSetWindowPos( int x, int y )
+{
+    NSRect contentRect = [_glfwWin.window contentRectForFrameRect:[_glfwWin.window frame]];
+
+    // We assume here that the client code wants to position the window within the
+    // screen the window currently occupies
+    NSRect screenRect = [[_glfwWin.window screen] visibleFrame];
+    contentRect.origin = NSMakePoint(screenRect.origin.x + x,
+                                     screenRect.origin.y + screenRect.size.height -
+                                         y - contentRect.size.height);
+
+    [_glfwWin.window setFrame:[_glfwWin.window frameRectForContentRect:contentRect]
+                      display:YES];
+}
+
+//========================================================================
+// Iconify the window
+//========================================================================
+
+void _glfwPlatformIconifyWindow( void )
+{
+    [_glfwWin.window miniaturize:nil];
+}
+
+//========================================================================
+// Restore (un-iconify) the window
+//========================================================================
+
+void _glfwPlatformRestoreWindow( void )
+{
+    [_glfwWin.window deminiaturize:nil];
+}
+
+//========================================================================
+// Swap buffers
+//========================================================================
+
+void _glfwPlatformSwapBuffers( void )
+{
+    // ARP appears to be unnecessary, but this is future-proof
+    [_glfwWin.context flushBuffer];
+}
+
+//========================================================================
+// Set double buffering swap interval
+//========================================================================
+
+void _glfwPlatformSwapInterval( int interval )
+{
+    GLint sync = interval;
+    [_glfwWin.context setValues:&sync forParameter:NSOpenGLCPSwapInterval];
+}
+
+//========================================================================
+// Write back window parameters into GLFW window structure
+//========================================================================
+
+void _glfwPlatformRefreshWindowParams( void )
+{
+    GLint value;
+
+    // Since GLFW 2.x doesn't understand screens, we use virtual screen zero
+
+    [_glfwWin.pixelFormat getValues:&value
+                       forAttribute:NSOpenGLPFAAccelerated
+                   forVirtualScreen:0];
+    _glfwWin.accelerated = value;
+
+    [_glfwWin.pixelFormat getValues:&value
+                       forAttribute:NSOpenGLPFAAlphaSize
+                   forVirtualScreen:0];
+    _glfwWin.alphaBits = value;
+
+    // It seems that the color size includes the size of the alpha channel
+    [_glfwWin.pixelFormat getValues:&value
+                       forAttribute:NSOpenGLPFAColorSize
+                   forVirtualScreen:0];
+    value -= _glfwWin.alphaBits;
+    _glfwWin.redBits = value / 3;
+    _glfwWin.greenBits = value / 3;
+    _glfwWin.blueBits = value / 3;
+
+    [_glfwWin.pixelFormat getValues:&value
+                       forAttribute:NSOpenGLPFADepthSize
+                   forVirtualScreen:0];
+    _glfwWin.depthBits = value;
+
+    [_glfwWin.pixelFormat getValues:&value
+                       forAttribute:NSOpenGLPFAStencilSize
+                   forVirtualScreen:0];
+    _glfwWin.stencilBits = value;
+
+    [_glfwWin.pixelFormat getValues:&value
+                       forAttribute:NSOpenGLPFAAccumSize
+                   forVirtualScreen:0];
+    _glfwWin.accumRedBits = value / 3;
+    _glfwWin.accumGreenBits = value / 3;
+    _glfwWin.accumBlueBits = value / 3;
+
+    // TODO: Figure out what to set this value to
+    _glfwWin.accumAlphaBits = 0;
+
+    [_glfwWin.pixelFormat getValues:&value
+                       forAttribute:NSOpenGLPFAAuxBuffers
+                   forVirtualScreen:0];
+    _glfwWin.auxBuffers = value;
+
+    [_glfwWin.pixelFormat getValues:&value
+                       forAttribute:NSOpenGLPFAStereo
+                   forVirtualScreen:0];
+    _glfwWin.stereo = value;
+
+    [_glfwWin.pixelFormat getValues:&value
+                       forAttribute:NSOpenGLPFASamples
+                   forVirtualScreen:0];
+    _glfwWin.samples = value;
+
+    // These are forced to false as long as Mac OS X lacks support for OpenGL 3.0+
+    _glfwWin.glForward = GL_FALSE;
+    _glfwWin.glDebug = GL_FALSE;
+    _glfwWin.glProfile = 0;
+}
+
+//========================================================================
+// Poll for new window and input events
+//========================================================================
+
+void _glfwPlatformPollEvents( void )
+{
+    NSEvent *event;
+
+    do
+    {
+        event = [NSApp nextEventMatchingMask:NSAnyEventMask
+                                   untilDate:[NSDate distantPast]
+                                      inMode:NSDefaultRunLoopMode
+                                     dequeue:YES];
+
+        if (event)
+        {
+            // Urho3D: detect events also outside the client area to detect window drag
+            NSEventType eventType = [event type];
+            if (eventType == NSLeftMouseDown)
+                _glfwWin.leftMouseDown = GL_TRUE;
+            else if (eventType == NSLeftMouseUp)
+                _glfwWin.leftMouseDown = GL_FALSE;
+            
+            [NSApp sendEvent:event];
+        }
+    }
+    while (event);
+
+    [_glfwLibrary.AutoreleasePool drain];
+    _glfwLibrary.AutoreleasePool = [[NSAutoreleasePool alloc] init];
+
+    // Urho3D: track activation
+    _glfwWin.iconified = [_glfwWin.window isMiniaturized] == YES;
+    _glfwWin.active = [_glfwWin.window isMainWindow] == YES && [_glfwWin.window isKeyWindow] == YES;
+    // When activation changes, disable/reenable mouse lock if necessary
+    if (_glfwWin.mouseLock)
+    {
+        if (_glfwWin.active && !_glfwWin.lastActive && !_glfwWin.leftMouseDown)
+        {
+            _glfwPlatformHideMouseCursor();
+            _glfwWin.lastActive = _glfwWin.active;
+        }
+        else if (!_glfwWin.active && _glfwWin.lastActive)
+        {
+            _glfwPlatformShowMouseCursor();
+            _glfwWin.lastActive = _glfwWin.active;
+        }
+    }
+}
+
+//========================================================================
+// Wait for new window and input events
+//========================================================================
+
+void _glfwPlatformWaitEvents( void )
+{
+    // I wanted to pass NO to dequeue:, and rely on PollEvents to
+    // dequeue and send.  For reasons not at all clear to me, passing
+    // NO to dequeue: causes this method never to return.
+    NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
+                                        untilDate:[NSDate distantFuture]
+                                           inMode:NSDefaultRunLoopMode
+                                          dequeue:YES];
+    [NSApp sendEvent:event];
+
+    _glfwPlatformPollEvents();
+}
+
+//========================================================================
+// Hide mouse cursor (lock it)
+//========================================================================
+
+void _glfwPlatformHideMouseCursor( void )
+{
+    [NSCursor hide];
+    CGAssociateMouseAndMouseCursorPosition( false );
+}
+
+//========================================================================
+// Show mouse cursor (unlock it)
+//========================================================================
+
+void _glfwPlatformShowMouseCursor( void )
+{
+    [NSCursor unhide];
+    CGAssociateMouseAndMouseCursorPosition( true );
+}
+
+//========================================================================
+// Set physical mouse cursor position
+//========================================================================
+
+void _glfwPlatformSetMouseCursorPos( int x, int y )
+{
+    // The library seems to assume that after calling this the mouse won't move,
+    // but obviously it will, and escape the app's window, and activate other apps,
+    // and other badness in pain.  I think the API's just silly, but maybe I'm
+    // misunderstanding it...
+
+    // Also, (x, y) are window coords...
+
+    // Also, it doesn't seem possible to write this robustly without
+    // calculating the maximum y coordinate of all screens, since Cocoa's
+    // "global coordinates" are upside down from CG's...
+
+    // Without this (once per app run, but it's convenient to do it here)
+    // events will be suppressed for a default of 0.25 seconds after we
+    // move the cursor.
+    CGSetLocalEventsSuppressionInterval( 0.0 );
+
+    NSPoint localPoint = NSMakePoint( x, y );
+    NSPoint globalPoint = [_glfwWin.window convertBaseToScreen:localPoint];
+    CGPoint mainScreenOrigin = CGDisplayBounds( CGMainDisplayID() ).origin;
+    double mainScreenHeight = CGDisplayBounds( CGMainDisplayID() ).size.height;
+    CGPoint targetPoint = CGPointMake( globalPoint.x - mainScreenOrigin.x,
+                                       mainScreenHeight - globalPoint.y - mainScreenOrigin.y );
+    CGDisplayMoveCursorToPoint( CGMainDisplayID(), targetPoint );
+}
+

+ 258 - 0
ThirdParty/GLFW/lib/cocoa/platform.h

@@ -0,0 +1,258 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund <[email protected]>
+//
+// 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.
+//
+//========================================================================
+
+// Modified by Lasse Öörni for Urho3D
+
+#ifndef _platform_h_
+#define _platform_h_
+
+
+// This is the Mac OS X version of GLFW
+#define _GLFW_MAC_OS_X
+
+#if defined(__OBJC__)
+#import <Cocoa/Cocoa.h>
+#else
+typedef void *id;
+#endif
+
+#include <pthread.h>
+
+#include "../../include/GL/glfw.h"
+
+
+#ifndef GL_VERSION_3_0
+
+typedef const GLubyte * (APIENTRY *PFNGLGETSTRINGIPROC) (GLenum, GLuint);
+
+#endif /*GL_VERSION_3_0*/
+
+
+//========================================================================
+// GLFW platform specific types
+//========================================================================
+
+//------------------------------------------------------------------------
+// Pointer length integer
+//------------------------------------------------------------------------
+typedef intptr_t GLFWintptr;
+
+//------------------------------------------------------------------------
+// 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
+    int       refreshRate;     // Vertical monitor refresh rate
+
+    // 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
+
+    // Framebuffer attributes
+    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       samples;
+
+    // OpenGL extensions and context attributes
+    int       has_GL_SGIS_generate_mipmap;
+    int       has_GL_ARB_texture_non_power_of_two;
+    int       glMajor, glMinor, glRevision;
+    int       glForward, glDebug, glProfile;
+
+    PFNGLGETSTRINGIPROC GetStringi;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+    id        window;
+    id        pixelFormat;
+    id	      context;
+    id	      delegate;
+    unsigned int modifierFlags;
+    
+    // Urho3D: added to track activation/deactivation, and left mouse status
+    int       lastActive;
+    int       leftMouseDown;
+};
+
+GLFWGLOBAL _GLFWwin _glfwWin;
+
+
+//------------------------------------------------------------------------
+// Library global data
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+    // Window opening hints
+    _GLFWhints      hints;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+    // Timer data
+    struct {
+        double t0;
+    } Timer;
+
+    // dlopen handle for dynamically-loading extension function pointers
+    void *OpenGLFramework;
+
+    int Unbundled;
+
+    id DesktopMode;
+
+    id AutoreleasePool;
+
+} _glfwLibrary;
+
+
+//------------------------------------------------------------------------
+// User input status (some 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 ======================================
+
+    double WheelPosFloating;
+
+} _glfwInput;
+
+//------------------------------------------------------------------------
+// Thread information
+//------------------------------------------------------------------------
+typedef struct _GLFWthread_struct _GLFWthread;
+
+// Thread record (one for each thread)
+struct _GLFWthread_struct {
+
+    // Pointer to previous and next threads in linked list
+    _GLFWthread   *Previous, *Next;
+
+    // GLFW user side thread information
+    GLFWthread    ID;
+    GLFWthreadfun Function;
+
+    // System side thread information
+    pthread_t     PosixID;
+};
+
+// General thread information
+GLFWGLOBAL struct {
+
+    // Critical section lock
+    pthread_mutex_t  CriticalSection;
+
+    // Next thread ID to use (increments for every created thread)
+    GLFWthread       NextID;
+
+    // First thread in linked list (always the main thread)
+    _GLFWthread      First;
+
+} _glfwThrd;
+
+
+//========================================================================
+// Macros for encapsulating critical code sections (i.e. making parts
+// of GLFW thread safe)
+//========================================================================
+
+// Define so we can use the same thread code as X11
+#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; \
+        } \
+    } \
+}
+
+// Thread list management
+#define ENTER_THREAD_CRITICAL_SECTION \
+pthread_mutex_lock( &_glfwThrd.CriticalSection );
+#define LEAVE_THREAD_CRITICAL_SECTION \
+pthread_mutex_unlock( &_glfwThrd.CriticalSection );
+
+
+#endif // _platform_h_

+ 310 - 0
ThirdParty/GLFW/lib/enable.c

@@ -0,0 +1,310 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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                       ****
+//************************************************************************
+
+//========================================================================
+// Enable (show) mouse cursor
+//========================================================================
+
+static void enableMouseCursor( void )
+{
+    int centerPosX, centerPosY;
+
+    if( !_glfwWin.opened || !_glfwWin.mouseLock )
+    {
+        return;
+    }
+
+    // Show mouse cursor
+    _glfwPlatformShowMouseCursor();
+
+    centerPosX = _glfwWin.width / 2;
+    centerPosY = _glfwWin.height / 2;
+
+    if( centerPosX != _glfwInput.MousePosX || centerPosY != _glfwInput.MousePosY )
+    {
+        _glfwPlatformSetMouseCursorPos( centerPosX, centerPosY );
+
+        _glfwInput.MousePosX = centerPosX;
+        _glfwInput.MousePosY = centerPosY;
+
+        if( _glfwWin.mousePosCallback )
+        {
+            _glfwWin.mousePosCallback( _glfwInput.MousePosX,
+                                       _glfwInput.MousePosY );
+        }
+    }
+
+    // From now on the mouse is unlocked
+    _glfwWin.mouseLock = GL_FALSE;
+}
+
+//========================================================================
+// Disable (hide) mouse cursor
+//========================================================================
+
+static void disableMouseCursor( void )
+{
+    if( !_glfwWin.opened || _glfwWin.mouseLock )
+    {
+        return;
+    }
+
+    // Hide mouse cursor
+    _glfwPlatformHideMouseCursor();
+
+    // Move cursor to the middle of the window
+    _glfwPlatformSetMouseCursorPos( _glfwWin.width >> 1,
+                                    _glfwWin.height >> 1 );
+
+    // From now on the mouse is locked
+    _glfwWin.mouseLock = GL_TRUE;
+}
+
+
+//========================================================================
+// Enable sticky keys
+//========================================================================
+
+static void enableStickyKeys( void )
+{
+    _glfwInput.StickyKeys = 1;
+}
+
+//========================================================================
+// Disable sticky keys
+//========================================================================
+
+static void disableStickyKeys( void )
+{
+    int i;
+
+    _glfwInput.StickyKeys = 0;
+
+    // Release all sticky keys
+    for( i = 0; i <= GLFW_KEY_LAST; i++ )
+    {
+        if( _glfwInput.Key[ i ] == 2 )
+        {
+            _glfwInput.Key[ i ] = 0;
+        }
+    }
+}
+
+
+//========================================================================
+// Enable sticky mouse buttons
+//========================================================================
+
+static void enableStickyMouseButtons( void )
+{
+    _glfwInput.StickyMouseButtons = 1;
+}
+
+//========================================================================
+// Disable sticky mouse buttons
+//========================================================================
+
+static void disableStickyMouseButtons( void )
+{
+    int i;
+
+    _glfwInput.StickyMouseButtons = 0;
+
+    // Release all sticky mouse buttons
+    for( i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++ )
+    {
+        if( _glfwInput.MouseButton[ i ] == 2 )
+        {
+            _glfwInput.MouseButton[ i ] = 0;
+        }
+    }
+}
+
+
+//========================================================================
+// Enable system keys
+//========================================================================
+
+static void enableSystemKeys( void )
+{
+    if( !_glfwWin.sysKeysDisabled )
+    {
+        return;
+    }
+
+    _glfwPlatformEnableSystemKeys();
+
+    // Indicate that system keys are no longer disabled
+    _glfwWin.sysKeysDisabled = GL_FALSE;
+}
+
+//========================================================================
+// Disable system keys
+//========================================================================
+
+static void disableSystemKeys( void )
+{
+    if( _glfwWin.sysKeysDisabled )
+    {
+        return;
+    }
+
+    _glfwPlatformDisableSystemKeys();
+
+    // Indicate that system keys are now disabled
+    _glfwWin.sysKeysDisabled = GL_TRUE;
+}
+
+
+//========================================================================
+// Enable key repeat
+//========================================================================
+
+static void enableKeyRepeat( void )
+{
+    _glfwInput.KeyRepeat = 1;
+}
+
+//========================================================================
+// Disable key repeat
+//========================================================================
+
+static void disableKeyRepeat( void )
+{
+    _glfwInput.KeyRepeat = 0;
+}
+
+
+//========================================================================
+// Enable automatic event polling
+//========================================================================
+
+static void enableAutoPollEvents( void )
+{
+    _glfwWin.autoPollEvents = 1;
+}
+
+//========================================================================
+// Disable automatic event polling
+//========================================================================
+
+static void disableAutoPollEvents( void )
+{
+    _glfwWin.autoPollEvents = 0;
+}
+
+
+
+//************************************************************************
+//****                    GLFW user functions                         ****
+//************************************************************************
+
+//========================================================================
+// Enable certain GLFW/window/system functions.
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwEnable( int token )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return;
+    }
+
+    switch( token )
+    {
+        case GLFW_MOUSE_CURSOR:
+            enableMouseCursor();
+            break;
+        case GLFW_STICKY_KEYS:
+            enableStickyKeys();
+            break;
+        case GLFW_STICKY_MOUSE_BUTTONS:
+            enableStickyMouseButtons();
+            break;
+        case GLFW_SYSTEM_KEYS:
+            enableSystemKeys();
+            break;
+        case GLFW_KEY_REPEAT:
+            enableKeyRepeat();
+            break;
+        case GLFW_AUTO_POLL_EVENTS:
+            enableAutoPollEvents();
+            break;
+        default:
+            break;
+    }
+}
+
+
+//========================================================================
+// Disable certain GLFW/window/system functions.
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwDisable( int token )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return;
+    }
+
+    switch( token )
+    {
+        case GLFW_MOUSE_CURSOR:
+            disableMouseCursor();
+            break;
+        case GLFW_STICKY_KEYS:
+            disableStickyKeys();
+            break;
+        case GLFW_STICKY_MOUSE_BUTTONS:
+            disableStickyMouseButtons();
+            break;
+        case GLFW_SYSTEM_KEYS:
+            disableSystemKeys();
+            break;
+        case GLFW_KEY_REPEAT:
+            disableKeyRepeat();
+            break;
+        case GLFW_AUTO_POLL_EVENTS:
+            disableAutoPollEvents();
+            break;
+        default:
+            break;
+    }
+}
+

+ 95 - 0
ThirdParty/GLFW/lib/fullscreen.c

@@ -0,0 +1,95 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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 user functions                         ****
+//************************************************************************
+
+//========================================================================
+// glfwGetVideoModes() - Get a list of available video modes
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwGetVideoModes( GLFWvidmode *list,
+    int maxcount )
+{
+    int         count, i, swap, res1, res2, depth1, depth2;
+    GLFWvidmode vm;
+
+    if( !_glfwInitialized || maxcount <= 0 || list == (GLFWvidmode*) 0 )
+    {
+        return 0;
+    }
+
+    // Get list of video modes
+    count = _glfwPlatformGetVideoModes( list, maxcount );
+
+    // Sort list (bubble sort)
+    do
+    {
+        swap = 0;
+        for( i = 0; i < count-1; ++ i )
+        {
+            res1   = list[i].Width*list[i].Height;
+            depth1 = list[i].RedBits+list[i].GreenBits+list[i].BlueBits;
+            res2   = list[i+1].Width*list[i+1].Height;
+            depth2 = list[i+1].RedBits+list[i+1].GreenBits+
+                     list[i+1].BlueBits;
+            if( (depth2<depth1) || ((depth2==depth1) && (res2<res1)) )
+            {
+                vm = list[i];
+                list[i] = list[i+1];
+                list[i+1] = vm;
+                swap = 1;
+            }
+        }
+    }
+    while( swap );
+
+    return count;
+}
+
+
+//========================================================================
+// glfwGetDesktopMode() - Get the desktop video mode
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwGetDesktopMode( GLFWvidmode *mode )
+{
+    if( !_glfwInitialized || mode == (GLFWvidmode*) 0 )
+    {
+        return;
+    }
+
+    _glfwPlatformGetDesktopMode( mode );
+}
+

+ 235 - 0
ThirdParty/GLFW/lib/glext.c

@@ -0,0 +1,235 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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                       ****
+//************************************************************************
+
+#ifndef GL_VERSION_3_0
+#define GL_NUM_EXTENSIONS 0x821D
+#endif
+
+//========================================================================
+// Parses the OpenGL version string and extracts the version number
+//========================================================================
+
+void _glfwParseGLVersion( int *major, int *minor, int *rev )
+{
+    GLuint _major, _minor = 0, _rev = 0;
+    const GLubyte *version;
+    const GLubyte *ptr;
+
+    // Get OpenGL version string
+    version = glGetString( GL_VERSION );
+    if( !version )
+    {
+        return;
+    }
+
+    // Parse string
+    ptr = version;
+    for( _major = 0; *ptr >= '0' && *ptr <= '9'; ptr ++ )
+    {
+        _major = 10*_major + (*ptr - '0');
+    }
+    if( *ptr == '.' )
+    {
+        ptr ++;
+        for( _minor = 0; *ptr >= '0' && *ptr <= '9'; ptr ++ )
+        {
+            _minor = 10*_minor + (*ptr - '0');
+        }
+        if( *ptr == '.' )
+        {
+            ptr ++;
+            for( _rev = 0; *ptr >= '0' && *ptr <= '9'; ptr ++ )
+            {
+                _rev = 10*_rev + (*ptr - '0');
+            }
+        }
+    }
+
+    // Return parsed values
+    *major = _major;
+    *minor = _minor;
+    *rev = _rev;
+}
+
+//========================================================================
+// _glfwStringInExtensionString() - Check if a string can be found in an
+// OpenGL extension string
+//========================================================================
+
+int _glfwStringInExtensionString( const char *string,
+                                  const GLubyte *extensions )
+{
+    const GLubyte *start;
+    GLubyte *where, *terminator;
+
+    // It takes a bit of care to be fool-proof about parsing the
+    // OpenGL extensions string. Don't be fooled by sub-strings,
+    // etc.
+    start = extensions;
+    while( 1 )
+    {
+        where = (GLubyte *) strstr( (const char *) start, string );
+        if( !where )
+        {
+            return GL_FALSE;
+        }
+        terminator = where + strlen( string );
+        if( where == start || *(where - 1) == ' ' )
+        {
+            if( *terminator == ' ' || *terminator == '\0' )
+            {
+                break;
+            }
+        }
+        start = terminator;
+    }
+
+    return GL_TRUE;
+}
+
+
+
+//************************************************************************
+//****                    GLFW user functions                         ****
+//************************************************************************
+
+//========================================================================
+// Check if an OpenGL extension is available at runtime
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwExtensionSupported( const char *extension )
+{
+    const GLubyte *extensions;
+    GLubyte *where;
+    GLint count;
+    int i;
+
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return GL_FALSE;
+    }
+
+    // Extension names should not have spaces
+    where = (GLubyte *) strchr( extension, ' ' );
+    if( where || *extension == '\0' )
+    {
+        return GL_FALSE;
+    }
+
+    if( _glfwWin.glMajor < 3 )
+    {
+        // Check if extension is in the old style OpenGL extensions string
+
+        extensions = glGetString( GL_EXTENSIONS );
+        if( extensions != NULL )
+        {
+            if( _glfwStringInExtensionString( extension, extensions ) )
+            {
+                return GL_TRUE;
+            }
+        }
+    }
+    else
+    {
+        // Check if extension is in the modern OpenGL extensions string list
+
+        glGetIntegerv( GL_NUM_EXTENSIONS, &count );
+
+        for( i = 0;  i < count;  i++ )
+        {
+             if( strcmp( (const char*) _glfwWin.GetStringi( GL_EXTENSIONS, i ),
+                         extension ) == 0 )
+             {
+                 return GL_TRUE;
+             }
+        }
+    }
+
+    // Additional platform specific extension checking (e.g. WGL)
+    if( _glfwPlatformExtensionSupported( extension ) )
+    {
+        return GL_TRUE;
+    }
+
+    return GL_FALSE;
+}
+
+
+//========================================================================
+// glfwGetProcAddress() - Get the function pointer to an OpenGL function.
+// This function can be used to get access to extended OpenGL functions.
+//========================================================================
+
+GLFWAPI void * GLFWAPIENTRY glfwGetProcAddress( const char *procname )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return NULL;
+    }
+
+    return _glfwPlatformGetProcAddress( procname );
+}
+
+
+//========================================================================
+// Returns the OpenGL version
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwGetGLVersion( int *major, int *minor, int *rev )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    if( major != NULL )
+    {
+        *major = _glfwWin.glMajor;
+    }
+    if( minor != NULL )
+    {
+        *minor = _glfwWin.glMinor;
+    }
+    if( rev != NULL )
+    {
+        *rev = _glfwWin.glRevision;
+    }
+}
+

+ 631 - 0
ThirdParty/GLFW/lib/image.c

@@ -0,0 +1,631 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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.
+//
+//========================================================================
+
+//========================================================================
+// Description:
+//
+// This module acts as an interface for different image file formats (the
+// image file format is detected automatically).
+//
+// By default the loaded image is rescaled (using bilinear interpolation)
+// to the next higher 2^N x 2^M resolution, unless it has a valid
+// 2^N x 2^M resolution. The interpolation is quite slow, even if the
+// routine has been optimized for speed (a 200x200 RGB image is scaled to
+// 256x256 in ~30 ms on a P3-500).
+//
+// Paletted images are converted to RGB/RGBA images.
+//
+// A convenience function is also included (glfwLoadTexture2D), which
+// loads a texture image from a file directly to OpenGL texture memory,
+// with an option to generate all mipmap levels. GL_SGIS_generate_mipmap
+// is used whenever available, which should give an optimal mipmap
+// generation speed (possibly performed in hardware). A software fallback
+// method is included when GL_SGIS_generate_mipmap is not supported (it
+// generates all mipmaps of a 256x256 RGB texture in ~3 ms on a P3-500).
+//
+//========================================================================
+
+
+#include "internal.h"
+
+
+// We want to support automatic mipmap generation
+#ifndef GL_SGIS_generate_mipmap
+ #define GL_GENERATE_MIPMAP_SGIS       0x8191
+ #define GL_GENERATE_MIPMAP_HINT_SGIS  0x8192
+ #define GL_SGIS_generate_mipmap    1
+#endif // GL_SGIS_generate_mipmap
+
+
+//************************************************************************
+//****                  GLFW internal functions                       ****
+//************************************************************************
+
+//========================================================================
+// Upsample image, from size w1 x h1 to w2 x h2
+//========================================================================
+
+static void UpsampleImage( unsigned char *src, unsigned char *dst,
+    int w1, int h1, int w2, int h2, int bpp )
+{
+    int m, n, k, x, y, col8;
+    float dx, dy, xstep, ystep, col, col1, col2;
+    unsigned char *src1, *src2, *src3, *src4;
+
+    // Calculate scaling factor
+    xstep = (float)(w1-1) / (float)(w2-1);
+    ystep = (float)(h1-1) / (float)(h2-1);
+
+    // Copy source data to destination data with bilinear interpolation
+    // Note: The rather strange look of this routine is a direct result of
+    // my attempts at optimizing it. Improvements are welcome!
+    dy = 0.0f;
+    y = 0;
+    for( n = 0; n < h2; n ++ )
+    {
+        dx = 0.0f;
+        src1 = &src[ y*w1*bpp ];
+        src3 = y < (h1-1) ? src1 + w1*bpp : src1;
+        src2 = src1 + bpp;
+        src4 = src3 + bpp;
+        x = 0;
+        for( m = 0; m < w2; m ++ )
+        {
+            for( k = 0; k < bpp; k ++ )
+            {
+                col1 = *src1 ++;
+                col2 = *src2 ++;
+                col = col1 + (col2 - col1) * dx;
+                col1 = *src3 ++;
+                col2 = *src4 ++;
+                col2 = col1 + (col2 - col1) * dx;
+                col += (col2 - col) * dy;
+                col8 = (int) (col + 0.5);
+                if( col8 >= 256 ) col8 = 255;
+                *dst++ = (unsigned char) col8;
+            }
+            dx += xstep;
+            if( dx >= 1.0f )
+            {
+                x ++;
+                dx -= 1.0f;
+                if( x >= (w1-1) )
+                {
+                    src2 = src1;
+                    src4 = src3;
+                }
+            }
+            else
+            {
+                src1 -= bpp;
+                src2 -= bpp;
+                src3 -= bpp;
+                src4 -= bpp;
+            }
+        }
+        dy += ystep;
+        if( dy >= 1.0f )
+        {
+            y ++;
+            dy -= 1.0f;
+        }
+    }
+}
+
+
+//========================================================================
+// Build the next mip-map level
+//========================================================================
+
+static int HalveImage( GLubyte *src, int *width, int *height,
+    int components )
+{
+    int     halfwidth, halfheight, m, n, k, idx1, idx2;
+    GLubyte *dst;
+
+    // Last level?
+    if( *width <= 1 && *height <= 1 )
+    {
+        return GL_FALSE;
+    }
+
+    // Calculate new width and height (handle 1D case)
+    halfwidth  = *width > 1 ? *width / 2 : 1;
+    halfheight = *height > 1 ? *height / 2 : 1;
+
+    // Downsample image with a simple box-filter
+    dst = src;
+    if( *width == 1 || *height == 1 )
+    {
+        // 1D case
+        for( m = 0; m < halfwidth+halfheight-1; m ++ )
+        {
+            for( k = 0; k < components; k ++ )
+            {
+                *dst ++ = (GLubyte) (((int)*src +
+                                      (int)src[components] + 1) >> 1);
+                src ++;
+            }
+            src += components;
+        }
+    }
+    else
+    {
+        // 2D case
+        idx1 = *width*components;
+        idx2 = (*width+1)*components;
+        for( m = 0; m < halfheight; m ++ )
+        {
+            for( n = 0; n < halfwidth; n ++ )
+            {
+                for( k = 0; k < components; k ++ )
+                {
+                    *dst ++ = (GLubyte) (((int)*src +
+                                          (int)src[components] +
+                                          (int)src[idx1] +
+                                          (int)src[idx2] + 2) >> 2);
+                    src ++;
+                }
+                src += components;
+            }
+            src += components * (*width);
+        }
+    }
+
+    // Return new width and height
+    *width = halfwidth;
+    *height = halfheight;
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Rescales an image into power-of-two dimensions
+//========================================================================
+
+static int RescaleImage( GLFWimage* image )
+{
+    int     width, height, log2, newsize;
+    unsigned char *data;
+
+    // Calculate next larger 2^N width
+    for( log2 = 0, width = image->Width; width > 1; width >>= 1, log2 ++ )
+      ;
+
+    width  = (int) 1 << log2;
+    if( width < image->Width )
+    {
+        width <<= 1;
+    }
+
+    // Calculate next larger 2^M height
+    for( log2 = 0, height = image->Height; height > 1; height >>= 1, log2 ++ )
+      ;
+
+    height = (int) 1 << log2;
+    if( height < image->Height )
+    {
+        height <<= 1;
+    }
+
+    // Do we really need to rescale?
+    if( width != image->Width || height != image->Height )
+    {
+        // Allocate memory for new (upsampled) image data
+        newsize = width * height * image->BytesPerPixel;
+        data = (unsigned char *) malloc( newsize );
+        if( data == NULL )
+        {
+            free( image->Data );
+            return GL_FALSE;
+        }
+
+        // Copy old image data to new image data with interpolation
+        UpsampleImage( image->Data, data, image->Width, image->Height,
+                       width, height, image->BytesPerPixel );
+
+        // Free memory for old image data (not needed anymore)
+        free( image->Data );
+
+        // Set pointer to new image data, and set new image dimensions
+        image->Data   = data;
+        image->Width  = width;
+        image->Height = height;
+    }
+
+    return GL_TRUE;
+}
+
+
+//************************************************************************
+//****                    GLFW user functions                         ****
+//************************************************************************
+
+//========================================================================
+// glfwReadImage() - Read an image from a named file
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwReadImage( const char *name, GLFWimage *img,
+    int flags )
+{
+    _GLFWstream stream;
+
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return GL_FALSE;
+    }
+
+    // Start with an empty image descriptor
+    img->Width         = 0;
+    img->Height        = 0;
+    img->BytesPerPixel = 0;
+    img->Data          = NULL;
+
+    // Open file
+    if( !_glfwOpenFileStream( &stream, name, "rb" ) )
+    {
+        return GL_FALSE;
+    }
+
+    // We only support TGA files at the moment
+    if( !_glfwReadTGA( &stream, img, flags ) )
+    {
+        _glfwCloseStream( &stream );
+        return GL_FALSE;
+    }
+
+    // Close stream
+    _glfwCloseStream( &stream );
+
+    // Should we rescale the image to closest 2^N x 2^M resolution?
+    if( !(flags & GLFW_NO_RESCALE_BIT) )
+    {
+        if( !RescaleImage( img ) )
+        {
+            return GL_FALSE;
+        }
+    }
+
+    // Interpret BytesPerPixel as an OpenGL format
+    switch( img->BytesPerPixel )
+    {
+        default:
+        case 1:
+            if( flags & GLFW_ALPHA_MAP_BIT )
+            {
+                img->Format = GL_ALPHA;
+            }
+            else
+            {
+                img->Format = GL_LUMINANCE;
+            }
+            break;
+        case 3:
+            img->Format = GL_RGB;
+            break;
+        case 4:
+            img->Format = GL_RGBA;
+            break;
+    }
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// glfwReadMemoryImage() - Read an image file from a memory buffer
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwReadMemoryImage( const void *data, long size, GLFWimage *img, int flags )
+{
+    _GLFWstream stream;
+
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return GL_FALSE;
+    }
+
+    // Start with an empty image descriptor
+    img->Width         = 0;
+    img->Height        = 0;
+    img->BytesPerPixel = 0;
+    img->Data          = NULL;
+
+    // Open buffer
+    if( !_glfwOpenBufferStream( &stream, (void*) data, size ) )
+    {
+        return GL_FALSE;
+    }
+
+    // We only support TGA files at the moment
+    if( !_glfwReadTGA( &stream, img, flags ) )
+    {
+        _glfwCloseStream( &stream );
+        return GL_FALSE;
+    }
+
+    // Close stream
+    _glfwCloseStream( &stream );
+
+    // Should we rescale the image to closest 2^N x 2^M resolution?
+    if( !(flags & GLFW_NO_RESCALE_BIT) )
+    {
+        if( !RescaleImage( img ) )
+        {
+            return GL_FALSE;
+        }
+    }
+
+    // Interpret BytesPerPixel as an OpenGL format
+    switch( img->BytesPerPixel )
+    {
+        default:
+        case 1:
+            if( flags & GLFW_ALPHA_MAP_BIT )
+            {
+                img->Format = GL_ALPHA;
+            }
+            else
+            {
+                img->Format = GL_LUMINANCE;
+            }
+            break;
+        case 3:
+            img->Format = GL_RGB;
+            break;
+        case 4:
+            img->Format = GL_RGBA;
+            break;
+    }
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// glfwFreeImage() - Free allocated memory for an image
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwFreeImage( GLFWimage *img )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return;
+    }
+
+    // Free memory
+    if( img->Data != NULL )
+    {
+        free( img->Data );
+        img->Data = NULL;
+    }
+
+    // Clear all fields
+    img->Width         = 0;
+    img->Height        = 0;
+    img->Format        = 0;
+    img->BytesPerPixel = 0;
+}
+
+
+//========================================================================
+// glfwLoadTexture2D() - Read an image from a file, and upload it to
+// texture memory
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwLoadTexture2D( const char *name, int flags )
+{
+    GLFWimage img;
+
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return GL_FALSE;
+    }
+
+    // Force rescaling if necessary
+    if( !_glfwWin.has_GL_ARB_texture_non_power_of_two )
+    {
+        flags &= (~GLFW_NO_RESCALE_BIT);
+    }
+
+    // Read image from file
+    if( !glfwReadImage( name, &img, flags ) )
+    {
+        return GL_FALSE;
+    }
+
+    if( !glfwLoadTextureImage2D( &img, flags ) )
+    {
+        return GL_FALSE;
+    }
+
+    // Data buffer is not needed anymore
+    glfwFreeImage( &img );
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// glfwLoadMemoryTexture2D() - Read an image from a buffer, and upload it to
+// texture memory
+//========================================================================
+
+GLFWAPI int  GLFWAPIENTRY glfwLoadMemoryTexture2D( const void *data, long size, int flags )
+{
+    GLFWimage img;
+
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return GL_FALSE;
+    }
+
+    // Force rescaling if necessary
+    if( !_glfwWin.has_GL_ARB_texture_non_power_of_two )
+    {
+        flags &= (~GLFW_NO_RESCALE_BIT);
+    }
+
+    // Read image from file
+    if( !glfwReadMemoryImage( data, size, &img, flags ) )
+    {
+        return GL_FALSE;
+    }
+
+    if( !glfwLoadTextureImage2D( &img, flags ) )
+    {
+        return GL_FALSE;
+    }
+
+    // Data buffer is not needed anymore
+    glfwFreeImage( &img );
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// glfwLoadTextureImage2D() - Upload an image object to texture memory
+//========================================================================
+
+GLFWAPI int  GLFWAPIENTRY glfwLoadTextureImage2D( GLFWimage *img, int flags )
+{
+    GLint   UnpackAlignment, GenMipMap;
+    int     level, format, AutoGen, newsize, n;
+    unsigned char *data, *dataptr;
+
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return GL_FALSE;
+    }
+
+    // TODO: Use GL_MAX_TEXTURE_SIZE or GL_PROXY_TEXTURE_2D to determine
+    //       whether the image size is valid.
+    // NOTE: May require box filter downsampling routine.
+
+    // Do we need to convert the alpha map to RGBA format (OpenGL 1.0)?
+    if( (_glfwWin.glMajor == 1) && (_glfwWin.glMinor == 0) &&
+        (img->Format == GL_ALPHA) )
+    {
+        // We go to RGBA representation instead
+        img->BytesPerPixel = 4;
+
+        // Allocate memory for new RGBA image data
+        newsize = img->Width * img->Height * img->BytesPerPixel;
+        data = (unsigned char *) malloc( newsize );
+        if( data == NULL )
+        {
+            free( img->Data );
+            return GL_FALSE;
+        }
+
+        // Convert Alpha map to RGBA
+        dataptr = data;
+        for( n = 0; n < (img->Width*img->Height); ++ n )
+        {
+            *dataptr ++ = 255;
+            *dataptr ++ = 255;
+            *dataptr ++ = 255;
+            *dataptr ++ = img->Data[n];
+        }
+
+        // Free memory for old image data (not needed anymore)
+        free( img->Data );
+
+        // Set pointer to new image data
+        img->Data = data;
+    }
+
+    // Set unpack alignment to one byte
+    glGetIntegerv( GL_UNPACK_ALIGNMENT, &UnpackAlignment );
+    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+    // Should we use automatic mipmap generation?
+    AutoGen = ( flags & GLFW_BUILD_MIPMAPS_BIT ) &&
+              _glfwWin.has_GL_SGIS_generate_mipmap;
+
+    // Enable automatic mipmap generation
+    if( AutoGen )
+    {
+        glGetTexParameteriv( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS,
+            &GenMipMap );
+        glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS,
+            GL_TRUE );
+    }
+
+    // Format specification is different for OpenGL 1.0
+    if( _glfwWin.glMajor == 1 && _glfwWin.glMinor == 0 )
+    {
+        format = img->BytesPerPixel;
+    }
+    else
+    {
+        format = img->Format;
+    }
+
+    // Upload to texture memeory
+    level = 0;
+    do
+    {
+        // Upload this mipmap level
+        glTexImage2D( GL_TEXTURE_2D, level, format,
+            img->Width, img->Height, 0, format,
+            GL_UNSIGNED_BYTE, (void*) img->Data );
+
+        // Build next mipmap level manually, if required
+        if( ( flags & GLFW_BUILD_MIPMAPS_BIT ) && !AutoGen )
+        {
+            level = HalveImage( img->Data, &img->Width,
+                        &img->Height, img->BytesPerPixel ) ?
+                    level + 1 : 0;
+        }
+    }
+    while( level != 0 );
+
+    // Restore old automatic mipmap generation state
+    if( AutoGen )
+    {
+        glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS,
+            GenMipMap );
+    }
+
+    // Restore old unpack alignment
+    glPixelStorei( GL_UNPACK_ALIGNMENT, UnpackAlignment );
+
+    return GL_TRUE;
+}
+

+ 111 - 0
ThirdParty/GLFW/lib/init.c

@@ -0,0 +1,111 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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.
+//
+//========================================================================
+
+#define _init_c_
+#include "internal.h"
+
+
+//************************************************************************
+//****                    GLFW user functions                         ****
+//************************************************************************
+
+//========================================================================
+// glfwInit() - Initialize various GLFW state
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwInit( void )
+{
+    // Is GLFW already initialized?
+    if( _glfwInitialized )
+    {
+        return GL_TRUE;
+    }
+
+    memset( &_glfwLibrary, 0, sizeof( _glfwLibrary ) );
+    memset( &_glfwWin, 0, sizeof( _glfwWin ) );
+
+    // Window is not yet opened
+    _glfwWin.opened = GL_FALSE;
+
+    // Default enable/disable settings
+    _glfwWin.sysKeysDisabled = GL_FALSE;
+
+    // Clear window hints
+    _glfwClearWindowHints();
+
+    // Platform specific initialization
+    if( !_glfwPlatformInit() )
+    {
+        return GL_FALSE;
+    }
+
+    // Form now on, GLFW state is valid
+    _glfwInitialized = GL_TRUE;
+
+    return GL_TRUE;
+}
+
+
+
+//========================================================================
+// glfwTerminate() - Close window and kill all threads.
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwTerminate( void )
+{       
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return;
+    }
+
+    // Platform specific termination
+    if( !_glfwPlatformTerminate() )
+    {
+        return;
+    }
+
+    // GLFW is no longer initialized
+    _glfwInitialized = GL_FALSE;
+}
+
+
+//========================================================================
+// glfwGetVersion() - Get GLFW version
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwGetVersion( int *major, int *minor,
+    int *rev )
+{
+    if( major != NULL ) *major = GLFW_VERSION_MAJOR;
+    if( minor != NULL ) *minor = GLFW_VERSION_MINOR;
+    if( rev   != NULL ) *rev   = GLFW_VERSION_REVISION;
+}
+

+ 280 - 0
ThirdParty/GLFW/lib/input.c

@@ -0,0 +1,280 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+
+//========================================================================
+// glfwGetKey()
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwGetKey( int key )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return GLFW_RELEASE;
+    }
+
+    // Is it a valid key?
+    if( key < 0 || key > GLFW_KEY_LAST )
+    {
+        return GLFW_RELEASE;
+    }
+
+    if( _glfwInput.Key[ key ] == GLFW_STICK )
+    {
+        // Sticky mode: release key now
+        _glfwInput.Key[ key ] = GLFW_RELEASE;
+        return GLFW_PRESS;
+    }
+
+    return (int) _glfwInput.Key[ key ];
+}
+
+
+//========================================================================
+// glfwGetMouseButton()
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwGetMouseButton( int button )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return GLFW_RELEASE;
+    }
+
+    // Is it a valid mouse button?
+    if( button < 0 || button > GLFW_MOUSE_BUTTON_LAST )
+    {
+        return GLFW_RELEASE;
+    }
+
+    if( _glfwInput.MouseButton[ button ] == GLFW_STICK )
+    {
+        // Sticky mode: release mouse button now
+        _glfwInput.MouseButton[ button ] = GLFW_RELEASE;
+        return GLFW_PRESS;
+    }
+
+    return (int) _glfwInput.MouseButton[ button ];
+}
+
+
+//========================================================================
+// glfwGetMousePos()
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwGetMousePos( int *xpos, int *ypos )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Return mouse position
+    if( xpos != NULL )
+    {
+        *xpos = _glfwInput.MousePosX;
+    }
+    if( ypos != NULL )
+    {
+        *ypos = _glfwInput.MousePosY;
+    }
+}
+
+
+//========================================================================
+// glfwSetMousePos()
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetMousePos( int xpos, int ypos )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Don't do anything if the mouse position did not change
+    if( xpos == _glfwInput.MousePosX && ypos == _glfwInput.MousePosY )
+    {
+        return;
+    }
+
+    // Set GLFW mouse position
+    _glfwInput.MousePosX = xpos;
+    _glfwInput.MousePosY = ypos;
+
+    // If we have a locked mouse, do not change cursor position
+    if( _glfwWin.mouseLock )
+    {
+        return;
+    }
+
+    // Update physical cursor position
+    _glfwPlatformSetMouseCursorPos( xpos, ypos );
+}
+
+
+//========================================================================
+// glfwGetMouseWheel()
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwGetMouseWheel( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return 0;
+    }
+
+    // Return mouse wheel position
+    return _glfwInput.WheelPos;
+}
+
+
+//========================================================================
+// glfwSetMouseWheel()
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetMouseWheel( int pos )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set mouse wheel position
+    _glfwInput.WheelPos = pos;
+}
+
+
+//========================================================================
+// glfwSetKeyCallback() - Set callback function for keyboard input
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetKeyCallback( GLFWkeyfun cbfun )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set callback function
+    _glfwWin.keyCallback = cbfun;
+}
+
+
+//========================================================================
+// glfwSetCharCallback() - Set callback function for character input
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetCharCallback( GLFWcharfun cbfun )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set callback function
+    _glfwWin.charCallback = cbfun;
+}
+
+
+//========================================================================
+// glfwSetMouseButtonCallback() - Set callback function for mouse clicks
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetMouseButtonCallback( GLFWmousebuttonfun cbfun )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set callback function
+    _glfwWin.mouseButtonCallback = cbfun;
+}
+
+
+//========================================================================
+// glfwSetMousePosCallback() - Set callback function for mouse moves
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetMousePosCallback( GLFWmouseposfun cbfun )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set callback function
+    _glfwWin.mousePosCallback = cbfun;
+
+    // Call the callback function to let the application know the current
+    // mouse position
+    if( cbfun )
+    {
+        cbfun( _glfwInput.MousePosX, _glfwInput.MousePosY );
+    }
+}
+
+
+//========================================================================
+// glfwSetMouseWheelCallback() - Set callback function for mouse wheel
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetMouseWheelCallback( GLFWmousewheelfun cbfun )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set callback function
+    _glfwWin.mouseWheelCallback = cbfun;
+
+    // Call the callback function to let the application know the current
+    // mouse wheel position
+    if( cbfun )
+    {
+        cbfun( _glfwInput.WheelPos );
+    }
+}
+

+ 265 - 0
ThirdParty/GLFW/lib/internal.h

@@ -0,0 +1,265 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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 _internal_h_
+#define _internal_h_
+
+//========================================================================
+// GLFWGLOBAL is a macro that places all global variables in the init.c
+// module (all other modules reference global variables as 'extern')
+//========================================================================
+
+#if defined( _init_c_ )
+#define GLFWGLOBAL
+#else
+#define GLFWGLOBAL extern
+#endif
+
+
+//========================================================================
+// Input handling definitions
+//========================================================================
+
+// Internal key and button state/action definitions
+#define GLFW_STICK 2
+
+
+//========================================================================
+// System independent include files
+//========================================================================
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+
+//------------------------------------------------------------------------
+// Window opening hints (set by glfwOpenWindowHint)
+// A bucket of semi-random stuff bunched together for historical reasons
+// This is used only by the platform independent code and only to store
+// parameters passed to us by glfwOpenWindowHint
+//------------------------------------------------------------------------
+typedef struct {
+    int         refreshRate;
+    int         accumRedBits;
+    int         accumGreenBits;
+    int         accumBlueBits;
+    int         accumAlphaBits;
+    int         auxBuffers;
+    int         stereo;
+    int         windowNoResize;
+    int         samples;
+    int         glMajor;
+    int         glMinor;
+    int         glForward;
+    int         glDebug;
+    int         glProfile;
+} _GLFWhints;
+
+
+//------------------------------------------------------------------------
+// Platform specific definitions goes in platform.h (which also includes
+// glfw.h)
+//------------------------------------------------------------------------
+
+#include "platform.h"
+
+
+//------------------------------------------------------------------------
+// Parameters relating to the creation of the context and window but not
+// directly related to the properties of the framebuffer
+// This is used to pass window and context creation parameters from the
+// platform independent code to the platform specific code
+//------------------------------------------------------------------------
+typedef struct {
+    int         mode;
+    int         refreshRate;
+    int         windowNoResize;
+    int         glMajor;
+    int         glMinor;
+    int         glForward;
+    int         glDebug;
+    int         glProfile;
+} _GLFWwndconfig;
+
+
+//------------------------------------------------------------------------
+// Framebuffer configuration descriptor, i.e. buffers and their sizes
+// Also a platform specific ID used to map back to the actual backend APIs
+// This is used to pass framebuffer parameters from the platform independent
+// code to the platform specific code, and also to enumerate and select
+// available framebuffer configurations
+//------------------------------------------------------------------------
+typedef struct {
+    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         samples;
+    GLFWintptr  platformID;
+} _GLFWfbconfig;
+
+
+//========================================================================
+// System independent global variables (GLFW internals)
+//========================================================================
+
+// Flag indicating if GLFW has been initialized
+#if defined( _init_c_ )
+int _glfwInitialized = 0;
+#else
+GLFWGLOBAL int _glfwInitialized;
+#endif
+
+
+//------------------------------------------------------------------------
+// Abstract data stream (for image I/O)
+//------------------------------------------------------------------------
+typedef struct {
+    FILE*   file;
+    void*   data;
+    long    position;
+    long    size;
+} _GLFWstream;
+
+
+//========================================================================
+// Prototypes for platform specific implementation functions
+//========================================================================
+
+// Init/terminate
+int _glfwPlatformInit( void );
+int _glfwPlatformTerminate( void );
+
+// Enable/Disable
+void _glfwPlatformEnableSystemKeys( void );
+void _glfwPlatformDisableSystemKeys( void );
+
+// Fullscreen
+int  _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount );
+void _glfwPlatformGetDesktopMode( GLFWvidmode *mode );
+
+// OpenGL extensions
+int _glfwPlatformExtensionSupported( const char *extension );
+void * _glfwPlatformGetProcAddress( const char *procname );
+
+// Joystick
+int _glfwPlatformGetJoystickParam( int joy, int param );
+int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes );
+int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons, int numbuttons );
+
+// Threads
+GLFWthread _glfwPlatformCreateThread( GLFWthreadfun fun, void *arg );
+void _glfwPlatformDestroyThread( GLFWthread ID );
+int _glfwPlatformWaitThread( GLFWthread ID, int waitmode );
+GLFWthread _glfwPlatformGetThreadID( void );
+GLFWmutex _glfwPlatformCreateMutex( void );
+void _glfwPlatformDestroyMutex( GLFWmutex mutex );
+void _glfwPlatformLockMutex( GLFWmutex mutex );
+void _glfwPlatformUnlockMutex( GLFWmutex mutex );
+GLFWcond _glfwPlatformCreateCond( void );
+void _glfwPlatformDestroyCond( GLFWcond cond );
+void _glfwPlatformWaitCond( GLFWcond cond, GLFWmutex mutex, double timeout );
+void _glfwPlatformSignalCond( GLFWcond cond );
+void _glfwPlatformBroadcastCond( GLFWcond cond );
+int _glfwPlatformGetNumberOfProcessors( void );
+
+// Time
+double _glfwPlatformGetTime( void );
+void _glfwPlatformSetTime( double time );
+void _glfwPlatformSleep( double time );
+
+// Window management
+int  _glfwPlatformOpenWindow( int width, int height, const _GLFWwndconfig *wndconfig, const _GLFWfbconfig *fbconfig );
+void _glfwPlatformCloseWindow( void );
+void _glfwPlatformSetWindowTitle( const char *title );
+void _glfwPlatformSetWindowSize( int width, int height );
+void _glfwPlatformSetWindowPos( int x, int y );
+void _glfwPlatformIconifyWindow( void );
+void _glfwPlatformRestoreWindow( void );
+void _glfwPlatformSwapBuffers( void );
+void _glfwPlatformSwapInterval( int interval );
+void _glfwPlatformRefreshWindowParams( void );
+void _glfwPlatformPollEvents( void );
+void _glfwPlatformWaitEvents( void );
+void _glfwPlatformHideMouseCursor( void );
+void _glfwPlatformShowMouseCursor( void );
+void _glfwPlatformSetMouseCursorPos( int x, int y );
+
+
+//========================================================================
+// Prototypes for platform independent internal functions
+//========================================================================
+
+// Window management (window.c)
+void _glfwClearWindowHints( void );
+
+// Input handling (window.c)
+void _glfwClearInput( void );
+void _glfwInputDeactivation( void );
+void _glfwInputKey( int key, int action );
+void _glfwInputChar( int character, int action );
+void _glfwInputMouseClick( int button, int action );
+
+// Threads (thread.c)
+_GLFWthread * _glfwGetThreadPointer( int ID );
+void _glfwAppendThread( _GLFWthread * t );
+void _glfwRemoveThread( _GLFWthread * t );
+
+// OpenGL extensions (glext.c)
+void _glfwParseGLVersion( int *major, int *minor, int *rev );
+int _glfwStringInExtensionString( const char *string, const GLubyte *extensions );
+
+// Abstracted data streams (stream.c)
+int _glfwOpenFileStream( _GLFWstream *stream, const char *name, const char *mode );
+int _glfwOpenBufferStream( _GLFWstream *stream, void *data, long size );
+long _glfwReadStream( _GLFWstream *stream, void *data, long size );
+long _glfwTellStream( _GLFWstream *stream );
+int _glfwSeekStream( _GLFWstream *stream, long offset, int whence );
+void _glfwCloseStream( _GLFWstream *stream );
+
+// Targa image I/O (tga.c)
+int _glfwReadTGA( _GLFWstream *s, GLFWimage *img, int flags );
+
+// Framebuffer configs
+const _GLFWfbconfig *_glfwChooseFBConfig( const _GLFWfbconfig *desired,
+                                          const _GLFWfbconfig *alternatives,
+                                          unsigned int count );
+
+
+#endif // _internal_h_

+ 102 - 0
ThirdParty/GLFW/lib/joystick.c

@@ -0,0 +1,102 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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 user functions                         ****
+//************************************************************************
+
+//========================================================================
+// glfwGetJoystickParam() - Determine joystick capabilities
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwGetJoystickParam( int joy, int param )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return 0;
+    }
+
+    return _glfwPlatformGetJoystickParam( joy, param );
+}
+
+
+//========================================================================
+// glfwGetJoystickPos() - Get joystick axis positions
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwGetJoystickPos( int joy, float *pos, int numaxes )
+{
+    int i;
+
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return 0;
+    }
+
+    // Clear positions
+    for( i = 0; i < numaxes; i++ )
+    {
+        pos[ i ] = 0.0f;
+    }
+
+    return _glfwPlatformGetJoystickPos( joy, pos, numaxes );
+}
+
+
+//========================================================================
+// glfwGetJoystickButtons() - Get joystick button states
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwGetJoystickButtons( int joy,
+                                                 unsigned char *buttons,
+                                                 int numbuttons )
+{
+    int i;
+
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return 0;
+    }
+
+    // Clear button states
+    for( i = 0; i < numbuttons; i++ )
+    {
+        buttons[ i ] = GLFW_RELEASE;
+    }
+
+    return _glfwPlatformGetJoystickButtons( joy, buttons, numbuttons );
+}
+

+ 194 - 0
ThirdParty/GLFW/lib/stream.c

@@ -0,0 +1,194 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+
+//========================================================================
+// Opens a GLFW stream with a file
+//========================================================================
+
+int _glfwOpenFileStream( _GLFWstream *stream, const char* name, const char* mode )
+{
+    memset( stream, 0, sizeof(_GLFWstream) );
+
+    stream->file = fopen( name, mode );
+    if( stream->file == NULL )
+    {
+        return GL_FALSE;
+    }
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Opens a GLFW stream with a memory block
+//========================================================================
+
+int _glfwOpenBufferStream( _GLFWstream *stream, void *data, long size )
+{
+    memset( stream, 0, sizeof(_GLFWstream) );
+
+    stream->data = data;
+    stream->size = size;
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Reads data from a GLFW stream
+//========================================================================
+
+long _glfwReadStream( _GLFWstream *stream, void *data, long size )
+{
+    if( stream->file != NULL )
+    {
+        return fread( data, 1, size, stream->file );
+    }
+
+    if( stream->data != NULL )
+    {
+        // Check for EOF
+        if( stream->position == stream->size )
+        {
+            return 0;
+        }
+
+        // Clamp read size to available data
+        if( stream->position + size > stream->size )
+        {
+            size = stream->size - stream->position;
+        }
+
+        // Perform data read
+        memcpy( data, (unsigned char*) stream->data + stream->position, size );
+        stream->position += size;
+        return size;
+    }
+
+    return 0;
+}
+
+
+//========================================================================
+// Returns the current position of a GLFW stream
+//========================================================================
+
+long _glfwTellStream( _GLFWstream *stream )
+{
+    if( stream->file != NULL )
+    {
+        return ftell( stream->file );
+    }
+
+    if( stream->data != NULL )
+    {
+        return stream->position;
+    }
+
+    return 0;
+}
+
+
+//========================================================================
+// Sets the current position of a GLFW stream
+//========================================================================
+
+int _glfwSeekStream( _GLFWstream *stream, long offset, int whence )
+{
+    long position;
+
+    if( stream->file != NULL )
+    {
+        if( fseek( stream->file, offset, whence ) != 0 )
+        {
+            return GL_FALSE;
+        }
+
+        return GL_TRUE;
+    }
+
+    if( stream->data != NULL )
+    {
+        position = offset;
+
+        // Handle whence parameter
+        if( whence == SEEK_CUR )
+        {
+            position += stream->position;
+        }
+        else if( whence == SEEK_END )
+        {
+            position += stream->size;
+        }
+        else if( whence != SEEK_SET )
+        {
+            return GL_FALSE;
+        }
+
+        // Clamp offset to buffer bounds and apply it
+        if( position > stream->size )
+        {
+            stream->position = stream->size;
+        }
+        else if( position < 0 )
+        {
+            stream->position = 0;
+        }
+        else
+        {
+            stream->position = position;
+        }
+
+        return GL_TRUE;
+    }
+
+    return GL_FALSE;
+}
+
+
+//========================================================================
+// Closes a GLFW stream
+//========================================================================
+
+void _glfwCloseStream( _GLFWstream *stream )
+{
+    if( stream->file != NULL )
+    {
+        fclose( stream->file );
+    }
+
+    // Nothing to be done about (user allocated) memory blocks
+
+    memset( stream, 0, sizeof(_GLFWstream) );
+}
+

+ 405 - 0
ThirdParty/GLFW/lib/tga.c

@@ -0,0 +1,405 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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.
+//
+//========================================================================
+
+//========================================================================
+// Description:
+//
+// TGA format image file loader. This module supports version 1 Targa
+// images, with these restrictions:
+//  - Pixel format may only be 8, 24 or 32 bits
+//  - Colormaps must be no longer than 256 entries
+//
+//========================================================================
+
+
+#include "internal.h"
+
+
+//************************************************************************
+//****            GLFW internal functions & declarations              ****
+//************************************************************************
+
+//========================================================================
+// TGA file header information
+//========================================================================
+
+typedef struct {
+    int idlen;                 // 1 byte
+    int cmaptype;              // 1 byte
+    int imagetype;             // 1 byte
+    int cmapfirstidx;          // 2 bytes
+    int cmaplen;               // 2 bytes
+    int cmapentrysize;         // 1 byte
+    int xorigin;               // 2 bytes
+    int yorigin;               // 2 bytes
+    int width;                 // 2 bytes
+    int height;                // 2 bytes
+    int bitsperpixel;          // 1 byte
+    int imageinfo;             // 1 byte
+    int _alphabits;            // (derived from imageinfo)
+    int _origin;               // (derived from imageinfo)
+} _tga_header_t;
+
+#define _TGA_CMAPTYPE_NONE      0
+#define _TGA_CMAPTYPE_PRESENT   1
+
+#define _TGA_IMAGETYPE_NONE     0
+#define _TGA_IMAGETYPE_CMAP     1
+#define _TGA_IMAGETYPE_TC       2
+#define _TGA_IMAGETYPE_GRAY     3
+#define _TGA_IMAGETYPE_CMAP_RLE 9
+#define _TGA_IMAGETYPE_TC_RLE   10
+#define _TGA_IMAGETYPE_GRAY_RLE 11
+
+#define _TGA_IMAGEINFO_ALPHA_MASK   0x0f
+#define _TGA_IMAGEINFO_ALPHA_SHIFT  0
+#define _TGA_IMAGEINFO_ORIGIN_MASK  0x30
+#define _TGA_IMAGEINFO_ORIGIN_SHIFT 4
+
+#define _TGA_ORIGIN_BL 0
+#define _TGA_ORIGIN_BR 1
+#define _TGA_ORIGIN_UL 2
+#define _TGA_ORIGIN_UR 3
+
+
+//========================================================================
+// _glfwReadTGAHeader() - Read TGA file header (and check that it is
+// valid)
+//========================================================================
+
+static int ReadTGAHeader( _GLFWstream *s, _tga_header_t *h )
+{
+    unsigned char buf[ 18 ];
+    int pos;
+
+    // Read TGA file header from file
+    pos = _glfwTellStream( s );
+    _glfwReadStream( s, buf, 18 );
+
+    // Interpret header (endian independent parsing)
+    h->idlen         = (int) buf[0];
+    h->cmaptype      = (int) buf[1];
+    h->imagetype     = (int) buf[2];
+    h->cmapfirstidx  = (int) buf[3] | (((int) buf[4]) << 8);
+    h->cmaplen       = (int) buf[5] | (((int) buf[6]) << 8);
+    h->cmapentrysize = (int) buf[7];
+    h->xorigin       = (int) buf[8] | (((int) buf[9]) << 8);
+    h->yorigin       = (int) buf[10] | (((int) buf[11]) << 8);
+    h->width         = (int) buf[12] | (((int) buf[13]) << 8);
+    h->height        = (int) buf[14] | (((int) buf[15]) << 8);
+    h->bitsperpixel  = (int) buf[16];
+    h->imageinfo     = (int) buf[17];
+
+    // Extract alphabits and origin information
+    h->_alphabits = (int) (h->imageinfo & _TGA_IMAGEINFO_ALPHA_MASK) >>
+                     _TGA_IMAGEINFO_ALPHA_SHIFT;
+    h->_origin    = (int) (h->imageinfo & _TGA_IMAGEINFO_ORIGIN_MASK) >>
+                     _TGA_IMAGEINFO_ORIGIN_SHIFT;
+
+    // Validate TGA header (is this a TGA file?)
+    if( (h->cmaptype == 0 || h->cmaptype == 1) &&
+        ((h->imagetype >= 1 && h->imagetype <= 3) ||
+         (h->imagetype >= 9 && h->imagetype <= 11)) &&
+         (h->bitsperpixel == 8 || h->bitsperpixel == 24 ||
+          h->bitsperpixel == 32) )
+    {
+        // Skip the ID field
+        _glfwSeekStream( s, h->idlen, SEEK_CUR );
+
+        // Indicate that the TGA header was valid
+        return GL_TRUE;
+    }
+    else
+    {
+        // Restore file position
+        _glfwSeekStream( s, pos, SEEK_SET );
+
+        // Indicate that the TGA header was invalid
+        return GL_FALSE;
+    }
+}
+
+//========================================================================
+// Read Run-Length Encoded data
+//========================================================================
+
+static void ReadTGA_RLE( unsigned char *buf, int size, int bpp,
+    _GLFWstream *s )
+{
+    int repcount, bytes, k, n;
+    unsigned char pixel[ 4 ];
+    char c;
+
+    // Dummy check
+    if( bpp > 4 )
+    {
+        return;
+    }
+
+    while( size > 0 )
+    {
+        // Get repetition count
+	_glfwReadStream( s, &c, 1 );
+        repcount = (unsigned int) c;
+        bytes = ((repcount & 127) + 1) * bpp;
+        if( size < bytes )
+        {
+            bytes = size;
+        }
+
+        // Run-Length packet?
+        if( repcount & 128 )
+        {
+            _glfwReadStream( s, pixel, bpp );
+            for( n = 0; n < (repcount & 127) + 1; n ++ )
+            {
+                for( k = 0; k < bpp; k ++ )
+                {
+                    *buf ++ = pixel[ k ];
+                }
+            }
+        }
+        else
+        {
+            // It's a Raw packet
+            _glfwReadStream( s, buf, bytes );
+            buf += bytes;
+        }
+
+        size -= bytes;
+    }
+}
+
+
+//========================================================================
+// _glfwReadTGA() - Read a TGA image from a file
+//========================================================================
+
+int _glfwReadTGA( _GLFWstream *s, GLFWimage *img, int flags )
+{
+    _tga_header_t h;
+    unsigned char *cmap, *pix, tmp, *src, *dst;
+    int cmapsize, pixsize, pixsize2;
+    int bpp, bpp2, k, m, n, swapx, swapy;
+
+    // Read TGA header
+    if( !ReadTGAHeader( s, &h ) )
+    {
+        return 0;
+    }
+
+    // Is there a colormap?
+    cmapsize = (h.cmaptype == _TGA_CMAPTYPE_PRESENT ? 1 : 0) * h.cmaplen *
+               ((h.cmapentrysize+7) / 8);
+    if( cmapsize > 0 )
+    {
+        // Is it a colormap that we can handle?
+        if( (h.cmapentrysize != 24 && h.cmapentrysize != 32) ||
+            h.cmaplen == 0 || h.cmaplen > 256 )
+        {
+            return 0;
+        }
+
+        // Allocate memory for colormap
+        cmap = (unsigned char *) malloc( cmapsize );
+        if( cmap == NULL )
+        {
+            return 0;
+        }
+
+        // Read colormap from file
+        _glfwReadStream( s, cmap, cmapsize );
+    }
+    else
+    {
+        cmap = NULL;
+    }
+
+    // Size of pixel data
+    pixsize = h.width * h.height * ((h.bitsperpixel + 7) / 8);
+
+    // Bytes per pixel (pixel data - unexpanded)
+    bpp = (h.bitsperpixel + 7) / 8;
+
+    // Bytes per pixel (expanded pixels - not colormap indeces)
+    if( cmap )
+    {
+        bpp2 = (h.cmapentrysize + 7) / 8;
+    }
+    else
+    {
+        bpp2 = bpp;
+    }
+
+    // For colormaped images, the RGB/RGBA image data may use more memory
+    // than the stored pixel data
+    pixsize2 = h.width * h.height * bpp2;
+
+    // Allocate memory for pixel data
+    pix = (unsigned char *) malloc( pixsize2 );
+    if( pix == NULL )
+    {
+        if( cmap )
+        {
+            free( cmap );
+        }
+        return 0;
+    }
+
+    // Read pixel data from file
+    if( h.imagetype >= _TGA_IMAGETYPE_CMAP_RLE )
+    {
+        ReadTGA_RLE( pix, pixsize, bpp, s );
+    }
+    else
+    {
+        _glfwReadStream( s, pix, pixsize );
+    }
+
+    // If the image origin is not what we want, re-arrange the pixels
+    switch( h._origin )
+    {
+    default:
+    case _TGA_ORIGIN_UL:
+        swapx = 0;
+        swapy = 1;
+        break;
+
+    case _TGA_ORIGIN_BL:
+        swapx = 0;
+        swapy = 0;
+        break;
+
+    case _TGA_ORIGIN_UR:
+        swapx = 1;
+        swapy = 1;
+        break;
+
+    case _TGA_ORIGIN_BR:
+        swapx = 1;
+        swapy = 0;
+        break;
+    }
+    if( (swapy && !(flags & GLFW_ORIGIN_UL_BIT)) ||
+        (!swapy && (flags & GLFW_ORIGIN_UL_BIT)) )
+    {
+        src = pix;
+        dst = &pix[ (h.height-1)*h.width*bpp ];
+        for( n = 0; n < h.height/2; n ++ )
+        {
+            for( m = 0; m < h.width ; m ++ )
+            {
+                for( k = 0; k < bpp; k ++ )
+                {
+                    tmp     = *src;
+                    *src ++ = *dst;
+                    *dst ++ = tmp;
+                }
+            }
+            dst -= 2*h.width*bpp;
+        }
+    }
+    if( swapx )
+    {
+        src = pix;
+        dst = &pix[ (h.width-1)*bpp ];
+        for( n = 0; n < h.height; n ++ )
+        {
+            for( m = 0; m < h.width/2 ; m ++ )
+            {
+                for( k = 0; k < bpp; k ++ )
+                {
+                    tmp     = *src;
+                    *src ++ = *dst;
+                    *dst ++ = tmp;
+                }
+                dst -= 2*bpp;
+            }
+            src += ((h.width+1)/2)*bpp;
+            dst += ((3*h.width+1)/2)*bpp;
+        }
+    }
+
+    // Convert BGR/BGRA to RGB/RGBA, and optionally colormap indeces to
+    // RGB/RGBA values
+    if( cmap )
+    {
+        // Convert colormap pixel format (BGR -> RGB or BGRA -> RGBA)
+        if( bpp2 == 3 || bpp2 == 4 )
+        {
+            for( n = 0; n < h.cmaplen; n ++ )
+            {
+                tmp                = cmap[ n*bpp2 ];
+                cmap[ n*bpp2 ]     = cmap[ n*bpp2 + 2 ];
+                cmap[ n*bpp2 + 2 ] = tmp;
+            }
+        }
+
+        // Convert pixel data to RGB/RGBA data
+        for( m = h.width * h.height - 1; m >= 0; m -- )
+        {
+            n = pix[ m ];
+            for( k = 0; k < bpp2; k ++ )
+            {
+                pix[ m*bpp2 + k ] = cmap[ n*bpp2 + k ];
+            }
+        }
+
+        // Free memory for colormap (it's not needed anymore)
+        free( cmap );
+    }
+    else
+    {
+        // Convert image pixel format (BGR -> RGB or BGRA -> RGBA)
+        if( bpp2 == 3 || bpp2 == 4 )
+        {
+            src = pix;
+            dst = &pix[ 2 ];
+            for( n = 0; n < h.height * h.width; n ++ )
+            {
+                tmp  = *src;
+                *src = *dst;
+                *dst = tmp;
+                src += bpp2;
+                dst += bpp2;
+            }
+        }
+    }
+
+    // Fill out GLFWimage struct (the Format field will be set by
+    // glfwReadImage)
+    img->Width         = h.width;
+    img->Height        = h.height;
+    img->BytesPerPixel = bpp2;
+    img->Data          = pix;
+
+    return 1;
+}
+

+ 340 - 0
ThirdParty/GLFW/lib/thread.c

@@ -0,0 +1,340 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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                       ****
+//************************************************************************
+
+//========================================================================
+// _glfwGetThreadPointer() - Find pointer to thread with a matching ID
+//========================================================================
+
+_GLFWthread * _glfwGetThreadPointer( int ID )
+{
+    _GLFWthread *t;
+
+    for( t = &_glfwThrd.First; t != NULL; t = t->Next )
+    {
+        if( t->ID == ID )
+        {
+            break;
+        }
+    }
+
+    return t;
+}
+
+
+//========================================================================
+// _glfwAppendThread() - Append thread to thread list
+//========================================================================
+
+void _glfwAppendThread( _GLFWthread * t )
+{
+    _GLFWthread *t_tmp;
+
+    t_tmp = &_glfwThrd.First;
+    while( t_tmp->Next != NULL )
+    {
+        t_tmp = t_tmp->Next;
+    }
+    t_tmp->Next = t;
+    t->Previous = t_tmp;
+    t->Next     = NULL;
+}
+
+
+//========================================================================
+// _glfwRemoveThread() - Remove thread from thread list
+//========================================================================
+
+void _glfwRemoveThread( _GLFWthread * t )
+{
+    if( t->Previous != NULL )
+    {
+        t->Previous->Next = t->Next;
+    }
+    if( t->Next != NULL )
+    {
+        t->Next->Previous = t->Previous;
+    }
+    free( (void *) t );
+}
+
+
+
+//************************************************************************
+//****                     GLFW user functions                        ****
+//************************************************************************
+
+//========================================================================
+// glfwCreateThread() - Create a new thread
+//========================================================================
+
+GLFWAPI GLFWthread GLFWAPIENTRY glfwCreateThread( GLFWthreadfun fun,
+    void *arg )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return -1;
+    }
+
+    // Return the GLFW thread ID
+    return _glfwPlatformCreateThread( fun, arg );
+}
+
+
+//========================================================================
+// glfwDestroyThread() - Kill a thread. NOTE: THIS IS A VERY DANGEROUS
+// OPERATION, AND SHOULD NOT BE USED EXCEPT IN EXTREME SITUATIONS!
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwDestroyThread( GLFWthread ID )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return;
+    }
+
+    // Is it a valid thread? (killing the main thread is not allowed)
+    if( ID < 1 )
+    {
+        return;
+    }
+
+    _glfwPlatformDestroyThread( ID );
+}
+
+
+//========================================================================
+// glfwWaitThread() - Wait for a thread to die
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwWaitThread( GLFWthread ID, int waitmode )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return GL_TRUE;
+    }
+
+    // Is it a valid thread? (waiting for the main thread is not allowed)
+    if( ID < 1 )
+    {
+        return GL_TRUE;
+    }
+
+    return _glfwPlatformWaitThread( ID, waitmode );
+}
+
+
+//========================================================================
+// glfwGetThreadID() - Return the thread ID for the current thread
+//========================================================================
+
+GLFWAPI GLFWthread GLFWAPIENTRY glfwGetThreadID( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return 0;
+    }
+
+    return _glfwPlatformGetThreadID();
+}
+
+
+//========================================================================
+// glfwCreateMutex() - Create a mutual exclusion object
+//========================================================================
+
+GLFWAPI GLFWmutex GLFWAPIENTRY glfwCreateMutex( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return (GLFWmutex) 0;
+    }
+
+    return _glfwPlatformCreateMutex();
+}
+
+
+//========================================================================
+// glfwDestroyMutex() - Destroy a mutual exclusion object
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwDestroyMutex( GLFWmutex mutex )
+{
+    // Initialized & valid mutex (no real way of assuring this)?
+    if( !_glfwInitialized || !mutex )
+    {
+        return;
+    }
+
+    _glfwPlatformDestroyMutex( mutex );
+}
+
+
+//========================================================================
+// glfwLockMutex() - Request access to a mutex
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwLockMutex( GLFWmutex mutex )
+{
+    // Initialized & valid mutex (no real way of assuring this)?
+    if( !_glfwInitialized && !mutex )
+    {
+        return;
+    }
+
+    _glfwPlatformLockMutex( mutex );
+}
+
+
+//========================================================================
+// glfwUnlockMutex() - Release a mutex
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwUnlockMutex( GLFWmutex mutex )
+{
+    // Initialized & valid mutex (no real way of assuring this)?
+    if( !_glfwInitialized && !mutex )
+    {
+        return;
+    }
+
+    _glfwPlatformUnlockMutex( mutex );
+}
+
+
+//========================================================================
+// glfwCreateCond() - Create a new condition variable object
+//========================================================================
+
+GLFWAPI GLFWcond GLFWAPIENTRY glfwCreateCond( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return (GLFWcond) 0;
+    }
+
+    return _glfwPlatformCreateCond();
+}
+
+
+//========================================================================
+// glfwDestroyCond() - Destroy a condition variable object
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwDestroyCond( GLFWcond cond )
+{
+    // Initialized & valid condition variable?
+    if( !_glfwInitialized || !cond )
+    {
+        return;
+    }
+
+    _glfwPlatformDestroyCond( cond );
+}
+
+
+//========================================================================
+// glfwWaitCond() - Wait for a condition to be raised
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwWaitCond( GLFWcond cond, GLFWmutex mutex,
+    double timeout )
+{
+    // Initialized & valid condition variable and mutex?
+    if( !_glfwInitialized || !cond || !mutex )
+    {
+        return;
+    }
+
+    _glfwPlatformWaitCond( cond, mutex, timeout );
+}
+
+
+//========================================================================
+// glfwSignalCond() - Signal a condition to one waiting thread
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSignalCond( GLFWcond cond )
+{
+    // Initialized & valid condition variable?
+    if( !_glfwInitialized || !cond )
+    {
+        return;
+    }
+
+    _glfwPlatformSignalCond( cond );
+}
+
+
+//========================================================================
+// glfwBroadcastCond() - Broadcast a condition to all waiting threads
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwBroadcastCond( GLFWcond cond )
+{
+    // Initialized & valid condition variable?
+    if( !_glfwInitialized || !cond )
+    {
+        return;
+    }
+
+    _glfwPlatformBroadcastCond( cond );
+}
+
+
+//========================================================================
+// glfwGetNumberOfProcessors() - Return the number of processors in the
+// system. This information can be useful for determining the optimal
+// number of threads to use for performing a certain task.
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwGetNumberOfProcessors( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return 0;
+    }
+
+    return _glfwPlatformGetNumberOfProcessors();
+}

+ 83 - 0
ThirdParty/GLFW/lib/time.c

@@ -0,0 +1,83 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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 user functions                         ****
+//************************************************************************
+
+//========================================================================
+// glfwGetTime() - Return timer value in seconds
+//========================================================================
+
+GLFWAPI double GLFWAPIENTRY glfwGetTime( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return 0.0;
+    }
+
+    return _glfwPlatformGetTime();
+}
+
+
+//========================================================================
+// glfwSetTime() - Set timer value in seconds
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetTime( double time )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return;
+    }
+
+    _glfwPlatformSetTime( time );
+}
+
+
+//========================================================================
+// glfwSleep() - Put a thread to sleep for a specified amount of time
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSleep( double time )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return;
+    }
+
+    _glfwPlatformSleep( time );
+}

+ 539 - 0
ThirdParty/GLFW/lib/win32/platform.h

@@ -0,0 +1,539 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Win32/WGL
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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 Windows version of GLFW
+#define _GLFW_WIN32
+
+// We don't need all the fancy stuff
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
+#define VC_EXTRALEAN
+
+// Include files
+#include <windows.h>
+#include <mmsystem.h>
+#include "../../include/GL/glfw.h"
+
+
+//========================================================================
+// Hack: Define things that some <windows.h>'s do not define
+//========================================================================
+
+// Some old versions of w32api (used by MinGW and Cygwin) define
+// WH_KEYBOARD_LL without typedef:ing KBDLLHOOKSTRUCT (!)
+#if defined(__MINGW32__) || defined(__CYGWIN__)
+#include <w32api.h>
+#if defined(WH_KEYBOARD_LL) && (__W32API_MAJOR_VERSION == 1) && (__W32API_MINOR_VERSION <= 2)
+#undef WH_KEYBOARD_LL
+#endif
+#endif
+
+//------------------------------------------------------------------------
+// ** NOTE **  If this gives you compiler errors and you are using MinGW
+// (or Dev-C++), update to w32api version 1.3 or later:
+// http://sourceforge.net/project/showfiles.php?group_id=2435
+//------------------------------------------------------------------------
+#ifndef WH_KEYBOARD_LL
+#define WH_KEYBOARD_LL 13
+typedef struct tagKBDLLHOOKSTRUCT {
+  DWORD   vkCode;
+  DWORD   scanCode;
+  DWORD   flags;
+  DWORD   time;
+  DWORD   dwExtraInfo;
+} KBDLLHOOKSTRUCT, FAR *LPKBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;
+#endif // WH_KEYBOARD_LL
+
+#ifndef LLKHF_ALTDOWN
+#define LLKHF_ALTDOWN  0x00000020
+#endif
+
+#ifndef SPI_SETSCREENSAVERRUNNING
+#define SPI_SETSCREENSAVERRUNNING 97
+#endif
+#ifndef SPI_GETANIMATION
+#define SPI_GETANIMATION 72
+#endif
+#ifndef SPI_SETANIMATION
+#define SPI_SETANIMATION 73
+#endif
+#ifndef SPI_GETFOREGROUNDLOCKTIMEOUT
+#define SPI_GETFOREGROUNDLOCKTIMEOUT 0x2000
+#endif
+#ifndef SPI_SETFOREGROUNDLOCKTIMEOUT
+#define SPI_SETFOREGROUNDLOCKTIMEOUT 0x2001
+#endif
+
+#ifndef CDS_FULLSCREEN
+#define CDS_FULLSCREEN 4
+#endif
+
+#ifndef PFD_GENERIC_ACCELERATED
+#define PFD_GENERIC_ACCELERATED 0x00001000
+#endif
+#ifndef PFD_DEPTH_DONTCARE
+#define PFD_DEPTH_DONTCARE 0x20000000
+#endif
+
+#ifndef ENUM_CURRENT_SETTINGS
+#define ENUM_CURRENT_SETTINGS -1
+#endif
+#ifndef ENUM_REGISTRY_SETTINGS
+#define ENUM_REGISTRY_SETTINGS -2
+#endif
+
+#ifndef WM_MOUSEWHEEL
+#define WM_MOUSEWHEEL 0x020A
+#endif
+#ifndef WHEEL_DELTA
+#define WHEEL_DELTA 120
+#endif
+
+#ifndef WM_XBUTTONDOWN
+#define WM_XBUTTONDOWN 0x020B
+#endif
+#ifndef WM_XBUTTONUP
+#define WM_XBUTTONUP 0x020C
+#endif
+#ifndef XBUTTON1
+#define XBUTTON1 1
+#endif
+#ifndef XBUTTON2
+#define XBUTTON2 2
+#endif
+
+#ifndef WGL_ARB_pixel_format
+
+// wglSwapIntervalEXT typedef (Win32 buffer-swap interval control)
+typedef int (APIENTRY * WGLSWAPINTERVALEXT_T) (int);
+// wglGetPixelFormatAttribivARB typedef
+typedef BOOL (WINAPI * WGLGETPIXELFORMATATTRIBIVARB_T) (HDC, int, int, UINT, const int *, int *);
+// wglGetExtensionStringEXT typedef
+typedef const char *(APIENTRY * WGLGETEXTENSIONSSTRINGEXT_T)( void );
+// wglGetExtensionStringARB typedef
+typedef const char *(APIENTRY * WGLGETEXTENSIONSSTRINGARB_T)( HDC );
+
+/* Constants for wglGetPixelFormatAttribivARB */
+#define WGL_NUMBER_PIXEL_FORMATS_ARB    0x2000
+#define WGL_DRAW_TO_WINDOW_ARB          0x2001
+#define WGL_SUPPORT_OPENGL_ARB          0x2010
+#define WGL_ACCELERATION_ARB            0x2003
+#define WGL_DOUBLE_BUFFER_ARB           0x2011
+#define WGL_STEREO_ARB                  0x2012
+#define WGL_PIXEL_TYPE_ARB              0x2013
+#define WGL_COLOR_BITS_ARB              0x2014
+#define WGL_RED_BITS_ARB                0x2015
+#define WGL_GREEN_BITS_ARB              0x2017
+#define WGL_BLUE_BITS_ARB               0x2019
+#define WGL_ALPHA_BITS_ARB              0x201B
+#define WGL_ACCUM_BITS_ARB              0x201D
+#define WGL_ACCUM_RED_BITS_ARB          0x201E
+#define WGL_ACCUM_GREEN_BITS_ARB        0x201F
+#define WGL_ACCUM_BLUE_BITS_ARB         0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB        0x2021
+#define WGL_DEPTH_BITS_ARB              0x2022
+#define WGL_STENCIL_BITS_ARB            0x2023
+#define WGL_AUX_BUFFERS_ARB             0x2024
+#define WGL_SAMPLE_BUFFERS_ARB          0x2041
+#define WGL_SAMPLES_ARB                 0x2042
+
+/* Constants for WGL_ACCELERATION_ARB */
+#define WGL_NO_ACCELERATION_ARB         0x2025
+#define WGL_GENERIC_ACCELERATION_ARB    0x2026
+#define WGL_FULL_ACCELERATION_ARB       0x2027
+
+/* Constants for WGL_PIXEL_TYPE_ARB */
+#define WGL_TYPE_RGBA_ARB               0x202B
+#define WGL_TYPE_COLORINDEX_ARB         0x202C
+
+#endif /*WGL_ARB_pixel_format*/
+
+
+#ifndef WGL_ARB_create_context
+
+/* wglCreateContextAttribsARB */
+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC, HGLRC, const int *);
+
+/* Tokens for wglCreateContextAttribsARB attributes */
+#define WGL_CONTEXT_MAJOR_VERSION_ARB          0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB          0x2092
+#define WGL_CONTEXT_LAYER_PLANE_ARB            0x2093
+#define WGL_CONTEXT_FLAGS_ARB                  0x2094
+#define WGL_CONTEXT_PROFILE_MASK_ARB           0x9126
+
+/* Bits for WGL_CONTEXT_FLAGS_ARB */
+#define WGL_CONTEXT_DEBUG_BIT_ARB              0x0001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+
+/* Bits for WGL_CONTEXT_PROFILE_MASK_ARB */
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB          0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+
+#endif /*WGL_ARB_create_context*/
+
+
+#ifndef GL_VERSION_3_0
+
+typedef const GLubyte * (APIENTRY *PFNGLGETSTRINGIPROC) (GLenum, GLuint);
+
+#endif /*GL_VERSION_3_0*/
+
+
+//========================================================================
+// DLLs that are loaded at glfwInit()
+//========================================================================
+
+// gdi32.dll function pointer typedefs
+#ifndef _GLFW_NO_DLOAD_GDI32
+typedef int  (WINAPI * CHOOSEPIXELFORMAT_T) (HDC,CONST PIXELFORMATDESCRIPTOR*);
+typedef int  (WINAPI * DESCRIBEPIXELFORMAT_T) (HDC,int,UINT,LPPIXELFORMATDESCRIPTOR);
+typedef int  (WINAPI * GETPIXELFORMAT_T) (HDC);
+typedef BOOL (WINAPI * SETPIXELFORMAT_T) (HDC,int,const PIXELFORMATDESCRIPTOR*);
+typedef BOOL (WINAPI * SWAPBUFFERS_T) (HDC);
+#endif // _GLFW_NO_DLOAD_GDI32
+
+// winmm.dll function pointer typedefs
+#ifndef _GLFW_NO_DLOAD_WINMM
+typedef MMRESULT (WINAPI * JOYGETDEVCAPSA_T) (UINT,LPJOYCAPSA,UINT);
+typedef MMRESULT (WINAPI * JOYGETPOS_T) (UINT,LPJOYINFO);
+typedef MMRESULT (WINAPI * JOYGETPOSEX_T) (UINT,LPJOYINFOEX);
+typedef DWORD (WINAPI * TIMEGETTIME_T) (void);
+#endif // _GLFW_NO_DLOAD_WINMM
+
+
+// gdi32.dll shortcuts
+#ifndef _GLFW_NO_DLOAD_GDI32
+#define _glfw_ChoosePixelFormat   _glfwLibrary.Libs.ChoosePixelFormat
+#define _glfw_DescribePixelFormat _glfwLibrary.Libs.DescribePixelFormat
+#define _glfw_GetPixelFormat      _glfwLibrary.Libs.GetPixelFormat
+#define _glfw_SetPixelFormat      _glfwLibrary.Libs.SetPixelFormat
+#define _glfw_SwapBuffers         _glfwLibrary.Libs.SwapBuffers
+#else
+#define _glfw_ChoosePixelFormat   ChoosePixelFormat
+#define _glfw_DescribePixelFormat DescribePixelFormat
+#define _glfw_GetPixelFormat      GetPixelFormat
+#define _glfw_SetPixelFormat      SetPixelFormat
+#define _glfw_SwapBuffers         SwapBuffers
+#endif // _GLFW_NO_DLOAD_GDI32
+
+// winmm.dll shortcuts
+#ifndef _GLFW_NO_DLOAD_WINMM
+#define _glfw_joyGetDevCaps _glfwLibrary.Libs.joyGetDevCapsA
+#define _glfw_joyGetPos     _glfwLibrary.Libs.joyGetPos
+#define _glfw_joyGetPosEx   _glfwLibrary.Libs.joyGetPosEx
+#define _glfw_timeGetTime   _glfwLibrary.Libs.timeGetTime
+#else
+#define _glfw_joyGetDevCaps joyGetDevCapsA
+#define _glfw_joyGetPos     joyGetPos
+#define _glfw_joyGetPosEx   joyGetPosEx
+#define _glfw_timeGetTime   timeGetTime
+#endif // _GLFW_NO_DLOAD_WINMM
+
+
+//========================================================================
+// GLFW platform specific types
+//========================================================================
+
+//------------------------------------------------------------------------
+// Pointer length integer
+//------------------------------------------------------------------------
+typedef INT_PTR GLFWintptr;
+
+
+//------------------------------------------------------------------------
+// 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
+    int       refreshRate;     // Vertical monitor refresh rate
+
+    // 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
+
+    // Framebuffer attributes
+    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       samples;
+
+    // OpenGL extensions and context attributes
+    int       has_GL_SGIS_generate_mipmap;
+    int       has_GL_ARB_texture_non_power_of_two;
+    int       glMajor, glMinor, glRevision;
+    int       glForward, glDebug, glProfile;
+
+    PFNGLGETSTRINGIPROC GetStringi;
+
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+    // Platform specific window resources
+    HDC       DC;              // Private GDI device context
+    HGLRC     context;         // Permanent rendering context
+    HWND      window;          // Window handle
+    ATOM      classAtom;       // Window class atom
+    int       modeID;          // Mode ID for fullscreen mode
+    HHOOK     keyboardHook;    // Keyboard hook handle
+    DWORD     dwStyle;         // Window styles used for window creation
+    DWORD     dwExStyle;       // --"--
+
+    // Platform specific extensions (context specific)
+    WGLSWAPINTERVALEXT_T           SwapIntervalEXT;
+    WGLGETPIXELFORMATATTRIBIVARB_T GetPixelFormatAttribivARB;
+    WGLGETEXTENSIONSSTRINGEXT_T    GetExtensionsStringEXT;
+    WGLGETEXTENSIONSSTRINGARB_T    GetExtensionsStringARB;
+    PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
+    GLboolean                      has_WGL_EXT_swap_control;
+    GLboolean                      has_WGL_ARB_multisample;
+    GLboolean                      has_WGL_ARB_pixel_format;
+    GLboolean                      has_WGL_ARB_create_context;
+
+    // Various platform specific internal variables
+    int       oldMouseLock;    // Old mouse-lock flag (used for remembering
+                               // mouse-lock state when iconifying)
+    int       oldMouseLockValid;
+    int       desiredRefreshRate; // Desired vertical monitor refresh rate
+
+};
+
+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, OldMouseX, OldMouseY;
+
+} _glfwInput;
+
+
+//------------------------------------------------------------------------
+// Library global data
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+    // Window opening hints
+    _GLFWhints      hints;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+  HINSTANCE instance;        // Instance of the application
+
+  // Timer data
+  struct {
+      int          HasPerformanceCounter;
+      double       Resolution;
+      unsigned int t0_32;
+      __int64      t0_64;
+  } Timer;
+
+  // System information
+  struct {
+      int     winVer;
+      int     hasUnicode;
+      DWORD   foregroundLockTimeout;
+  } Sys;
+
+#if !defined(_GLFW_NO_DLOAD_WINMM) || !defined(_GLFW_NO_DLOAD_GDI32)
+  // Library handles and function pointers
+  struct {
+#ifndef _GLFW_NO_DLOAD_GDI32
+      // gdi32.dll
+      HINSTANCE             gdi32;
+      CHOOSEPIXELFORMAT_T   ChoosePixelFormat;
+      DESCRIBEPIXELFORMAT_T DescribePixelFormat;
+      GETPIXELFORMAT_T      GetPixelFormat;
+      SETPIXELFORMAT_T      SetPixelFormat;
+      SWAPBUFFERS_T         SwapBuffers;
+#endif // _GLFW_NO_DLOAD_GDI32
+
+      // winmm.dll
+#ifndef _GLFW_NO_DLOAD_WINMM
+      HINSTANCE             winmm;
+      JOYGETDEVCAPSA_T      joyGetDevCapsA;
+      JOYGETPOS_T           joyGetPos;
+      JOYGETPOSEX_T         joyGetPosEx;
+      TIMEGETTIME_T         timeGetTime;
+#endif // _GLFW_NO_DLOAD_WINMM
+  } 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
+    HANDLE        Handle;
+    DWORD         WinID;
+
+};
+
+
+//------------------------------------------------------------------------
+// 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
+    CRITICAL_SECTION CriticalSection;
+
+} _glfwThrd;
+
+
+
+//========================================================================
+// Macros for encapsulating critical code sections (i.e. making parts
+// of GLFW thread safe)
+//========================================================================
+
+// Thread list management
+#define ENTER_THREAD_CRITICAL_SECTION \
+        EnterCriticalSection( &_glfwThrd.CriticalSection );
+#define LEAVE_THREAD_CRITICAL_SECTION \
+        LeaveCriticalSection( &_glfwThrd.CriticalSection );
+
+
+//========================================================================
+// Various Windows version constants
+//========================================================================
+
+#define _GLFW_WIN_UNKNOWN    0x0000  // Earlier than 95 or NT4
+#define _GLFW_WIN_95         0x0001
+#define _GLFW_WIN_98         0x0002
+#define _GLFW_WIN_ME         0x0003
+#define _GLFW_WIN_UNKNOWN_9x 0x0004  // Later than ME
+#define _GLFW_WIN_NT4        0x0101
+#define _GLFW_WIN_2K         0x0102
+#define _GLFW_WIN_XP         0x0103
+#define _GLFW_WIN_NET_SERVER 0x0104
+#define _GLFW_WIN_UNKNOWN_NT 0x0105  // Later than .NET Server
+
+
+//========================================================================
+// Prototypes for platform specific internal functions
+//========================================================================
+
+// Time
+void _glfwInitTimer( void );
+
+// Fullscreen support
+int _glfwGetClosestVideoModeBPP( int *w, int *h, int *bpp, int *refresh );
+int _glfwGetClosestVideoMode( int *w, int *h, int *r, int *g, int *b, int *refresh );
+void _glfwSetVideoModeMODE( int mode );
+void _glfwSetVideoMode( int *w, int *h, int r, int g, int b, int refresh );
+
+
+#endif // _platform_h_

+ 49 - 0
ThirdParty/GLFW/lib/win32/win32_dllmain.c

@@ -0,0 +1,49 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Win32/WGL
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+
+#if defined(GLFW_BUILD_DLL)
+
+//========================================================================
+// GLFW DLL entry point
+//========================================================================
+
+BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, LPVOID reserved )
+{
+    // NOTE: Some compilers complains about instance and x never being used -
+    // never mind that (we don't want to use them)!
+
+    return TRUE;
+}
+
+#endif // GLFW_BUILD_DLL
+

+ 155 - 0
ThirdParty/GLFW/lib/win32/win32_enable.c

@@ -0,0 +1,155 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Win32/WGL
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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                       ****
+//************************************************************************
+
+//========================================================================
+// Low level keyboard hook (system callback) function
+// Used to disable system keys under Windows NT
+//========================================================================
+
+static LRESULT CALLBACK keyboardHook( int nCode, WPARAM wParam, LPARAM lParam )
+{
+    BOOL syskeys = FALSE;
+    PKBDLLHOOKSTRUCT p;
+
+    // We are only looking for keyboard events - interpret lParam as a
+    // pointer to a KBDLLHOOKSTRUCT
+    p = (PKBDLLHOOKSTRUCT) lParam;
+
+    if( nCode == HC_ACTION )
+    {
+        // We have a keyboard event
+
+        switch( wParam )
+        {
+            case WM_KEYDOWN:
+            case WM_SYSKEYDOWN:
+            case WM_KEYUP:
+            case WM_SYSKEYUP:
+                // Detect: ALT+TAB, ALT+ESC, ALT+F4, CTRL+ESC,
+                // LWIN, RWIN, APPS (mysterious menu key)
+                syskeys = ( p->vkCode == VK_TAB &&
+                            p->flags & LLKHF_ALTDOWN ) ||
+                          ( p->vkCode == VK_ESCAPE &&
+                            p->flags & LLKHF_ALTDOWN ) ||
+                          ( p->vkCode == VK_F4 &&
+                            p->flags & LLKHF_ALTDOWN ) ||
+                          ( p->vkCode == VK_ESCAPE &&
+                            (GetKeyState(VK_CONTROL) & 0x8000)) ||
+                          p->vkCode == VK_LWIN ||
+                          p->vkCode == VK_RWIN ||
+                          p->vkCode == VK_APPS;
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    // Was it a system key combination (e.g. ALT+TAB)?
+    if( syskeys )
+    {
+        // Pass the key event to our window message loop
+        if( _glfwWin.opened )
+        {
+            PostMessage( _glfwWin.window, (UINT) wParam, p->vkCode, 0 );
+        }
+
+        // We've taken care of it - don't let the system know about this
+        // key event
+        return 1;
+    }
+    else
+    {
+        // It's a harmless key press, let the system deal with it
+        return CallNextHookEx( _glfwWin.keyboardHook, nCode, wParam, lParam );
+    }
+}
+
+
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// Enable system keys
+//========================================================================
+
+void _glfwPlatformEnableSystemKeys( void )
+{
+    BOOL dummy;
+
+    // Use different methods depending on operating system version
+    if( _glfwLibrary.Sys.winVer >= _GLFW_WIN_NT4 )
+    {
+        if( _glfwWin.keyboardHook != NULL )
+        {
+            UnhookWindowsHookEx( _glfwWin.keyboardHook );
+            _glfwWin.keyboardHook = NULL;
+        }
+    }
+    else
+    {
+        (void) SystemParametersInfo( SPI_SETSCREENSAVERRUNNING, FALSE, &dummy, 0 );
+    }
+}
+
+//========================================================================
+// Disable system keys
+//========================================================================
+
+void _glfwPlatformDisableSystemKeys( void )
+{
+    BOOL dummy;
+
+    // Use different methods depending on operating system version
+    if( _glfwLibrary.Sys.winVer >= _GLFW_WIN_NT4 )
+    {
+        // Under Windows NT, install a low level keyboard hook
+        _glfwWin.keyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL,
+                                                  keyboardHook,
+                                                  _glfwLibrary.instance,
+                                                  0 );
+    }
+    else
+    {
+        // Under Windows 95/98/ME, fool Windows that a screensaver
+        // is running => prevents ALT+TAB, CTRL+ESC and CTRL+ALT+DEL
+        (void) SystemParametersInfo( SPI_SETSCREENSAVERRUNNING, TRUE, &dummy, 0 );
+    }
+}
+

+ 320 - 0
ThirdParty/GLFW/lib/win32/win32_fullscreen.c

@@ -0,0 +1,320 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Win32/WGL
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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                       ****
+//************************************************************************
+
+//========================================================================
+// Convert BPP to RGB bits based on "best guess"
+//========================================================================
+
+static void bpp2rgb( int bpp, int *r, int *g, int *b )
+{
+    int delta;
+
+    // We assume that by 32 they really meant 24
+    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;
+    }
+}
+
+
+//========================================================================
+// Return closest video mode by dimensions, refresh rate and bits per pixel
+//========================================================================
+
+int _glfwGetClosestVideoModeBPP( int *w, int *h, int *bpp, int *refresh )
+{
+    int     mode, bestmode, match, bestmatch, rr, bestrr, success;
+    DEVMODE dm;
+
+    // Find best match
+    bestmatch = 0x7fffffff;
+    bestrr    = 0x7fffffff;
+    mode = bestmode = 0;
+    do
+    {
+        dm.dmSize = sizeof( DEVMODE );
+        success = EnumDisplaySettings( NULL, mode, &dm );
+        if( success )
+        {
+            match = dm.dmBitsPerPel - *bpp;
+            if( match < 0 ) match = -match;
+            match = ( match << 25 ) |
+                    ( (dm.dmPelsWidth - *w) *
+                      (dm.dmPelsWidth - *w) +
+                      (dm.dmPelsHeight - *h) *
+                      (dm.dmPelsHeight - *h) );
+            if( match < bestmatch )
+            {
+                bestmatch = match;
+                bestmode  = mode;
+                bestrr = (dm.dmDisplayFrequency - *refresh) *
+                         (dm.dmDisplayFrequency - *refresh);
+            }
+            else if( match == bestmatch && *refresh > 0 )
+            {
+                rr = (dm.dmDisplayFrequency - *refresh) *
+                     (dm.dmDisplayFrequency - *refresh);
+                if( rr < bestrr )
+                {
+                    bestmatch = match;
+                    bestmode  = mode;
+                    bestrr    = rr;
+                }
+            }
+        }
+        mode ++;
+    }
+    while( success );
+
+    // Get the parameters for the best matching display mode
+    dm.dmSize = sizeof( DEVMODE );
+    (void) EnumDisplaySettings( NULL, bestmode, &dm );
+
+    // Fill out actual width and height
+    *w = dm.dmPelsWidth;
+    *h = dm.dmPelsHeight;
+
+    // Return bits per pixel
+    *bpp = dm.dmBitsPerPel;
+
+    // Return vertical refresh rate
+    *refresh = dm.dmDisplayFrequency;
+
+    return bestmode;
+}
+
+
+//========================================================================
+// Return closest video mode by dimensions, refresh rate and channel sizes
+//========================================================================
+
+static int getClosestVideoMode( int *w, int *h,
+                                int *r, int *g, int *b,
+                                int *refresh )
+{
+    int bpp, bestmode;
+
+    // Colorbits = sum of red/green/blue bits
+    bpp = *r + *g + *b;
+
+    // If colorbits < 15 (e.g. 0) or >= 24, default to 32 bpp
+    if( bpp < 15 || bpp >= 24 )
+    {
+        bpp = 32;
+    }
+
+    // Find best match
+    bestmode = _glfwGetClosestVideoModeBPP( w, h, &bpp, refresh );
+
+    // Convert "bits per pixel" to red, green & blue sizes
+    bpp2rgb( bpp, r, g, b );
+
+    return bestmode;
+}
+
+
+//========================================================================
+// Change the current video mode
+//========================================================================
+
+void _glfwSetVideoModeMODE( int mode )
+{
+    DEVMODE dm;
+    int success;
+
+    // Get the parameters for the best matching display mode
+    dm.dmSize = sizeof( DEVMODE );
+    (void) EnumDisplaySettings( NULL, mode, &dm );
+
+    // Set which fields we want to specify
+    dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
+
+    // Do we have a prefered refresh rate?
+    if( _glfwWin.desiredRefreshRate > 0 )
+    {
+        dm.dmFields = dm.dmFields | DM_DISPLAYFREQUENCY;
+        dm.dmDisplayFrequency = _glfwWin.desiredRefreshRate;
+    }
+
+    // Change display setting
+    dm.dmSize = sizeof( DEVMODE );
+    success = ChangeDisplaySettings( &dm, CDS_FULLSCREEN );
+
+    // If the mode change was not possible, query the current display
+    // settings (we'll use the desktop resolution for fullscreen mode)
+    if( success == DISP_CHANGE_SUCCESSFUL )
+    {
+        _glfwWin.modeID = mode;
+    }
+    else
+    {
+        _glfwWin.modeID = ENUM_REGISTRY_SETTINGS;
+        EnumDisplaySettings( NULL, ENUM_REGISTRY_SETTINGS, &dm );
+    }
+
+    // Set the window size to that of the display mode
+    _glfwWin.width  = dm.dmPelsWidth;
+    _glfwWin.height = dm.dmPelsHeight;
+}
+
+
+//========================================================================
+// _glfwSetVideoMode() - Change the current video mode
+//========================================================================
+
+void _glfwSetVideoMode( int *w, int *h, int r, int g, int b, int refresh )
+{
+    int     bestmode;
+
+    // Find a best match mode
+    bestmode = getClosestVideoMode( w, h, &r, &g, &b, &refresh );
+
+    // Change mode
+    _glfwSetVideoModeMODE( bestmode );
+}
+
+
+//************************************************************************
+//****                    GLFW user functions                         ****
+//************************************************************************
+
+//========================================================================
+// _glfwPlatformGetVideoModes() - Get a list of available video modes
+//========================================================================
+
+int _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount )
+{
+    int count, success, mode, i, j;
+    int m1, m2, bpp, r, g, b;
+    DEVMODE dm;
+
+    // Loop through all video modes and extract all the UNIQUE modes
+    count = 0;
+    mode  = 0;
+    do
+    {
+        // Get video mode properties
+        dm.dmSize = sizeof( DEVMODE );
+        success = EnumDisplaySettings( NULL, mode, &dm );
+
+        // Is it a valid mode? (only list depths >= 15 bpp)
+        if( success && dm.dmBitsPerPel >= 15 )
+        {
+            // Convert to RGB, and back to bpp ("mask out" alpha bits etc)
+            bpp2rgb( dm.dmBitsPerPel, &r, &g, &b );
+            bpp = r + g + b;
+
+            // Mode "code" for this mode
+            m1 = (bpp << 25) | (dm.dmPelsWidth * dm.dmPelsHeight);
+
+            // Insert mode in list (sorted), and avoid duplicates
+            for( i = 0; i < count; i ++ )
+            {
+                // Mode "code" for already listed mode
+                bpp = list[i].RedBits + list[i].GreenBits +
+                      list[i].BlueBits;
+                m2 = (bpp << 25) | (list[i].Width * list[i].Height);
+                if( m1 <= m2 )
+                {
+                    break;
+                }
+            }
+
+            // New entry at the end of the list?
+            if( i >= count )
+            {
+                list[count].Width     = dm.dmPelsWidth;
+                list[count].Height    = dm.dmPelsHeight;
+                list[count].RedBits   = r;
+                list[count].GreenBits = g;
+                list[count].BlueBits  = b;
+                count ++;
+            }
+            // Insert new entry in the list?
+            else if( m1 < m2 )
+            {
+                for( j = count; j > i; j -- )
+                {
+                    list[j] = list[j-1];
+                }
+                list[i].Width     = dm.dmPelsWidth;
+                list[i].Height    = dm.dmPelsHeight;
+                list[i].RedBits   = r;
+                list[i].GreenBits = g;
+                list[i].BlueBits  = b;
+                count ++;
+            }
+        }
+        mode ++;
+    }
+    while( success && (count < maxcount) );
+
+    return count;
+}
+
+
+//========================================================================
+// Get the desktop video mode
+//========================================================================
+
+void _glfwPlatformGetDesktopMode( GLFWvidmode *mode )
+{
+    DEVMODE dm;
+
+    // Get desktop display mode
+    dm.dmSize = sizeof( DEVMODE );
+    (void) EnumDisplaySettings( NULL, ENUM_REGISTRY_SETTINGS, &dm );
+
+    // Return desktop mode parameters
+    mode->Width  = dm.dmPelsWidth;
+    mode->Height = dm.dmPelsHeight;
+    bpp2rgb( dm.dmBitsPerPel, &mode->RedBits, &mode->GreenBits, &mode->BlueBits );
+}
+

+ 82 - 0
ThirdParty/GLFW/lib/win32/win32_glext.c

@@ -0,0 +1,82 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Win32/WGL
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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 the current context supports the specified WGL extension
+//========================================================================
+
+int _glfwPlatformExtensionSupported( const char *extension )
+{
+    const GLubyte *extensions;
+
+    if( _glfwWin.GetExtensionsStringEXT != NULL )
+    {
+        extensions = (GLubyte *) _glfwWin.GetExtensionsStringEXT();
+        if( extensions != NULL )
+        {
+            if( _glfwStringInExtensionString( extension, extensions ) )
+            {
+                return GL_TRUE;
+            }
+        }
+    }
+
+    if( _glfwWin.GetExtensionsStringARB != NULL )
+    {
+        extensions = (GLubyte *) _glfwWin.GetExtensionsStringARB( _glfwWin.DC );
+        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 *) wglGetProcAddress( procname );
+}
+

+ 356 - 0
ThirdParty/GLFW/lib/win32/win32_init.c

@@ -0,0 +1,356 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Win32/WGL
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+// With the Borland C++ compiler, we want to disable FPU exceptions
+#ifdef __BORLANDC__
+#include <float.h>
+#endif // __BORLANDC__
+
+
+
+//************************************************************************
+//****                  GLFW internal functions                       ****
+//************************************************************************
+
+//========================================================================
+// _glfwInitLibraries() - Load necessary libraries (DLLs)
+//========================================================================
+
+static int _glfwInitLibraries( void )
+{
+    // gdi32.dll (OpenGL pixel format functions & SwapBuffers)
+#ifndef _GLFW_NO_DLOAD_GDI32
+    _glfwLibrary.Libs.gdi32 = LoadLibrary( "gdi32.dll" );
+    if( _glfwLibrary.Libs.gdi32 != NULL )
+    {
+        _glfwLibrary.Libs.ChoosePixelFormat   = (CHOOSEPIXELFORMAT_T)
+            GetProcAddress( _glfwLibrary.Libs.gdi32, "ChoosePixelFormat" );
+        _glfwLibrary.Libs.DescribePixelFormat = (DESCRIBEPIXELFORMAT_T)
+            GetProcAddress( _glfwLibrary.Libs.gdi32, "DescribePixelFormat" );
+        _glfwLibrary.Libs.GetPixelFormat      = (GETPIXELFORMAT_T)
+            GetProcAddress( _glfwLibrary.Libs.gdi32, "GetPixelFormat" );
+        _glfwLibrary.Libs.SetPixelFormat      = (SETPIXELFORMAT_T)
+            GetProcAddress( _glfwLibrary.Libs.gdi32, "SetPixelFormat" );
+        _glfwLibrary.Libs.SwapBuffers         = (SWAPBUFFERS_T)
+            GetProcAddress( _glfwLibrary.Libs.gdi32, "SwapBuffers" );
+        if( _glfwLibrary.Libs.ChoosePixelFormat   == NULL ||
+            _glfwLibrary.Libs.DescribePixelFormat == NULL ||
+            _glfwLibrary.Libs.GetPixelFormat      == NULL ||
+            _glfwLibrary.Libs.SetPixelFormat      == NULL ||
+            _glfwLibrary.Libs.SwapBuffers         == NULL )
+        {
+            FreeLibrary( _glfwLibrary.Libs.gdi32 );
+            _glfwLibrary.Libs.gdi32 = NULL;
+            return GL_FALSE;
+        }
+    }
+    else
+    {
+        return GL_FALSE;
+    }
+#endif // _GLFW_NO_DLOAD_GDI32
+
+    // winmm.dll (for joystick and timer support)
+#ifndef _GLFW_NO_DLOAD_WINMM
+    _glfwLibrary.Libs.winmm = LoadLibrary( "winmm.dll" );
+    if( _glfwLibrary.Libs.winmm != NULL )
+    {
+        _glfwLibrary.Libs.joyGetDevCapsA = (JOYGETDEVCAPSA_T)
+            GetProcAddress( _glfwLibrary.Libs.winmm, "joyGetDevCapsA" );
+        _glfwLibrary.Libs.joyGetPos      = (JOYGETPOS_T)
+            GetProcAddress( _glfwLibrary.Libs.winmm, "joyGetPos" );
+        _glfwLibrary.Libs.joyGetPosEx    = (JOYGETPOSEX_T)
+            GetProcAddress( _glfwLibrary.Libs.winmm, "joyGetPosEx" );
+        _glfwLibrary.Libs.timeGetTime    = (TIMEGETTIME_T)
+            GetProcAddress( _glfwLibrary.Libs.winmm, "timeGetTime" );
+        if( _glfwLibrary.Libs.joyGetDevCapsA == NULL ||
+            _glfwLibrary.Libs.joyGetPos      == NULL ||
+            _glfwLibrary.Libs.joyGetPosEx    == NULL ||
+            _glfwLibrary.Libs.timeGetTime    == NULL )
+        {
+            FreeLibrary( _glfwLibrary.Libs.winmm );
+            _glfwLibrary.Libs.winmm = NULL;
+            return GL_FALSE;
+        }
+    }
+    else
+    {
+        return GL_FALSE;
+    }
+#endif // _GLFW_NO_DLOAD_WINMM
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// _glfwFreeLibraries() - Unload used libraries (DLLs)
+//========================================================================
+
+static void _glfwFreeLibraries( void )
+{
+    // gdi32.dll
+#ifndef _GLFW_NO_DLOAD_GDI32
+    if( _glfwLibrary.Libs.gdi32 != NULL )
+    {
+        FreeLibrary( _glfwLibrary.Libs.gdi32 );
+        _glfwLibrary.Libs.gdi32 = NULL;
+    }
+#endif // _GLFW_NO_DLOAD_GDI32
+
+    // winmm.dll
+#ifndef _GLFW_NO_DLOAD_WINMM
+    if( _glfwLibrary.Libs.winmm != NULL )
+    {
+        FreeLibrary( _glfwLibrary.Libs.winmm );
+        _glfwLibrary.Libs.winmm = NULL;
+    }
+#endif // _GLFW_NO_DLOAD_WINMM
+}
+
+
+//========================================================================
+// _glfwInitThreads() - Initialize GLFW thread package
+//========================================================================
+
+static void _glfwInitThreads( void )
+{
+    // Initialize critical section handle
+    InitializeCriticalSection( &_glfwThrd.CriticalSection );
+
+    // 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.Handle   = GetCurrentThread();
+    _glfwThrd.First.WinID    = GetCurrentThreadId();
+    _glfwThrd.First.Previous = NULL;
+    _glfwThrd.First.Next     = NULL;
+}
+
+
+//========================================================================
+// _glfwTerminateThreads() - Terminate GLFW thread package
+//========================================================================
+
+static void _glfwTerminateThreads( void )
+{
+    _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!
+        if( TerminateThread( t->Handle, 0 ) )
+        {
+            // Close thread handle
+            CloseHandle( t->Handle );
+
+            // 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
+    DeleteCriticalSection( &_glfwThrd.CriticalSection );
+}
+
+
+//========================================================================
+// _glfwTerminate_atexit() - Terminate GLFW when exiting application
+//========================================================================
+
+void _glfwTerminate_atexit( void )
+{
+    glfwTerminate();
+}
+
+
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// _glfwPlatformInit() - Initialize various GLFW state
+//========================================================================
+
+int _glfwPlatformInit( void )
+{
+    OSVERSIONINFO osi;
+
+    // To make SetForegroundWindow() work as we want, we need to fiddle
+    // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
+    // as possible in the hope of still being the foreground process)
+    SystemParametersInfo( SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
+                          &_glfwLibrary.Sys.foregroundLockTimeout, 0 );
+    SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0,
+                          SPIF_SENDCHANGE );
+
+    // Check which OS version we are running
+    osi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+    GetVersionEx( &osi );
+    _glfwLibrary.Sys.winVer = _GLFW_WIN_UNKNOWN;
+    if( osi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
+    {
+        if( osi.dwMajorVersion == 4 && osi.dwMinorVersion < 10 )
+        {
+            _glfwLibrary.Sys.winVer = _GLFW_WIN_95;
+        }
+        else if( osi.dwMajorVersion == 4 && osi.dwMinorVersion < 90 )
+        {
+            _glfwLibrary.Sys.winVer = _GLFW_WIN_98;
+        }
+        else if( osi.dwMajorVersion == 4 && osi.dwMinorVersion == 90 )
+        {
+            _glfwLibrary.Sys.winVer = _GLFW_WIN_ME;
+        }
+        else if( osi.dwMajorVersion >= 4 )
+        {
+            _glfwLibrary.Sys.winVer = _GLFW_WIN_UNKNOWN_9x;
+        }
+    }
+    else if( osi.dwPlatformId == VER_PLATFORM_WIN32_NT )
+    {
+        if( osi.dwMajorVersion == 4 && osi.dwMinorVersion == 0 )
+        {
+            _glfwLibrary.Sys.winVer = _GLFW_WIN_NT4;
+        }
+        else if( osi.dwMajorVersion == 5 && osi.dwMinorVersion == 0 )
+        {
+            _glfwLibrary.Sys.winVer = _GLFW_WIN_2K;
+        }
+        else if( osi.dwMajorVersion == 5 && osi.dwMinorVersion == 1 )
+        {
+            _glfwLibrary.Sys.winVer = _GLFW_WIN_XP;
+        }
+        else if( osi.dwMajorVersion == 5 && osi.dwMinorVersion == 2 )
+        {
+            _glfwLibrary.Sys.winVer = _GLFW_WIN_NET_SERVER;
+        }
+        else if( osi.dwMajorVersion >= 5 )
+        {
+            _glfwLibrary.Sys.winVer = _GLFW_WIN_UNKNOWN_NT;
+        }
+    }
+
+    // Do we have Unicode support?
+    if( _glfwLibrary.Sys.winVer >= _GLFW_WIN_NT4 )
+    {
+        // Windows NT/2000/XP/.NET has Unicode support
+        _glfwLibrary.Sys.hasUnicode = GL_TRUE;
+    }
+    else
+    {
+        // Windows 9x/ME does not have Unicode support
+        _glfwLibrary.Sys.hasUnicode = GL_FALSE;
+    }
+
+    // Load libraries (DLLs)
+    if( !_glfwInitLibraries() )
+    {
+        return GL_FALSE;
+    }
+
+    // With the Borland C++ compiler, we want to disable FPU exceptions
+    // (this is recommended for OpenGL applications under Windows)
+#ifdef __BORLANDC__
+    _control87( MCW_EM, MCW_EM );
+#endif
+
+    // Retrieve GLFW instance handle
+    _glfwLibrary.instance = GetModuleHandle( NULL );
+
+    // System keys are not disabled
+    _glfwWin.keyboardHook = NULL;
+
+    // Initialise thread package
+    _glfwInitThreads();
+
+    // Install atexit() routine
+    atexit( _glfwTerminate_atexit );
+
+    // Start the timer
+    _glfwInitTimer();
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// _glfwPlatformTerminate() - Close window and kill all threads
+//========================================================================
+
+int _glfwPlatformTerminate( void )
+{
+    // Only the main thread is allowed to do this...
+    if( GetCurrentThreadId() != _glfwThrd.First.WinID )
+    {
+        return GL_FALSE;
+    }
+
+    // Close OpenGL window
+    glfwCloseWindow();
+
+    // Kill thread package
+    _glfwTerminateThreads();
+
+    // Enable system keys again (if they were disabled)
+    glfwEnable( GLFW_SYSTEM_KEYS );
+
+    // Unload libraries (DLLs)
+    _glfwFreeLibraries();
+
+    // Restore FOREGROUNDLOCKTIMEOUT system setting
+    SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
+                          (LPVOID)_glfwLibrary.Sys.foregroundLockTimeout,
+                          SPIF_SENDCHANGE );
+
+    return GL_TRUE;
+}
+

+ 234 - 0
ThirdParty/GLFW/lib/win32/win32_joystick.c

@@ -0,0 +1,234 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Win32/WGL
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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                       ****
+//************************************************************************
+
+//========================================================================
+// _glfwJoystickPresent() - Return GL_TRUE if joystick is present,
+// else return GL_FALSE.
+//========================================================================
+
+static int _glfwJoystickPresent( int joy )
+{
+    JOYINFO ji;
+
+    // Windows NT 4.0 MMSYSTEM only supports 2 sticks (other Windows
+    // versions support 16 sticks)
+    if( _glfwLibrary.Sys.winVer == _GLFW_WIN_NT4 && joy > GLFW_JOYSTICK_2 )
+    {
+        return GL_FALSE;
+    }
+
+    // Is it a valid stick ID (Windows don't support more than 16 sticks)?
+    if( joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_16 )
+    {
+        return GL_FALSE;
+    }
+
+    // Is the joystick present?
+    if( _glfw_joyGetPos( joy - GLFW_JOYSTICK_1, &ji ) != JOYERR_NOERROR )
+    {
+        return GL_FALSE;
+    }
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// _glfwCalcJoystickPos() - Calculate joystick position
+//========================================================================
+
+static float _glfwCalcJoystickPos( DWORD pos, DWORD min, DWORD max )
+{
+    float fpos = (float) pos;
+    float fmin = (float) min;
+    float fmax = (float) max;
+    return (2.0f*(fpos - fmin) / (fmax - fmin)) - 1.0f;
+}
+
+
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// _glfwPlatformGetJoystickParam() - Determine joystick capabilities
+//========================================================================
+
+int _glfwPlatformGetJoystickParam( int joy, int param )
+{
+    JOYCAPS jc;
+
+//  return 0;
+
+    // Is joystick present?
+    if( !_glfwJoystickPresent( joy ) )
+    {
+        return 0;
+    }
+
+    // We got this far, the joystick is present
+    if( param == GLFW_PRESENT )
+    {
+        return GL_TRUE;
+    }
+
+    // Get joystick capabilities
+    _glfw_joyGetDevCaps( joy - GLFW_JOYSTICK_1, &jc, sizeof(JOYCAPS) );
+
+    switch( param )
+    {
+    case GLFW_AXES:
+        // Return number of joystick axes
+        return jc.wNumAxes;
+
+    case GLFW_BUTTONS:
+        // Return number of joystick axes
+        return jc.wNumButtons;
+
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+
+//========================================================================
+// _glfwPlatformGetJoystickPos() - Get joystick axis positions
+//========================================================================
+
+int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes )
+{
+    JOYCAPS   jc;
+    JOYINFOEX ji;
+    int       axis;
+
+//  return 0;
+
+    // Is joystick present?
+    if( !_glfwJoystickPresent( joy ) )
+    {
+        return 0;
+    }
+
+    // Get joystick capabilities
+    _glfw_joyGetDevCaps( joy - GLFW_JOYSTICK_1, &jc, sizeof(JOYCAPS) );
+
+    // Get joystick state
+    ji.dwSize = sizeof( JOYINFOEX );
+    ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ |
+                 JOY_RETURNR | JOY_RETURNU | JOY_RETURNV;
+    _glfw_joyGetPosEx( joy - GLFW_JOYSTICK_1, &ji );
+
+    // Get position values for all axes
+    axis = 0;
+    if( axis < numaxes )
+    {
+        pos[ axis++ ] = _glfwCalcJoystickPos( ji.dwXpos, jc.wXmin,
+                                              jc.wXmax );
+    }
+    if( axis < numaxes )
+    {
+        pos[ axis++ ] = -_glfwCalcJoystickPos( ji.dwYpos, jc.wYmin,
+                                               jc.wYmax );
+    }
+    if( axis < numaxes && jc.wCaps & JOYCAPS_HASZ )
+    {
+        pos[ axis++ ] = _glfwCalcJoystickPos( ji.dwZpos, jc.wZmin,
+                                              jc.wZmax );
+    }
+    if( axis < numaxes && jc.wCaps & JOYCAPS_HASR )
+    {
+        pos[ axis++ ] = _glfwCalcJoystickPos( ji.dwRpos, jc.wRmin,
+                                              jc.wRmax );
+    }
+    if( axis < numaxes && jc.wCaps & JOYCAPS_HASU )
+    {
+        pos[ axis++ ] = _glfwCalcJoystickPos( ji.dwUpos, jc.wUmin,
+                                              jc.wUmax );
+    }
+    if( axis < numaxes && jc.wCaps & JOYCAPS_HASV )
+    {
+        pos[ axis++ ] = -_glfwCalcJoystickPos( ji.dwVpos, jc.wVmin,
+                                               jc.wVmax );
+    }
+
+    // Return number of returned axes
+    return axis;
+}
+
+
+//========================================================================
+// _glfwPlatformGetJoystickButtons() - Get joystick button states
+//========================================================================
+
+int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons,
+    int numbuttons )
+{
+    JOYCAPS   jc;
+    JOYINFOEX ji;
+    int       button;
+
+//  return 0;
+
+    // Is joystick present?
+    if( !_glfwJoystickPresent( joy ) )
+    {
+        return 0;
+    }
+
+    // Get joystick capabilities
+    _glfw_joyGetDevCaps( joy - GLFW_JOYSTICK_1, &jc, sizeof(JOYCAPS) );
+
+    // Get joystick state
+    ji.dwSize = sizeof( JOYINFOEX );
+    ji.dwFlags = JOY_RETURNBUTTONS;
+    _glfw_joyGetPosEx( joy - GLFW_JOYSTICK_1, &ji );
+
+    // Get states of all requested buttons
+    button = 0;
+    while( button < numbuttons && button < (int) jc.wNumButtons )
+    {
+        buttons[ button ] = (unsigned char)
+            (ji.dwButtons & (1UL << button) ? GLFW_PRESS : GLFW_RELEASE);
+        button ++;
+    }
+
+    return button;
+}
+

+ 511 - 0
ThirdParty/GLFW/lib/win32/win32_thread.c

@@ -0,0 +1,511 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Win32/WGL
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+
+//************************************************************************
+// This is an implementation of POSIX "compatible" condition variables for
+// Win32, as described by Douglas C. Schmidt and Irfan Pyarali:
+// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
+//************************************************************************
+
+enum {
+    _GLFW_COND_SIGNAL     = 0,
+    _GLFW_COND_BROADCAST  = 1
+};
+
+typedef struct {
+    // Signal and broadcast event HANDLEs
+    HANDLE events[ 2 ];
+
+    // Count of the number of waiters
+    unsigned int waiters_count;
+
+    // Serialize access to <waiters_count>
+    CRITICAL_SECTION waiters_count_lock;
+} _GLFWcond;
+
+
+
+//************************************************************************
+//****                  GLFW internal functions                       ****
+//************************************************************************
+
+//========================================================================
+// _glfwNewThread() - This is simply a "wrapper" for calling the user
+// thread function.
+//========================================================================
+
+DWORD WINAPI _glfwNewThread( LPVOID lpParam )
+{
+    GLFWthreadfun threadfun;
+    _GLFWthread   *t;
+
+    // Get pointer to thread information for current thread
+    t = _glfwGetThreadPointer( _glfwPlatformGetThreadID() );
+    if( t == NULL )
+    {
+        return 0;
+    }
+
+    // Get user thread function pointer
+    threadfun = t->Function;
+
+    // Call the user thread function
+    threadfun( (void *) lpParam );
+
+    // 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 0;
+}
+
+
+
+//************************************************************************
+//****                     GLFW user functions                        ****
+//************************************************************************
+
+//========================================================================
+// _glfwPlatformCreateThread() - Create a new thread
+//========================================================================
+
+GLFWthread _glfwPlatformCreateThread( GLFWthreadfun fun, void *arg )
+{
+    GLFWthread  ID;
+    _GLFWthread *t, *t_tmp;
+    HANDLE      hThread;
+    DWORD       dwThreadId;
+
+    // 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
+    hThread = CreateThread(
+        NULL,              // Default security attributes
+        0,                 // Default stack size (1 MB)
+        _glfwNewThread,    // Thread function (a wrapper function)
+        (LPVOID)arg,       // Argument to thread is the user argument
+        0,                 // Default creation flags
+        &dwThreadId        // Returned thread identifier
+    );
+
+    // Did the thread creation fail?
+    if( hThread == NULL )
+    {
+        free( (void *) t );
+        LEAVE_THREAD_CRITICAL_SECTION
+        return -1;
+    }
+
+    // Store more thread information in the thread list
+    t->Handle = hThread;
+    t->WinID  = dwThreadId;
+
+    // Append thread to thread list
+    t_tmp = &_glfwThrd.First;
+    while( t_tmp->Next != NULL )
+    {
+        t_tmp = t_tmp->Next;
+    }
+    t_tmp->Next = t;
+    t->Previous = t_tmp;
+    t->Next     = NULL;
+
+    // Leave critical section
+    LEAVE_THREAD_CRITICAL_SECTION
+
+    // Return the GLFW thread ID
+    return ID;
+}
+
+
+//========================================================================
+// _glfwPlatformDestroyThread() - Kill a thread. NOTE: THIS IS A VERY
+// DANGEROUS OPERATION, AND SHOULD NOT BE USED EXCEPT IN EXTREME
+// SITUATIONS!
+//========================================================================
+
+void _glfwPlatformDestroyThread( GLFWthread ID )
+{
+    _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!
+    if( TerminateThread( t->Handle, 0 ) )
+    {
+        // Close thread handle
+        CloseHandle( t->Handle );
+
+        // Remove thread from thread list
+        _glfwRemoveThread( t );
+    }
+
+    // Leave critical section
+    LEAVE_THREAD_CRITICAL_SECTION
+}
+
+
+//========================================================================
+// _glfwPlatformWaitThread() - Wait for a thread to die
+//========================================================================
+
+int _glfwPlatformWaitThread( GLFWthread ID, int waitmode )
+{
+    DWORD       result;
+    HANDLE      hThread;
+    _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;
+    }
+
+    // Get thread handle
+    hThread = t->Handle;
+
+    // Leave critical section
+    LEAVE_THREAD_CRITICAL_SECTION
+
+    // Wait for thread to die
+    if( waitmode == GLFW_WAIT )
+    {
+        result = WaitForSingleObject( hThread, INFINITE );
+    }
+    else if( waitmode == GLFW_NOWAIT )
+    {
+        result = WaitForSingleObject( hThread, 0 );
+    }
+    else
+    {
+        return GL_FALSE;
+    }
+
+    // Did we have a time-out?
+    if( result == WAIT_TIMEOUT )
+    {
+        return GL_FALSE;
+    }
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// _glfwPlatformGetThreadID() - Return the thread ID for the current
+// thread
+//========================================================================
+
+GLFWthread _glfwPlatformGetThreadID( void )
+{
+    _GLFWthread *t;
+    GLFWthread  ID = -1;
+    DWORD       WinID;
+
+    // Get Windows thread ID
+    WinID = GetCurrentThreadId();
+
+    // Enter critical section (to avoid an inconsistent thread list)
+    ENTER_THREAD_CRITICAL_SECTION
+
+    // Loop through entire list of threads to find the matching Windows
+    // thread ID
+    for( t = &_glfwThrd.First; t != NULL; t = t->Next )
+    {
+        if( t->WinID == WinID )
+        {
+            ID = t->ID;
+            break;
+        }
+    }
+
+    // Leave critical section
+    LEAVE_THREAD_CRITICAL_SECTION
+
+    // Return the found GLFW thread identifier
+    return ID;
+}
+
+
+//========================================================================
+// _glfwPlatformCreateMutex() - Create a mutual exclusion object
+//========================================================================
+
+GLFWmutex _glfwPlatformCreateMutex( void )
+{
+    CRITICAL_SECTION *mutex;
+
+    // Allocate memory for mutex
+    mutex = (CRITICAL_SECTION *) malloc( sizeof(CRITICAL_SECTION) );
+    if( !mutex )
+    {
+        return NULL;
+    }
+
+    // Initialize mutex
+    InitializeCriticalSection( mutex );
+
+    // Cast to GLFWmutex and return
+    return (GLFWmutex) mutex;
+}
+
+
+//========================================================================
+// glfwDestroyMutex() - Destroy a mutual exclusion object
+//========================================================================
+
+void _glfwPlatformDestroyMutex( GLFWmutex mutex )
+{
+    // Destroy mutex
+    DeleteCriticalSection( (CRITICAL_SECTION *) mutex );
+    free( mutex );
+}
+
+
+//========================================================================
+// _glfwPlatformLockMutex() - Request access to a mutex
+//========================================================================
+
+void _glfwPlatformLockMutex( GLFWmutex mutex )
+{
+    // Wait for mutex to be released
+    EnterCriticalSection( (CRITICAL_SECTION *) mutex );
+}
+
+
+//========================================================================
+// _glfwPlatformUnlockMutex() - Release a mutex
+//========================================================================
+
+void _glfwPlatformUnlockMutex( GLFWmutex mutex )
+{
+    // Release mutex
+    LeaveCriticalSection( (CRITICAL_SECTION *) mutex );
+}
+
+
+//========================================================================
+// _glfwPlatformCreateCond() - Create a new condition variable object
+//========================================================================
+
+GLFWcond _glfwPlatformCreateCond( void )
+{
+    _GLFWcond   *cond;
+
+    // Allocate memory for condition variable
+    cond = (_GLFWcond *) malloc( sizeof(_GLFWcond) );
+    if( !cond )
+    {
+        return NULL;
+    }
+
+    // Initialize condition variable
+    cond->waiters_count = 0;
+    cond->events[ _GLFW_COND_SIGNAL ]    = CreateEvent( NULL, FALSE,
+                                                        FALSE, NULL );
+    cond->events[ _GLFW_COND_BROADCAST ] = CreateEvent( NULL, TRUE,
+                                                        FALSE, NULL );
+    InitializeCriticalSection( &cond->waiters_count_lock );
+
+    // Cast to GLFWcond and return
+    return (GLFWcond) cond;
+}
+
+
+//========================================================================
+// _glfwPlatformDestroyCond() - Destroy a condition variable object
+//========================================================================
+
+void _glfwPlatformDestroyCond( GLFWcond cond )
+{
+    // Close the condition variable handles
+    CloseHandle( ((_GLFWcond *)cond)->events[ _GLFW_COND_SIGNAL ] );
+    CloseHandle( ((_GLFWcond *)cond)->events[ _GLFW_COND_BROADCAST ] );
+
+    // Delete critical section
+    DeleteCriticalSection( &((_GLFWcond *)cond)->waiters_count_lock );
+
+    // Free memory for condition variable
+    free( (void *) cond );
+}
+
+
+//========================================================================
+// _glfwPlatformWaitCond() - Wait for a condition to be raised
+//========================================================================
+
+void _glfwPlatformWaitCond( GLFWcond cond, GLFWmutex mutex,
+    double timeout )
+{
+    _GLFWcond *cv = (_GLFWcond *) cond;
+    int       result, last_waiter;
+    DWORD     timeout_ms;
+
+    // Avoid race conditions
+    EnterCriticalSection( &cv->waiters_count_lock );
+    cv->waiters_count ++;
+    LeaveCriticalSection( &cv->waiters_count_lock );
+
+    // It's ok to release the mutex here since Win32 manual-reset events
+    // maintain state when used with SetEvent()
+    LeaveCriticalSection( (CRITICAL_SECTION *) mutex );
+
+    // Translate timeout into milliseconds
+    if( timeout >= GLFW_INFINITY )
+    {
+        timeout_ms = INFINITE;
+    }
+    else
+    {
+        timeout_ms = (DWORD) (1000.0 * timeout + 0.5);
+        if( timeout_ms <= 0 )
+        {
+            timeout_ms = 1;
+        }
+    }
+
+    // Wait for either event to become signaled due to glfwSignalCond or
+    // glfwBroadcastCond being called
+    result = WaitForMultipleObjects( 2, cv->events, FALSE, timeout_ms );
+
+    // Check if we are the last waiter
+    EnterCriticalSection( &cv->waiters_count_lock );
+    cv->waiters_count --;
+    last_waiter = (result == WAIT_OBJECT_0 + _GLFW_COND_BROADCAST) &&
+                  (cv->waiters_count == 0);
+    LeaveCriticalSection( &cv->waiters_count_lock );
+
+    // Some thread called glfwBroadcastCond
+    if( last_waiter )
+    {
+        // We're the last waiter to be notified or to stop waiting, so
+        // reset the manual event
+        ResetEvent( cv->events[ _GLFW_COND_BROADCAST ] );
+    }
+
+    // Reacquire the mutex
+    EnterCriticalSection( (CRITICAL_SECTION *) mutex );
+}
+
+
+//========================================================================
+// _glfwPlatformSignalCond() - Signal a condition to one waiting thread
+//========================================================================
+
+void _glfwPlatformSignalCond( GLFWcond cond )
+{
+    _GLFWcond *cv = (_GLFWcond *) cond;
+    int       have_waiters;
+
+    // Avoid race conditions
+    EnterCriticalSection( &cv->waiters_count_lock );
+    have_waiters = cv->waiters_count > 0;
+    LeaveCriticalSection( &cv->waiters_count_lock );
+
+    if( have_waiters )
+    {
+        SetEvent( cv->events[ _GLFW_COND_SIGNAL ] );
+    }
+}
+
+
+//========================================================================
+// _glfwPlatformBroadcastCond() - Broadcast a condition to all waiting
+// threads
+//========================================================================
+
+void _glfwPlatformBroadcastCond( GLFWcond cond )
+{
+    _GLFWcond *cv = (_GLFWcond *) cond;
+    int       have_waiters;
+
+    // Avoid race conditions
+    EnterCriticalSection( &cv->waiters_count_lock );
+    have_waiters = cv->waiters_count > 0;
+    LeaveCriticalSection( &cv->waiters_count_lock );
+
+    if( have_waiters )
+    {
+        SetEvent( cv->events[ _GLFW_COND_BROADCAST ] );
+    }
+}
+
+
+//========================================================================
+// _glfwPlatformGetNumberOfProcessors() - Return the number of processors
+// in the system.
+//========================================================================
+
+int _glfwPlatformGetNumberOfProcessors( void )
+{
+    SYSTEM_INFO si;
+
+    // Get hardware system information
+    GetSystemInfo( &si );
+
+    return (int) si.dwNumberOfProcessors;
+}

+ 146 - 0
ThirdParty/GLFW/lib/win32/win32_time.c

@@ -0,0 +1,146 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Win32/WGL
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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                       ****
+//************************************************************************
+
+//========================================================================
+// _glfwInitTimer() - Initialise timer
+//========================================================================
+
+void _glfwInitTimer( void )
+{
+    __int64 freq;
+
+    // Check if we have a performance counter
+    if( QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ) )
+    {
+        // Performance counter is available => use it!
+        _glfwLibrary.Timer.HasPerformanceCounter = GL_TRUE;
+
+        // Counter resolution is 1 / counter frequency
+        _glfwLibrary.Timer.Resolution = 1.0 / (double)freq;
+
+        // Set start time for timer
+        QueryPerformanceCounter( (LARGE_INTEGER *)&_glfwLibrary.Timer.t0_64 );
+    }
+    else
+    {
+        // No performace counter available => use the tick counter
+        _glfwLibrary.Timer.HasPerformanceCounter = GL_FALSE;
+
+        // Counter resolution is 1 ms
+        _glfwLibrary.Timer.Resolution = 0.001;
+
+        // Set start time for timer
+        _glfwLibrary.Timer.t0_32 = _glfw_timeGetTime();
+    }
+}
+
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// Return timer value in seconds
+//========================================================================
+
+double _glfwPlatformGetTime( void )
+{
+    double  t;
+    __int64 t_64;
+
+    if( _glfwLibrary.Timer.HasPerformanceCounter )
+    {
+        QueryPerformanceCounter( (LARGE_INTEGER *)&t_64 );
+        t =  (double)(t_64 - _glfwLibrary.Timer.t0_64);
+    }
+    else
+    {
+        t = (double)(_glfw_timeGetTime() - _glfwLibrary.Timer.t0_32);
+    }
+
+    // Calculate the current time in seconds
+    return t * _glfwLibrary.Timer.Resolution;
+}
+
+
+//========================================================================
+// Set timer value in seconds
+//========================================================================
+
+void _glfwPlatformSetTime( double t )
+{
+    __int64 t_64;
+
+    if( _glfwLibrary.Timer.HasPerformanceCounter )
+    {
+        QueryPerformanceCounter( (LARGE_INTEGER *)&t_64 );
+        _glfwLibrary.Timer.t0_64 = t_64 - (__int64)(t/_glfwLibrary.Timer.Resolution);
+    }
+    else
+    {
+        _glfwLibrary.Timer.t0_32 = _glfw_timeGetTime() - (int)(t*1000.0);
+    }
+}
+
+
+//========================================================================
+// Put a thread to sleep for a specified amount of time
+//========================================================================
+
+void _glfwPlatformSleep( double time )
+{
+    DWORD t;
+
+    if( time == 0.0 )
+    {
+	t = 0;
+    }
+    else if( time < 0.001 )
+    {
+        t = 1;
+    }
+    else if( time > 2147483647.0 )
+    {
+        t = 2147483647;
+    }
+    else
+    {
+        t = (DWORD)(time*1000.0 + 0.5);
+    }
+    Sleep( t );
+}
+

+ 1819 - 0
ThirdParty/GLFW/lib/win32/win32_window.c

@@ -0,0 +1,1819 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Win32/WGL
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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.
+//
+//========================================================================
+
+// Modified by Lasse Öörni for Urho3D
+
+#include "internal.h"
+
+
+
+//************************************************************************
+//****                  GLFW internal functions                       ****
+//************************************************************************
+
+// We use versioned window class names in order not to cause conflicts
+// between applications using different versions of GLFW
+#define _GLFW_WNDCLASSNAME "GLFW27"
+
+
+//========================================================================
+// Enable/disable minimize/restore animations
+//========================================================================
+
+static int setMinMaxAnimations( int enable )
+{
+    ANIMATIONINFO AI;
+    int old_enable;
+
+    // Get old animation setting
+    AI.cbSize = sizeof( ANIMATIONINFO );
+    SystemParametersInfo( SPI_GETANIMATION, AI.cbSize, &AI, 0 );
+    old_enable = AI.iMinAnimate;
+
+    // If requested, change setting
+    if( old_enable != enable )
+    {
+        AI.iMinAnimate = enable;
+        SystemParametersInfo( SPI_SETANIMATION, AI.cbSize, &AI,
+                              SPIF_SENDCHANGE );
+    }
+
+    return old_enable;
+}
+
+
+//========================================================================
+// Focus the window and bring it to the top of the stack
+// Due to some nastiness with how Win98/ME/2k/XP handles SetForegroundWindow,
+// we have to go through some really bizarre measures to achieve this
+//========================================================================
+
+static void setForegroundWindow( HWND hWnd )
+{
+    int try_count = 0;
+    int old_animate;
+
+    // Try the standard approach first...
+    BringWindowToTop( hWnd );
+    SetForegroundWindow( hWnd );
+
+    // If it worked, return now
+    if( hWnd == GetForegroundWindow() )
+    {
+        // Try to modify the system settings (since this is the foreground
+        // process, we are allowed to do this)
+        SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0,
+                              SPIF_SENDCHANGE );
+        return;
+    }
+
+    // For other Windows versions than 95 & NT4.0, the standard approach
+    // may not work, so if we failed we have to "trick" Windows into
+    // making our window the foureground window: Iconify and restore
+    // again. It is ugly, but it seems to work (we turn off those annoying
+    // zoom animations to make it look a bit better at least).
+
+    // Turn off minimize/restore animations
+    old_animate = setMinMaxAnimations( 0 );
+
+    // We try this a few times, just to be on the safe side of things...
+    do
+    {
+        // Iconify & restore
+        ShowWindow( hWnd, SW_HIDE );
+        ShowWindow( hWnd, SW_SHOWMINIMIZED );
+        ShowWindow( hWnd, SW_SHOWNORMAL );
+
+        // Try to get focus
+        BringWindowToTop( hWnd );
+        SetForegroundWindow( hWnd );
+
+        // We do not want to keep going on forever, so we keep track of
+        // how many times we tried
+        try_count ++;
+    }
+    while( hWnd != GetForegroundWindow() && try_count <= 3 );
+
+    // Restore the system minimize/restore animation setting
+    (void) setMinMaxAnimations( old_animate );
+
+    // Try to modify the system settings (since this is now hopefully the
+    // foreground process, we are probably allowed to do this)
+    SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0,
+                          SPIF_SENDCHANGE );
+}
+
+
+//========================================================================
+// Returns the specified attribute of the specified pixel format
+// NOTE: Do not call this unless we have found WGL_ARB_pixel_format
+//========================================================================
+
+static int getPixelFormatAttrib(int pixelFormat, int attrib)
+{
+    int value = 0;
+
+    if( !_glfwWin.GetPixelFormatAttribivARB( _glfwWin.DC, pixelFormat, 0, 1, &attrib, &value) )
+    {
+        // NOTE: We should probably handle this error somehow
+        return 0;
+    }
+
+    return value;
+}
+
+
+//========================================================================
+// Return a list of available and usable framebuffer configs
+//========================================================================
+
+static _GLFWfbconfig *getFBConfigs( unsigned int *found )
+{
+    _GLFWfbconfig *result;
+    PIXELFORMATDESCRIPTOR pfd;
+    int i, count;
+
+    *found = 0;
+
+    if( _glfwWin.has_WGL_ARB_pixel_format )
+    {
+        count = getPixelFormatAttrib( 1, WGL_NUMBER_PIXEL_FORMATS_ARB );
+    }
+    else
+    {
+        count = _glfw_DescribePixelFormat( _glfwWin.DC, 1, sizeof( PIXELFORMATDESCRIPTOR ), NULL );
+    }
+
+    if( !count )
+    {
+        fprintf( stderr, "No Win32 pixel formats available\n" );
+        return NULL;
+    }
+
+    result = (_GLFWfbconfig*) malloc( sizeof( _GLFWfbconfig ) * count );
+    if( !result )
+    {
+        fprintf(stderr, "Out of memory");
+        return NULL;
+    }
+
+    for( i = 1;  i <= count;  i++ )
+    {
+        if( _glfwWin.has_WGL_ARB_pixel_format )
+        {
+            // Get pixel format attributes through WGL_ARB_pixel_format
+
+            if( !getPixelFormatAttrib( i, WGL_SUPPORT_OPENGL_ARB ) ||
+                !getPixelFormatAttrib( i, WGL_DRAW_TO_WINDOW_ARB ) ||
+                !getPixelFormatAttrib( i, WGL_DOUBLE_BUFFER_ARB ) )
+            {
+                // Only consider doublebuffered OpenGL pixel formats for windows
+                continue;
+            }
+
+            if( getPixelFormatAttrib( i, WGL_PIXEL_TYPE_ARB ) != WGL_TYPE_RGBA_ARB )
+            {
+                // Only consider RGBA pixel formats
+                continue;
+            }
+
+            result[*found].redBits = getPixelFormatAttrib( i, WGL_RED_BITS_ARB );
+            result[*found].greenBits = getPixelFormatAttrib( i, WGL_GREEN_BITS_ARB );
+            result[*found].blueBits = getPixelFormatAttrib( i, WGL_BLUE_BITS_ARB );
+            result[*found].alphaBits = getPixelFormatAttrib( i, WGL_ALPHA_BITS_ARB );
+
+            result[*found].depthBits = getPixelFormatAttrib( i, WGL_DEPTH_BITS_ARB );
+            result[*found].stencilBits = getPixelFormatAttrib( i, WGL_STENCIL_BITS_ARB );
+
+            result[*found].accumRedBits = getPixelFormatAttrib( i, WGL_ACCUM_RED_BITS_ARB );
+            result[*found].accumGreenBits = getPixelFormatAttrib( i, WGL_ACCUM_GREEN_BITS_ARB );
+            result[*found].accumBlueBits = getPixelFormatAttrib( i, WGL_ACCUM_BLUE_BITS_ARB );
+            result[*found].accumAlphaBits = getPixelFormatAttrib( i, WGL_ACCUM_ALPHA_BITS_ARB );
+
+            result[*found].auxBuffers = getPixelFormatAttrib( i, WGL_AUX_BUFFERS_ARB );
+            result[*found].stereo = getPixelFormatAttrib( i, WGL_STEREO_ARB );
+
+            if( _glfwWin.has_WGL_ARB_multisample )
+            {
+                result[*found].samples = getPixelFormatAttrib( i, WGL_SAMPLES_ARB );
+            }
+            else
+            {
+                result[*found].samples = 0;
+            }
+        }
+        else
+        {
+            // Get pixel format attributes through old-fashioned PFDs
+
+            if( !_glfw_DescribePixelFormat( _glfwWin.DC, i, sizeof( PIXELFORMATDESCRIPTOR ), &pfd ) )
+            {
+                continue;
+            }
+
+            if( !( pfd.dwFlags & PFD_DRAW_TO_WINDOW ) ||
+                !( pfd.dwFlags & PFD_SUPPORT_OPENGL ) ||
+                !( pfd.dwFlags & PFD_DOUBLEBUFFER ) )
+            {
+                // Only consider doublebuffered OpenGL pixel formats for windows
+                continue;
+            }
+
+            if( !( pfd.dwFlags & PFD_GENERIC_ACCELERATED ) &&
+                ( pfd.dwFlags & PFD_GENERIC_FORMAT ) )
+            {
+                continue;
+            }
+
+            if( pfd.iPixelType != PFD_TYPE_RGBA )
+            {
+                // Only RGBA pixel formats considered
+                continue;
+            }
+
+            result[*found].redBits = pfd.cRedBits;
+            result[*found].greenBits = pfd.cGreenBits;
+            result[*found].blueBits = pfd.cBlueBits;
+            result[*found].alphaBits = pfd.cAlphaBits;
+
+            result[*found].depthBits = pfd.cDepthBits;
+            result[*found].stencilBits = pfd.cStencilBits;
+
+            result[*found].accumRedBits = pfd.cAccumRedBits;
+            result[*found].accumGreenBits = pfd.cAccumGreenBits;
+            result[*found].accumBlueBits = pfd.cAccumBlueBits;
+            result[*found].accumAlphaBits = pfd.cAccumAlphaBits;
+
+            result[*found].auxBuffers = pfd.cAuxBuffers;
+            result[*found].stereo = ( pfd.dwFlags & PFD_STEREO ) ? GL_TRUE : GL_FALSE;
+
+            // PFD pixel formats do not support FSAA
+            result[*found].samples = 0;
+        }
+
+        result[*found].platformID = i;
+
+        (*found)++;
+    }
+
+    return result;
+}
+
+
+//========================================================================
+// Creates an OpenGL context on the specified device context
+//========================================================================
+
+static HGLRC createContext( HDC dc, const _GLFWwndconfig* wndconfig, int pixelFormat )
+{
+    PIXELFORMATDESCRIPTOR pfd;
+    int flags, i = 0, attribs[7];
+
+    if( !_glfw_DescribePixelFormat( dc, pixelFormat, sizeof(pfd), &pfd ) )
+    {
+        return NULL;
+    }
+
+    if( !_glfw_SetPixelFormat( dc, pixelFormat, &pfd ) )
+    {
+        return NULL;
+    }
+
+    if( _glfwWin.has_WGL_ARB_create_context )
+    {
+        // Use the newer wglCreateContextAttribsARB
+
+        if( wndconfig->glMajor != 1 || wndconfig->glMinor != 0 )
+        {
+            // Request an explicitly versioned context
+
+            attribs[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
+            attribs[i++] = wndconfig->glMajor;
+            attribs[i++] = WGL_CONTEXT_MINOR_VERSION_ARB;
+            attribs[i++] = wndconfig->glMinor;
+        }
+
+        if( wndconfig->glForward || wndconfig->glDebug )
+        {
+            flags = 0;
+
+            if( wndconfig->glForward )
+            {
+                flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+            }
+
+            if( wndconfig->glDebug )
+            {
+                flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
+            }
+
+            attribs[i++] = WGL_CONTEXT_FLAGS_ARB;
+            attribs[i++] = flags;
+        }
+
+        if( wndconfig->glProfile )
+        {
+            if( wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE )
+            {
+                flags = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+            }
+            else
+            {
+                flags = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+            }
+
+            attribs[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
+            attribs[i++] = flags;
+        }
+
+        attribs[i++] = 0;
+
+        return _glfwWin.CreateContextAttribsARB( dc, NULL, attribs );
+    }
+
+    return wglCreateContext( dc );
+}
+
+
+//========================================================================
+// Translates a Windows key to the corresponding GLFW key
+//========================================================================
+
+static int translateKey( WPARAM wParam, LPARAM lParam )
+{
+    MSG next_msg;
+    DWORD msg_time;
+    DWORD scan_code;
+
+    // Check for numeric keypad keys
+    // Note: This way we always force "NumLock = ON", which at least
+    // enables GLFW users to detect numeric keypad keys
+    int hiFlags = HIWORD( lParam );
+
+    if ( !( hiFlags & 0x100 ) )
+    {
+        switch( MapVirtualKey( hiFlags & 0xFF, 1 ) )
+        {
+            case VK_INSERT:   return GLFW_KEY_KP_0;
+            case VK_END:      return GLFW_KEY_KP_1;
+            case VK_DOWN:     return GLFW_KEY_KP_2;
+            case VK_NEXT:     return GLFW_KEY_KP_3;
+            case VK_LEFT:     return GLFW_KEY_KP_4;
+            case VK_CLEAR:    return GLFW_KEY_KP_5;
+            case VK_RIGHT:    return GLFW_KEY_KP_6;
+            case VK_HOME:     return GLFW_KEY_KP_7;
+            case VK_UP:       return GLFW_KEY_KP_8;
+            case VK_PRIOR:    return GLFW_KEY_KP_9;
+            case VK_DIVIDE:   return GLFW_KEY_KP_DIVIDE;
+            case VK_MULTIPLY: return GLFW_KEY_KP_MULTIPLY;
+            case VK_SUBTRACT: return GLFW_KEY_KP_SUBTRACT;
+            case VK_ADD:      return GLFW_KEY_KP_ADD;
+            case VK_DELETE:   return GLFW_KEY_KP_DECIMAL;
+        }
+    }
+
+    // Check which key was pressed or released
+    switch( wParam )
+    {
+        // The SHIFT keys require special handling
+        case VK_SHIFT:
+        {
+            // Compare scan code for this key with that of VK_RSHIFT in
+            // order to determine which shift key was pressed (left or
+            // right)
+            scan_code = MapVirtualKey( VK_RSHIFT, 0 );
+            if( ((lParam & 0x01ff0000) >> 16) == scan_code )
+            {
+                return GLFW_KEY_RSHIFT;
+            }
+
+            return GLFW_KEY_LSHIFT;
+        }
+
+        // The CTRL keys require special handling
+        case VK_CONTROL:
+        {
+            // Is this an extended key (i.e. right key)?
+            if( lParam & 0x01000000 )
+            {
+                return GLFW_KEY_RCTRL;
+            }
+
+            // Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only
+            // want the RALT message, so we try to see if the next message
+            // is a RALT message. In that case, this is a false LCTRL!
+            msg_time = GetMessageTime();
+            if( PeekMessage( &next_msg, NULL, 0, 0, PM_NOREMOVE ) )
+            {
+                if( next_msg.message == WM_KEYDOWN ||
+                    next_msg.message == WM_SYSKEYDOWN )
+                {
+                    if( next_msg.wParam == VK_MENU &&
+                        (next_msg.lParam & 0x01000000) &&
+                        next_msg.time == msg_time )
+                    {
+                        // Next message is a RALT down message, which
+                        // means that this is NOT a proper LCTRL message!
+                        return GLFW_KEY_UNKNOWN;
+                    }
+                }
+            }
+
+            return GLFW_KEY_LCTRL;
+        }
+
+        // The ALT keys require special handling
+        case VK_MENU:
+        {
+            // Is this an extended key (i.e. right key)?
+            if( lParam & 0x01000000 )
+            {
+                return GLFW_KEY_RALT;
+            }
+
+            return GLFW_KEY_LALT;
+        }
+
+        // The ENTER keys require special handling
+        case VK_RETURN:
+        {
+            // Is this an extended key (i.e. right key)?
+            if( lParam & 0x01000000 )
+            {
+                return GLFW_KEY_KP_ENTER;
+            }
+
+            return GLFW_KEY_ENTER;
+        }
+
+        // Special keys (non character keys)
+        case VK_ESCAPE:        return GLFW_KEY_ESC;
+        case VK_TAB:           return GLFW_KEY_TAB;
+        case VK_BACK:          return GLFW_KEY_BACKSPACE;
+        case VK_HOME:          return GLFW_KEY_HOME;
+        case VK_END:           return GLFW_KEY_END;
+        case VK_PRIOR:         return GLFW_KEY_PAGEUP;
+        case VK_NEXT:          return GLFW_KEY_PAGEDOWN;
+        case VK_INSERT:        return GLFW_KEY_INSERT;
+        case VK_DELETE:        return GLFW_KEY_DEL;
+        case VK_LEFT:          return GLFW_KEY_LEFT;
+        case VK_UP:            return GLFW_KEY_UP;
+        case VK_RIGHT:         return GLFW_KEY_RIGHT;
+        case VK_DOWN:          return GLFW_KEY_DOWN;
+        case VK_F1:            return GLFW_KEY_F1;
+        case VK_F2:            return GLFW_KEY_F2;
+        case VK_F3:            return GLFW_KEY_F3;
+        case VK_F4:            return GLFW_KEY_F4;
+        case VK_F5:            return GLFW_KEY_F5;
+        case VK_F6:            return GLFW_KEY_F6;
+        case VK_F7:            return GLFW_KEY_F7;
+        case VK_F8:            return GLFW_KEY_F8;
+        case VK_F9:            return GLFW_KEY_F9;
+        case VK_F10:           return GLFW_KEY_F10;
+        case VK_F11:           return GLFW_KEY_F11;
+        case VK_F12:           return GLFW_KEY_F12;
+        case VK_F13:           return GLFW_KEY_F13;
+        case VK_F14:           return GLFW_KEY_F14;
+        case VK_F15:           return GLFW_KEY_F15;
+        case VK_F16:           return GLFW_KEY_F16;
+        case VK_F17:           return GLFW_KEY_F17;
+        case VK_F18:           return GLFW_KEY_F18;
+        case VK_F19:           return GLFW_KEY_F19;
+        case VK_F20:           return GLFW_KEY_F20;
+        case VK_F21:           return GLFW_KEY_F21;
+        case VK_F22:           return GLFW_KEY_F22;
+        case VK_F23:           return GLFW_KEY_F23;
+        case VK_F24:           return GLFW_KEY_F24;
+        case VK_SPACE:         return GLFW_KEY_SPACE;
+
+        // Numeric keypad
+        case VK_NUMPAD0:       return GLFW_KEY_KP_0;
+        case VK_NUMPAD1:       return GLFW_KEY_KP_1;
+        case VK_NUMPAD2:       return GLFW_KEY_KP_2;
+        case VK_NUMPAD3:       return GLFW_KEY_KP_3;
+        case VK_NUMPAD4:       return GLFW_KEY_KP_4;
+        case VK_NUMPAD5:       return GLFW_KEY_KP_5;
+        case VK_NUMPAD6:       return GLFW_KEY_KP_6;
+        case VK_NUMPAD7:       return GLFW_KEY_KP_7;
+        case VK_NUMPAD8:       return GLFW_KEY_KP_8;
+        case VK_NUMPAD9:       return GLFW_KEY_KP_9;
+        case VK_DIVIDE:        return GLFW_KEY_KP_DIVIDE;
+        case VK_MULTIPLY:      return GLFW_KEY_KP_MULTIPLY;
+        case VK_SUBTRACT:      return GLFW_KEY_KP_SUBTRACT;
+        case VK_ADD:           return GLFW_KEY_KP_ADD;
+        case VK_DECIMAL:       return GLFW_KEY_KP_DECIMAL;
+        case VK_NUMLOCK:       return GLFW_KEY_KP_NUM_LOCK;
+
+        case VK_CAPITAL:       return GLFW_KEY_CAPS_LOCK;
+        case VK_SCROLL:        return GLFW_KEY_SCROLL_LOCK;
+        case VK_PAUSE:         return GLFW_KEY_PAUSE;
+
+        case VK_LWIN:          return GLFW_KEY_LSUPER;
+        case VK_RWIN:          return GLFW_KEY_RSUPER;
+        case VK_APPS:          return GLFW_KEY_MENU;
+
+        // The rest (should be printable keys)
+        default:
+        {
+            // Convert to printable character (ISO-8859-1 or Unicode)
+            wParam = MapVirtualKey( (UINT) wParam, 2 ) & 0x0000FFFF;
+
+            // Make sure that the character is uppercase
+            if( _glfwLibrary.Sys.hasUnicode )
+            {
+                wParam = (WPARAM) CharUpperW( (LPWSTR) wParam );
+            }
+            else
+            {
+                wParam = (WPARAM) CharUpperA( (LPSTR) wParam );
+            }
+
+            // Valid ISO-8859-1 character?
+            if( (wParam >=  32 && wParam <= 126) ||
+                (wParam >= 160 && wParam <= 255) )
+            {
+                return (int) wParam;
+            }
+
+            return GLFW_KEY_UNKNOWN;
+        }
+    }
+}
+
+
+//========================================================================
+// Translates a Windows key to Unicode
+//========================================================================
+
+static void translateChar( DWORD wParam, DWORD lParam, int action )
+{
+    BYTE  keyboard_state[ 256 ];
+    UCHAR char_buf[ 10 ];
+    WCHAR unicode_buf[ 10 ];
+    UINT  scan_code;
+    int   i, num_chars, unicode;
+
+    GetKeyboardState( keyboard_state );
+
+    // Derive scan code from lParam and action
+    scan_code = (lParam & 0x01ff0000) >> 16;
+    if( action == GLFW_RELEASE )
+    {
+        scan_code |= 0x8000000;
+    }
+
+    if( _glfwLibrary.Sys.hasUnicode )
+    {
+        num_chars = ToUnicode(
+            wParam,          // virtual-key code
+            scan_code,       // scan code
+            keyboard_state,  // key-state array
+            unicode_buf,     // buffer for translated key
+            10,              // size of translated key buffer
+            0                // active-menu flag
+        );
+        unicode = 1;
+    }
+    else
+    {
+        // Convert to ISO-8859-1
+        num_chars = ToAscii(
+            wParam,            // virtual-key code
+            scan_code,         // scan code
+            keyboard_state,    // key-state array
+            (LPWORD) char_buf, // buffer for translated key
+            0                  // active-menu flag
+        );
+        unicode = 0;
+    }
+
+    // Report characters
+    for( i = 0;  i < num_chars;  i++ )
+    {
+        // Get next character from buffer
+        if( unicode )
+        {
+            _glfwInputChar( (int) unicode_buf[ i ], action );
+        }
+        else
+        {
+            _glfwInputChar( (int) char_buf[ i ], action );
+        }
+    }
+}
+
+
+//========================================================================
+// Window callback function (handles window events)
+//========================================================================
+
+static LRESULT CALLBACK windowProc( HWND hWnd, UINT uMsg,
+                                    WPARAM wParam, LPARAM lParam )
+{
+    int wheelDelta, iconified;
+
+    switch( uMsg )
+    {
+        // Window activate message? (iconification?)
+        case WM_ACTIVATE:
+        {
+            _glfwWin.active = LOWORD(wParam) != WA_INACTIVE ? GL_TRUE : GL_FALSE;
+
+            iconified = HIWORD(wParam) ? GL_TRUE : GL_FALSE;
+
+            // Were we deactivated/iconified?
+            if( (!_glfwWin.active || iconified) && !_glfwWin.iconified )
+            {
+                _glfwInputDeactivation();
+
+                // If we are in fullscreen mode we need to iconify
+                if( _glfwWin.opened && _glfwWin.fullscreen )
+                {
+                    // Do we need to manually iconify?
+                    if( !iconified )
+                    {
+                        // Minimize window
+                        CloseWindow( _glfwWin.window );
+                        iconified = GL_TRUE;
+                    }
+
+                    // Restore the original desktop resolution
+                    ChangeDisplaySettings( NULL, CDS_FULLSCREEN );
+                }
+
+                // Unlock mouse if locked
+                if( !_glfwWin.oldMouseLockValid )
+                {
+                    _glfwWin.oldMouseLock = _glfwWin.mouseLock;
+                    _glfwWin.oldMouseLockValid = GL_TRUE;
+                    glfwEnable( GLFW_MOUSE_CURSOR );
+                }
+            }
+            else if( _glfwWin.active || !iconified )
+            {
+                // If we are in fullscreen mode we need to maximize
+                if( _glfwWin.opened && _glfwWin.fullscreen && _glfwWin.iconified )
+                {
+                    // Change display settings to the user selected mode
+                    _glfwSetVideoModeMODE( _glfwWin.modeID );
+
+                    // Do we need to manually restore window?
+                    if( iconified )
+                    {
+                        // Restore window
+                        OpenIcon( _glfwWin.window );
+                        iconified = GL_FALSE;
+
+                        // Activate window
+                        ShowWindow( hWnd, SW_SHOW );
+                        setForegroundWindow( _glfwWin.window );
+                        SetFocus( _glfwWin.window );
+                    }
+                }
+            }
+
+            _glfwWin.iconified = iconified;
+            return 0;
+        }
+
+        case WM_SYSCOMMAND:
+        {
+            switch( wParam & 0xfff0 )
+            {
+                case SC_SCREENSAVE:
+                case SC_MONITORPOWER:
+                {
+                    if( _glfwWin.fullscreen )
+                    {
+                        // Disallow screen saver and screen blanking if we are
+                        // running in fullscreen mode
+                        return 0;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+
+                // User trying to access application menu using ALT?
+                case SC_KEYMENU:
+                    return 0;
+            }
+            break;
+        }
+
+        case WM_CLOSE:
+        {
+            // Translate this to WM_QUIT so that we can handle all cases in the
+            // same place
+            PostQuitMessage( 0 );
+            return 0;
+        }
+
+        case WM_KEYDOWN:
+        case WM_SYSKEYDOWN:
+        {
+            _glfwInputKey( translateKey( wParam, lParam ), GLFW_PRESS );
+
+            if( _glfwWin.charCallback )
+            {
+                translateChar( (DWORD) wParam, (DWORD) lParam, GLFW_PRESS );
+            }
+            return 0;
+          }
+
+        case WM_KEYUP:
+        case WM_SYSKEYUP:
+        {
+            // Special trick: release both shift keys on SHIFT up event
+            if( wParam == VK_SHIFT )
+            {
+                _glfwInputKey( GLFW_KEY_LSHIFT, GLFW_RELEASE );
+                _glfwInputKey( GLFW_KEY_RSHIFT, GLFW_RELEASE );
+            }
+            else
+            {
+                _glfwInputKey( translateKey( wParam, lParam ), GLFW_RELEASE );
+            }
+
+            if( _glfwWin.charCallback )
+            {
+                translateChar( (DWORD) wParam, (DWORD) lParam, GLFW_RELEASE );
+            }
+
+            return 0;
+        }
+
+        case WM_LBUTTONDOWN:
+            SetCapture(hWnd);
+            _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS );
+            return 0;
+        case WM_RBUTTONDOWN:
+            SetCapture(hWnd);
+            _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS );
+            return 0;
+        case WM_MBUTTONDOWN:
+            SetCapture(hWnd);
+            _glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS );
+            return 0;
+        case WM_XBUTTONDOWN:
+        {
+            if( HIWORD(wParam) == XBUTTON1 )
+            {
+                SetCapture(hWnd);
+                _glfwInputMouseClick( GLFW_MOUSE_BUTTON_4, GLFW_PRESS );
+            }
+            else if( HIWORD(wParam) == XBUTTON2 )
+            {
+                SetCapture(hWnd);
+                _glfwInputMouseClick( GLFW_MOUSE_BUTTON_5, GLFW_PRESS );
+            }
+            return 1;
+        }
+
+        case WM_LBUTTONUP:
+            ReleaseCapture();
+            _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE );
+            return 0;
+        case WM_RBUTTONUP:
+            ReleaseCapture();
+            _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE );
+            return 0;
+        case WM_MBUTTONUP:
+            ReleaseCapture();
+            _glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE );
+            return 0;
+        case WM_XBUTTONUP:
+        {
+            if( HIWORD(wParam) == XBUTTON1 )
+            {
+                ReleaseCapture();
+                _glfwInputMouseClick( GLFW_MOUSE_BUTTON_4, GLFW_RELEASE );
+            }
+            else if( HIWORD(wParam) == XBUTTON2 )
+            {
+                ReleaseCapture();
+                _glfwInputMouseClick( GLFW_MOUSE_BUTTON_5, GLFW_RELEASE );
+            }
+            return 1;
+        }
+
+        case WM_MOUSEMOVE:
+        {
+            int NewMouseX, NewMouseY;
+
+            // Get signed (!) mouse position
+            NewMouseX = (int)((short)LOWORD(lParam));
+            NewMouseY = (int)((short)HIWORD(lParam));
+
+            if( NewMouseX != _glfwInput.OldMouseX ||
+                NewMouseY != _glfwInput.OldMouseY )
+            {
+                if( _glfwWin.mouseLock )
+                {
+                    _glfwInput.MousePosX += NewMouseX -
+                                            _glfwInput.OldMouseX;
+                    _glfwInput.MousePosY += NewMouseY -
+                                            _glfwInput.OldMouseY;
+                }
+                else
+                {
+                    _glfwInput.MousePosX = NewMouseX;
+                    _glfwInput.MousePosY = NewMouseY;
+                }
+                _glfwInput.OldMouseX = NewMouseX;
+                _glfwInput.OldMouseY = NewMouseY;
+                _glfwInput.MouseMoved = GL_TRUE;
+
+                if( _glfwWin.mousePosCallback )
+                {
+                    _glfwWin.mousePosCallback( _glfwInput.MousePosX,
+                                               _glfwInput.MousePosY );
+                }
+            }
+            return 0;
+        }
+
+        case WM_MOUSEWHEEL:
+        {
+            // WM_MOUSEWHEEL is not supported under Windows 95
+            if( _glfwLibrary.Sys.winVer != _GLFW_WIN_95 )
+            {
+                wheelDelta = (((int)wParam) >> 16) / WHEEL_DELTA;
+                _glfwInput.WheelPos += wheelDelta;
+                if( _glfwWin.mouseWheelCallback )
+                {
+                    _glfwWin.mouseWheelCallback( _glfwInput.WheelPos );
+                }
+                return 0;
+            }
+            break;
+        }
+
+        case WM_SIZE:
+        {
+            _glfwWin.width  = LOWORD(lParam);
+            _glfwWin.height = HIWORD(lParam);
+
+            // If the mouse is locked, update the clipping rect
+            if( _glfwWin.mouseLock )
+            {
+                RECT ClipWindowRect;
+                if( GetWindowRect( _glfwWin.window, &ClipWindowRect ) )
+                {
+                    ClipCursor( &ClipWindowRect );
+                }
+            }
+
+            if( _glfwWin.windowSizeCallback )
+            {
+                _glfwWin.windowSizeCallback( LOWORD(lParam), HIWORD(lParam) );
+            }
+            return 0;
+        }
+
+        case WM_MOVE:
+        {
+            // If the mouse is locked, update the clipping rect
+            if( _glfwWin.mouseLock )
+            {
+                RECT ClipWindowRect;
+                if( GetWindowRect( _glfwWin.window, &ClipWindowRect ) )
+                {
+                    ClipCursor( &ClipWindowRect );
+                }
+            }
+            return 0;
+        }
+
+        // Was the window contents damaged?
+        case WM_PAINT:
+        {
+            if( _glfwWin.windowRefreshCallback )
+            {
+                _glfwWin.windowRefreshCallback();
+            }
+            break;
+        }
+
+        case WM_DISPLAYCHANGE:
+        {
+            // TODO: Do stuff here.
+
+            break;
+        }
+    }
+    
+    // Pass all unhandled messages to DefWindowProc
+    return DefWindowProc( hWnd, uMsg, wParam, lParam );
+}
+
+
+//========================================================================
+// Translate client window size to full window size (including window borders)
+//========================================================================
+
+static void getFullWindowSize( int clientWidth, int clientHeight,
+                               int *fullWidth, int *fullHeight )
+{
+    RECT rect;
+
+    // Create a window rectangle
+    rect.left   = (long)0;
+    rect.right  = (long)clientWidth - 1;
+    rect.top    = (long)0;
+    rect.bottom = (long)clientHeight - 1;
+
+    // Adjust according to window styles
+    AdjustWindowRectEx( &rect, _glfwWin.dwStyle, FALSE, _glfwWin.dwExStyle );
+
+    // Calculate width and height of full window
+    *fullWidth = rect.right - rect.left + 1;
+    *fullHeight = rect.bottom - rect.top + 1;
+}
+
+
+//========================================================================
+// Initialize WGL-specific extensions
+// This function is called once before initial context creation, i.e. before
+// any WGL extensions could be present.  This is done in order to have both
+// extension variable clearing and loading in the same place, hopefully
+// decreasing the possibility of forgetting to add one without the other.
+//========================================================================
+
+static void initWGLExtensions( void )
+{
+    // This needs to include every function pointer loaded below
+    _glfwWin.SwapIntervalEXT = NULL;
+    _glfwWin.GetPixelFormatAttribivARB = NULL;
+    _glfwWin.GetExtensionsStringARB = NULL;
+    _glfwWin.GetExtensionsStringEXT = NULL;
+    _glfwWin.CreateContextAttribsARB = NULL;
+
+    // This needs to include every extension used below except for
+    // WGL_ARB_extensions_string and WGL_EXT_extensions_string
+    _glfwWin.has_WGL_EXT_swap_control = GL_FALSE;
+    _glfwWin.has_WGL_ARB_pixel_format = GL_FALSE;
+    _glfwWin.has_WGL_ARB_multisample = GL_FALSE;
+    _glfwWin.has_WGL_ARB_create_context = GL_FALSE;
+
+    _glfwWin.GetExtensionsStringEXT = (WGLGETEXTENSIONSSTRINGEXT_T)
+        wglGetProcAddress( "wglGetExtensionsStringEXT" );
+    if( !_glfwWin.GetExtensionsStringEXT )
+    {
+        _glfwWin.GetExtensionsStringARB = (WGLGETEXTENSIONSSTRINGARB_T)
+            wglGetProcAddress( "wglGetExtensionsStringARB" );
+        if( !_glfwWin.GetExtensionsStringARB )
+        {
+            return;
+        }
+    }
+
+    if( _glfwPlatformExtensionSupported( "WGL_ARB_multisample" ) )
+    {
+        _glfwWin.has_WGL_ARB_multisample = GL_TRUE;
+    }
+
+    if( _glfwPlatformExtensionSupported( "WGL_ARB_create_context" ) )
+    {
+        _glfwWin.has_WGL_ARB_create_context = GL_TRUE;
+        _glfwWin.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
+            wglGetProcAddress( "wglCreateContextAttribsARB" );
+    }
+
+    if( _glfwPlatformExtensionSupported( "WGL_EXT_swap_control" ) )
+    {
+        _glfwWin.has_WGL_EXT_swap_control = GL_TRUE;
+        _glfwWin.SwapIntervalEXT = (WGLSWAPINTERVALEXT_T)
+            wglGetProcAddress( "wglSwapIntervalEXT" );
+    }
+
+    if( _glfwPlatformExtensionSupported( "WGL_ARB_pixel_format" ) )
+    {
+        _glfwWin.has_WGL_ARB_pixel_format = GL_TRUE;
+        _glfwWin.GetPixelFormatAttribivARB = (WGLGETPIXELFORMATATTRIBIVARB_T)
+            wglGetProcAddress( "wglGetPixelFormatAttribivARB" );
+    }
+}
+
+
+//========================================================================
+// Registers the GLFW window class
+//========================================================================
+
+static ATOM registerWindowClass( void )
+{
+    WNDCLASS wc;
+
+    // Set window class parameters
+    wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw on...
+    wc.lpfnWndProc   = (WNDPROC)windowProc;           // Message handler
+    wc.cbClsExtra    = 0;                             // No extra class data
+    wc.cbWndExtra    = 0;                             // No extra window data
+    wc.hInstance     = _glfwLibrary.instance;         // Set instance
+    wc.hCursor       = LoadCursor( NULL, IDC_ARROW ); // Load arrow pointer
+    wc.hbrBackground = NULL;                          // No background
+    wc.lpszMenuName  = NULL;                          // No menu
+    wc.lpszClassName = _GLFW_WNDCLASSNAME;            // Set class name
+
+    // Load user-provided icon if available
+    wc.hIcon = LoadIcon( _glfwLibrary.instance, "GLFW_ICON" );
+    if( !wc.hIcon )
+    {
+        // Load default icon
+        wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );
+    }
+
+    return RegisterClass( &wc );
+}
+
+
+//========================================================================
+// Returns the closest matching pixel format, or zero on error
+//========================================================================
+
+static int choosePixelFormat( const _GLFWfbconfig *fbconfig )
+{
+    unsigned int fbcount;
+    int pixelFormat;
+    _GLFWfbconfig *fbconfigs;
+    const _GLFWfbconfig *closest;
+
+    fbconfigs = getFBConfigs( &fbcount );
+    if( !fbconfigs )
+    {
+        fprintf( stderr, "Failed to find any usable GLFWFBConfigs\n" );
+        return 0;
+    }
+
+    closest = _glfwChooseFBConfig( fbconfig, fbconfigs, fbcount );
+    if( !closest )
+    {
+        fprintf( stderr, "Failed to select a GLFWFBConfig from the alternatives\n" );
+        free( fbconfigs );
+        return 0;
+    }
+
+    pixelFormat = (int) closest->platformID;
+
+    free( fbconfigs );
+    fbconfigs = NULL;
+    closest = NULL;
+
+    return pixelFormat;
+}
+
+
+//========================================================================
+// Creates the GLFW window and rendering context
+//========================================================================
+
+static int createWindow( const _GLFWwndconfig *wndconfig,
+                         const _GLFWfbconfig *fbconfig )
+{
+    DWORD dwStyle, dwExStyle;
+    int pixelFormat, fullWidth, fullHeight;
+    RECT wa;
+    POINT pos;
+
+    _glfwWin.DC  = NULL;
+    _glfwWin.context = NULL;
+    _glfwWin.window = NULL;
+
+    // Set common window styles
+    dwStyle   = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
+    dwExStyle = WS_EX_APPWINDOW;
+
+    // Set window style, depending on fullscreen mode
+    if( _glfwWin.fullscreen )
+    {
+        dwStyle |= WS_POPUP;
+
+        // Here's a trick for helping us getting window focus
+        // (SetForegroundWindow doesn't work properly under
+        // Win98/ME/2K/.NET/+)
+        /*
+        if( _glfwLibrary.Sys.WinVer != _GLFW_WIN_95 &&
+            _glfwLibrary.Sys.WinVer != _GLFW_WIN_NT4 &&
+            _glfwLibrary.Sys.WinVer != _GLFW_WIN_XP )
+        {
+            dwStyle |= WS_MINIMIZE;
+        }
+        */
+    }
+    else
+    {
+        dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
+
+        if( !wndconfig->windowNoResize )
+        {
+            dwStyle |= ( WS_MAXIMIZEBOX | WS_SIZEBOX );
+            dwExStyle |= WS_EX_WINDOWEDGE;
+        }
+    }
+
+    // Remember window styles (used by getFullWindowSize)
+    _glfwWin.dwStyle   = dwStyle;
+    _glfwWin.dwExStyle = dwExStyle;
+
+    // Adjust window size for frame and title bar
+    getFullWindowSize( _glfwWin.width, _glfwWin.height, &fullWidth, &fullHeight );
+
+    // Adjust window position to working area (e.g. if the task bar is at
+    // the top of the display). Fullscreen windows are always opened in
+    // the upper left corner regardless of the desktop working area.
+    if( _glfwWin.fullscreen )
+    {
+        wa.left = wa.top = 0;
+    }
+    else
+    {
+        SystemParametersInfo( SPI_GETWORKAREA, 0, &wa, 0 );
+    }
+
+    _glfwWin.window = CreateWindowEx( _glfwWin.dwExStyle,    // Extended style
+                                      _GLFW_WNDCLASSNAME,    // Class name
+                                      "GLFW Window",         // Window title
+                                      _glfwWin.dwStyle,      // Defined window style
+                                      wa.left, wa.top,       // Window position
+                                      fullWidth,             // Decorated window width
+                                      fullHeight,            // Decorated window height
+                                      NULL,                  // No parent window
+                                      NULL,                  // No menu
+                                      _glfwLibrary.instance, // Instance
+                                      NULL );                // Nothing to WM_CREATE
+
+    if( !_glfwWin.window )
+    {
+        fprintf( stderr, "Unable to create Win32 window\n" );
+        return GL_FALSE;
+    }
+
+    _glfwWin.DC = GetDC( _glfwWin.window );
+    if( !_glfwWin.DC )
+    {
+        fprintf( stderr, "Unable to retrieve GLFW window DC\n" );
+        return GL_FALSE;
+    }
+
+    pixelFormat = choosePixelFormat( fbconfig );
+    if( !pixelFormat )
+    {
+        fprintf( stderr, "Unable to find a usable pixel format\n" );
+        return GL_FALSE;
+    }
+
+    _glfwWin.context = createContext( _glfwWin.DC, wndconfig, pixelFormat );
+    if( !_glfwWin.context )
+    {
+        fprintf( stderr, "Unable to create OpenGL context\n" );
+        return GL_FALSE;
+    }
+
+    if( !wglMakeCurrent( _glfwWin.DC, _glfwWin.context ) )
+    {
+        fprintf( stderr, "Unable to make OpenGL context current\n" );
+        return GL_FALSE;
+    }
+
+    initWGLExtensions();
+
+    // Initialize mouse position data
+    GetCursorPos( &pos );
+    ScreenToClient( _glfwWin.window, &pos );
+    _glfwInput.OldMouseX = _glfwInput.MousePosX = pos.x;
+    _glfwInput.OldMouseY = _glfwInput.MousePosY = pos.y;
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Destroys the GLFW window and rendering context
+//========================================================================
+
+static void destroyWindow( void )
+{
+    if( _glfwWin.context )
+    {
+        wglMakeCurrent( NULL, NULL );
+        wglDeleteContext( _glfwWin.context );
+        _glfwWin.context = NULL;
+    }
+
+    if( _glfwWin.DC )
+    {
+        ReleaseDC( _glfwWin.window, _glfwWin.DC );
+        _glfwWin.DC = NULL;
+    }
+
+    if( _glfwWin.window )
+    {
+        if( _glfwLibrary.Sys.winVer <= _GLFW_WIN_NT4 )
+        {
+            // Note: Hiding the window first fixes an annoying W98/NT4
+            // remaining icon bug for fullscreen displays
+            ShowWindow( _glfwWin.window, SW_HIDE );
+        }
+
+        DestroyWindow( _glfwWin.window );
+        _glfwWin.window = NULL;
+    }
+}
+
+
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// Here is where the window is created, and the OpenGL rendering context is
+// created
+//========================================================================
+
+int _glfwPlatformOpenWindow( int width, int height,
+                             const _GLFWwndconfig *wndconfig,
+                             const _GLFWfbconfig *fbconfig )
+{
+    GLboolean recreateContext = GL_FALSE;
+
+    // Clear platform specific GLFW window state
+    _glfwWin.classAtom         = 0;
+    _glfwWin.oldMouseLockValid = GL_FALSE;
+
+    _glfwWin.desiredRefreshRate = wndconfig->refreshRate;
+
+    _glfwWin.classAtom = registerWindowClass();
+    if( !_glfwWin.classAtom )
+    {
+        fprintf( stderr, "Failed to register GLFW window class\n" );
+        _glfwPlatformCloseWindow();
+        return GL_FALSE;
+    }
+
+    if( _glfwWin.fullscreen )
+    {
+        _glfwSetVideoMode( &_glfwWin.width, &_glfwWin.height,
+                           fbconfig->redBits, fbconfig->greenBits, fbconfig->blueBits,
+                           wndconfig->refreshRate );
+    }
+
+    initWGLExtensions();
+
+    if( !createWindow( wndconfig, fbconfig ) )
+    {
+        fprintf( stderr, "Failed to create GLFW window\n" );
+        _glfwPlatformCloseWindow();
+        return GL_FALSE;
+    }
+
+    if( wndconfig->glMajor > 2 )
+    {
+        if( !_glfwWin.has_WGL_ARB_create_context )
+        {
+            fprintf( stderr, "OpenGL 3.0+ is not supported\n" );
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        recreateContext = GL_TRUE;
+    }
+
+    if( fbconfig->samples > 0 )
+    {
+        // We want FSAA, but can we get it?
+        // FSAA is not a hard constraint, so otherwise we just don't care
+
+        if( _glfwWin.has_WGL_ARB_multisample && _glfwWin.has_WGL_ARB_pixel_format )
+        {
+            // We appear to have both the FSAA extension and the means to ask for it
+            recreateContext = GL_TRUE;
+        }
+    }
+
+    if( recreateContext )
+    {
+        // Some window hints require us to re-create the context using WGL
+        // extensions retrieved through the current context, as we cannot check
+        // for WGL extensions or retrieve WGL entry points before we have a
+        // current context (actually until we have implicitly loaded the ICD)
+
+        // Yes, this is strange, and yes, this is the proper way on Win32
+
+        // As Windows only allows you to set the pixel format once for a
+        // window, we need to destroy the current window and create a new one
+        // to be able to use the new pixel format
+
+        // Technically, it may be possible to keep the old window around if
+        // we're just creating an OpenGL 3.0+ context with the same pixel
+        // format, but it's not worth the potential compatibility problems
+
+        destroyWindow();
+
+        if( !createWindow( wndconfig, fbconfig ) )
+        {
+            fprintf( stderr, "Unable to re-create GLFW window\n" );
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+    }
+
+    if( _glfwWin.fullscreen )
+    {
+        // Place the window above all topmost windows
+        SetWindowPos( _glfwWin.window, HWND_TOPMOST, 0,0,0,0,
+                      SWP_NOMOVE | SWP_NOSIZE );
+    }
+
+    setForegroundWindow( _glfwWin.window );
+    SetFocus( _glfwWin.window );
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Properly kill the window / video display
+//========================================================================
+
+void _glfwPlatformCloseWindow( void )
+{
+    destroyWindow();
+
+    if( _glfwWin.classAtom )
+    {
+        UnregisterClass( _GLFW_WNDCLASSNAME, _glfwLibrary.instance );
+        _glfwWin.classAtom = 0;
+    }
+
+    if( _glfwWin.fullscreen )
+    {
+        // Restore original desktop resolution
+        ChangeDisplaySettings( NULL, CDS_FULLSCREEN );
+    }
+}
+
+
+//========================================================================
+// Set the window title
+//========================================================================
+
+void _glfwPlatformSetWindowTitle( const char *title )
+{
+    (void) SetWindowText( _glfwWin.window, title );
+}
+
+
+//========================================================================
+// Set the window size.
+//========================================================================
+
+void _glfwPlatformSetWindowSize( int width, int height )
+{
+    int     bpp, mode = 0, refresh;
+    int     sizechanged = GL_FALSE;
+    GLint   drawbuffer;
+    GLfloat clearcolor[4];
+
+    if( _glfwWin.fullscreen )
+    {
+        // Get some info about the current mode
+
+        DEVMODE dm;
+
+        // Get current BPP settings
+        dm.dmSize = sizeof( DEVMODE );
+        if( EnumDisplaySettings( NULL, _glfwWin.modeID, &dm ) )
+        {
+            // Get bpp
+            bpp = dm.dmBitsPerPel;
+
+            // Get closest match for target video mode
+            refresh = _glfwWin.desiredRefreshRate;
+            mode = _glfwGetClosestVideoModeBPP( &width, &height, &bpp,
+                                                &refresh );
+        }
+        else
+        {
+            mode = _glfwWin.modeID;
+        }
+    }
+    else
+    {
+        // If we are in windowed mode, adjust the window size to
+        // compensate for window decorations
+        getFullWindowSize( width, height, &width, &height );
+    }
+
+    // Change window size before changing fullscreen mode?
+    if( _glfwWin.fullscreen && (width > _glfwWin.width) )
+    {
+        SetWindowPos( _glfwWin.window, HWND_TOP, 0, 0, width, height,
+                      SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER );
+        sizechanged = GL_TRUE;
+    }
+
+    // Change fullscreen video mode?
+    if( _glfwWin.fullscreen && mode != _glfwWin.modeID )
+    {
+        _glfwSetVideoModeMODE( mode );
+
+        // 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 )
+        {
+            _glfw_SwapBuffers( _glfwWin.DC );
+        }
+        glClearColor( clearcolor[0], clearcolor[1], clearcolor[2],
+                      clearcolor[3] );
+    }
+
+    // Set window size (if not already changed)
+    if( !sizechanged )
+    {
+        SetWindowPos( _glfwWin.window, HWND_TOP, 0, 0, width, height,
+                      SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER );
+    }
+}
+
+
+//========================================================================
+// Set the window position
+//========================================================================
+
+void _glfwPlatformSetWindowPos( int x, int y )
+{
+    (void) SetWindowPos( _glfwWin.window, HWND_TOP, x, y, 0, 0,
+                         SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER );
+}
+
+
+//========================================================================
+// Window iconification
+//========================================================================
+
+void _glfwPlatformIconifyWindow( void )
+{
+    // Iconify window
+    CloseWindow( _glfwWin.window );
+    _glfwWin.iconified = GL_TRUE;
+
+    // If we are in fullscreen mode we need to change video modes
+    if( _glfwWin.fullscreen )
+    {
+        // Change display settings to the desktop resolution
+        ChangeDisplaySettings( NULL, CDS_FULLSCREEN );
+    }
+
+    // Unlock mouse
+    if( !_glfwWin.oldMouseLockValid )
+    {
+        _glfwWin.oldMouseLock = _glfwWin.mouseLock;
+        _glfwWin.oldMouseLockValid = GL_TRUE;
+        glfwEnable( GLFW_MOUSE_CURSOR );
+    }
+}
+
+
+//========================================================================
+// Window un-iconification
+//========================================================================
+
+void _glfwPlatformRestoreWindow( void )
+{
+    // If we are in fullscreen mode we need to change video modes
+    if( _glfwWin.fullscreen )
+    {
+        // Change display settings to the user selected mode
+        _glfwSetVideoModeMODE( _glfwWin.modeID );
+    }
+
+    // Un-iconify window
+    OpenIcon( _glfwWin.window );
+
+    // Make sure that our window ends up on top of things
+    ShowWindow( _glfwWin.window, SW_SHOW );
+    setForegroundWindow( _glfwWin.window );
+    SetFocus( _glfwWin.window );
+
+    // Window is no longer iconified
+    _glfwWin.iconified = GL_FALSE;
+
+    // Lock mouse, if necessary
+    if( _glfwWin.oldMouseLockValid && _glfwWin.oldMouseLock )
+    {
+        glfwDisable( GLFW_MOUSE_CURSOR );
+    }
+    _glfwWin.oldMouseLockValid = GL_FALSE;
+}
+
+
+//========================================================================
+// Swap buffers (double-buffering)
+//========================================================================
+
+void _glfwPlatformSwapBuffers( void )
+{
+    _glfw_SwapBuffers( _glfwWin.DC );
+}
+
+
+//========================================================================
+// Set double buffering swap interval
+//========================================================================
+
+void _glfwPlatformSwapInterval( int interval )
+{
+    if( _glfwWin.has_WGL_EXT_swap_control )
+    {
+        _glfwWin.SwapIntervalEXT( interval );
+    }
+}
+
+
+//========================================================================
+// Write back window parameters into GLFW window structure
+//========================================================================
+
+void _glfwPlatformRefreshWindowParams( void )
+{
+    PIXELFORMATDESCRIPTOR pfd;
+    DEVMODE dm;
+    int pixelFormat, mode;
+
+    // Obtain a detailed description of current pixel format
+    pixelFormat = _glfw_GetPixelFormat( _glfwWin.DC );
+
+    if( _glfwWin.has_WGL_ARB_pixel_format )
+    {
+        if( getPixelFormatAttrib( pixelFormat, WGL_ACCELERATION_ARB ) !=
+            WGL_NO_ACCELERATION_ARB )
+        {
+            _glfwWin.accelerated = GL_TRUE;
+        }
+        else
+        {
+            _glfwWin.accelerated = GL_FALSE;
+        }
+
+        _glfwWin.redBits = getPixelFormatAttrib( pixelFormat, WGL_RED_BITS_ARB );
+        _glfwWin.greenBits = getPixelFormatAttrib( pixelFormat, WGL_GREEN_BITS_ARB );
+        _glfwWin.blueBits = getPixelFormatAttrib( pixelFormat, WGL_BLUE_BITS_ARB );
+
+        _glfwWin.alphaBits = getPixelFormatAttrib( pixelFormat, WGL_ALPHA_BITS_ARB );
+        _glfwWin.depthBits = getPixelFormatAttrib( pixelFormat, WGL_DEPTH_BITS_ARB );
+        _glfwWin.stencilBits = getPixelFormatAttrib( pixelFormat, WGL_STENCIL_BITS_ARB );
+
+        _glfwWin.accumRedBits = getPixelFormatAttrib( pixelFormat, WGL_ACCUM_RED_BITS_ARB );
+        _glfwWin.accumGreenBits = getPixelFormatAttrib( pixelFormat, WGL_ACCUM_GREEN_BITS_ARB );
+        _glfwWin.accumBlueBits = getPixelFormatAttrib( pixelFormat, WGL_ACCUM_BLUE_BITS_ARB );
+        _glfwWin.accumAlphaBits = getPixelFormatAttrib( pixelFormat, WGL_ACCUM_ALPHA_BITS_ARB );
+
+        _glfwWin.auxBuffers = getPixelFormatAttrib( pixelFormat, WGL_AUX_BUFFERS_ARB );
+        _glfwWin.stereo = getPixelFormatAttrib( pixelFormat, WGL_STEREO_ARB ) ? GL_TRUE : GL_FALSE;
+
+        if( _glfwWin.has_WGL_ARB_multisample )
+        {
+            _glfwWin.samples = getPixelFormatAttrib( pixelFormat, WGL_SAMPLES_ARB );
+            // Should we force 1 to 0 here for consistency, or keep 1 for transparency?
+        }
+        else
+        {
+            _glfwWin.samples = 0;
+        }
+    }
+    else
+    {
+        _glfw_DescribePixelFormat( _glfwWin.DC, pixelFormat,
+                                   sizeof(PIXELFORMATDESCRIPTOR), &pfd );
+
+        // Is current OpenGL context accelerated?
+        _glfwWin.accelerated = (pfd.dwFlags & PFD_GENERIC_ACCELERATED) ||
+                               !(pfd.dwFlags & PFD_GENERIC_FORMAT) ? 1 : 0;
+
+        // "Standard" window parameters
+        _glfwWin.redBits        = pfd.cRedBits;
+        _glfwWin.greenBits      = pfd.cGreenBits;
+        _glfwWin.blueBits       = pfd.cBlueBits;
+        _glfwWin.alphaBits      = pfd.cAlphaBits;
+        _glfwWin.depthBits      = pfd.cDepthBits;
+        _glfwWin.stencilBits    = pfd.cStencilBits;
+        _glfwWin.accumRedBits   = pfd.cAccumRedBits;
+        _glfwWin.accumGreenBits = pfd.cAccumGreenBits;
+        _glfwWin.accumBlueBits  = pfd.cAccumBlueBits;
+        _glfwWin.accumAlphaBits = pfd.cAccumAlphaBits;
+        _glfwWin.auxBuffers     = pfd.cAuxBuffers;
+        _glfwWin.stereo         = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE;
+
+        // If we don't have WGL_ARB_pixel_format then we can't have created a
+        // multisampling context, so it's safe to hardcode zero here
+        _glfwWin.samples = 0;
+    }
+
+    // Get refresh rate
+    mode = _glfwWin.fullscreen ? _glfwWin.modeID : ENUM_CURRENT_SETTINGS;
+    dm.dmSize = sizeof( DEVMODE );
+
+    if( EnumDisplaySettings( NULL, mode, &dm ) )
+    {
+        _glfwWin.refreshRate = dm.dmDisplayFrequency;
+        if( _glfwWin.refreshRate <= 1 )
+        {
+            _glfwWin.refreshRate = 0;
+        }
+    }
+    else
+    {
+        _glfwWin.refreshRate = 0;
+    }
+}
+
+
+//========================================================================
+// Poll for new window and input events
+//========================================================================
+
+void _glfwPlatformPollEvents( void )
+{
+    MSG msg;
+    int winclosed = GL_FALSE;
+
+    // Flag: mouse was not moved (will be changed by _glfwGetNextEvent if
+    // there was a mouse move event)
+    _glfwInput.MouseMoved = GL_FALSE;
+    if( _glfwWin.mouseLock )
+    {
+        _glfwInput.OldMouseX = _glfwWin.width/2;
+        _glfwInput.OldMouseY = _glfwWin.height/2;
+    }
+    else
+    {
+        _glfwInput.OldMouseX = _glfwInput.MousePosX;
+        _glfwInput.OldMouseY = _glfwInput.MousePosY;
+    }
+
+    // Check for new window messages
+    while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
+    {
+        switch( msg.message )
+        {
+            // QUIT-message (from close window)?
+            case WM_QUIT:
+                winclosed = GL_TRUE;
+                break;
+
+            // Ok, send it to the window message handler
+            default:
+                DispatchMessage( &msg );
+                break;
+        }
+    }
+
+    // Urho3D: relock mouse if necessary after polling all the messages
+    if( _glfwWin.active && _glfwWin.oldMouseLockValid && _glfwWin.oldMouseLock )
+    {
+        glfwDisable( GLFW_MOUSE_CURSOR );
+        _glfwWin.oldMouseLockValid = GL_FALSE;
+    }
+    
+    // LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)
+    // This is the only async event handling in GLFW, but it solves some
+    // nasty problems.
+    // Caveat: Does not work under Win 9x/ME.
+    if( _glfwLibrary.Sys.winVer >= _GLFW_WIN_NT4 )
+    {
+        int lshift_down, rshift_down;
+
+        // Get current state of left and right shift keys
+        lshift_down = (GetAsyncKeyState( VK_LSHIFT ) >> 15) & 1;
+        rshift_down = (GetAsyncKeyState( VK_RSHIFT ) >> 15) & 1;
+
+        // See if this differs from our belief of what has happened
+        // (we only have to check for lost key up events)
+        if( !lshift_down && _glfwInput.Key[ GLFW_KEY_LSHIFT ] == 1 )
+        {
+            _glfwInputKey( GLFW_KEY_LSHIFT, GLFW_RELEASE );
+        }
+        if( !rshift_down && _glfwInput.Key[ GLFW_KEY_RSHIFT ] == 1 )
+        {
+            _glfwInputKey( GLFW_KEY_RSHIFT, GLFW_RELEASE );
+        }
+    }
+
+    // Did we have mouse movement in locked cursor mode?
+    if( _glfwInput.MouseMoved && _glfwWin.mouseLock )
+    {
+        _glfwPlatformSetMouseCursorPos( _glfwWin.width / 2,
+                                        _glfwWin.height / 2 );
+    }
+
+    // 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 )
+{
+    WaitMessage();
+
+    _glfwPlatformPollEvents();
+}
+
+
+//========================================================================
+// Hide mouse cursor (lock it)
+//========================================================================
+
+void _glfwPlatformHideMouseCursor( void )
+{
+    RECT ClipWindowRect;
+
+    ShowCursor( FALSE );
+
+    // Clip cursor to the window
+    if( GetWindowRect( _glfwWin.window, &ClipWindowRect ) )
+    {
+        ClipCursor( &ClipWindowRect );
+    }
+
+    // Capture cursor to user window
+    SetCapture( _glfwWin.window );
+}
+
+
+//========================================================================
+// Show mouse cursor (unlock it)
+//========================================================================
+
+void _glfwPlatformShowMouseCursor( void )
+{
+    // Un-capture cursor
+    ReleaseCapture();
+
+    // Release the cursor from the window
+    ClipCursor( NULL );
+
+    ShowCursor( TRUE );
+}
+
+
+//========================================================================
+// Set physical mouse cursor position
+//========================================================================
+
+void _glfwPlatformSetMouseCursorPos( int x, int y )
+{
+    POINT pos;
+
+    // Convert client coordinates to screen coordinates
+    pos.x = x;
+    pos.y = y;
+    ClientToScreen( _glfwWin.window, &pos );
+
+    SetCursorPos( pos.x, pos.y );
+}
+

+ 1030 - 0
ThirdParty/GLFW/lib/window.c

@@ -0,0 +1,1030 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    Any
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+#include <limits.h>
+
+
+
+//************************************************************************
+//****                  GLFW internal functions                       ****
+//************************************************************************
+
+static int Max(int a, int b)
+{
+    return (a > b) ? a : b;
+}
+
+//========================================================================
+// Clear all open window hints
+//========================================================================
+
+void _glfwClearWindowHints( void )
+{
+    memset( &_glfwLibrary.hints, 0, sizeof( _glfwLibrary.hints ) );
+    _glfwLibrary.hints.glMajor = 1;
+}
+
+
+//========================================================================
+// Handle the input tracking part of window deactivation
+//========================================================================
+
+void _glfwInputDeactivation( void )
+{
+    int i;
+
+    // Release all keyboard keys
+    for( i = 0; i <= GLFW_KEY_LAST; i ++ )
+    {
+        if( _glfwInput.Key[ i ] == GLFW_PRESS )
+        {
+            _glfwInputKey( i, GLFW_RELEASE );
+        }
+    }
+
+    // Release all mouse buttons
+    for( i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i ++ )
+    {
+        if( _glfwInput.MouseButton[ i ] == GLFW_PRESS )
+        {
+            _glfwInputMouseClick( i, GLFW_RELEASE );
+        }
+    }
+}
+
+
+//========================================================================
+// _glfwClearInput() - Clear all input state
+//========================================================================
+
+void _glfwClearInput( void )
+{
+    int i;
+
+    // Release all keyboard keys
+    for( i = 0; i <= GLFW_KEY_LAST; i ++ )
+    {
+        _glfwInput.Key[ i ] = GLFW_RELEASE;
+    }
+
+    // Clear last character
+    _glfwInput.LastChar = 0;
+
+    // Release all mouse buttons
+    for( i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i ++ )
+    {
+        _glfwInput.MouseButton[ i ] = GLFW_RELEASE;
+    }
+
+    // Set mouse position to (0,0)
+    _glfwInput.MousePosX = 0;
+    _glfwInput.MousePosY = 0;
+
+    // Set mouse wheel position to 0
+    _glfwInput.WheelPos = 0;
+
+    // The default is to use non sticky keys and mouse buttons
+    _glfwInput.StickyKeys = GL_FALSE;
+    _glfwInput.StickyMouseButtons = GL_FALSE;
+
+    // The default is to disable key repeat
+    _glfwInput.KeyRepeat = GL_FALSE;
+}
+
+
+//========================================================================
+// _glfwInputKey() - Register keyboard activity
+//========================================================================
+
+void _glfwInputKey( int key, int action )
+{
+    int keyrepeat = 0;
+
+    if( key < 0 || key > GLFW_KEY_LAST )
+    {
+        return;
+    }
+
+    // Are we trying to release an already released key?
+    if( action == GLFW_RELEASE && _glfwInput.Key[ key ] != GLFW_PRESS )
+    {
+        return;
+    }
+
+    // Register key action
+    if( action == GLFW_RELEASE && _glfwInput.StickyKeys )
+    {
+        _glfwInput.Key[ key ] = GLFW_STICK;
+    }
+    else
+    {
+        keyrepeat = (_glfwInput.Key[ key ] == GLFW_PRESS) &&
+                    (action == GLFW_PRESS);
+        _glfwInput.Key[ key ] = (char) action;
+    }
+
+    // Call user callback function
+    if( _glfwWin.keyCallback && (_glfwInput.KeyRepeat || !keyrepeat) )
+    {
+        _glfwWin.keyCallback( key, action );
+    }
+}
+
+
+//========================================================================
+// Register (keyboard) character activity
+//========================================================================
+
+void _glfwInputChar( int character, int action )
+{
+    int keyrepeat = 0;
+
+    // Valid Unicode (ISO 10646) character?
+    if( !( (character >= 32 && character <= 126) || character >= 160 ) )
+    {
+        return;
+    }
+
+    // Is this a key repeat?
+    if( action == GLFW_PRESS && _glfwInput.LastChar == character )
+    {
+        keyrepeat = 1;
+    }
+
+    // Store this character as last character (or clear it, if released)
+    if( action == GLFW_PRESS )
+    {
+        _glfwInput.LastChar = character;
+    }
+    else
+    {
+        _glfwInput.LastChar = 0;
+    }
+
+    if( action != GLFW_PRESS )
+    {
+        // This intentionally breaks release notifications for Unicode
+        // characters, partly to see if anyone cares but mostly because it's
+        // a nonsensical concept to begin with
+        //
+        // It will remain broken either until its removal in the 3.0 API or
+        // until someone explains, in a way that makes sense to people outside
+        // the US and Scandinavia, what "Unicode character up" actually means
+        //
+        // If what you want is "physical key up" then you should be using the
+        // key functions and/or the key callback, NOT the Unicode input
+        //
+        // However, if your particular application uses this misfeature for...
+        // something, you can re-enable it by removing this if-statement
+        return;
+    }
+
+    if( _glfwWin.charCallback && (_glfwInput.KeyRepeat || !keyrepeat) )
+    {
+        _glfwWin.charCallback( character, action );
+    }
+}
+
+
+//========================================================================
+// _glfwInputMouseClick() - Register mouse button clicks
+//========================================================================
+
+void _glfwInputMouseClick( int button, int action )
+{
+    if( button >= 0 && button <= GLFW_MOUSE_BUTTON_LAST )
+    {
+        // Register mouse button action
+        if( action == GLFW_RELEASE && _glfwInput.StickyMouseButtons )
+        {
+            _glfwInput.MouseButton[ button ] = GLFW_STICK;
+        }
+        else
+        {
+            _glfwInput.MouseButton[ button ] = (char) action;
+        }
+
+        // Call user callback function
+        if( _glfwWin.mouseButtonCallback )
+        {
+            _glfwWin.mouseButtonCallback( button, action );
+        }
+    }
+}
+
+
+//========================================================================
+// Return the available framebuffer config closest to the desired values
+// This is based on the manual GLX Visual selection from 2.6
+//========================================================================
+
+const _GLFWfbconfig *_glfwChooseFBConfig( const _GLFWfbconfig *desired,
+                                          const _GLFWfbconfig *alternatives,
+                                          unsigned int count )
+{
+    unsigned int i;
+    unsigned int missing, leastMissing = UINT_MAX;
+    unsigned int colorDiff, leastColorDiff = UINT_MAX;
+    unsigned int extraDiff, leastExtraDiff = UINT_MAX;
+    GLboolean desiresColor = GL_FALSE;
+    const _GLFWfbconfig *current;
+    const _GLFWfbconfig *closest = NULL;
+
+    // Cache some long-winded preferences
+
+    if( desired->redBits || desired->greenBits || desired->blueBits ||
+        desired->alphaBits )
+    {
+        desiresColor = GL_TRUE;
+    }
+
+    for( i = 0;  i < count;  i++ )
+    {
+        current = alternatives + i;
+
+        if( desired->stereo > 0 && current->stereo == 0 )
+        {
+            // Stereo is a hard constraint
+            continue;
+        }
+
+        // Count number of missing buffers
+        {
+            missing = 0;
+
+            if( desired->alphaBits > 0 && current->alphaBits == 0 )
+            {
+                missing++;
+            }
+
+            if( desired->depthBits > 0 && current->depthBits == 0 )
+            {
+                missing++;
+            }
+
+            if( desired->stencilBits > 0 && current->stencilBits == 0 )
+            {
+                missing++;
+            }
+
+            if( desired->auxBuffers > 0 && current->auxBuffers < desired->auxBuffers )
+            {
+                missing += desired->auxBuffers - current->auxBuffers;
+            }
+
+            if( desired->samples > 0 && current->samples == 0 )
+            {
+                // Technically, several multisampling buffers could be
+                // involved, but that's a lower level implementation detail and
+                // not important to us here, so we count them as one
+                missing++;
+            }
+        }
+
+        // These polynomials make many small channel size differences matter
+        // less than one large channel size difference
+
+        // Calculate color channel size difference value
+        {
+            colorDiff = 0;
+
+            if ( desired->redBits > 0 )
+            {
+                colorDiff += ( desired->redBits - current->redBits ) *
+                             ( desired->redBits - current->redBits );
+            }
+
+            if ( desired->greenBits > 0 )
+            {
+                colorDiff += ( desired->greenBits - current->greenBits ) *
+                             ( desired->greenBits - current->greenBits );
+            }
+
+            if ( desired->blueBits > 0 )
+            {
+                colorDiff += ( desired->blueBits - current->blueBits ) *
+                             ( desired->blueBits - current->blueBits );
+            }
+        }
+
+        // Calculate non-color channel size difference value
+        {
+            extraDiff = 0;
+
+            if( desired->alphaBits > 0 )
+            {
+                extraDiff += ( desired->alphaBits - current->alphaBits ) *
+                             ( desired->alphaBits - current->alphaBits );
+            }
+
+            if( desired->depthBits > 0 )
+            {
+                extraDiff += ( desired->depthBits - current->depthBits ) *
+                             ( desired->depthBits - current->depthBits );
+            }
+
+            if( desired->stencilBits > 0 )
+            {
+                extraDiff += ( desired->stencilBits - current->stencilBits ) *
+                             ( desired->stencilBits - current->stencilBits );
+            }
+
+            if( desired->accumRedBits > 0 )
+            {
+                extraDiff += ( desired->accumRedBits - current->accumRedBits ) *
+                             ( desired->accumRedBits - current->accumRedBits );
+            }
+
+            if( desired->accumGreenBits > 0 )
+            {
+                extraDiff += ( desired->accumGreenBits - current->accumGreenBits ) *
+                             ( desired->accumGreenBits - current->accumGreenBits );
+            }
+
+            if( desired->accumBlueBits > 0 )
+            {
+                extraDiff += ( desired->accumBlueBits - current->accumBlueBits ) *
+                             ( desired->accumBlueBits - current->accumBlueBits );
+            }
+
+            if( desired->accumAlphaBits > 0 )
+            {
+                extraDiff += ( desired->accumAlphaBits - current->accumAlphaBits ) *
+                             ( desired->accumAlphaBits - current->accumAlphaBits );
+            }
+
+            if( desired->samples > 0 )
+            {
+                extraDiff += ( desired->samples - current->samples ) *
+                             ( desired->samples - current->samples );
+            }
+        }
+
+        // Figure out if the current one is better than the best one found so far
+
+        if( missing < leastMissing )
+        {
+            closest = current;
+        }
+        else if( missing == leastMissing )
+        {
+            if( desiresColor )
+            {
+                if( ( colorDiff < leastColorDiff ) ||
+                    ( colorDiff == leastColorDiff && extraDiff < leastExtraDiff ) )
+                {
+                    closest = current;
+                }
+            }
+            else
+            {
+                if( ( extraDiff < leastExtraDiff ) ||
+                    ( extraDiff == leastExtraDiff && colorDiff < leastColorDiff ) )
+                {
+                    closest = current;
+                }
+            }
+        }
+
+        if( current == closest )
+        {
+            leastMissing = missing;
+            leastColorDiff = colorDiff;
+            leastExtraDiff = extraDiff;
+        }
+    }
+
+    return closest;
+}
+
+
+//************************************************************************
+//****                    GLFW user functions                         ****
+//************************************************************************
+
+//========================================================================
+// Create the GLFW window and its associated context
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwOpenWindow( int width, int height,
+    int redbits, int greenbits, int bluebits, int alphabits,
+    int depthbits, int stencilbits, int mode )
+{
+    _GLFWfbconfig fbconfig;
+    _GLFWwndconfig wndconfig;
+
+    // Is GLFW initialized?
+    if( !_glfwInitialized || _glfwWin.opened )
+    {
+        return GL_FALSE;
+    }
+
+    // Set up desired framebuffer config
+    fbconfig.redBits        = Max( redbits, 0 );
+    fbconfig.greenBits      = Max( greenbits, 0 );
+    fbconfig.blueBits       = Max( bluebits, 0 );
+    fbconfig.alphaBits      = Max( alphabits, 0 );
+    fbconfig.depthBits      = Max( depthbits, 0 );
+    fbconfig.stencilBits    = Max( stencilbits, 0 );
+    fbconfig.accumRedBits   = Max( _glfwLibrary.hints.accumRedBits, 0 );
+    fbconfig.accumGreenBits = Max( _glfwLibrary.hints.accumGreenBits, 0 );
+    fbconfig.accumBlueBits  = Max( _glfwLibrary.hints.accumBlueBits, 0 );
+    fbconfig.accumAlphaBits = Max( _glfwLibrary.hints.accumAlphaBits, 0 );
+    fbconfig.auxBuffers     = Max( _glfwLibrary.hints.auxBuffers, 0 );
+    fbconfig.stereo         = _glfwLibrary.hints.stereo ? GL_TRUE : GL_FALSE;
+    fbconfig.samples        = Max( _glfwLibrary.hints.samples, 0 );
+
+    // Set up desired window config
+    wndconfig.mode           = mode;
+    wndconfig.refreshRate    = Max( _glfwLibrary.hints.refreshRate, 0 );
+    wndconfig.windowNoResize = _glfwLibrary.hints.windowNoResize ? GL_TRUE : GL_FALSE;
+    wndconfig.glMajor        = Max( _glfwLibrary.hints.glMajor, 1 );
+    wndconfig.glMinor        = Max( _glfwLibrary.hints.glMinor, 0 );
+    wndconfig.glForward      = _glfwLibrary.hints.glForward ? GL_TRUE : GL_FALSE;
+    wndconfig.glDebug        = _glfwLibrary.hints.glDebug ? GL_TRUE : GL_FALSE;
+    wndconfig.glProfile      = _glfwLibrary.hints.glProfile;
+
+    if( wndconfig.glMajor == 1 && wndconfig.glMinor > 5 )
+    {
+        // OpenGL 1.x series ended with version 1.5
+        return GL_FALSE;
+    }
+    else if( wndconfig.glMajor == 2 && wndconfig.glMinor > 1 )
+    {
+        // OpenGL 2.x series ended with version 2.1
+        return GL_FALSE;
+    }
+    else if( wndconfig.glMajor == 3 && wndconfig.glMinor > 3 )
+    {
+        // OpenGL 3.x series ended with version 3.3
+        return GL_FALSE;
+    }
+    else
+    {
+        // For now, let everything else through
+    }
+
+    if( wndconfig.glProfile &&
+        ( wndconfig.glMajor < 3 || ( wndconfig.glMajor == 3 && wndconfig.glMinor < 2 ) ) )
+    {
+        // Context profiles are only defined for OpenGL version 3.2 and above
+        return GL_FALSE;
+    }
+
+    if( wndconfig.glForward && wndconfig.glMajor < 3 )
+    {
+        // Forward-compatible contexts are only defined for OpenGL version 3.0 and above
+        return GL_FALSE;
+    }
+
+    // Clear for next open call
+    _glfwClearWindowHints();
+
+    // Check input arguments
+    if( mode != GLFW_WINDOW && mode != GLFW_FULLSCREEN )
+    {
+        return GL_FALSE;
+    }
+
+    // Clear GLFW window state
+    _glfwWin.active         = GL_TRUE;
+    _glfwWin.iconified      = GL_FALSE;
+    _glfwWin.mouseLock      = GL_FALSE;
+    _glfwWin.autoPollEvents = GL_TRUE;
+    _glfwClearInput();
+
+    // Unregister all callback functions
+    _glfwWin.windowSizeCallback    = NULL;
+    _glfwWin.windowCloseCallback   = NULL;
+    _glfwWin.windowRefreshCallback = NULL;
+    _glfwWin.keyCallback           = NULL;
+    _glfwWin.charCallback          = NULL;
+    _glfwWin.mousePosCallback      = NULL;
+    _glfwWin.mouseButtonCallback   = NULL;
+    _glfwWin.mouseWheelCallback    = NULL;
+
+    // Check width & height
+    if( width > 0 && height <= 0 )
+    {
+        // Set the window aspect ratio to 4:3
+        height = (width * 3) / 4;
+    }
+    else if( width <= 0 && height > 0 )
+    {
+        // Set the window aspect ratio to 4:3
+        width = (height * 4) / 3;
+    }
+    else if( width <= 0 && height <= 0 )
+    {
+        // Default window size
+        width  = 640;
+        height = 480;
+    }
+
+    // Remember window settings
+    _glfwWin.width      = width;
+    _glfwWin.height     = height;
+    _glfwWin.fullscreen = (mode == GLFW_FULLSCREEN ? GL_TRUE : GL_FALSE);
+
+    // Platform specific window opening routine
+    if( !_glfwPlatformOpenWindow( width, height, &wndconfig, &fbconfig ) )
+    {
+        return GL_FALSE;
+    }
+
+    // Flag that window is now opened
+    _glfwWin.opened = GL_TRUE;
+
+    // Get window parameters (such as color buffer bits etc)
+    _glfwPlatformRefreshWindowParams();
+
+    // Get OpenGL version
+    _glfwParseGLVersion( &_glfwWin.glMajor, &_glfwWin.glMinor,
+                         &_glfwWin.glRevision );
+
+    if( _glfwWin.glMajor < wndconfig.glMajor ||
+        ( _glfwWin.glMajor == wndconfig.glMajor &&
+          _glfwWin.glMinor < wndconfig.glMinor ) )
+    {
+        _glfwPlatformCloseWindow();
+        return GL_FALSE;
+    }
+
+    // Do we have non-power-of-two textures (added to core in version 2.0)?
+    _glfwWin.has_GL_ARB_texture_non_power_of_two =
+        ( _glfwWin.glMajor >= 2 ) ||
+        glfwExtensionSupported( "GL_ARB_texture_non_power_of_two" );
+
+    // Do we have automatic mipmap generation (added to core in version 1.4)?
+    _glfwWin.has_GL_SGIS_generate_mipmap =
+        ( _glfwWin.glMajor >= 2 ) || ( _glfwWin.glMinor >= 4 ) ||
+        glfwExtensionSupported( "GL_SGIS_generate_mipmap" );
+
+    if( _glfwWin.glMajor > 2 )
+    {
+        _glfwWin.GetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress( "glGetStringi" );
+        if( !_glfwWin.GetStringi )
+        {
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+    }
+
+    // If full-screen mode was requested, disable mouse cursor
+    if( mode == GLFW_FULLSCREEN )
+    {
+        glfwDisable( GLFW_MOUSE_CURSOR );
+    }
+
+    // Start by clearing the front buffer to black (avoid ugly desktop
+    // remains in our OpenGL window)
+    glClear( GL_COLOR_BUFFER_BIT );
+    _glfwPlatformSwapBuffers();
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Set hints for opening the window
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwOpenWindowHint( int target, int hint )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return;
+    }
+
+    switch( target )
+    {
+        case GLFW_REFRESH_RATE:
+            _glfwLibrary.hints.refreshRate = hint;
+            break;
+        case GLFW_ACCUM_RED_BITS:
+            _glfwLibrary.hints.accumRedBits = hint;
+            break;
+        case GLFW_ACCUM_GREEN_BITS:
+            _glfwLibrary.hints.accumGreenBits = hint;
+            break;
+        case GLFW_ACCUM_BLUE_BITS:
+            _glfwLibrary.hints.accumBlueBits = hint;
+            break;
+        case GLFW_ACCUM_ALPHA_BITS:
+            _glfwLibrary.hints.accumAlphaBits = hint;
+            break;
+        case GLFW_AUX_BUFFERS:
+            _glfwLibrary.hints.auxBuffers = hint;
+            break;
+        case GLFW_STEREO:
+            _glfwLibrary.hints.stereo = hint;
+            break;
+        case GLFW_WINDOW_NO_RESIZE:
+            _glfwLibrary.hints.windowNoResize = hint;
+            break;
+        case GLFW_FSAA_SAMPLES:
+            _glfwLibrary.hints.samples = hint;
+            break;
+        case GLFW_OPENGL_VERSION_MAJOR:
+            _glfwLibrary.hints.glMajor = hint;
+            break;
+        case GLFW_OPENGL_VERSION_MINOR:
+            _glfwLibrary.hints.glMinor = hint;
+            break;
+        case GLFW_OPENGL_FORWARD_COMPAT:
+            _glfwLibrary.hints.glForward = hint;
+            break;
+        case GLFW_OPENGL_DEBUG_CONTEXT:
+            _glfwLibrary.hints.glDebug = hint;
+            break;
+        case GLFW_OPENGL_PROFILE:
+            _glfwLibrary.hints.glProfile = hint;
+            break;
+        default:
+            break;
+    }
+}
+
+
+//========================================================================
+// Properly kill the window / video display
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwCloseWindow( void )
+{
+    if( !_glfwInitialized )
+    {
+        return;
+    }
+
+    // Show mouse pointer again (if hidden)
+    glfwEnable( GLFW_MOUSE_CURSOR );
+
+    _glfwPlatformCloseWindow();
+
+    memset( &_glfwWin, 0, sizeof(_glfwWin) );
+    _glfwWin.opened = GL_FALSE;
+}
+
+
+//========================================================================
+// glfwSetWindowTitle() - Set the window title
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetWindowTitle( const char *title )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set window title
+    _glfwPlatformSetWindowTitle( title );
+}
+
+
+//========================================================================
+// glfwGetWindowSize() - Get the window size
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwGetWindowSize( int *width, int *height )
+{
+    if( width != NULL )
+    {
+        *width = _glfwWin.width;
+    }
+    if( height != NULL )
+    {
+        *height = _glfwWin.height;
+    }
+}
+
+
+//========================================================================
+// glfwSetWindowSize() - Set the window size
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetWindowSize( int width, int height )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened || _glfwWin.iconified )
+    {
+        return;
+    }
+
+    // Don't do anything if the window size did not change
+    if( width == _glfwWin.width && height == _glfwWin.height )
+    {
+        return;
+    }
+
+    // Change window size
+    _glfwPlatformSetWindowSize( width, height );
+
+    // Refresh window parameters (may have changed due to changed video
+    // modes)
+    _glfwPlatformRefreshWindowParams();
+}
+
+
+//========================================================================
+// glfwSetWindowPos() - Set the window position
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetWindowPos( int x, int y )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened || _glfwWin.fullscreen ||
+        _glfwWin.iconified )
+    {
+        return;
+    }
+
+    // Set window position
+    _glfwPlatformSetWindowPos( x, y );
+}
+
+
+//========================================================================
+// glfwIconfyWindow() - Window iconification
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwIconifyWindow( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened || _glfwWin.iconified )
+    {
+        return;
+    }
+
+    // Iconify window
+    _glfwPlatformIconifyWindow();
+}
+
+
+//========================================================================
+// glfwRestoreWindow() - Window un-iconification
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwRestoreWindow( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened || !_glfwWin.iconified )
+    {
+        return;
+    }
+
+    // Restore iconified window
+    _glfwPlatformRestoreWindow();
+
+    // Refresh window parameters
+    _glfwPlatformRefreshWindowParams();
+}
+
+
+//========================================================================
+// Swap buffers (double-buffering) and poll any new events
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSwapBuffers( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Update display-buffer
+    if( _glfwWin.opened )
+    {
+        _glfwPlatformSwapBuffers();
+    }
+
+    // Check for window messages
+    if( _glfwWin.autoPollEvents )
+    {
+        glfwPollEvents();
+    }
+}
+
+
+//========================================================================
+// glfwSwapInterval() - Set double buffering swap interval (0 = vsync off)
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSwapInterval( int interval )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set double buffering swap interval
+    _glfwPlatformSwapInterval( interval );
+}
+
+
+//========================================================================
+// glfwGetWindowParam() - Get window parameter
+//========================================================================
+
+GLFWAPI int GLFWAPIENTRY glfwGetWindowParam( int param )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized )
+    {
+        return 0;
+    }
+
+    // Is the window opened?
+    if( !_glfwWin.opened )
+    {
+        if( param == GLFW_OPENED )
+        {
+            return GL_FALSE;
+        }
+        return 0;
+    }
+
+    // Window parameters
+    switch( param )
+    {
+        case GLFW_OPENED:
+            return GL_TRUE;
+        case GLFW_ACTIVE:
+            return _glfwWin.active;
+        case GLFW_ICONIFIED:
+            return _glfwWin.iconified;
+        case GLFW_ACCELERATED:
+            return _glfwWin.accelerated;
+        case GLFW_RED_BITS:
+            return _glfwWin.redBits;
+        case GLFW_GREEN_BITS:
+            return _glfwWin.greenBits;
+        case GLFW_BLUE_BITS:
+            return _glfwWin.blueBits;
+        case GLFW_ALPHA_BITS:
+            return _glfwWin.alphaBits;
+        case GLFW_DEPTH_BITS:
+            return _glfwWin.depthBits;
+        case GLFW_STENCIL_BITS:
+            return _glfwWin.stencilBits;
+        case GLFW_ACCUM_RED_BITS:
+            return _glfwWin.accumRedBits;
+        case GLFW_ACCUM_GREEN_BITS:
+            return _glfwWin.accumGreenBits;
+        case GLFW_ACCUM_BLUE_BITS:
+            return _glfwWin.accumBlueBits;
+        case GLFW_ACCUM_ALPHA_BITS:
+            return _glfwWin.accumAlphaBits;
+        case GLFW_AUX_BUFFERS:
+            return _glfwWin.auxBuffers;
+        case GLFW_STEREO:
+            return _glfwWin.stereo;
+        case GLFW_REFRESH_RATE:
+            return _glfwWin.refreshRate;
+        case GLFW_WINDOW_NO_RESIZE:
+            return _glfwWin.windowNoResize;
+        case GLFW_FSAA_SAMPLES:
+            return _glfwWin.samples;
+        case GLFW_OPENGL_VERSION_MAJOR:
+            return _glfwWin.glMajor;
+        case GLFW_OPENGL_VERSION_MINOR:
+            return _glfwWin.glMinor;
+        case GLFW_OPENGL_FORWARD_COMPAT:
+            return _glfwWin.glForward;
+        case GLFW_OPENGL_DEBUG_CONTEXT:
+            return _glfwWin.glDebug;
+        case GLFW_OPENGL_PROFILE:
+            return _glfwWin.glProfile;
+        default:
+            return 0;
+    }
+}
+
+
+//========================================================================
+// glfwSetWindowSizeCallback() - Set callback function for window size
+// changes
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetWindowSizeCallback( GLFWwindowsizefun cbfun )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set callback function
+    _glfwWin.windowSizeCallback = cbfun;
+
+    // Call the callback function to let the application know the current
+    // window size
+    if( cbfun )
+    {
+        cbfun( _glfwWin.width, _glfwWin.height );
+    }
+}
+
+//========================================================================
+// glfwSetWindowCloseCallback() - Set callback function for window close
+// events
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetWindowCloseCallback( GLFWwindowclosefun cbfun )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set callback function
+    _glfwWin.windowCloseCallback = cbfun;
+}
+
+
+//========================================================================
+// glfwSetWindowRefreshCallback() - Set callback function for window
+// refresh events
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwSetWindowRefreshCallback( GLFWwindowrefreshfun cbfun )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Set callback function
+    _glfwWin.windowRefreshCallback = cbfun;
+}
+
+
+//========================================================================
+// glfwPollEvents() - Poll for new window and input events
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwPollEvents( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Poll for new events
+    _glfwPlatformPollEvents();
+}
+
+
+//========================================================================
+// glfwWaitEvents() - Wait for new window and input events
+//========================================================================
+
+GLFWAPI void GLFWAPIENTRY glfwWaitEvents( void )
+{
+    // Is GLFW initialized?
+    if( !_glfwInitialized || !_glfwWin.opened )
+    {
+        return;
+    }
+
+    // Poll for new events
+    _glfwPlatformWaitEvents();
+}
+

+ 503 - 0
ThirdParty/GLFW/lib/x11/platform.h

@@ -0,0 +1,503 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    X11/GLX
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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
+
+// We need declarations for GLX version 1.3 or above even if the server doesn't
+// support version 1.3
+#ifndef GLX_VERSION_1_3
+ #error "GLX header version 1.3 or above is required"
+#endif
+
+#if defined( _GLFW_HAS_XF86VIDMODE ) && defined( _GLFW_HAS_XRANDR )
+ #error "Xf86VidMode and RandR extensions cannot both be enabled"
+#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
+
+// Pointer length integer
+// One day, this will most likely move into glfw.h
+typedef intptr_t GLFWintptr;
+
+
+#ifndef GLX_SGI_swap_control
+
+// Function signature for GLX_SGI_swap_control
+typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);
+
+#endif /*GLX_SGI_swap_control*/
+
+
+#ifndef GLX_SGIX_fbconfig
+
+/* Type definitions for GLX_SGIX_fbconfig */
+typedef XID GLXFBConfigIDSGIX;
+typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
+
+/* Function signatures for GLX_SGIX_fbconfig */
+typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value);
+typedef GLXFBConfigSGIX * ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, int *attrib_list, int *nelements);
+typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct);
+typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config);
+
+/* Tokens for GLX_SGIX_fbconfig */
+#define GLX_WINDOW_BIT_SGIX                0x00000001
+#define GLX_PIXMAP_BIT_SGIX                0x00000002
+#define GLX_RGBA_BIT_SGIX                  0x00000001
+#define GLX_COLOR_INDEX_BIT_SGIX           0x00000002
+#define GLX_DRAWABLE_TYPE_SGIX             0x8010
+#define GLX_RENDER_TYPE_SGIX               0x8011
+#define GLX_X_RENDERABLE_SGIX              0x8012
+#define GLX_FBCONFIG_ID_SGIX               0x8013
+#define GLX_RGBA_TYPE_SGIX                 0x8014
+#define GLX_COLOR_INDEX_TYPE_SGIX          0x8015
+#define GLX_SCREEN_EXT                     0x800C
+
+#endif /*GLX_SGIX_fbconfig*/
+
+
+#ifndef GLX_ARB_create_context
+
+/* Tokens for glXCreateContextAttribsARB attributes */
+#define GLX_CONTEXT_MAJOR_VERSION_ARB           0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB           0x2092
+#define GLX_CONTEXT_FLAGS_ARB                   0x2094
+
+/* Bits for WGL_CONTEXT_FLAGS_ARB */
+#define GLX_CONTEXT_DEBUG_BIT_ARB               0x0001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB  0x0002
+
+/* Prototype for glXCreateContextAttribs */
+typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)( Display *display, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
+
+#endif /*GLX_ARB_create_context*/
+
+
+#ifndef GLX_ARB_create_context_profile
+
+/* Tokens for glXCreateContextAttribsARB attributes */
+#define GLX_CONTEXT_PROFILE_MASK_ARB            0x9126
+
+/* BIts for GLX_CONTEXT_PROFILE_MASK_ARB */
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB        0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+
+#endif /*GLX_ARB_create_context_profile*/
+
+
+#ifndef GL_VERSION_3_0
+
+typedef const GLubyte * (APIENTRY *PFNGLGETSTRINGIPROC) (GLenum, GLuint);
+
+#endif /*GL_VERSION_3_0*/
+
+
+
+//========================================================================
+// 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
+    int       refreshRate;     // Vertical monitor refresh rate
+
+    // 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
+
+    // Framebuffer attributes
+    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       samples;
+
+    // OpenGL extensions and context attributes
+    int       has_GL_SGIS_generate_mipmap;
+    int       has_GL_ARB_texture_non_power_of_two;
+    int       glMajor, glMinor, glRevision;
+    int       glForward, glDebug, glProfile;
+
+    PFNGLGETSTRINGIPROC GetStringi;
+
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+    // Platform specific window resources
+    Colormap      colormap;          // Window colormap
+    Window        window;            // Window
+    Window        root;              // Root window for screen
+    int           screen;            // Screen ID
+    XVisualInfo  *visual;            // Visual for selected GLXFBConfig
+    GLXFBConfigID fbconfigID;        // ID of selected GLXFBConfig
+    GLXContext    context;           // OpenGL rendering context
+    Atom          wmDeleteWindow;    // WM_DELETE_WINDOW atom
+    Atom          wmPing;            // _NET_WM_PING atom
+    Atom          wmState;           // _NET_WM_STATE atom
+    Atom          wmStateFullscreen; // _NET_WM_STATE_FULLSCREEN atom
+    Atom          wmActiveWindow;    // _NET_ACTIVE_WINDOW atom
+    Cursor        cursor;            // Invisible cursor for hidden cursor
+
+    // GLX extensions
+    PFNGLXSWAPINTERVALSGIPROC             SwapIntervalSGI;
+    PFNGLXGETFBCONFIGATTRIBSGIXPROC       GetFBConfigAttribSGIX;
+    PFNGLXCHOOSEFBCONFIGSGIXPROC          ChooseFBConfigSGIX;
+    PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC CreateContextWithConfigSGIX;
+    PFNGLXGETVISUALFROMFBCONFIGSGIXPROC   GetVisualFromFBConfigSGIX;
+    PFNGLXCREATECONTEXTATTRIBSARBPROC     CreateContextAttribsARB;
+    GLboolean   has_GLX_SGIX_fbconfig;
+    GLboolean   has_GLX_SGI_swap_control;
+    GLboolean   has_GLX_ARB_multisample;
+    GLboolean   has_GLX_ARB_create_context;
+    GLboolean   has_GLX_ARB_create_context_profile;
+
+    // Various platform specific internal variables
+    GLboolean   hasEWMH;          // True if window manager supports EWMH
+    GLboolean   overrideRedirect; // True if window is OverrideRedirect
+    GLboolean   keyboardGrabbed;  // True if keyboard is currently grabbed
+    GLboolean   pointerGrabbed;   // True if pointer is currently grabbed
+    GLboolean   pointerHidden;    // True if pointer is currently hidden
+
+    // 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 INDEPENDENT MANDATORY PART =========================
+
+    // Window opening hints
+    _GLFWhints      hints;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+    Display        *display;
+
+    // Server-side GLX version
+    int             glxMajor, glxMinor;
+
+    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 );
+void _glfwRestoreVideoMode( void );
+
+// Joystick input
+void _glfwInitJoysticks( void );
+void _glfwTerminateJoysticks( void );
+
+// Unicode support
+long _glfwKeySym2Unicode( KeySym keysym );
+
+
+#endif // _platform_h_

+ 64 - 0
ThirdParty/GLFW/lib/x11/x11_enable.c

@@ -0,0 +1,64 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    X11 (Unix)
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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                ****
+//************************************************************************
+
+//========================================================================
+// Enable system keys
+//========================================================================
+
+void _glfwPlatformEnableSystemKeys( void )
+{
+    if( _glfwWin.keyboardGrabbed )
+    {
+        XUngrabKeyboard( _glfwLibrary.display, CurrentTime );
+        _glfwWin.keyboardGrabbed = GL_FALSE;
+    }
+}
+
+//========================================================================
+// Disable system keys
+//========================================================================
+
+void _glfwPlatformDisableSystemKeys( void )
+{
+    if( XGrabKeyboard( _glfwLibrary.display, _glfwWin.window, True,
+                        GrabModeAsync, GrabModeAsync, CurrentTime ) ==
+        GrabSuccess )
+    {
+        _glfwWin.keyboardGrabbed = GL_TRUE;
+    }
+}
+

+ 572 - 0
ThirdParty/GLFW/lib/x11/x11_fullscreen.c

@@ -0,0 +1,572 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    X11/GLX
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+#include <limits.h>
+
+
+//************************************************************************
+//****                  GLFW internal functions                       ****
+//************************************************************************
+
+//========================================================================
+// Convert BPP to RGB bits (based on "best guess")
+//========================================================================
+
+static void BPP2RGB( 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.display,
+                               RootWindow( _glfwLibrary.display, screen ) );
+
+        sizelist = XRRConfigSizes( sc, &sizecount );
+
+        // Find the best matching mode
+        bestsize  = -1;
+        bestmatch = INT_MAX;
+        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 = INT_MAX;
+                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.display, screen,
+                                    &modecount, &modelist );
+
+        // Find the best matching mode
+        bestmode  = -1;
+        bestmatch = INT_MAX;
+        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;
+            *height = modelist[ bestmode ]->vdisplay;
+        }
+
+        // Free modelist
+        XFree( modelist );
+
+        if( bestmode != -1 )
+        {
+            return bestmode;
+        }
+    }
+#endif
+
+    // Default: Simply use the screen resolution
+    *width = DisplayWidth( _glfwLibrary.display, screen );
+    *height = DisplayHeight( _glfwLibrary.display, 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.display, screen );
+        sc   = XRRGetScreenInfo( _glfwLibrary.display, 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.display, screen );
+            _glfwWin.FS.oldHeight = DisplayHeight( _glfwLibrary.display, screen );
+
+            _glfwWin.FS.modeChanged = GL_TRUE;
+        }
+
+        if( rate > 0 )
+        {
+            // Set desired configuration
+            XRRSetScreenConfigAndRate( _glfwLibrary.display,
+                                       sc,
+                                       root,
+                                       mode,
+                                       RR_Rotate_0,
+                                       (short) rate,
+                                       CurrentTime );
+        }
+        else
+        {
+            // Set desired configuration
+            XRRSetScreenConfig( _glfwLibrary.display,
+                                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.display, screen,
+                                    &modecount, &modelist );
+
+        // Unlock mode switch if necessary
+        if( _glfwWin.FS.modeChanged )
+        {
+            XF86VidModeLockModeSwitch( _glfwLibrary.display, screen, 0 );
+        }
+
+        // Change the video mode to the desired mode
+        XF86VidModeSwitchToMode(  _glfwLibrary.display, screen,
+                                  modelist[ mode ] );
+
+        // Set viewport to upper left corner (where our window will be)
+        XF86VidModeSetViewPort( _glfwLibrary.display, screen, 0, 0 );
+
+        // Lock mode switch
+        XF86VidModeLockModeSwitch( _glfwLibrary.display, 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 );
+}
+
+
+//========================================================================
+// Restore the previously saved (original) video mode
+//========================================================================
+
+void _glfwRestoreVideoMode( void )
+{
+    if( _glfwWin.FS.modeChanged )
+    {
+#if defined( _GLFW_HAS_XRANDR )
+        if( _glfwLibrary.XRandR.available )
+        {
+            XRRScreenConfiguration *sc;
+
+            if( _glfwLibrary.XRandR.available )
+            {
+                sc = XRRGetScreenInfo( _glfwLibrary.display, _glfwWin.root );
+
+                XRRSetScreenConfig( _glfwLibrary.display,
+                                    sc,
+                                    _glfwWin.root,
+                                    _glfwWin.FS.oldSizeID,
+                                    _glfwWin.FS.oldRotation,
+                                    CurrentTime );
+
+                XRRFreeScreenConfigInfo( sc );
+            }
+        }
+#elif defined( _GLFW_HAS_XF86VIDMODE )
+        if( _glfwLibrary.XF86VidMode.available )
+        {
+            // Unlock mode switch
+            XF86VidModeLockModeSwitch( _glfwLibrary.display, _glfwWin.screen, 0 );
+
+            // Change the video mode back to the old mode
+            XF86VidModeSwitchToMode( _glfwLibrary.display,
+                                    _glfwWin.screen,
+                                    &_glfwWin.FS.oldMode );
+        }
+#endif
+        _glfwWin.FS.modeChanged = GL_FALSE;
+    }
+}
+
+
+
+//************************************************************************
+//****               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.display;
+    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
+            BPP2RGB( 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.display;
+    screen = DefaultScreen( dpy );
+
+    // Get display depth
+    bpp = DefaultDepth( dpy, screen );
+
+    // Convert BPP to RGB bits
+    BPP2RGB( 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 );
+}
+

+ 90 - 0
ThirdParty/GLFW/lib/x11/x11_glext.c

@@ -0,0 +1,90 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    X11/GLX
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+
+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
+
+
+//************************************************************************
+//****               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.display,
+                                                            _glfwWin.screen );
+    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 );
+}
+

+ 286 - 0
ThirdParty/GLFW/lib/x11/x11_init.c

@@ -0,0 +1,286 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    X11/GLX
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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 initThreads( 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 terminateThreads( 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
+//========================================================================
+
+static void initLibraries( void )
+{
+#ifdef _GLFW_DLOPEN_LIBGL
+    int i;
+    char *libGL_names[ ] =
+    {
+        "libGL.so",
+        "libGL.so.1",
+        "/usr/lib/libGL.so",
+        "/usr/lib/libGL.so.1",
+        NULL
+    };
+
+    _glfwLibrary.Libs.libGL = NULL;
+    for( i = 0; !libGL_names[ i ] != NULL; i ++ )
+    {
+        _glfwLibrary.Libs.libGL = dlopen( libGL_names[ i ],
+                                          RTLD_LAZY | RTLD_GLOBAL );
+        if( _glfwLibrary.Libs.libGL )
+            break;
+    }
+#endif
+}
+
+
+//========================================================================
+// Terminate GLFW when exiting application
+//========================================================================
+
+static void glfw_atexit( void )
+{
+    glfwTerminate();
+}
+
+
+//========================================================================
+// Initialize X11 display
+//========================================================================
+
+static int initDisplay( void )
+{
+    // Open display
+    _glfwLibrary.display = XOpenDisplay( 0 );
+    if( !_glfwLibrary.display )
+    {
+        fprintf(stderr, "Failed to open X display\n");
+        return GL_FALSE;
+    }
+
+    // Check for XF86VidMode extension
+#ifdef _GLFW_HAS_XF86VIDMODE
+    _glfwLibrary.XF86VidMode.available =
+        XF86VidModeQueryExtension( _glfwLibrary.display,
+                                   &_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.display,
+                           &_glfwLibrary.XRandR.eventBase,
+                           &_glfwLibrary.XRandR.errorBase );
+#else
+    _glfwLibrary.XRandR.available = 0;
+#endif
+
+    // Fullscreen & screen saver settings
+    // Check if GLX is supported on this display
+    if( !glXQueryExtension( _glfwLibrary.display, NULL, NULL ) )
+    {
+        fprintf(stderr, "GLX not supported\n");
+        return GL_FALSE;
+    }
+
+    // Retrieve GLX version
+    if( !glXQueryVersion( _glfwLibrary.display,
+                          &_glfwLibrary.glxMajor,
+                          &_glfwLibrary.glxMinor ) )
+    {
+        fprintf(stderr, "Unable to query GLX version\n");
+        return GL_FALSE;
+    }
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Terminate X11 display
+//========================================================================
+
+static void terminateDisplay( void )
+{
+    // Open display
+    if( _glfwLibrary.display )
+    {
+        XCloseDisplay( _glfwLibrary.display );
+        _glfwLibrary.display = NULL;
+    }
+}
+
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// Initialize various GLFW state
+//========================================================================
+
+int _glfwPlatformInit( void )
+{
+    // Initialize display
+    if( !initDisplay() )
+    {
+        return GL_FALSE;
+    }
+
+    // Initialize thread package
+    initThreads();
+
+    // Try to load libGL.so if necessary
+    initLibraries();
+
+    // Install atexit() routine
+    atexit( glfw_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
+    terminateThreads();
+
+    // Terminate display
+    terminateDisplay();
+
+    // 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;
+}
+

+ 367 - 0
ThirdParty/GLFW/lib/x11/x11_joystick.c

@@ -0,0 +1,367 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    X11/GLX
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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.
+//========================================================================
+
+
+//************************************************************************
+//****                  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 =
+                    (unsigned 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
+
+}
+
+
+//========================================================================
+// Empty joystick event queue
+//========================================================================
+
+static void pollJoystickEvents( 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
+    pollJoystickEvents();
+
+    // 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
+    pollJoystickEvents();
+
+    // 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;
+}
+

+ 901 - 0
ThirdParty/GLFW/lib/x11/x11_keysym2unicode.c

@@ -0,0 +1,901 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    X11/GLX
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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 <[email protected]>, University of
+ *                  Cambridge, April 2001
+ *
+ * Special thanks to Richard Verhoeven <[email protected]> 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;
+}

+ 508 - 0
ThirdParty/GLFW/lib/x11/x11_thread.c

@@ -0,0 +1,508 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    X11/GLX
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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;
+}
+

+ 154 - 0
ThirdParty/GLFW/lib/x11/x11_time.c

@@ -0,0 +1,154 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    X11/GLX
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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
+}
+

+ 1875 - 0
ThirdParty/GLFW/lib/x11/x11_window.c

@@ -0,0 +1,1875 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform:    X11/GLX
+// API version: 2.7
+// WWW:         http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
+//
+// 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"
+
+#include <limits.h>
+
+
+/* Define GLX 1.4 FSAA tokens if not already defined */
+#ifndef GLX_VERSION_1_4
+
+#define GLX_SAMPLE_BUFFERS  100000
+#define GLX_SAMPLES         100001
+
+#endif /*GLX_VERSION_1_4*/
+
+// Action for EWMH client messages
+#define _NET_WM_STATE_REMOVE        0
+#define _NET_WM_STATE_ADD           1
+#define _NET_WM_STATE_TOGGLE        2
+
+
+//************************************************************************
+//****                  GLFW internal functions                       ****
+//************************************************************************
+
+//========================================================================
+// Checks whether the event is a MapNotify for the specified window
+//========================================================================
+
+static Bool isMapNotify( Display *d, XEvent *e, char *arg )
+{
+    return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
+}
+
+
+//========================================================================
+// Retrieve a single window property of the specified type
+// Inspired by fghGetWindowProperty from freeglut
+//========================================================================
+
+static unsigned long getWindowProperty( Window window,
+                                        Atom property,
+                                        Atom type,
+                                        unsigned char** value )
+{
+    Atom actualType;
+    int actualFormat;
+    unsigned long itemCount, bytesAfter;
+
+    XGetWindowProperty( _glfwLibrary.display,
+                        window,
+                        property,
+                        0,
+                        LONG_MAX,
+                        False,
+                        type,
+                        &actualType,
+                        &actualFormat,
+                        &itemCount,
+                        &bytesAfter,
+                        value );
+
+    if( actualType != type )
+    {
+        return 0;
+    }
+
+    return itemCount;
+}
+
+
+//========================================================================
+// Check whether the specified atom is supported
+//========================================================================
+
+static Atom getSupportedAtom( Atom* supportedAtoms,
+                              unsigned long atomCount,
+                              const char* atomName )
+{
+    Atom atom = XInternAtom( _glfwLibrary.display, atomName, True );
+    if( atom != None )
+    {
+        unsigned long i;
+
+        for( i = 0;  i < atomCount;  i++ )
+        {
+            if( supportedAtoms[i] == atom )
+            {
+                return atom;
+            }
+        }
+    }
+
+    return None;
+}
+
+
+//========================================================================
+// Check whether the running window manager is EWMH-compliant
+//========================================================================
+
+static GLboolean checkForEWMH( void )
+{
+    Window *windowFromRoot = NULL;
+    Window *windowFromChild = NULL;
+
+    // Hey kids; let's see if the window manager supports EWMH!
+
+    // First we need a couple of atoms, which should already be there
+    Atom supportingWmCheck = XInternAtom( _glfwLibrary.display,
+                                          "_NET_SUPPORTING_WM_CHECK",
+                                          True );
+    Atom wmSupported = XInternAtom( _glfwLibrary.display,
+                                    "_NET_SUPPORTED",
+                                    True );
+    if( supportingWmCheck == None || wmSupported == None )
+    {
+        return GL_FALSE;
+    }
+
+    // Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
+    if( getWindowProperty( _glfwWin.root,
+                           supportingWmCheck,
+                           XA_WINDOW,
+                           (unsigned char**) &windowFromRoot ) != 1 )
+    {
+        XFree( windowFromRoot );
+        return GL_FALSE;
+    }
+
+    // It should be the ID of a child window (of the root)
+    // Then we look for the same property on the child window
+    if( getWindowProperty( *windowFromRoot,
+                           supportingWmCheck,
+                           XA_WINDOW,
+                           (unsigned char**) &windowFromChild ) != 1 )
+    {
+        XFree( windowFromRoot );
+        XFree( windowFromChild );
+        return GL_FALSE;
+    }
+
+    // It should be the ID of that same child window
+    if( *windowFromRoot != *windowFromChild )
+    {
+        XFree( windowFromRoot );
+        XFree( windowFromChild );
+        return GL_FALSE;
+    }
+
+    XFree( windowFromRoot );
+    XFree( windowFromChild );
+
+    // We are now fairly sure that an EWMH-compliant window manager is running
+
+    Atom *supportedAtoms;
+    unsigned long atomCount;
+
+    // Now we need to check the _NET_SUPPORTED property of the root window
+    atomCount = getWindowProperty( _glfwWin.root,
+                                   wmSupported,
+                                   XA_ATOM,
+                                   (unsigned char**) &supportedAtoms );
+
+    // See which of the atoms we support that are supported by the WM
+
+    _glfwWin.wmState = getSupportedAtom( supportedAtoms,
+                                         atomCount,
+                                         "_NET_WM_STATE" );
+
+    _glfwWin.wmStateFullscreen = getSupportedAtom( supportedAtoms,
+                                                   atomCount,
+                                                   "_NET_WM_STATE_FULLSCREEN" );
+
+    _glfwWin.wmPing = getSupportedAtom( supportedAtoms,
+                                        atomCount,
+                                        "_NET_WM_PING" );
+
+    _glfwWin.wmActiveWindow = getSupportedAtom( supportedAtoms,
+                                                atomCount,
+                                                "_NET_ACTIVE_WINDOW" );
+
+    XFree( supportedAtoms );
+
+    return GL_TRUE;
+}
+
+//========================================================================
+// Translates an X Window key to internal coding
+//========================================================================
+
+static int translateKey( 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.display, 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.display, 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_ISO_Level3_Shift: // AltGr on at least some machines
+        case XK_Alt_R:        return GLFW_KEY_RALT;
+        case XK_Super_L:      return GLFW_KEY_LSUPER;
+        case XK_Super_R:      return GLFW_KEY_RSUPER;
+        case XK_Menu:         return GLFW_KEY_MENU;
+        case XK_Num_Lock:     return GLFW_KEY_KP_NUM_LOCK;
+        case XK_Caps_Lock:    return GLFW_KEY_CAPS_LOCK;
+        case XK_Scroll_Lock:  return GLFW_KEY_SCROLL_LOCK;
+        case XK_Pause:        return GLFW_KEY_PAUSE;
+        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;
+    }
+}
+
+
+//========================================================================
+// Translates an X Window event to Unicode
+//========================================================================
+
+static int translateChar( XKeyEvent *event )
+{
+    KeySym keysym;
+
+    // Get X11 keysym
+    XLookupString( event, NULL, 0, &keysym, NULL );
+
+    // Convert to Unicode (see x11_keysym2unicode.c)
+    return (int) _glfwKeySym2Unicode( keysym );
+}
+
+
+//========================================================================
+// Create a blank cursor (for locked mouse mode)
+//========================================================================
+
+static Cursor createNULLCursor( 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;
+}
+
+
+//========================================================================
+// Returns the specified attribute of the specified GLXFBConfig
+// NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig
+//========================================================================
+
+static int getFBConfigAttrib( GLXFBConfig fbconfig, int attrib )
+{
+    int value;
+
+    if( _glfwWin.has_GLX_SGIX_fbconfig )
+    {
+        _glfwWin.GetFBConfigAttribSGIX( _glfwLibrary.display, fbconfig, attrib, &value );
+    }
+    else
+    {
+        glXGetFBConfigAttrib( _glfwLibrary.display, fbconfig, attrib, &value );
+    }
+
+    return value;
+}
+
+
+//========================================================================
+// Return a list of available and usable framebuffer configs
+//========================================================================
+
+static _GLFWfbconfig *getFBConfigs( unsigned int *found )
+{
+    GLXFBConfig *fbconfigs;
+    _GLFWfbconfig *result;
+    int i, count = 0;
+
+    *found = 0;
+
+    if( _glfwLibrary.glxMajor == 1 && _glfwLibrary.glxMinor < 3 )
+    {
+        if( !_glfwWin.has_GLX_SGIX_fbconfig )
+        {
+            fprintf( stderr, "GLXFBConfigs are not supported by the X server\n" );
+            return NULL;
+        }
+    }
+
+    if( _glfwWin.has_GLX_SGIX_fbconfig )
+    {
+        fbconfigs = _glfwWin.ChooseFBConfigSGIX( _glfwLibrary.display,
+                                                 _glfwWin.screen,
+                                                 NULL,
+                                                 &count );
+        if( !count )
+        {
+            fprintf( stderr, "No GLXFBConfigs returned\n" );
+            return NULL;
+        }
+    }
+    else
+    {
+        fbconfigs = glXGetFBConfigs( _glfwLibrary.display, _glfwWin.screen, &count );
+        if( !count )
+        {
+            fprintf( stderr, "No GLXFBConfigs returned\n" );
+            return NULL;
+        }
+    }
+
+    result = (_GLFWfbconfig*) malloc( sizeof(_GLFWfbconfig) * count );
+    if( !result )
+    {
+        fprintf( stderr, "Out of memory\n" );
+        return NULL;
+    }
+
+    for( i = 0;  i < count;  i++ )
+    {
+        if( !getFBConfigAttrib( fbconfigs[i], GLX_DOUBLEBUFFER ) ||
+            !getFBConfigAttrib( fbconfigs[i], GLX_VISUAL_ID ) )
+        {
+            // Only consider double-buffered GLXFBConfigs with associated visuals
+            continue;
+        }
+
+        if( !( getFBConfigAttrib( fbconfigs[i], GLX_RENDER_TYPE ) & GLX_RGBA_BIT ) )
+        {
+            // Only consider RGBA GLXFBConfigs
+            continue;
+        }
+
+        if( !( getFBConfigAttrib( fbconfigs[i], GLX_DRAWABLE_TYPE ) & GLX_WINDOW_BIT ) )
+        {
+            // Only consider window GLXFBConfigs
+            continue;
+        }
+
+        result[*found].redBits = getFBConfigAttrib( fbconfigs[i], GLX_RED_SIZE );
+        result[*found].greenBits = getFBConfigAttrib( fbconfigs[i], GLX_GREEN_SIZE );
+        result[*found].blueBits = getFBConfigAttrib( fbconfigs[i], GLX_BLUE_SIZE );
+
+        result[*found].alphaBits = getFBConfigAttrib( fbconfigs[i], GLX_ALPHA_SIZE );
+        result[*found].depthBits = getFBConfigAttrib( fbconfigs[i], GLX_DEPTH_SIZE );
+        result[*found].stencilBits = getFBConfigAttrib( fbconfigs[i], GLX_STENCIL_SIZE );
+
+        result[*found].accumRedBits = getFBConfigAttrib( fbconfigs[i], GLX_ACCUM_RED_SIZE );
+        result[*found].accumGreenBits = getFBConfigAttrib( fbconfigs[i], GLX_ACCUM_GREEN_SIZE );
+        result[*found].accumBlueBits = getFBConfigAttrib( fbconfigs[i], GLX_ACCUM_BLUE_SIZE );
+        result[*found].accumAlphaBits = getFBConfigAttrib( fbconfigs[i], GLX_ACCUM_ALPHA_SIZE );
+
+        result[*found].auxBuffers = getFBConfigAttrib( fbconfigs[i], GLX_AUX_BUFFERS );
+        result[*found].stereo = getFBConfigAttrib( fbconfigs[i], GLX_STEREO );
+
+        if( _glfwWin.has_GLX_ARB_multisample )
+        {
+            result[*found].samples = getFBConfigAttrib( fbconfigs[i], GLX_SAMPLES );
+        }
+        else
+        {
+            result[*found].samples = 0;
+        }
+
+        result[*found].platformID = (GLFWintptr) getFBConfigAttrib( fbconfigs[i], GLX_FBCONFIG_ID );
+
+        (*found)++;
+    }
+
+    XFree( fbconfigs );
+
+    return result;
+}
+
+
+//========================================================================
+// Create the OpenGL context
+//========================================================================
+
+#define setGLXattrib( attribs, index, attribName, attribValue ) \
+    attribs[index++] = attribName; \
+    attribs[index++] = attribValue;
+
+static int createContext( const _GLFWwndconfig *wndconfig, GLXFBConfigID fbconfigID )
+{
+    int attribs[40];
+    int flags, dummy, index;
+    GLXFBConfig *fbconfig;
+
+    // Retrieve the previously selected GLXFBConfig
+    {
+        index = 0;
+
+        setGLXattrib( attribs, index, GLX_FBCONFIG_ID, (int) fbconfigID );
+        setGLXattrib( attribs, index, None, None );
+
+        if( _glfwWin.has_GLX_SGIX_fbconfig )
+        {
+            fbconfig = _glfwWin.ChooseFBConfigSGIX( _glfwLibrary.display,
+                                                    _glfwWin.screen,
+                                                    attribs,
+                                                    &dummy );
+        }
+        else
+        {
+            fbconfig = glXChooseFBConfig( _glfwLibrary.display,
+                                          _glfwWin.screen,
+                                          attribs,
+                                          &dummy );
+        }
+
+        if( fbconfig == NULL )
+        {
+            fprintf(stderr, "Unable to retrieve the selected GLXFBConfig\n");
+            return GL_FALSE;
+        }
+    }
+
+    // Retrieve the corresponding visual
+    if( _glfwWin.has_GLX_SGIX_fbconfig )
+    {
+        _glfwWin.visual = _glfwWin.GetVisualFromFBConfigSGIX( _glfwLibrary.display,
+                                                              *fbconfig );
+    }
+    else
+    {
+        _glfwWin.visual = glXGetVisualFromFBConfig( _glfwLibrary.display, *fbconfig );
+    }
+
+    if( _glfwWin.visual == NULL )
+    {
+        XFree( fbconfig );
+
+        fprintf(stderr, "Unable to retrieve visual for GLXFBconfig\n");
+        return GL_FALSE;
+    }
+
+    if( _glfwWin.has_GLX_ARB_create_context )
+    {
+        index = 0;
+
+        if( wndconfig->glMajor != 1 || wndconfig->glMinor != 0 )
+        {
+            // Request an explicitly versioned context
+
+            setGLXattrib( attribs, index, GLX_CONTEXT_MAJOR_VERSION_ARB, wndconfig->glMajor );
+            setGLXattrib( attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor );
+        }
+
+        if( wndconfig->glForward || wndconfig->glDebug )
+        {
+            flags = 0;
+
+            if( wndconfig->glForward )
+            {
+                flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+            }
+
+            if( wndconfig->glDebug )
+            {
+                flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
+            }
+
+            setGLXattrib( attribs, index, GLX_CONTEXT_FLAGS_ARB, flags );
+        }
+
+        if( wndconfig->glProfile )
+        {
+            if( !_glfwWin.has_GLX_ARB_create_context_profile )
+            {
+                fprintf( stderr, "OpenGL profile requested but GLX_ARB_create_context_profile "
+                                 "is unavailable\n" );
+                return GL_FALSE;
+            }
+
+            if( wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE )
+            {
+                flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+            }
+            else
+            {
+                flags = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+            }
+
+            setGLXattrib( attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags );
+        }
+
+        setGLXattrib( attribs, index, None, None );
+
+        _glfwWin.context = _glfwWin.CreateContextAttribsARB( _glfwLibrary.display,
+                                                             *fbconfig,
+                                                             NULL,
+                                                             True,
+                                                             attribs );
+    }
+    else
+    {
+        if( _glfwWin.has_GLX_SGIX_fbconfig )
+        {
+            _glfwWin.context = _glfwWin.CreateContextWithConfigSGIX( _glfwLibrary.display,
+                                                                     *fbconfig,
+                                                                     GLX_RGBA_TYPE,
+                                                                     NULL,
+                                                                     True );
+        }
+        else
+        {
+            _glfwWin.context = glXCreateNewContext( _glfwLibrary.display,
+                                                    *fbconfig,
+                                                    GLX_RGBA_TYPE,
+                                                    NULL,
+                                                    True );
+        }
+    }
+
+    XFree( fbconfig );
+
+    if( _glfwWin.context == NULL )
+    {
+        fprintf(stderr, "Unable to create OpenGL context\n");
+        return GL_FALSE;
+    }
+
+    _glfwWin.fbconfigID = fbconfigID;
+
+    return GL_TRUE;
+}
+
+#undef setGLXattrib
+
+
+//========================================================================
+// Initialize GLX-specific extensions
+//========================================================================
+
+static void initGLXExtensions( void )
+{
+    // This needs to include every function pointer loaded below
+    _glfwWin.SwapIntervalSGI             = NULL;
+    _glfwWin.GetFBConfigAttribSGIX       = NULL;
+    _glfwWin.ChooseFBConfigSGIX          = NULL;
+    _glfwWin.CreateContextWithConfigSGIX = NULL;
+    _glfwWin.GetVisualFromFBConfigSGIX   = NULL;
+    _glfwWin.CreateContextAttribsARB     = NULL;
+
+    // This needs to include every extension used below
+    _glfwWin.has_GLX_SGIX_fbconfig              = GL_FALSE;
+    _glfwWin.has_GLX_SGI_swap_control           = GL_FALSE;
+    _glfwWin.has_GLX_ARB_multisample            = GL_FALSE;
+    _glfwWin.has_GLX_ARB_create_context         = GL_FALSE;
+    _glfwWin.has_GLX_ARB_create_context_profile = GL_FALSE;
+
+    if( _glfwPlatformExtensionSupported( "GLX_SGI_swap_control" ) )
+    {
+        _glfwWin.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
+            _glfwPlatformGetProcAddress( "glXSwapIntervalSGI" );
+
+        if( _glfwWin.SwapIntervalSGI )
+        {
+            _glfwWin.has_GLX_SGI_swap_control = GL_TRUE;
+        }
+    }
+
+    if( _glfwPlatformExtensionSupported( "GLX_SGIX_fbconfig" ) )
+    {
+        _glfwWin.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC)
+            _glfwPlatformGetProcAddress( "glXGetFBConfigAttribSGIX" );
+        _glfwWin.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC)
+            _glfwPlatformGetProcAddress( "glXChooseFBConfigSGIX" );
+        _glfwWin.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC)
+            _glfwPlatformGetProcAddress( "glXCreateContextWithConfigSGIX" );
+        _glfwWin.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC)
+            _glfwPlatformGetProcAddress( "glXGetVisualFromFBConfigSGIX" );
+
+        if( _glfwWin.GetFBConfigAttribSGIX &&
+            _glfwWin.ChooseFBConfigSGIX &&
+            _glfwWin.CreateContextWithConfigSGIX &&
+            _glfwWin.GetVisualFromFBConfigSGIX )
+        {
+            _glfwWin.has_GLX_SGIX_fbconfig = GL_TRUE;
+        }
+    }
+
+    if( _glfwPlatformExtensionSupported( "GLX_ARB_multisample" ) )
+    {
+        _glfwWin.has_GLX_ARB_multisample = GL_TRUE;
+    }
+
+    if( _glfwPlatformExtensionSupported( "GLX_ARB_create_context" ) )
+    {
+        _glfwWin.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
+            _glfwPlatformGetProcAddress( "glXCreateContextAttribsARB" );
+
+        if( _glfwWin.CreateContextAttribsARB )
+        {
+            _glfwWin.has_GLX_ARB_create_context = GL_TRUE;
+        }
+    }
+
+    if( _glfwPlatformExtensionSupported( "GLX_ARB_create_context_profile" ) )
+    {
+        _glfwWin.has_GLX_ARB_create_context_profile = GL_TRUE;
+    }
+}
+
+
+//========================================================================
+// Create the X11 window (and its colormap)
+//========================================================================
+
+static GLboolean createWindow( int width, int height,
+                               const _GLFWwndconfig *wndconfig )
+{
+    XEvent event;
+    unsigned long wamask;
+    XSetWindowAttributes wa;
+
+    // Every window needs a colormap
+    // Create one based on the visual used by the current context
+
+    _glfwWin.colormap = XCreateColormap( _glfwLibrary.display,
+                                         _glfwWin.root,
+                                         _glfwWin.visual->visual,
+                                         AllocNone );
+
+    // Create the actual window
+    {
+        wamask = CWBorderPixel | CWColormap | CWEventMask;
+
+        wa.colormap = _glfwWin.colormap;
+        wa.border_pixel = 0;
+        wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
+            PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
+            ExposureMask | FocusChangeMask | VisibilityChangeMask;
+
+        if( wndconfig->mode == GLFW_WINDOW )
+        {
+            // The /only/ reason we are setting the background pixel here is
+            // that otherwise our window wont get any decorations on systems
+            // using Compiz on Intel hardware
+            wa.background_pixel = BlackPixel( _glfwLibrary.display, _glfwWin.screen );
+            wamask |= CWBackPixel;
+        }
+
+        _glfwWin.window = XCreateWindow(
+            _glfwLibrary.display,
+            _glfwWin.root,
+            0, 0,                            // Upper left corner of this window on root
+            _glfwWin.width, _glfwWin.height,
+            0,                               // Border width
+            _glfwWin.visual->depth,          // Color depth
+            InputOutput,
+            _glfwWin.visual->visual,
+            wamask,
+            &wa
+        );
+        if( !_glfwWin.window )
+        {
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+    }
+
+    // Check whether an EWMH-compliant window manager is running
+    _glfwWin.hasEWMH = checkForEWMH();
+
+    if( _glfwWin.fullscreen && !_glfwWin.hasEWMH )
+    {
+        // This is the butcher's way of removing window decorations
+        // Setting the override-redirect attribute on a window makes the window
+        // manager ignore the window completely (ICCCM, section 4)
+        // The good thing is that this makes undecorated fullscreen windows
+        // easy to do; the bad thing is that we have to do everything manually
+        // and some things (like iconify/restore) won't work at all, as they're
+        // usually performed by the window manager
+
+        XSetWindowAttributes attributes;
+        attributes.override_redirect = True;
+        XChangeWindowAttributes( _glfwLibrary.display,
+                                 _glfwWin.window,
+                                 CWOverrideRedirect,
+                                 &attributes );
+
+        _glfwWin.overrideRedirect = GL_TRUE;
+    }
+
+    // Find or create the protocol atom for window close notifications
+    _glfwWin.wmDeleteWindow = XInternAtom( _glfwLibrary.display,
+                                            "WM_DELETE_WINDOW",
+                                            False );
+
+    // Declare the WM protocols we support
+    {
+        int count = 0;
+        Atom protocols[2];
+
+        // The WM_DELETE_WINDOW ICCCM protocol
+        // Basic window close notification protocol
+        if( _glfwWin.wmDeleteWindow != None )
+        {
+            protocols[count++] = _glfwWin.wmDeleteWindow;
+        }
+
+        // The _NET_WM_PING EWMH protocol
+        // Tells the WM to ping our window and flag us as unresponsive if we
+        // don't reply within a few seconds
+        if( _glfwWin.wmPing != None )
+        {
+            protocols[count++] = _glfwWin.wmPing;
+        }
+
+        if( count > 0 )
+        {
+            XSetWMProtocols( _glfwLibrary.display, _glfwWin.window,
+                             protocols, count );
+        }
+    }
+
+    // Set ICCCM WM_HINTS property
+    {
+        XWMHints *hints = XAllocWMHints();
+        if( !hints )
+        {
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        hints->flags = StateHint;
+        hints->initial_state = NormalState;
+
+        XSetWMHints( _glfwLibrary.display, _glfwWin.window, hints );
+        XFree( hints );
+    }
+
+    // Set ICCCM WM_NORMAL_HINTS property (even if no parts are set)
+    {
+        XSizeHints *hints = XAllocSizeHints();
+        if( !hints )
+        {
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        hints->flags = 0;
+
+        if( wndconfig->windowNoResize )
+        {
+            hints->flags |= (PMinSize | PMaxSize);
+            hints->min_width  = hints->max_width  = _glfwWin.width;
+            hints->min_height = hints->max_height = _glfwWin.height;
+        }
+
+        XSetWMNormalHints( _glfwLibrary.display, _glfwWin.window, hints );
+        XFree( hints );
+    }
+
+    _glfwPlatformSetWindowTitle( "GLFW Window" );
+
+    // Make sure the window is mapped before proceeding
+    XMapWindow( _glfwLibrary.display, _glfwWin.window );
+    XPeekIfEvent( _glfwLibrary.display, &event, isMapNotify,
+                  (char*)_glfwWin.window );
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Enter fullscreen mode
+//========================================================================
+
+static void enterFullscreenMode( void )
+{
+    if( !_glfwWin.Saver.changed )
+    {
+        // Remember old screen saver settings
+        XGetScreenSaver( _glfwLibrary.display,
+                         &_glfwWin.Saver.timeout, &_glfwWin.Saver.interval,
+                         &_glfwWin.Saver.blanking, &_glfwWin.Saver.exposure );
+
+        // Disable screen saver
+        XSetScreenSaver( _glfwLibrary.display, 0, 0, DontPreferBlanking,
+                        DefaultExposures );
+
+        _glfwWin.Saver.changed = GL_TRUE;
+    }
+
+    _glfwSetVideoMode( _glfwWin.screen,
+                       &_glfwWin.width, &_glfwWin.height,
+                       &_glfwWin.refreshRate );
+
+    if( _glfwWin.hasEWMH &&
+        _glfwWin.wmState != None &&
+        _glfwWin.wmStateFullscreen != None )
+    {
+        if( _glfwWin.wmActiveWindow != None )
+        {
+            // Ask the window manager to raise and focus the GLFW window
+            // Only focused windows with the _NET_WM_STATE_FULLSCREEN state end
+            // up on top of all other windows ("Stacking order" in EWMH spec)
+
+            XEvent event;
+            memset( &event, 0, sizeof(event) );
+
+            event.type = ClientMessage;
+            event.xclient.window = _glfwWin.window;
+            event.xclient.format = 32; // Data is 32-bit longs
+            event.xclient.message_type = _glfwWin.wmActiveWindow;
+            event.xclient.data.l[0] = 1; // Sender is a normal application
+            event.xclient.data.l[1] = 0; // We don't really know the timestamp
+
+            XSendEvent( _glfwLibrary.display,
+                        _glfwWin.root,
+                        False,
+                        SubstructureNotifyMask | SubstructureRedirectMask,
+                        &event );
+        }
+
+        // Ask the window manager to make the GLFW window a fullscreen window
+        // Fullscreen windows are undecorated and, when focused, are kept
+        // on top of all other windows
+
+        XEvent event;
+        memset( &event, 0, sizeof(event) );
+
+        event.type = ClientMessage;
+        event.xclient.window = _glfwWin.window;
+        event.xclient.format = 32; // Data is 32-bit longs
+        event.xclient.message_type = _glfwWin.wmState;
+        event.xclient.data.l[0] = _NET_WM_STATE_ADD;
+        event.xclient.data.l[1] = _glfwWin.wmStateFullscreen;
+        event.xclient.data.l[2] = 0; // No secondary property
+        event.xclient.data.l[3] = 1; // Sender is a normal application
+
+        XSendEvent( _glfwLibrary.display,
+                    _glfwWin.root,
+                    False,
+                    SubstructureNotifyMask | SubstructureRedirectMask,
+                    &event );
+    }
+    else if( _glfwWin.overrideRedirect )
+    {
+        // In override-redirect mode, we have divorced ourselves from the
+        // window manager, so we need to do everything manually
+
+        XRaiseWindow( _glfwLibrary.display, _glfwWin.window );
+        XSetInputFocus( _glfwLibrary.display, _glfwWin.window,
+                        RevertToParent, CurrentTime );
+        XMoveWindow( _glfwLibrary.display, _glfwWin.window, 0, 0 );
+        XResizeWindow( _glfwLibrary.display, _glfwWin.window,
+                       _glfwWin.width, _glfwWin.height );
+    }
+
+    if( _glfwWin.mouseLock )
+    {
+        _glfwPlatformHideMouseCursor();
+    }
+
+    // HACK: 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 hack should be harmless on saner systems as well
+    XWarpPointer( _glfwLibrary.display, None, _glfwWin.window, 0,0,0,0, 0,0 );
+    XWarpPointer( _glfwLibrary.display, None, _glfwWin.window, 0,0,0,0,
+                  _glfwWin.width / 2, _glfwWin.height / 2 );
+}
+
+//========================================================================
+// Leave fullscreen mode
+//========================================================================
+
+static void leaveFullscreenMode( void )
+{
+    _glfwRestoreVideoMode();
+
+    // Did we change the screen saver setting?
+    if( _glfwWin.Saver.changed )
+    {
+        // Restore old screen saver settings
+        XSetScreenSaver( _glfwLibrary.display,
+                         _glfwWin.Saver.timeout,
+                         _glfwWin.Saver.interval,
+                         _glfwWin.Saver.blanking,
+                         _glfwWin.Saver.exposure );
+
+        _glfwWin.Saver.changed = GL_FALSE;
+    }
+
+    if( _glfwWin.hasEWMH &&
+        _glfwWin.wmState != None &&
+        _glfwWin.wmStateFullscreen != None )
+    {
+        // Ask the window manager to make the GLFW window a normal window
+        // Normal windows usually have frames and other decorations
+
+        XEvent event;
+        memset( &event, 0, sizeof(event) );
+
+        event.type = ClientMessage;
+        event.xclient.window = _glfwWin.window;
+        event.xclient.format = 32; // Data is 32-bit longs
+        event.xclient.message_type = _glfwWin.wmState;
+        event.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
+        event.xclient.data.l[1] = _glfwWin.wmStateFullscreen;
+        event.xclient.data.l[2] = 0; // No secondary property
+        event.xclient.data.l[3] = 1; // Sender is a normal application
+
+        XSendEvent( _glfwLibrary.display,
+                    _glfwWin.root,
+                    False,
+                    SubstructureNotifyMask | SubstructureRedirectMask,
+                    &event );
+    }
+
+    if( _glfwWin.mouseLock )
+    {
+        _glfwPlatformShowMouseCursor();
+    }
+}
+
+//========================================================================
+// Get and process next X event (called by _glfwPlatformPollEvents)
+// Returns GL_TRUE if a window close request was received
+//========================================================================
+
+static GLboolean processSingleEvent( void )
+{
+    XEvent event;
+    XNextEvent( _glfwLibrary.display, &event );
+
+    switch( event.type )
+    {
+        case KeyPress:
+        {
+            // A keyboard key was pressed
+
+            // Translate and report key press
+            _glfwInputKey( translateKey( event.xkey.keycode ), GLFW_PRESS );
+
+            // Translate and report character input
+            if( _glfwWin.charCallback )
+            {
+                _glfwInputChar( translateChar( &event.xkey ), GLFW_PRESS );
+            }
+            break;
+        }
+
+        case KeyRelease:
+        {
+            // A keyboard key was released
+
+            // Do not report key releases for key repeats. For key repeats we
+            // will get KeyRelease/KeyPress pairs with similar or identical
+            // time stamps. User selected key repeat filtering is handled in
+            // _glfwInputKey()/_glfwInputChar().
+            if( XEventsQueued( _glfwLibrary.display, QueuedAfterReading ) )
+            {
+                XEvent nextEvent;
+                XPeekEvent( _glfwLibrary.display, &nextEvent );
+
+                if( nextEvent.type == KeyPress &&
+                    nextEvent.xkey.window == event.xkey.window &&
+                    nextEvent.xkey.keycode == event.xkey.keycode )
+                {
+                    // This last check is a hack to work around key repeats
+                    // leaking through due to some sort of time drift
+                    // Toshiyuki Takahashi can press a button 16 times per
+                    // second so it's fairly safe to assume that no human is
+                    // pressing the key 50 times per second (value is ms)
+                    if( ( nextEvent.xkey.time - event.xkey.time ) < 20 )
+                    {
+                        // Do not report anything for this event
+                        break;
+                    }
+                }
+            }
+
+            // Translate and report key release
+            _glfwInputKey( translateKey( event.xkey.keycode ), GLFW_RELEASE );
+
+            // Translate and report character input
+            if( _glfwWin.charCallback )
+            {
+                _glfwInputChar( translateChar( &event.xkey ), GLFW_RELEASE );
+            }
+            break;
+        }
+
+        case ButtonPress:
+        {
+            // A mouse button was pressed or a scrolling event occurred
+
+            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;
+        }
+
+        case ButtonRelease:
+        {
+            // A mouse button was released
+
+            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;
+        }
+
+        case MotionNotify:
+        {
+            // The mouse cursor was moved
+
+            if( event.xmotion.x != _glfwInput.CursorPosX ||
+                event.xmotion.y != _glfwInput.CursorPosY )
+            {
+                // The mouse cursor was moved and we didn't do it
+
+                if( _glfwWin.mouseLock )
+                {
+                    if( _glfwWin.pointerHidden )
+                    {
+                        _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;
+
+                if( _glfwWin.mousePosCallback )
+                {
+                    _glfwWin.mousePosCallback( _glfwInput.MousePosX,
+                                               _glfwInput.MousePosY );
+                }
+            }
+            break;
+        }
+
+        case ConfigureNotify:
+        {
+            if( event.xconfigure.width != _glfwWin.width ||
+                event.xconfigure.height != _glfwWin.height )
+            {
+                // The window was resized
+
+                _glfwWin.width = event.xconfigure.width;
+                _glfwWin.height = event.xconfigure.height;
+                if( _glfwWin.windowSizeCallback )
+                {
+                    _glfwWin.windowSizeCallback( _glfwWin.width,
+                                                 _glfwWin.height );
+                }
+            }
+            break;
+        }
+
+        case ClientMessage:
+        {
+            if( (Atom) event.xclient.data.l[ 0 ] == _glfwWin.wmDeleteWindow )
+            {
+                // The window manager was asked to close the window, for example by
+                // the user pressing a 'close' window decoration button
+
+                return GL_TRUE;
+            }
+            else if( _glfwWin.wmPing != None &&
+                     (Atom) event.xclient.data.l[ 0 ] == _glfwWin.wmPing )
+            {
+                // The window manager is pinging us to make sure we are still
+                // responding to events
+
+                event.xclient.window = _glfwWin.root;
+                XSendEvent( _glfwLibrary.display,
+                            event.xclient.window,
+                            False,
+                            SubstructureNotifyMask | SubstructureRedirectMask,
+                            &event );
+            }
+
+            break;
+        }
+
+        case MapNotify:
+        {
+            // The window was mapped
+
+            _glfwWin.iconified = GL_FALSE;
+            break;
+        }
+
+        case UnmapNotify:
+        {
+            // The window was unmapped
+
+            _glfwWin.iconified = GL_TRUE;
+            break;
+        }
+
+        case FocusIn:
+        {
+            // The window gained focus
+
+            _glfwWin.active = GL_TRUE;
+
+            if( _glfwWin.mouseLock )
+            {
+                _glfwPlatformHideMouseCursor();
+            }
+
+            break;
+        }
+
+        case FocusOut:
+        {
+            // The window lost focus
+
+            _glfwWin.active = GL_FALSE;
+            _glfwInputDeactivation();
+
+            if( _glfwWin.mouseLock )
+            {
+                _glfwPlatformShowMouseCursor();
+            }
+
+            break;
+        }
+
+        case Expose:
+        {
+            // The window's contents was damaged
+
+            if( _glfwWin.windowRefreshCallback )
+            {
+                _glfwWin.windowRefreshCallback();
+            }
+            break;
+        }
+
+        // Was the window destroyed?
+        case DestroyNotify:
+            return GL_FALSE;
+
+        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;
+}
+
+
+
+//************************************************************************
+//****               Platform implementation functions                ****
+//************************************************************************
+
+//========================================================================
+// Here is where the window is created, and
+// the OpenGL rendering context is created
+//========================================================================
+
+int _glfwPlatformOpenWindow( int width, int height,
+                             const _GLFWwndconfig* wndconfig,
+                             const _GLFWfbconfig* fbconfig )
+{
+    _GLFWfbconfig closest;
+
+    // Clear platform specific GLFW window state
+    _glfwWin.visual           = (XVisualInfo*)NULL;
+    _glfwWin.colormap         = (Colormap)0;
+    _glfwWin.context          = (GLXContext)NULL;
+    _glfwWin.window           = (Window)0;
+    _glfwWin.pointerGrabbed   = GL_FALSE;
+    _glfwWin.pointerHidden    = GL_FALSE;
+    _glfwWin.keyboardGrabbed  = GL_FALSE;
+    _glfwWin.overrideRedirect = GL_FALSE;
+    _glfwWin.FS.modeChanged   = GL_FALSE;
+    _glfwWin.Saver.changed    = GL_FALSE;
+    _glfwWin.refreshRate      = wndconfig->refreshRate;
+    _glfwWin.windowNoResize   = wndconfig->windowNoResize;
+
+    _glfwWin.wmDeleteWindow    = None;
+    _glfwWin.wmPing            = None;
+    _glfwWin.wmState           = None;
+    _glfwWin.wmStateFullscreen = None;
+    _glfwWin.wmActiveWindow    = None;
+
+    // As the 2.x API doesn't understand multiple display devices, we hardcode
+    // this choice and hope for the best
+    _glfwWin.screen = DefaultScreen( _glfwLibrary.display );
+    _glfwWin.root = RootWindow( _glfwLibrary.display, _glfwWin.screen );
+
+    // Create the invisible cursor for hidden cursor mode
+    _glfwWin.cursor = createNULLCursor( _glfwLibrary.display, _glfwWin.root );
+
+    initGLXExtensions();
+
+    // Choose the best available fbconfig
+    {
+        unsigned int fbcount;
+        _GLFWfbconfig *fbconfigs;
+        const _GLFWfbconfig *result;
+
+        fbconfigs = getFBConfigs( &fbcount );
+        if( !fbconfigs )
+        {
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        result = _glfwChooseFBConfig( fbconfig, fbconfigs, fbcount );
+        if( !result )
+        {
+            free( fbconfigs );
+            _glfwPlatformCloseWindow();
+            return GL_FALSE;
+        }
+
+        closest = *result;
+        free( fbconfigs );
+    }
+
+    if( !createContext( wndconfig, (GLXFBConfigID) closest.platformID ) )
+    {
+        _glfwPlatformCloseWindow();
+        return GL_FALSE;
+    }
+
+    if( !createWindow( width, height, wndconfig ) )
+    {
+        _glfwPlatformCloseWindow();
+        return GL_FALSE;
+    }
+
+    if( wndconfig->mode == GLFW_FULLSCREEN )
+    {
+#if defined( _GLFW_HAS_XRANDR )
+        // Request screen change notifications
+        if( _glfwLibrary.XRandR.available )
+        {
+            XRRSelectInput( _glfwLibrary.display,
+                            _glfwWin.window,
+                            RRScreenChangeNotifyMask );
+        }
+#endif
+        enterFullscreenMode();
+    }
+
+    // Process the window map event and any other that may have arrived
+    _glfwPlatformPollEvents();
+
+    // Retrieve and set initial cursor position
+    {
+        Window window, root;
+        int windowX, windowY, rootX, rootY;
+        unsigned int mask;
+
+        XQueryPointer( _glfwLibrary.display,
+                       _glfwWin.window,
+                       &root,
+                       &window,
+                       &rootX, &rootY,
+                       &windowX, &windowY,
+                       &mask );
+
+        // TODO: Probably check for some corner cases here.
+
+        _glfwInput.MousePosX = windowX;
+        _glfwInput.MousePosY = windowY;
+    }
+
+    // Connect the context to the window
+    glXMakeCurrent( _glfwLibrary.display, _glfwWin.window, _glfwWin.context );
+
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Properly kill the window/video display
+//========================================================================
+
+void _glfwPlatformCloseWindow( void )
+{
+    if( _glfwWin.fullscreen )
+    {
+        leaveFullscreenMode();
+    }
+
+    if( _glfwWin.context )
+    {
+        // Release and destroy the context
+        glXMakeCurrent( _glfwLibrary.display, None, NULL );
+        glXDestroyContext( _glfwLibrary.display, _glfwWin.context );
+        _glfwWin.context = NULL;
+    }
+
+    if( _glfwWin.visual )
+    {
+        XFree( _glfwWin.visual );
+        _glfwWin.visual = NULL;
+    }
+
+    if( _glfwWin.window )
+    {
+        XUnmapWindow( _glfwLibrary.display, _glfwWin.window );
+        XDestroyWindow( _glfwLibrary.display, _glfwWin.window );
+        _glfwWin.window = (Window) 0;
+    }
+
+    if( _glfwWin.colormap )
+    {
+        XFreeColormap( _glfwLibrary.display, _glfwWin.colormap );
+        _glfwWin.colormap = (Colormap) 0;
+    }
+
+    if( _glfwWin.cursor )
+    {
+        XFreeCursor( _glfwLibrary.display, _glfwWin.cursor );
+        _glfwWin.cursor = (Cursor) 0;
+    }
+}
+
+
+//========================================================================
+// Set the window title
+//========================================================================
+
+void _glfwPlatformSetWindowTitle( const char *title )
+{
+    // Set window & icon title
+    XStoreName( _glfwLibrary.display, _glfwWin.window, title );
+    XSetIconName( _glfwLibrary.display, _glfwWin.window, title );
+}
+
+
+//========================================================================
+// Set the window size
+//========================================================================
+
+void _glfwPlatformSetWindowSize( int width, int height )
+{
+    int     mode = 0, rate, sizeChanged = GL_FALSE;
+    XSizeHints *sizehints;
+
+    rate = _glfwWin.refreshRate;
+
+    if( _glfwWin.fullscreen )
+    {
+        // Get the closest matching video mode for the specified window size
+        mode = _glfwGetClosestVideoMode( _glfwWin.screen, &width, &height, &rate );
+    }
+
+    if( _glfwWin.windowNoResize )
+    {
+        // Update window size restrictions to match new window size
+
+        sizehints = XAllocSizeHints();
+        sizehints->flags = 0;
+
+        sizehints->min_width  = sizehints->max_width  = width;
+        sizehints->min_height = sizehints->max_height = height;
+
+        XSetWMNormalHints( _glfwLibrary.display, _glfwWin.window, sizehints );
+        XFree( sizehints );
+    }
+
+    // Change window size before changing fullscreen mode?
+    if( _glfwWin.fullscreen && (width > _glfwWin.width) )
+    {
+        XResizeWindow( _glfwLibrary.display, _glfwWin.window, width, height );
+        sizeChanged = GL_TRUE;
+    }
+
+    if( _glfwWin.fullscreen )
+    {
+        // Change video mode, keeping current refresh rate
+        _glfwSetVideoModeMODE( _glfwWin.screen, mode, _glfwWin.refreshRate );
+    }
+
+    // Set window size (if not already changed)
+    if( !sizeChanged )
+    {
+        XResizeWindow( _glfwLibrary.display, _glfwWin.window, width, height );
+    }
+}
+
+
+//========================================================================
+// Set the window position.
+//========================================================================
+
+void _glfwPlatformSetWindowPos( int x, int y )
+{
+    XMoveWindow( _glfwLibrary.display, _glfwWin.window, x, y );
+}
+
+
+//========================================================================
+// Window iconification
+//========================================================================
+
+void _glfwPlatformIconifyWindow( void )
+{
+    if( _glfwWin.overrideRedirect )
+    {
+        // We can't iconify/restore override-redirect windows, as that's
+        // performed by the window manager
+        return;
+    }
+
+    XIconifyWindow( _glfwLibrary.display, _glfwWin.window, _glfwWin.screen );
+}
+
+
+//========================================================================
+// Window un-iconification
+//========================================================================
+
+void _glfwPlatformRestoreWindow( void )
+{
+    if( _glfwWin.overrideRedirect )
+    {
+        // We can't iconify/restore override-redirect windows, as that's
+        // performed by the window manager
+        return;
+    }
+
+    XMapWindow( _glfwLibrary.display, _glfwWin.window );
+}
+
+
+//========================================================================
+// Swap OpenGL buffers and poll any new events
+//========================================================================
+
+void _glfwPlatformSwapBuffers( void )
+{
+    // Update display-buffer
+    glXSwapBuffers( _glfwLibrary.display, _glfwWin.window );
+}
+
+
+//========================================================================
+// Set double buffering swap interval
+//========================================================================
+
+void _glfwPlatformSwapInterval( int interval )
+{
+    if( _glfwWin.has_GLX_SGI_swap_control )
+    {
+        _glfwWin.SwapIntervalSGI( interval );
+    }
+}
+
+
+//========================================================================
+// Read back framebuffer parameters from the context
+//========================================================================
+
+void _glfwPlatformRefreshWindowParams( void )
+{
+    int dummy;
+    GLXFBConfig *fbconfig;
+#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 attribs[] = { GLX_FBCONFIG_ID, _glfwWin.fbconfigID, None };
+
+    if( _glfwWin.has_GLX_SGIX_fbconfig )
+    {
+        fbconfig = _glfwWin.ChooseFBConfigSGIX( _glfwLibrary.display,
+                                                _glfwWin.screen,
+                                                attribs,
+                                                &dummy );
+    }
+    else
+    {
+        fbconfig = glXChooseFBConfig( _glfwLibrary.display,
+                                    _glfwWin.screen,
+                                    attribs,
+                                    &dummy );
+    }
+
+    if( fbconfig == NULL )
+    {
+        // This should never ever happen
+        // TODO: Figure out what to do when this happens
+        fprintf( stderr, "Cannot find known GLXFBConfig by ID. "
+                         "This cannot happen. Have a nice day.\n");
+        abort();
+    }
+
+    // There is no clear definition of an "accelerated" context on X11/GLX, and
+    // true sounds better than false, so we hardcode true here
+    _glfwWin.accelerated = GL_TRUE;
+
+    _glfwWin.redBits = getFBConfigAttrib( *fbconfig, GLX_RED_SIZE );
+    _glfwWin.greenBits = getFBConfigAttrib( *fbconfig, GLX_GREEN_SIZE );
+    _glfwWin.blueBits = getFBConfigAttrib( *fbconfig, GLX_BLUE_SIZE );
+
+    _glfwWin.alphaBits = getFBConfigAttrib( *fbconfig, GLX_ALPHA_SIZE );
+    _glfwWin.depthBits = getFBConfigAttrib( *fbconfig, GLX_DEPTH_SIZE );
+    _glfwWin.stencilBits = getFBConfigAttrib( *fbconfig, GLX_STENCIL_SIZE );
+
+    _glfwWin.accumRedBits = getFBConfigAttrib( *fbconfig, GLX_ACCUM_RED_SIZE );
+    _glfwWin.accumGreenBits = getFBConfigAttrib( *fbconfig, GLX_ACCUM_GREEN_SIZE );
+    _glfwWin.accumBlueBits = getFBConfigAttrib( *fbconfig, GLX_ACCUM_BLUE_SIZE );
+    _glfwWin.accumAlphaBits = getFBConfigAttrib( *fbconfig, GLX_ACCUM_ALPHA_SIZE );
+
+    _glfwWin.auxBuffers = getFBConfigAttrib( *fbconfig, GLX_AUX_BUFFERS );
+    _glfwWin.stereo = getFBConfigAttrib( *fbconfig, GLX_STEREO ) ? 1 : 0;
+
+    // Get FSAA buffer sample count
+    if( _glfwWin.has_GLX_ARB_multisample )
+    {
+        _glfwWin.samples = getFBConfigAttrib( *fbconfig, GLX_SAMPLES );
+    }
+    else
+    {
+        _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.display, _glfwWin.root );
+        _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.display, _glfwWin.screen,
+                                &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
+
+    XFree( fbconfig );
+}
+
+
+//========================================================================
+// Poll for new window and input events
+//========================================================================
+
+void _glfwPlatformPollEvents( void )
+{
+    GLboolean closeRequested = GL_FALSE;
+
+    // Flag that the cursor has not moved
+    _glfwInput.MouseMoved = GL_FALSE;
+
+    // Process all pending events
+    while( XPending( _glfwLibrary.display ) )
+    {
+        if( processSingleEvent() )
+        {
+            closeRequested = GL_TRUE;
+        }
+    }
+
+    // Did we get mouse movement in fully enabled hidden cursor mode?
+    if( _glfwInput.MouseMoved && _glfwWin.pointerHidden )
+    {
+        _glfwPlatformSetMouseCursorPos( _glfwWin.width/2,
+                                        _glfwWin.height/2 );
+    }
+
+    if( closeRequested && _glfwWin.windowCloseCallback )
+    {
+        closeRequested = _glfwWin.windowCloseCallback();
+    }
+    if( closeRequested )
+    {
+        glfwCloseWindow();
+    }
+}
+
+
+//========================================================================
+// Wait for new window and input events
+//========================================================================
+
+void _glfwPlatformWaitEvents( void )
+{
+    XEvent event;
+
+    // Block waiting for an event to arrive
+    XNextEvent( _glfwLibrary.display, &event );
+    XPutBackEvent( _glfwLibrary.display, &event );
+
+    _glfwPlatformPollEvents();
+}
+
+
+//========================================================================
+// Hide mouse cursor (lock it)
+//========================================================================
+
+void _glfwPlatformHideMouseCursor( void )
+{
+    // Hide cursor
+    if( !_glfwWin.pointerHidden )
+    {
+        XDefineCursor( _glfwLibrary.display, _glfwWin.window, _glfwWin.cursor );
+        _glfwWin.pointerHidden = GL_TRUE;
+    }
+
+    // Grab cursor to user window
+    if( !_glfwWin.pointerGrabbed )
+    {
+        if( XGrabPointer( _glfwLibrary.display, _glfwWin.window, True,
+                          ButtonPressMask | ButtonReleaseMask |
+                          PointerMotionMask, GrabModeAsync, GrabModeAsync,
+                          _glfwWin.window, None, CurrentTime ) ==
+            GrabSuccess )
+        {
+            _glfwWin.pointerGrabbed = GL_TRUE;
+        }
+    }
+}
+
+
+//========================================================================
+// 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 )
+    {
+        XUngrabPointer( _glfwLibrary.display, CurrentTime );
+        _glfwWin.pointerGrabbed = GL_FALSE;
+    }
+
+    // Show cursor
+    if( _glfwWin.pointerHidden )
+    {
+        XUndefineCursor( _glfwLibrary.display, _glfwWin.window );
+        _glfwWin.pointerHidden = GL_FALSE;
+    }
+}
+
+
+//========================================================================
+// Set physical mouse cursor position
+//========================================================================
+
+void _glfwPlatformSetMouseCursorPos( int x, int y )
+{
+    // Store the new position so we can recognise it later
+    _glfwInput.CursorPosX = x;
+    _glfwInput.CursorPosY = y;
+
+    XWarpPointer( _glfwLibrary.display, None, _glfwWin.window, 0,0,0,0, x, y );
+}
+

+ 1149 - 0
ThirdParty/GLFW/readme.html

@@ -0,0 +1,1149 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+  <title>GLFW Readme File</title>
+</head>
+
+<body>
+
+<h1>GLFW 2.7 source distribution</h1>
+
+<ol>
+ <li><a href="#intro">Introduction</a></li>
+ <li><a href="#compiling">Compiling GLFW and the example programs</a></li>
+ <li><a href="#installing">Installing GLFW</a></li>
+ <li><a href="#using">Using GLFW</a></li>
+ <li><a href="#changelog">Version history</a></li>
+ <li><a href="#structure">Directory structure of the GLFW distribution</a></li>
+ <li><a href="#contact">Contacting the project</a></li>
+ <li><a href="#credits">Acknowledgements</a></li>
+</ol>
+
+<a name="intro">
+<h2>1. Introduction</h2>
+
+<p>Welcome to version 2.7 of the GLFW OpenGL framework, codenamed "Godot". GLFW
+is a free, open source, portable framework for OpenGL application development.
+In short, it is a library that provides a powerful API for handling operating
+system specific tasks, such as opening an OpenGL window, reading keyboard,
+mouse, joystick and time input, creating threads, and more.</p>
+
+<p>This is expected to be the last major release of the 2.x series, with the
+expectation being that most development will take place in the 3.0 branch.</p>
+
+<p>only major additions in this release is support for creating OpenGL contexts
+of version 3.0 and above, and a new Cocoa port for Mac OS X 10.5 and above.
+Note that as Mac OS X does not yet support OpenGL 3.0, attempts to create such
+a context on that system will fail.</p>
+
+<a name="compiling">
+<h2>2. Compiling GLFW and the example programs</h2>
+
+<p>A top level makefile can be found in the root directory of the GLFW
+distribution that has been designed to work with several compilers. If you
+simply enter the GLFW root directory in a shell and type <code>make</code> (or
+<code>nmake</code> or <code>gmake</code>, depending on the name of your make
+tool), and a list should appear with the currently supported options for
+systems and compilers.</p>
+
+<p>For example, one of the options is to compile GLFW for Windows with the
+LCC-Win32 C compiler, i.e.:</p>
+
+<blockquote><code>make win32-lcc</code></blockquote>
+
+<p>That will compile the GLFW static link library and the supplied example
+programs. For Windows compilers, a Win32 DLL will also be compiled.</p>
+
+<p>Currently supported compilers and systems are:</p>
+
+<ol>
+  <li>Microsoft Visual C++ 9.0 and above</li>
+  <li>MSYS or Cygwin for Windows</li>
+  <li>Bare MinGW for Windows</li>
+  <li>LCC-Win32 for Windows</li>
+  <li>OpenWatcom for Windows</li>
+  <li>MinGW cross-compilation for Unix or Unix-like systems</li>
+  <li>Unix or Unix-like systems running the X Window System</li>
+  <li>Apple GCC or Clang on Mac OS X</li>
+</ol>
+
+<p>There are also project files available for Microsoft Visual C++ 9.0 in the
+<code>support/msvc90</code> directory.</p>
+
+<p>If your compiler/system is not in the list, you may have to create new
+makefiles in the <code>lib\win32</code>, <code>lib/x11</code> or
+<code>lib/cocoa</code> directory, and in the <code>examples</code> directory.
+If you have any problems, please use our
+<a href="http://sourceforge.net/projects/glfw/forums/forum/247562">support forum</a>
+and
+<a href="http://sourceforge.net/tracker/?group_id=72569&atid=534938">bug tracker</a>
+on SourceForge.net. We would like to support as many systems as possible, so if
+you had to make any modifications or additions to the source and/or makefiles
+in order to make GLFW compile successfully, we would very much like to know
+what you had to do.</p>
+
+
+<h3>2.1 Microsoft Windows</h3>
+
+<p>When building GLFW as a DLL (dynamic link library), all compilation units
+need to have the <code>GLFW_BUILD_DLL</code> macro defined.  All build methods
+listed below already does this, but you need to do it yourself if you are
+making a custom build.  Without this macro, the GLFW DLL will not export
+functions correctly and code calling the DLL will be incorrectly generated.</p>
+
+<h4>2.1.1 Microsoft Visual C++ 9.0 and above</h4>
+
+<p>Project files for both the static and dynamic versions of the GLFW library
+are provided in the <code>support/msvc90</code> directory, as well as project
+files for all example and test programs.</p>
+
+
+<h4>2.1.2 MSYS or Cygwin on Windows</h4>
+
+<p>GLFW can be cross-compiled to native Win32 code using the Cygwin
+environment.  The Cygwin build path will also work on MinGW with MSYS.</p>
+
+<p>Open a Cygwin or MSYS shell, enter the GLFW root directory and run make with
+the <code>win32-cygwin</code> target.</p>
+
+
+<h4>2.1.3 Bare MinGW on Windows</h4>
+
+<p>GLFW can be compiled using only bare bone MinGW, using the Windows
+command-line environment for file management.  Open a regular command prompt,
+enter the GLFW root directory and run the MinGW make program
+<code>mingw32-make</code> with the <code>win32-mingw</code> target.</p>
+
+
+<h4>2.1.4 OpenWatcom on Windows</h4>
+
+<p>GLFW can be compiled using <a href="http://www.openwatcom.org/">OpenWatcom</a>
+for Windows by running the following in the GLFW root directory:</p>
+
+<blockquote><code>nmake MAKE=nmake win32-ow</code></blockquote>
+
+<p>Also make sure that you have all your environment variables set up
+correctly.  It is the default option when installing OpenWatcom to permanently
+set up all the required environment variables.  If <code>nmake</code> is
+unavailable, you probably have to run <code>WATCOM\setvars.bat</code> from the
+command prompt first, where <code>WATCOM</code> is the directory in which you
+installed OpenWatcom (e.g. <code>C:\Watcom</code>).</p>
+
+
+<h4>2.1.5 MinGW cross-compilation for Unix or Unix-like systems</h4>
+
+<p>Some Unix-like systems have a MinGW cross-compilation package for compiling
+native Win32 binaries, for example the <code>mingw32</code> package on Debian
+GNU/Linux and its derivatives.  You can use this to build Win32 binaries of
+GLFW and all examples without having to run Microsoft Windows.  Use the regular
+make program with the <code>cross-mgw</code> target.  These binaries are also
+regularly tested with Wine.</p>
+
+
+<h3>2.2 X11 on Unix-like systems</h3>
+
+<p>Compiler and link library capabilities are auto-detected with a script
+called <code>compile.sh</code>.  Note that you don't need to run this script
+yourself, as it is run automatically when necessary.  It has been tested under
+Ubuntu Linux, Slackware Linux, Debian GNU/Linux and others and should
+hopefully run on the majority of available Unix-like systems and generate
+functional Makefiles.  You do not have to run the script manually, since it is
+called from the top-level makefile.</p>
+
+<p>If you wish to customize the compilation or link flags for GLFW, set the
+<code>CFLAGS</code> or <code>LFLAGS</code> environment variables as needed
+before building the library.  These flags will be picked up and added to the
+generated <code>Makefile.x11</code> files.</p>
+
+<p>If you wish to use a certain compiler, set the <code>CC</code> environment
+variable before building the library.  This will also be stored in the
+generated <code>Makefile.x11</code> files.</p>
+
+<p>If you have already configured your source tree, you can reset it to an
+un-configured state by running make with the <code>x11-dist-clean</code>
+target.</p>
+
+<p>If you are making your own build setup for GLFW, you need to be aware of the
+various preprocessor symbols that the bundled makefiles use to enable various
+features and code paths.  They need to be defined either on the command-line or
+at the very beginning for each GLFW source file with an <code>x11_</code>
+prefix.</p>
+
+<p>Note that the X11 port of GLFW compiles on Mac OS X, but is currently unable
+to open a window when running against X11.app, due to Apple's incomplete
+implementation of GLXFBConfigs.</p>
+
+<table border=1>
+  <tr>
+    <td>_GLFW_USE_LINUX_JOYSTICKS</td>
+    <td>Use the Linux joystick API. This is the only supported API for the X11
+        port. Without it, joystick input will be unavailable.</td>
+  </tr>
+  <tr>
+    <td>_GLFW_HAS_XRANDR</td>
+    <td>Use the X Resize and Rotate extension for display mode changes. This is
+        the preferred method.</td>
+  </tr>
+  <tr>
+    <td>_GLFW_HAS_XF86VIDMODE</td>
+    <td>Use the Xf86VidMode extension for display mode changes. This is a
+        fall-back method.</td>
+  </tr>
+  <tr>
+    <td>_GLFW_HAS_PTHREAD</td>
+    <td>Use the POSIX Threads API for threading. This is the only supported API
+        for the X11 port. Without it, threading will be disabled.</td>
+  </tr>
+  <tr>
+    <td>_GLFW_HAS_SCHED_YIELD</td>
+    <td>Call the <code>sched_yield</code> function inside <code>glfwPlatformSleep</code>.</td>
+  </tr>
+  <tr>
+    <td>_GLFW_HAS_GLXGETPROCADDRESS</td>
+    <td>Use the <code>glXGetProcAddress</code> function to retrieve OpenGL
+        entry point addresses.</td>
+  </tr>
+  <tr>
+    <td>_GLFW_HAS_GLXGETPROCADDRESSARB</td>
+    <td>Use the <code>glXGetProcAddressARB</code> function to retrieve OpenGL
+        entry point addresses.</td>
+  </tr>
+  <tr>
+    <td>_GLFW_HAS_GLXGETPROCADDRESSEXT</td>
+    <td>Use the <code>glXGetProcAddressEXT</code> function to retrieve OpenGL
+        entry point addresses.</td>
+  </tr>
+  <tr>
+    <td>_GLFW_HAS_DLOPEN</td>
+    <td>Use <code>dlopen</code> on the OpenGL shared library to retrieve OpenGL
+        entry point addresses.  This is a fall-back method.</td>
+  </tr>
+  <tr>
+    <td>_GLFW_HAS_SYSCONF</td>
+    <td>Use the sysconf API to find the number of processors.</td>
+  </tr>
+  <tr>
+    <td>_GLFW_HAS_SYSCTL</td>
+    <td>Use the sysctl API to find the number of processors.</td>
+  </tr>
+</table>
+
+
+<h3>2.3 Apple GCC or Clang on Mac OS X</h3>
+
+<p>To compile GLFW for Mac OS X, you will need to have installed the Developer
+Tools.  A version of these tools can be found on your Mac OS X disc, with newer
+versions available from the Apple Developer Connection site.  When they are
+installed, simply open Terminal and go to the root GLFW directory.  From there,
+you can build the library and all the examples by running make with the
+appropriate target, i.e.:</p>
+
+<blockquote><code>make cocoa</code></blockquote>
+
+<p>The default compiler for the Cocoa port of GLFW is <code>cc</code>, which as
+of Mac OS X 10.6 still defaults to GCC, but you can override this using the
+<code>CC</code> environment variable.  For example, to build GLFW using Clang,
+use:</p>
+
+<blockquote><code>env CC=clang make cocoa</code></blockquote>
+
+<p>There is also a deprecated Carbon port of GLFW, which is limited to
+32-bit code and only runs well on Mac OS X 10.3 and 10.4.  However, if you
+need to build applications for those systems, it is a better choice than
+the Cocoa port, which uses APIs unavailable on systems older than 10.5.</p>
+
+
+<a name="installing">
+<h2>3. Installing GLFW</h2>
+
+<h3>3.1 Windows</h3>
+
+<p>After compiling GLFW with MinGW or Cygwin, three files of interest should
+have appeared in the <code>lib\win32</code> directory. They are:
+<code>libglfw.a</code> (the static link version of GLFW), <code>glfw.dll</code>
+(the DLL version of GLFW) and <code>libglfwdll.a</code> (the DLL import
+library).</p>
+
+<p>To install GLFW on Cygwin (and possibly MinGW), run make with the
+<code>cygwin-install</code> target.  This will generate the pkg-config file and
+copy it, the header file and the library to the correct locations of your
+Cygwin installation. If you wish to change the installation location from its
+default, set the desired prefix path with the environment variable
+<code>PREFIX</code>.</p>
+
+<p>If you used Borland C++ Builder, LCC-Win32, Microsoft Visual C++ or
+OpenWatcom, the files are named <code>glfw.lib</code> (the static link version
+of GLFW), <code>glfw.dll</code> (the DLL version of GLFW) and
+<code>glfwdll.lib</code> (the DLL import library).</p>
+
+<p>The static link library and the DLL import library should be copied to your
+compiler's <code>LIB</code> directory (where all other link libraries are
+located).  The DLL can be copied either to your Windows system directory (where
+opengl32.dll is located), or to the project directory of your GLFW-based
+projects (where you place your executable files).</p>
+
+<p>You should also copy the GLFW include file, <code>include\GL\glfw.h</code>,
+to the <code>GL</code> directory of your compiler's include directory (i.e.
+where <code>gl.h</code>, <code>glu.h</code> etc. are located).</p>
+
+
+<h3>3.2 Unix</h3>
+
+<p>After compiling GLFW, three files named <code>libglfw.pc.in</code>,
+<code>libglfw.a</code> and <code>libglfw.so</code> should have appeared in the
+<code>lib/x11</code> directory. This is the pkg-config template file, the GLFW
+static link library and the GLFW shared library, respectively.</p>
+
+<p>To install GLFW onto your system, run make as root with the
+<code>x11-install</code> make target. This will install the pkg-config file, the
+static library and the header. By default, the files will be installed under
+<code>/usr/local</code>. If you wish to install to a different location, set the
+<code>PREFIX</code> environment variable appropriately when running make.</p>
+
+<p>Note that the shared library is not installed by default, as you really
+should think twice before using it. GLFW is very small and shared library
+distribution on Unix outside of packaging systems is quite tricky. The GLFW
+license also allows static linking without requiring you to share your
+code.</p>
+
+<p>However, if you're a *nix distribution packager, use a language binding or
+for some other reason wish to install the shared library along with the rest,
+run make with the <code>x11-distro-install</code> target.</p>
+
+
+<h3>3.4 Mac OS X</h3>
+
+<p>After compiling GLFW, three files named <code>libglfw.pc.in</code>,
+<code>libglfw.a</code> and <code>libglfw.dylib</code> should appear in the
+<code>lib/cocoa</code> directory. This is the pkg-config template file, the GLFW
+static link library and the GLFW dynamic library, respectively.</p>
+
+<p>To install GLFW onto your system, run make with sudo and the
+<code>cocoa-install</code> build target, i.e.:</p>
+
+<blockquote><code>sudo make cocoa-install</code></blockquote>
+
+<p>This will install the pkg-config file, the static library and the header. By
+default, the files will be installed under <code>/usr/local</code>. If you wish
+to install to a different location, set the environment variable
+<code>PREFIX</code> appropriately when running make.</p>
+
+<p>Note that the shared library is not installed by default, as you really
+should think twice before using it. GLFW is very small and very suitable for
+static linking. The GLFW license also allows static linking without requiring
+your to share your code.</p>
+
+<a name="using">
+<h2>4. Using GLFW</h2>
+
+<p>There are two aspects to using GLFW:</p>
+
+<ol>
+  <li>How does the GLFW API work</li>
+  <li>How to compile programs that use GLFW</li>
+</ol>
+
+<p>The first point is covered in the
+<a href="docs/UsersGuide.pdf">GLFW Users Guide</a> and the
+<a href="docs/Reference.pdf">GLFW Reference Manual</a>, and we suggest that you
+read at least the Users Guide, since it's a good introduction to the GLFW
+API.</p>
+
+<p>Designing and compiling programs that use GLFW is not very difficult.
+A few rules for successfully designing GLFW-based programs are presented
+in the following sections.</p>
+
+<h3>4.1 Include the GLFW header file</h3>
+
+<p>In the files of your program where you use OpenGL or GLFW, you should
+include the <code>GL/glfw.h</code> header file, i.e.:</p>
+
+<blockquote><code>#include &lt;GL/glfw.h&gt;</code></blockquote>
+
+<p>This defines all the constants, types and function prototypes of the GLFW
+API.  It also includes the <code>gl.h</code> and </code>GL/glu.h</code> header
+files, and - this is very important - <em>it defines all the necessary
+constants and types that are necessary for the OpenGL headers to work on
+different platforms</em>.</p>
+
+<p>For example, under Microsoft Windows you are normally required to include
+<code>windows.h</code> before you include <code>GL/gl.h</code>.  This would
+however make your code dependent on the Windows platform, or at least require
+your program to check which platform it is being compiled on.
+
+The GLFW header file takes care of this for you, not by including
+<code>windows.h</code>, but rather by itself duplicating the necessary parts of
+it.  This way, the namespace won't be cluttered by the entire Windows API.</p>
+
+<p>In other words:
+<ul>
+  <li>Do <em>not</em> include <code>GL/gl.h</code> or <code>GL/glu.h</code>
+      yourself, as GLFW does this for you</li>
+  <li>Do <em>not</em> include <code>windows.h</code> unless you actually need
+      direct access to the Windows API</li>
+  <li>If you <em>do</em> need to include <code>windows.h</code>, do it
+      <em>before</em> including <code>GL/glfw.h</code> and the GLFW header will
+      detect this.</p>
+</ul>
+
+<p>Also note that if you are using an OpenGL extension loading library such as
+<a href="http://glew.sourceforge.net/">GLEW</a>, you should include the GLEW
+header <em>before</em> the GLFW one.  The GLEW header defines macros that
+disable any <code>gl.h</code> that the GLFW header includes and GLEW will work
+as expected.</p>
+
+
+
+<h3>4.2 Link with the right libraries</h3>
+
+<h4>4.2.1 Windows static library</h4>
+
+<p>If you link with the static version of GLFW, it is also necessary to
+link with some system libraries that GLFW uses.</p>
+
+<p>When linking a program under Windows that uses the static version of GLFW,
+you must also link with the following libraries: <code>opengl32</code>,
+<code>user32</code> and <code>kernel32</code>. Some of these libraries may be
+linked with by default by your compiler. In the table below you can see the
+minimum required link options for each supported Windows compiler (you may want
+to add other libraries as well, such as <code>glu32</code>):</p>
+
+<table border=1>
+  <tr>
+    <td><b>Compiler</b></td>
+    <td><b>Link options</b></td>
+  </tr>
+  <tr>
+    <td>Borland C++ Builder</td>
+    <td><code>glfw.lib opengl32.lib</code></td>
+  </tr>
+  <tr>
+    <td>Cygwin</td>
+    <td><i>See Unix static library below</i></td>
+  </tr>
+  <tr>
+    <td>LCC-Win32</td>
+    <td><code>glfw.lib opengl32.lib</code></td>
+  </tr>
+  <tr>
+    <td>Microsoft Visual C++</td>
+    <td><code>glfw.lib opengl32.lib user32.lib</code></td>
+  </tr>
+  <tr>
+    <td>MinGW32</td>
+    <td><code>-lglfw -lopengl32</code></td>
+  </tr>
+  <tr>
+    <td>OpenWatcom</td>
+    <td><code>glfw.lib opengl32.lib user32.lib</code></td>
+  </tr>
+</table>
+
+
+<h4>4.2.2 Windows DLL</h4>
+
+<p>To compile a program that uses the DLL version of GLFW, you need to
+define the <code>GLFW_DLL</code> constant. This can either be done with a
+compiler switch, typically by adding <code>-DGLFW_DLL</code> to the list of
+compiler options. You can also do it by adding the following line to all your
+source files <b>before</b> including the GLFW header file:</p>
+
+<blockquote><code>#define GLFW_DLL</code></blockquote>
+
+<p>When linking a program under Windows that uses the DLL version of GLFW,
+the only library you need to link with for GLFW to work is <code>glfwdll</code>.
+In the table below you can see the minimum required link options for each
+supported Windows compiler (you may want to add other libraries as well,
+such as <code>opengl32</code> and <code>glu32</code>):</p>
+
+<table border=1>
+  <tr>
+    <td><b>Compiler</b></td>
+    <td><b>Link options</b></td>
+  </tr>
+  <tr>
+    <td>Borland C++ Builder</td>
+    <td><code>glfwdll.lib</code></td>
+  </tr>
+  <tr>
+    <td>Cygwin</td>
+    <td><code>-lglfwdll</code></td>
+  </tr>
+  <tr>
+    <td>LCC-Win32</td>
+    <td><code>glfwdll.lib</code></td>
+  </tr>
+  <tr>
+    <td>Microsoft Visual C++</td>
+    <td><code>glfwdll.lib</code></td>
+  </tr>
+  <tr>
+    <td>MinGW32</td>
+    <td><code>-lglfwdll</code></td>
+  </tr>
+  <tr>
+    <td>OpenWatcom</td>
+    <td><code>glfwdll.lib</code></td>
+  </tr>
+</table>
+
+
+
+<h4>4.2.3 Unix static library</h4>
+
+<p>GLFW supports
+<a href="http://pkgconfig.freedesktop.org/wiki/">pkg-config</a>,
+and a <code>libglfw.pc</code> file is generated and installed when you install
+the library.  For systems that do not provide pkg-config, you should look in
+this file for the proper compile and link flags for your system, as determined
+by compile.sh at compile time.</p>
+
+<p>A typical compile and link command-line may look like this:</p>
+
+<blockquote><code>cc `pkg-config --cflags libglfw` -o myprog myprog.c `pkg-config --libs libglfw`</code></blockquote>
+
+<p>If you use GLU functions in your program you should also add
+<code>-lGLU</code> to your link flags.</p>
+
+
+
+<h4>4.2.5 Mac OS X static library</h4>
+
+<p>When compiling and linking a program under Mac OS X that uses GLFW, you
+must also link with Cocoa and OpenGL frameworks.
+
+<p>If you are using Xcode, you simply add the GLFW library <code>libglfw.a</code> and
+these frameworks to your project. If, however, you are building your program
+from the command-line, there are two methods for correctly linking your GLFW
+program.</p>
+
+<p>GLFW supports
+<a href="http://pkgconfig.freedesktop.org/wiki/">pkg-config</a>, and a
+libglfw.pc file is generated and installed when you install the library. You
+can find pkg-config in most packaging systems, such as
+<a href="http://www.finkproject.org/">Fink</a> and
+<a href="http://www.macports.org/">MacPorts</a>, so if you have one of them
+installed, simply install pkg-config. Once you have pkg-config available, the
+command-line for compiling and linking your program is:</p>
+
+<blockquote><code>cc `pkg-config --cflags libglfw` -o myprog myprog.c `pkg-config --libs libglfw`</code></blockquote>
+
+<p>If you do not wish to use pkg-config, you will need to add the required
+frameworks and libraries to your command-line using the <code>-l</code> and
+<code>-framework</code> switches, i.e.:</p>
+
+<blockquote><code>cc -o myprog myprog.c -lglfw -framework Cocoa -framework OpenGL</code></blockquote>
+
+<p>Note that you do not add the .framework extension to a framework when adding
+it from the command-line.</p>
+
+<p>These frameworks contain all OpenGL and GLU functions, so there is no need to
+add additional libraries or frameworks when using GLU functionality. Also note
+that even though your machine may have Unix-style OpenGL libraries, they are for
+use with the X Window System, and will <em>not</em> work with the Mac OS X native
+version of GLFW.</p>
+
+<a name="changelog">
+<h2>5. Version history</h2>
+
+<h3>v2.7</h3>
+<ul>
+  <li>Added <code>GLFW_OPENGL_VERSION_MAJOR</code> and <code>GLFW_OPENGL_VERSION_MINOR</code>
+      hints for versioned context creation</li>
+  <li>Added <code>GLFW_OPENGL_FORWARD_COMPAT</code> hint for forward compatible context creation</li>
+  <li>Added <code>GLFW_OPENGL_DEBUG_CONTEXT</code> hint for debug context creation</li>
+  <li>Added <code>GLFW_OPENL_PROFILE</code> hint for context creation using profiles</li>
+  <li>Added <code>GLFW_NO_GLU</code> macro for disabling the inclusion of the GLU header by the GLFW header</li>
+  <li>Added platform-independent pixel format selection (not used on Mac OS X)</li>
+  <li>Added support and symbols for several additional keys, including Windows/Command keys, Pause, Caps Lock and Menu</li>
+  <li>Added conservative value clamping to <code>glfwOpenWindowHint</code></li>
+  <li>Added a number of test programs mostly useful to developers of GLFW</li>
+  <li>Added error messages and graceful failure to example programs</li>
+  <li>Added Cocoa port for Mac OS X 10.5 Leopard and later</li>
+  <li>Added vsync to all relevant example programs</li>
+  <li>Added a rudimentary OpenGL 3.2+ core profile example program</li>
+  <li>Updated Pascal (formerly Delphi) bindings to support more compilers</li>
+  <li>Clarified and expanded the User's Guide and Reference Manual</li>
+  <li>Fixed a number of compiler warnings in the example programs</li>
+  <li>OpenGL version is now only parsed once, at window creation time</li>
+  <li>Changed <code>glfwSwapBuffers</code> to call <code>glfwPollEvents</code> <em>after</em> buffer swap</li>
+  <li>Changed all comments in public header file to plain C style</li>
+  <li>Removed the <code>keytest</code> example program, as it was superseded by the <code>events</code> test</li>
+  <li>Removed deprecated AmigaOS and DOS ports</li>
+  <li>Removed all FPS counters from example programs</li>
+  <li>Removed all unmaintained language bindings</li>
+  <li>Removed support for Pelles C</li>
+  <li>Removed broken Microsoft Visual C++ 6.0 build path</li>
+  <li>[X11] Added <code>x11-dist-install</code> install target, intended for packagers of GLFW</li>
+  <li>[X11] Added <code>x11-dist-clean</code> build target, intended for developers of GLFW</li>
+  <li>[X11] Added support for <code>GLX_SGIX_fbconfig</code></li>
+  <li>[X11] Added support for user-specified compilation flags via <code>CFLAGS</code></li>
+  <li>[X11] Added documentation of configuration macros</li>
+  <li>[X11] Implemented support for <code>GLFW_SYSTEM_KEYS</code></li>
+  <li>[X11] Improved configuration and makefile creation logic</li>
+  <li>[X11] Removed support for GLX version 1.2 and below</li>
+  <li>[X11] Removed unnecessary calls to XSync</li>
+  <li>[X11] Removed use of legacy window style atoms</li>
+  <li>[X11] Bugfix: Repeated keys would sometimes leak through despite key repeat being disabled</li>
+  <li>[X11] Bugfix: Fullscreen window resizing would cause color buffer clearing without taking framebuffer objects into account</li>
+  <li>[X11] Bugfix: AltGr was not reported as right Alt</li>
+  <li>[X11] Bugfix: Window colormap was not freed</li>
+  <li>[X11] Bugfix: Close callback was called for <code>glfwCloseWindow</code></li>
+  <li>[X11] Bugfix: Misspelt struct member in XF86VidMode code path</li>
+  <li>[X11] Bugfix: Window decorations would not appear using certain versions of Compiz on Intel hardware</li>
+  <li>[X11] Bugfix: Numeric keypad key symbols would change depending on Num Lock state</li>
+  <li>[X11] Bugfix: Hidden cursor position snapped back when halfway from window center to edge</li>
+  <li>[X11] Bugfix: Not properly verifying that the window was mapped before making certain calls caused a <code>BadMatch</code> error</li>
+  <li>[X11] Bugfix: The response to <code>_NET_WM_PING</code> events was malformed</li>
+  <li>[X11] Bugfix: Hidden cursor mode interfered with other applications when GLFW window was unfocused</li>
+  <li>[X11] Bugfix: The invisible cursor objects used for hidden cursor mode were not freed</li>
+  <li>[X11] Bugfix: EWMH-compliant window managers were incorrectly detected</li>
+  <li>[X11] Bugfix: The EWMH code path for fullscreen windows did not present the window using <code>_NET_ACTIVE_WINDOW</code></li>
+  <li>[X11] Bugfix: The EWMH code path for fullscreen windows did not send a <code>_NET_WM_STATE</code> client message</li>
+  <li>[Carbon] Added Universal Binary build targets for all examples</li>
+  <li>[Carbon] Renamed MacOSX port to Carbon</li>
+  <li>[Carbon] Removed support for 10.2 Jaguar</li>
+  <li>[Carbon] Deprecated Carbon port</li>
+  <li>[Carbon] Bugfix: Using the Dock or menu Quit command did not call the close callback</li>
+  <li>[Carbon] Bugfix: Key repeat events were not caught on 10.5 Leopard</li>
+  <li>[Carbon] Bugfix: Certain keys were not reported</li>
+  <li>[Carbon] Bugfix: Missing <code>-m32</code> flag caused build failure on 10.6 Snow Leopard</li>
+  <li>[Carbon] Bugfix: Missing <code>-mmacosx-version-min</code> flag caused build failure on 10.5 Leopard</li>
+  <li>[Carbon] Bugfix: <code>glfwOpenWindow</code> did not call <code>glClear</code></li>
+  <li>[Win32] Added Visual C++ project files for all examples and test programs</li>
+  <li>[Win32] Removed iterative context re-creation attempts for FSAA sample count</li>
+  <li>[Win32] Bugfix: The Visual C++ GLFW DLL project file did not use the correct DEF file</li>
+  <li>[Win32] Bugfix: WGL extensions were not detected and/or used correctly</li>
+  <li>[Win32] Bugfix: Improper use of wParam for <code>WM_SYSCOMMAND</code></li>
+  <li>[Win32] Bugfix: Derivatives of stream.c were not cleaned up by compile.bat</li>
+  <li>[Win32] Bugfix: Pointer for <code>GetExtensionsStringARB</code> was not initialized</li>
+  <li>[Win32] Bugfix: Makefiles contained the wrong GLFW API version</li>
+  <li>[Win32] Bugfix: Numeric keypad key symbols would change depending on Num Lock state</li>
+  <li>[Win32] Bugfix: <code>DllMain</code> performed a number of forbidden actions (by calling <code>glfwTerminate</code>)</li>
+</ul>
+
+<h3>v2.6</h3>
+<ul>
+  <li>Added <code>GLFW_FSAA_SAMPLES</code> multisampling hint</li>
+  <li>Added <code>GLFW_WINDOW_NO_RESIZE</code> hint for non-resizable windows</li>
+  <li>Added install targets for all Unix-like build targets</li>
+  <li>Added <code>glfwReadMemoryImage</code> function for creating a <code>GLFWImage</code> object from an image file in a memory buffer</li>
+  <li>Added <code>glfwLoadMemoryTexture2D</code> function for decoding an image file in a memory buffer into a texture</li>
+  <li>Added <code>glfwLoadTextureImage2D</code> function for loading a <code>GLFWImage</code> object into a texture</li>
+  <li>Added cross-compilation support for MinGW under a Unix-like host</li>
+  <li>D bindings updated and all examples ported to modern D</li>
+  <li>Delphi bindings updated to reflect API additions</li>
+  <li>Bugfix: The interaction between key repeat and window focus code caused duplicate presses</li>
+  <li>Bugfix: The mouse position was not properly updated when re-enabling the mouse cursor</li>
+  <li>[Win32] Added pkg-config file generation for Cygwin</li>
+  <li>[Win32] Added version number to window class name</li>
+  <li>[Win32] Added optional loading of user provided window icon resource</li>
+  <li>[Win32] Bugfix: Very small sleep periods were forced to higher value</li>
+  <li>[Win32] Bugfix: The nmake makefile did not handle paths with spaces correctly</li>
+  <li>[Win32] Bugfix: Removed assembly RDTSC timing code</li>
+  <li>[Win32] Bugfix: Hidden cursor was not clipped to windowed windows</li>
+  <li>[X11] Added XRandR code path for fullscreen windows</li>
+  <li>[X11] Added building of shared library</li>
+  <li>[X11] Added <a href="http://tronche.com/gui/x/icccm/">ICCCM</a> WM fullscreen hints</li>
+  <li>[X11] Added support for the <code>_NET_WM_PING</code> protocol</li>
+  <li>[X11] Added pkg-config file generation</li>
+  <li>[X11] Added setting of WM size hints</li>
+  <li>[X11] Bugfix: Removed assembly RDTSC timing code</li>
+  <li>[X11] Bugfix: Window re-opening now works properly (including fullscreen windows)</li>
+  <li>[X11] Bugfix: Potential crash bug in video mode matching code</li>
+  <li>[X11] Bugfix: Static buffers imposed an invisible limit on reported video mode count</li>
+  <li>[X11] Bugfix: Interaction with certain window managers when setting input focus would cause termination with a BadMatch error</li>
+  <li>[X11] Bugfix: Keypad keys did not trigger the character callback</li>
+  <li>[MacOSX] Added pkg-config file generation</li>
+  <li>[MacOSX] Added building of shared library</li>
+  <li>[MacOSX] Added building of Universal Binary libraries</li>
+  <li>[MacOSX] Replaced fullscreen code path with CGL version</li>
+  <li>[MacOSX] Bugfix: Binaries without bundles or resource forks now interact properly with the WM</li>
+  <li>[MacOSX] Bugfix: Replaced Carbon event time source with <code>gettimeofday</code></li>
+  <li>[MacOSX] Bugfix: Added code to minimize the dreaded OpenGL application startup jump</li>
+  <li>[MacOSX] Bugfix: Fixed broken implementation of <code>glfwSetMousePos</code> for windowed mode</li>
+  <li>[MacOSX] Bugfix: Fixed broken implementation of hidden cursor</li>
+  <li>[MacOSX] Bugfix: Capturing all displays and not just the main one</li>
+  <li>[AmigaOS] Obsoleted platform due to lack of maintainer and community interest</li>
+  <li>[DOS] Obsoleted platform due to lack of maintainer and community interest</li>
+</ul>
+
+<h3>v2.5</h3>
+<ul>
+ <li>Added the function glfwWaitEvents</li>
+ <li>Added window close callback, which enables a program to prevent a user
+     from closing a window with the window manager</li>
+ <li>Added window refresh callback, which is called when the window needs
+     to be refreshed</li>
+ <li>Added support for loading alpha textures (GLFW_ALPHA_MAP_BIT)</li>
+ <li>Added support for the Lua programming language</li>
+ <li>Added support for the D programming language</li>
+ <li>Added support for the Pelles C compiler for Windows</li>
+ <li>Added API level support for up to eight mouse buttons</li>
+ <li>[Win32] Added support for up to five mouse buttons</li>
+ <li>[Win32] Mouse down events capture mouse input</li>
+ <li>[Win32] Bugfix: The DLL now exports glfwSetTime</li>
+ <li>[Win32] Fix: The GLFW window is now placed in the upper left corner
+     of the desktop working area</li>
+ <li>[Win32/X11] Bugfix: More robust check for SwapInterval</li>
+ <li>[X11] Added support for USB joysticks under Linux (/dev/input/js*)</li>
+ <li>[X11] Bugfix: Added support for GLX extensions in glfwExtensionSupported</li>
+ <li>[X11] Bugfix: More robust fullscreen mode (?)</li>
+ <li>[X11] Bugfix: Runtime check of XF86VidMode support for the active
+     display</li>
+ <li>[X11] Bugfix: Some mouse button events were reported incorrectly</li>
+ <li>[MacOSX] Added support for the input char callback.</li>
+ <li>[MacOSX] Added video mode validation and duplicate elimination.</li>
+ <li>[MacOSX] Switched to a new MakeBundle.sh script.</li>
+ <li>[MacOSX] Added emulation of the window refresh callback.</li>
+ <li>[MacOSX] Bugfix: The window and its associated resources are now
+     properly released.</li>
+ <li>[MacOSX] Bugfix: Removed support for more than eight mouse buttons.</li>
+ <li>[x86 CPUs] Improved Intel mobile CPU detection (e.g. disables RDTSC
+     timing on Centrino systems)</li>
+</ul>
+
+<h3>v2.4.2</h3>
+<ul>
+ <li>Preliminary native Mac OS X support (via the Carbon interface)</li>
+ <li>Preliminary DOS support (DJGPP + Mesa)</li>
+ <li>Changed license to the zlib license (almost identical to the previous
+     GLFW license), so now GLFW is OSI Certified</li>
+ <li>Rewrote the GLFW documentation in LaTeX, meaning several improvements
+     (both visual and practical)</li>
+ <li>Added the <code>support</code> folder to the distribution, which includes
+     support for various languages</li>
+ <li>[Win32] Added OpenWatcom compiler support (thanks Sebastian
+     Schuberth!)</li>
+ <li>[Win32] Changed fallback timer from GetTickCount to timeGetTime,
+     which usually provides better resolution</li>
+ <li>[Win32] Bugfix: Accumulator buffer selection should be more
+     robust</li>
+ <li>[Win32] Bugfix: If stereo rendering is requested, and no stereo pixel
+     format could be created, glfwOpenWindow now fails</li>
+ <li>[Win32] Bugfix: glfwSetWindowSize now sets the size of the client
+     area, NOT the entire window, meaning that there is a 1:1 relationship
+     between glfwSetWindowSize and glfwGetWindowSize</li>
+ <li>[X11] Added FreeBSD and QNX support</li>
+ <li>[X11] Added support for non-pthread capable systems</li>
+ <li>[X11] Hopefully more robust configuration script (compile.sh)</li>
+ <li>[X11] Bugfix: When mouse cursor is hidden, mouse sensitivity is no
+     longer degraded</li>
+ <li>[X11] Bugfix: Source files EOL was PC style (CR/LF) in v2.4.1 (blame
+     my WinCVS configuration)</li>
+ <li>[X11] Bugfix: When a GLFW window is closed, input focus is properly
+     released</li>
+ <li>[X11] Bugfix: Iconification of fullscreen windows should now work
+     properly</li>
+ <li>[x86 CPUs] Improved RDTSC timing (e.g. RDTSC support on single-CPU
+     Intel Hyper-Threading enabled systems)</li>
+ <li>[AmigaOS] Added joystick support</li>
+ <li>[AmigaOS] Mouse cursor positioning is now implemented</li>
+ <li>[AmigaOS] Added support for Geek Gadgets GCC</li>
+ <li>[AmigaOS] Bugfix: glfwGetWindowParam now returns proper values for
+     all parameters (except for GLFW_ACCELERATED)</li>
+</ul>
+
+<h3>v2.4.1</h3>
+<ul>
+ <li>Added AmigaOS support (preliminary)</li>
+ <li>GLFW for the X Window System now works under Mac OS X</li>
+ <li>[Win32] Bugfix: glfwWaitCond treated the timeout as milliseconds
+     instead of seconds</li>
+ <li>[X11] Bugfix: GLFW should now compile under IRIX v5.3</li>
+ <li>[X11] Bugfix: GLFW should now compile with Kylix</li>
+</ul>
+
+<h3>v2.4</h3>
+<ul>
+ <li>Major source code rearrangement - much code is now shared between
+     different platforms, and it should be easier to port GLFW to new
+     platforms</li>
+ <li>Added a Unicode keyboard text input interface (CharCallback)</li>
+ <li>Keyboard key input is now slightly more internationalized: GLFW now
+     uses 8-bit ISO-8859-1 encoding for keys representing printable
+     characters (e.g. &quot;&Ouml;&quot;, &quot;&#167;&quot;, etc), as
+     opposed to the previous 7-bit US-ASCII encoding</li>
+ <li>Added more key constants (F13-F25, keypad '=')</li>
+ <li>Added an enable/disable swicth for automatic event polling from
+     glfwSwapBuffers</li>
+ <li>[X11] Added support for sysctl for querying the number of processors
+     in the system (if POSIX sysconf is not supported)</li>
+ <li>[X11] Bugfix: compile.sh now works with Sun sh (and hopefully others
+     too)</li>
+ <li>[X11] Bugfix: compile.sh now detects the need for -ldl when dlopen is
+     used</li>
+ <li>[Win32] Bugfix: When closing a fullscreen window under Win 9x/NT4,
+     the task bar icon now disappears properly</li>
+ <li>[Win32] Bugfix: GLFW should now compile on a wider range of MSVC
+     compilers (e.g. .NET) - Thanks Tim Little!</li>
+</ul>
+
+<h3>v2.3.2</h3>
+<ul>
+ <li>Removed the silly limitation of 100 threads (the thread information
+     is now kept in a linked list)</li>
+ <li>General source cleanup (window state is now kept in a single
+     struct, plus some other minor changes)</li>
+ <li>[X11] Added Solaris gethrtime() support (not tested yet), which
+     should give an improved timer for Sun/Solaris stations</li>
+ <li>[X11] Some fixes to the 'compile.sh' script (-O for non-gcc compilers
+     and 'make x11-gcc' should now really force GCC)</li>
+</ul>
+
+<h3>v2.3.1</h3>
+<ul>
+ <li>[X11] A minimalist configuration script was added that solves the
+     issue with glXGetProcAddressARB, and unifies all Unix/X11 Makefiles
+     into one template Makefile (well, one for GLFW, and one for the
+     examples)</li>
+</ul>
+
+<h3>v2.3</h3>
+<ul>
+ <li>Added OpenGL stereo rendering support</li>
+ <li>Added a function for parsing the OpenGL version string
+     (glfwGetGLVersion)</li>
+ <li>[x86] Bugfix: Hopefully the CPU core clock dependent timer RDTSC will
+     never be used on CPUs with variable core frequencies anymore</li>
+ <li>[X11] Bugfix: GLFW could create stereo rendering capable windows,
+     even if it was not requested (GLFW v2.2.x did not support selection
+     of stereo rendering)</li>
+ <li>[X11] Bugfix: glfwGetProcAddress returned NULL on most systems (even
+     on those that supported glXGetProcAddressARB). Now GLFW assumes that
+     glXGetProcAddressARB is supported on all systems, which solves the
+     bug, but may result in compiler errors on some systems (please let me
+     know if you have any related problems).</li>
+</ul>
+
+<h3>v2.2.3</h3>
+<ul>
+ <li>Bugfix: Checking for GL_SGIS_generate_mipmap is more robust</li>
+ <li>Bugfix: glfwLoadTexture2D will now fail if no window is opened</li>
+ <li>[Win32] Bugfix: Right shift was not detected under Win 9x/ME (it is
+     still not as good as under NT/2K/XP, but at least you get right
+     shifts)</li>
+ <li>[X11] Bugfix: Visuals are now selected more accurately. For instance,
+     glfwOpenWindow will no longer fail if you request a 24-bit color
+     buffer if only 16-bit color visuals are available (which means that
+     pong3d should work on 16-bit displays).</li>
+</ul>
+
+<h3>v2.2.2</h3>
+<ul>
+ <li>[Win32] Bugfix: Windows did not always get focus (this was a tough
+     one!)</li>
+ <li>[Win32] Bugfix: glfwGetWindowParam did not work with
+     GLFW_ACCUM_*_BITS or GLFW_AUX_BUFFERS</li>
+ <li>[X11] Bugfix: Linux joystick Y axis positions were reversed</li>
+</ul>
+
+<h3>v2.2.1</h3>
+<ul>
+ <li>[X11] Added joystick support for Linux</li>
+</ul>
+
+<h3>v2.2</h3>
+<ul>
+ <li>Added joystick support (only supported under Windows so far)</li>
+ <li>Added joystick controls to pong3d.c (only 3 more lines of code)</li>
+ <li>Added glfwOpenWindowHint() function</li>
+ <li>It is now possible to specify a desired vertical monitor refresh
+     rate (for fullscreen windows)</li>
+ <li>It is now possible to request an accumulator buffer and auxiliary
+     buffers</li>
+ <li>Added glfwSetTime() function</li>
+ <li>Added a GLFW conversion of the MESA/GLUT gears.c demo to the example
+     programs</li>
+ <li>[Win32] gdi32.dll and winmm.dll are now loaded dynamically when
+     glfwInit() is called. This means that there is no need to link with
+     gdi32.lib or winmm.lib when using the static version of GLFW, which
+     should make GLFW usage more convenient.</li>
+ <li>[Win32] Bugfix: Greatly improved keyboard input (detect left/right
+     CTRL etc)</li>
+ <li>[Win32] Bugfix: glfwExtensionSupported now detects all WGL extensions
+     (e.g. WGL_ARB_pbuffer)</li>
+ <li>[Win32] Bugfix: Mouse cursor was not re-hidden when a GLFW window was
+     deselected and then selected again (with ALT+TAB)</li>
+ <li>[X11] Bugfix: Minor bug in the SGI timer - and ugly (unintended) SGI
+     timer debug info removed</li>
+ <li>[X11] Bugfix: glfwGetDesktopMode and glfwGetVideoModes no longer give
+     segmentation faults if no X server is available</li>
+</ul>
+
+<h3>v2.1</h3>
+<ul>
+ <li>Added image and texture loading capabilities (support for the TGA
+     file format at the moment)</li>
+ <li>Added a new example program (mipmaps.c) for showing off the automatic
+     mipmap generation and texture loading capabilities of GLFW 2.1</li>
+ <li>Removed the separate TGA loader (tga.c in the examples directory)
+     since texture loading is supported natively by GLFW. Also updated the
+     Pong3D demo to use GLFW texture loading instead of tga.c.</li>
+ <li>Improved keyboard handling (e.g. numeric keypad keys can be
+     detected)</li>
+ <li>Added a new example program, keytest.c</li>
+ <li>Changed the GLFWvidmode structure and the corresponding API functions
+     to report pure color bits instead of the confusing (and unportable)
+     "BPP" field</li>
+ <li>Changed glfwSetWindowSize so that it operates in fullscreen mode
+     too</li>
+ <li>Added mouse wheel support under Windows (not Win95) and X11</li>
+ <li>Added window iconification functions (glfwInconifyWindow and
+     glfwRestoreWindow)</li>
+ <li>Improved iconification and deactivation handling under both Windows
+     and X11</li>
+ <li>Made it possible to turn on/off key repeat (the default is now no key
+     repeat)</li>
+ <li>Added SGI hardware timer support (CLOCK_SGI_CYCLE) for improved
+     timer resolution for SGI computers</li>
+ <li>Added support for the free Borland C++ Builder 5.x compiler for
+     Windows</li>
+ <li>Made it possible to compiler GLFW as a Windows DLL using any of the
+     supported compilers</li>
+ <li>Some constants have changed names (e.g. GLFW_REDBITS is now called
+     GLFW_RED_BITS)</li>
+ <li>Updated GLFW documentation (GLFW Users Guide and GLFW Reference
+     Manual) to reflect the changes in the API</li>
+ <li>[Win32] Bugfix: Corrected Cygwin toplevel makefile entry</li>
+ <li>[Win32] Bugfix: Fixed event lag bug</li>
+ <li>[Win32] Bugfix: Fixed Radeon 8500 crash</li>
+ <li>[X11] Bugfix: Fixed the window close bug</li>
+ <li>[X11] Bugfix: Iconification/deactivation is now detected</li>
+ <li>[X11] Bugfix: Non-OpenGL visuals are not listed anymore</li>
+ <li>[XFree86] Bugfix: Undesired video mode changes are now prevented</li>
+</ul>
+
+<h3>v2.0.3</h3>
+<ul>
+ <li>Added precise CPU cycle based timing support (RDTSC) for x86
+     CPUs (under both Windows and Unix)</li>
+ <li>Added a makefile option for building for Windows with Cygwin</li>
+ <li>Corrected the CC for Unix/X11 makefiles (-Wall is usually not a
+     supported flag for CC, so it was removed from the CFLAGS list)</li>
+</ul>
+
+<h3>v2.0.2</h3>
+<ul>
+ <li>Added a makefile option for building for X11 with 'cc' rather than
+     'gcc' (useful for IRIX users for instance).</li>
+ <li>[Win32] Bugfix: Mouse coordinates are now relative to the window
+     upper left corner, which also means that disabling the mouse cursor
+     in windowed mode should work much better.</li>
+ <li>[X11] Bugfix: Added a bunch of more keys that are recognized by
+     GLFW.</li>
+ <li>[X11] Bugfix: glfwGetNumberOfProcessors now works for IRIX (earlier
+     versions of GLFW would not compile under IRIX).</li>
+</ul>
+
+<h3>v2.0.1</h3>
+<ul>
+ <li>glfwTerminate() will now be called automatically upon normal program
+     termination (using atexit())</li>
+ <li>[Win32] Bugfix: Buffer-swapping did not work if a window lost
+     focus.</li>
+ <li>[Win32] Bugfix: Top level Makefile did not work under Windows
+     9x.</li>
+ <li>[Win32] Bugfix: NULL declaratoin in glfw.h was not MSVC 7.x
+     compatible.</li>
+ <li>[X11] Bugfix: GLFW would not build with C++ (e.g. g++).</li>
+</ul>
+
+<h3>v2.0</h3>
+<ul>
+ <li>GLFW is no longer a single source file, but an entire link library.</li>
+ <li>Added multi threading support.</li>
+ <li>Added more window control.</li>
+ <li>New distribution layout (both Win32 and X11 version in same archive).</li>
+ <li>Added GLFW Users Manual and GLFW Reference Manual as PDF files.</li>
+ <li>Some bugfixes.</li>
+</ul>
+
+<h3>v1.0.2</h3>
+<ul>
+ <li>Improved fullscreen functionality.</li>
+ <li>Added fullscreen support for X11.</li>
+</ul>
+
+<h3>v1.0.1</h3>
+<ul>
+ <li>Added support for the X Window System.</li>
+ <li>Fixed bugs.</li>
+</ul>
+
+<h3>v1.0.0</h3>
+<ul>
+ <li>First release.</li>
+ <li>Only supported Windows.</li>
+</ul>
+
+
+<a name="structure">
+<h2>6. Directory structure of the GLFW distribution</h2>
+
+<p>Here is an overview of the directory structure of the GLFW distribution:
+
+<p>
+<table border=0 cellspacing=0>
+<tr valign="top"><td width=100><code>docs</code></td><td>&nbsp;</td><td>GLFW manuals in PDF format</td></tr>
+<tr valign="top"><td><code>examples</code></td><td>&nbsp;</td><td>Several example programs in C</td></tr>
+<tr valign="top"><td><code>include</code></td><td>&nbsp;</td><td>&nbsp;</td></tr>
+<tr valign="top"><td><code>&nbsp;&nbsp;&nbsp;GL</code></td><td>&nbsp;</td><td>Here is the GLFW C/C++ include file</td></tr>
+<tr valign="top"><td><code>lib</code></td><td>&nbsp;</td><td>The source code for GLFW</td></tr>
+<tr valign="top"><td><code>&nbsp;&nbsp;&nbsp;cocoa</code></td><td>&nbsp;</td><td>Mac OS X/Cocoa specific implementation</td></tr>
+<tr valign="top"><td><code>&nbsp;&nbsp;&nbsp;win32</code></td><td>&nbsp;</td><td>Windows specific implementation</td></tr>
+<tr valign="top"><td><code>&nbsp;&nbsp;&nbsp;x11</code></td><td>&nbsp;</td><td>Unix/X11 specific implementation</td></tr>
+<tr valign="top"><td><code>support</code></td><td>&nbsp;</td><td>&nbsp;</td></tr>
+<tr valign="top"><td><code>&nbsp;&nbsp;&nbsp;d</code></td><td>&nbsp;</td><td>D support</td></tr>
+<tr valign="top"><td><code>&nbsp;&nbsp;&nbsp;msvc90</code></td><td>&nbsp;</td><td>Project files for Visual C++ 9.0</td></tr>
+<tr valign="top"><td><code>&nbsp;&nbsp;&nbsp;pascal</code></td><td>&nbsp;</td><td>Pascal support</td></tr>
+<tr valign="top"><td><code>tests</code></td><td>&nbsp;</td><td>Several test programs in C</td></tr>
+</table>
+
+
+<a name="contact">
+<h2>7. Contacting the project</h2>
+
+<p>The official website for GLFW is <a href="http://www.glfw.org/">glfw.org</a>.
+It contains the latest version of GLFW, news and other information that is
+useful for OpenGL development.</p>
+
+<p>If you have questions related to the use of GLFW, we have a
+<a href="https://sourceforge.net/forum/forum.php?forum_id=247562">user's web forum</a>,
+and a
+<a href="https://lists.sourceforge.net/lists/listinfo/glfw-user">user's mailing list</a>
+on SF.net, and the registered IRC channel <code>#glfw</code> on
+<a href="http://freenode.net/">Freenode</a>.</p>
+
+<p>If you have a bug to report, a patch to submit or a feature you'd like to
+request, please file it in one of the
+<a href="http://sourceforge.net/tracker/?group_id=72569">GLFW trackers</a> on SF.net.</p>
+
+Finally, if you're interested in helping out with the development of
+GLFW or porting it to your favorite platform, we have a
+<a href="https://lists.stacken.kth.se/mailman/listinfo/glfw-dev">developer's mailing list</a>,
+or you could join us on <code>#glfw</code>.
+
+
+<a name="credits">
+<h2>8. Acknowledgements</h2>
+
+<p>GLFW exists because people around the world donated their time and lent
+their skills.  Special thanks go out to:</p>
+
+<ul>
+
+  <li>Bobyshev Alexander and Martins Mozeiko, for the original proposal of
+  an FSAA hint and their work on the Win32 implementation of FSAA</li>
+
+  <li>Keith Bauer, for his invaluable help with porting and maintaining GLFW on
+  Mac OS X, and for his many ideas</li>
+
+  <li>Jarrod Davis, for the Delphi port of GLFW</li>
+
+  <li>Olivier Delannoy, for the initial implementation of FSAA support on
+  X11, cross-compiling support for MinGW and general extreme usefulness</li>
+
+  <li>Paul R. Deppe, who helped with Cygwin support, and made an
+  adaption of <a href="http://plib.sourceforge.net/">PLIB</a>
+  so that it can use GLFW (instead of GLUT)</li>
+
+  <li>Jonathan Dummer, for submitting a patch fixing an input bug on Win32 and
+  adding logic for the GLFW_ICON resource</li>
+
+  <li>Gerald Franz, who made GLFW compile under IRIX, and supplied patches
+  for the X11 keyboard translation routine</li>
+
+  <li>Marcus Geelnard, the original author and long-time maintainer of GLFW,
+  without whose brilliant work none of this would have happened</li>
+
+  <li>Stefan Gustavson, for quick and thorough testing of GLFW on many and
+  varied operating systems and hardware configurations</li>
+
+  <li>Sylvain Hellegouarch, for support, bug reports and testing</li>
+
+  <li>Alex Holkner, for writing the code from which the Compiz/Intel fix was
+  stolen</li>
+
+  <li>Toni Jovanoski, for helping with the MASM32 port of GLFW, and
+  supplying the example program and fixed OpenGL and GLU bindings for
+  MASM32</li>
+
+  <li>Cameron King, for reporting a hidden cursor mouse bug on X11</li>
+
+  <li>Peter Knut, for his many and detailed reports of difficult to find input
+  bugs</li>
+
+  <li>Robin Leffmann, for his work on Mac OS X and other platforms, and his
+  invaluable support</li>
+
+  <li>Glenn Lewis, for helping out with support for the D programming
+  language</li>
+
+  <li>Tristam MacDonald, for his bug reports and feedback on the Cocoa port</li>
+
+  <li>David Medlock, for doing the initial Lua port</li>
+
+  <li>Kenneth Miller, for his many and detailed bug reports on Win32</li>
+
+  <li>Jeff Molofee, the author of the excellent OpenGL tutorials at <a
+  href="http://nehe.gamedev.net/">NeHe Productions</a>.
+  Much of the Windows code of GLFW was originally based on Jeff's
+  code</li>
+
+  <li>Douglas C. Schmidt and Irfan Pyarali, for their excellent article
+  <a href="http://www.cs.wustl.edu/~schmidt/win32-cv-1.html">Strategies for Implementing POSIX Condition Variables on Win32</a></li>
+
+  <li>Sebastian Schuberth, for the OpenWatcom makefiles</li>
+
+  <li>Matt Sealey, for helping with the MorphOS port</li>
+
+  <li>Steve Sexton, for reporting an input bug in the Carbon port</li>
+
+  <li>Dmitri Shuralyov, for support, bug reports and testing</li>
+
+  <li>Daniel Skorupski, for reporting a bug in the Win32 DEF file</li>
+
+  <li>Bradley Smith, for his updates of the D support and his ports of the
+  remaining examples to the D language</li>
+
+  <li>Julian Squires, for submitting a patch for a bug in the key repeat logic on X11</li>
+
+  <li>Johannes Stein, for maintaining the Pascal bindings</li>
+
+  <li>Samuli Tuomola, for support, bug reports and testing</li>
+
+  <li>Frank Wille, for helping with the AmigaOS port and making GLFW
+  compile under IRIX 5.3</li>
+
+  <li>Santi Zupancic, for support, bug reports and testing</li>
+
+  <li>Lasse Öörni, for submitting patches for the input code of the Win32 and X11 ports</li>
+
+  <li>Дмитри Малышев, for the idea of a GLFW_NO_GLU macro</li>
+
+  <li>blanco, for submitting a patch for a deprecation bug in the Cocoa port</li>
+
+  <li>heromyth, for reporting a bug in the D bindings</li>
+
+  <li>Ozzy @ <a href="http://www.orkysquad.org">Orkysquad</a>,
+  for his dedication to GLFW, for debugging my source, and for his
+  valuable experience with game development</li>
+
+  <li>Peoro, for reporting a bug in the <code>_NET_WM_PING</code> response</li>
+
+  <li>TTK-Bandit, for submitting a number of input patches adding many missing
+  keys to the Win32 and X11 ports</li>
+
+  <li>All the unmentioned and anonymous contributors in the GLFW community, for
+  bug reports, patches, feedback and encouragement</li>
+
+  <li><a href="http://www.opengl.org/">OpenGL.org</a>, and all the people on
+  the discussion forums there that have provided help during the development of
+  GLFW</li>
+
+</ul>
+
+</body>
+</html>

+ 2 - 2
ThirdParty/GLee/CMakeLists.txt

@@ -6,9 +6,9 @@ file (GLOB C_FILES *.c)
 file (GLOB H_FILES *.h)
 set (SOURCE_FILES ${C_FILES} ${H_FILES})
 
-include_directories (../SDL/include)
+include_directories (../GLFW/include)
 
 # Define target & libraries to link
 add_library (${TARGET_NAME} STATIC ${SOURCE_FILES})
-target_link_libraries (${TARGET_NAME} SDL)
+target_link_libraries (${TARGET_NAME} GLFW)
 finalize_lib ()

+ 3 - 3
ThirdParty/GLee/GLee.c

@@ -43,8 +43,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include "GLee.h"
-
-#include <SDL.h>
+
+#include <GL/glfw.h>
 
 typedef GLuint(*GLEE_LINK_FUNCTION)(void);
 
@@ -56,7 +56,7 @@ GLboolean __GLeeInited=GL_FALSE;
 
 void * __GLeeGetProcAddress(const char *extname)
 {
-    return SDL_GL_GetProcAddress(extname);
+    return glfwGetProcAddress(extname);
 }
 
 

+ 117 - 0
ThirdParty/PortAudio/CMakeLists.txt

@@ -0,0 +1,117 @@
+# Define target name
+set (TARGET_NAME PortAudio)
+
+# Common source files
+set (SOURCE_FILES
+    src/common/pa_allocation.c
+    src/common/pa_allocation.h
+    src/common/pa_converters.c
+    src/common/pa_converters.h
+    src/common/pa_cpuload.c
+    src/common/pa_cpuload.h
+    src/common/pa_debugprint.c
+    src/common/pa_debugprint.h
+    src/common/pa_dither.c
+    src/common/pa_dither.h
+    src/common/pa_endianness.h
+    src/common/pa_front.c
+    src/common/pa_hostapi.h
+    src/common/pa_memorybarrier.h
+    src/common/pa_process.c
+    src/common/pa_process.h
+    src/common/pa_ringbuffer.c
+    src/common/pa_ringbuffer.h
+    src/common/pa_skeleton.c
+    src/common/pa_stream.c
+    src/common/pa_stream.h
+    src/common/pa_trace.c
+    src/common/pa_trace.h
+    src/common/pa_types.h
+    src/common/pa_util.h
+)
+
+include_directories (include src/common)
+
+# OS specific source files
+if (WIN32)
+    add_definitions (-DPA_NO_ASIO -DPA_NO_WASAPI -DPA_NO_WDMKS -DPA_NO_WMME)
+    set (SOURCE_FILES
+        ${SOURCE_FILES}
+        src/os/win/pa_win_hostapis.c
+        src/os/win/pa_win_util.c
+        src/os/win/pa_win_waveformat.c
+        src/os/win/pa_win_wdmks_utils.c
+        src/os/win/pa_win_wdmks_utils.h
+        src/os/win/pa_x86_plain_converters.c
+        src/os/win/pa_x86_plain_converters.h
+        src/hostapi/dsound/pa_win_ds.c
+        src/hostapi/dsound/pa_win_ds_dynlink.c
+        src/hostapi/dsound/pa_win_ds_dynlink.h
+    )
+    include_directories (src/os/win)
+elseif (UNIX)
+    set (SOURCE_FILES
+        ${SOURCE_FILES}
+        src/os/unix/pa_unix_hostapis.c
+        src/os/unix/pa_unix_util.c
+        src/os/unix/pa_unix_util.h
+    )
+    
+    include_directories (src/os/unix)
+    
+    if (APPLE)
+        add_definitions (-DPA_USE_COREAUDIO)
+        set (SOURCE_FILES
+            ${SOURCE_FILES}
+            src/hostapi/coreaudio/pa_mac_core.c
+            src/hostapi/coreaudio/pa_mac_core_blocking.c
+            src/hostapi/coreaudio/pa_mac_core_blocking.h
+            src/hostapi/coreaudio/pa_mac_core_internal.h
+            src/hostapi/coreaudio/pa_mac_core_utilities.c
+            src/hostapi/coreaudio/pa_mac_core_utilities.h
+        )
+    else ()
+        include (CheckIncludeFiles)
+    
+        add_definitions (-DPA_USE_ALSA -DPA_USE_OSS)
+        check_include_files (sys/soundcard.h HAVE_SYS_SOUNDCARD_H)
+        check_include_files (linux/soundcard.h HAVE_LINUX_SOUNDCARD_H)
+        check_include_files (machine/soundcard.h HAVE_MACHINE_SOUNDCARD_H)
+        if (HAVE_SYS_SOUNDCARD_H)
+            add_definitions (-DHAVE_SYS_SOUNDCARD_H)
+        endif ()
+        if (HAVE_LINUX_SOUNDCARD_H)
+            add_definitions (-DHAVE_LINUX_SOUNDCARD_H)
+        endif ()
+        if (HAVE_MACHINE_SOUNDCARD_H)
+            add_definitions (-DHAVE_MACHINE_SOUNDCARD_H)
+        endif ()
+        
+        set (SOURCE_FILES
+            ${SOURCE_FILES}
+            src/hostapi/alsa/pa_linux_alsa.c
+            src/hostapi/oss/pa_unix_oss.c
+            src/hostapi/oss/recplay.c
+        )
+   endif ()
+endif ()
+
+add_library (${TARGET_NAME} STATIC ${SOURCE_FILES})
+
+if (APPLE)
+    find_library (AUDIOTOOLBOX_FW AudioToolBox)
+    find_library (AUDIOUNIT_FW AudioUnit)
+    find_library (COREAUDIO_FW CoreAudio)
+    find_library (CORESERVICES_FW CoreServices)
+    target_link_libraries (${TARGET_NAME} ${AUDIOTOOLBOX_FW} ${AUDIOUNIT_FW} ${COREAUDIO_FW} ${CORESERVICES_FW})    
+elseif (UNIX)
+    target_link_libraries (${TARGET_NAME} rt asound pthread)        
+endif()
+
+
+
+
+
+
+
+

+ 81 - 0
ThirdParty/PortAudio/LICENSE.txt

@@ -0,0 +1,81 @@
+Portable header file to contain:
+>>>>>
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * PortAudio API Header File
+ * Latest version available at: http://www.portaudio.com
+ *
+ * Copyright (c) 1999-2006 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+<<<<<
+ 
+
+Implementation files to contain:
+>>>>>
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * Latest version at: http://www.portaudio.com
+ * <platform> Implementation
+ * Copyright (c) 1999-2000 <author(s)>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+<<<<<

+ 98 - 0
ThirdParty/PortAudio/README.txt

@@ -0,0 +1,98 @@
+README for PortAudio
+
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * Latest Version at: http://www.portaudio.com
+ *
+ * Copyright (c) 1999-2008 Phil Burk and Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+
+PortAudio is a portable audio I/O library designed for cross-platform
+support of audio. It uses either a callback mechanism to request audio 
+processing, or blocking read/write calls to buffer data between the 
+native audio subsystem and the client. Audio can be processed in various 
+formats, including 32 bit floating point, and will be converted to the 
+native format internally.
+
+Documentation:
+	Documentation is available in "/doc/html/index.html"
+	Also see "src/common/portaudio.h" for API spec.
+	Also see http://www.portaudio.com/docs/
+	And see the "test/" directory for many examples of usage
+		(we suggest "test/patest_saw.c" for an example)
+
+For information on compiling programs with PortAudio, please see the
+tutorial at:
+
+  http://portaudio.com/trac/wiki/TutorialDir/TutorialStart
+  
+We have an active mailing list for user and developer discussions.
+Please feel free to join. See http://www.portaudio.com for details.
+
+
+Important Files and Folders:
+    include/portaudio.h     = header file for PortAudio API. Specifies API.	
+    src/common/             = platform independant code, host independant 
+                              code for all implementations.
+    src/os                  = os specific (but host api neutral) code
+    src/hostapi             = implementations for different host apis
+
+
+Host API Implementations:
+    src/hostapi/alsa        = Advanced Linux Sound Architecture (ALSA)
+    src/hostapi/asihpi      = AudioScience HPI
+    src/hostapi/asio        = ASIO for Windows and Macintosh
+    src/hostapi/coreaudio   = Macintosh Core Audio for OS X
+    src/hostapi/dsound      = Windows Direct Sound
+    src/hostapi/jack        = JACK Audio Connection Kit
+    src/hostapi/oss         = Unix Open Sound System (OSS)
+    src/hostapi/wasapi      = Windows Vista WASAPI
+    src/hostapi/wdmks       = Windows WDM Kernel Streaming
+    src/hostapi/wmme        = Windows MultiMedia Extensions (MME)
+
+
+Test Programs:
+    test/pa_fuzz.c         = guitar fuzz box
+    test/pa_devs.c         = print a list of available devices
+    test/pa_minlat.c       = determine minimum latency for your machine
+    test/paqa_devs.c       = self test that opens all devices
+    test/paqa_errs.c       = test error detection and reporting
+    test/patest_clip.c     = hear a sine wave clipped and unclipped
+    test/patest_dither.c   = hear effects of dithering (extremely subtle)
+    test/patest_pink.c     = fun with pink noise
+    test/patest_record.c   = record and playback some audio
+    test/patest_maxsines.c = how many sine waves can we play? Tests Pa_GetCPULoad().
+    test/patest_sine.c     = output a sine wave in a simple PA app
+    test/patest_sync.c     = test syncronization of audio and video
+    test/patest_wire.c     = pass input to output, wire simulator

+ 143 - 0
ThirdParty/PortAudio/include/pa_asio.h

@@ -0,0 +1,143 @@
+#ifndef PA_ASIO_H
+#define PA_ASIO_H
+/*
+ * $Id: pa_asio.h 1400 2009-01-21 10:20:42Z rossb $
+ * PortAudio Portable Real-Time Audio Library
+ * ASIO specific extensions
+ *
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+
+/** @file
+ @ingroup public_header
+ @brief ASIO-specific PortAudio API extension header file.
+*/
+
+
+#include "portaudio.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+/** Retrieve legal latency settings for the specificed device, in samples.
+
+ @param device The global index of the device about which the query is being made.
+ @param minLatency A pointer to the location which will recieve the minimum latency value.
+ @param maxLatency A pointer to the location which will recieve the maximum latency value.
+ @param preferredLatency A pointer to the location which will recieve the preferred latency value.
+ @param granularity A pointer to the location which will recieve the granularity. This value 
+ determines which values between minLatency and maxLatency are available. ie the step size,
+ if granularity is -1 then available latency settings are powers of two.
+
+ @see ASIOGetBufferSize in the ASIO SDK.
+
+ @todo This function should have a better name, any suggestions?
+*/
+PaError PaAsio_GetAvailableLatencyValues( PaDeviceIndex device,
+		long *minLatency, long *maxLatency, long *preferredLatency, long *granularity );
+
+        
+/** Display the ASIO control panel for the specified device.
+
+  @param device The global index of the device whose control panel is to be displayed.
+  @param systemSpecific On Windows, the calling application's main window handle,
+  on Macintosh this value should be zero.
+*/
+PaError PaAsio_ShowControlPanel( PaDeviceIndex device, void* systemSpecific );
+
+
+
+
+/** Retrieve a pointer to a string containing the name of the specified
+ input channel. The string is valid until Pa_Terminate is called.
+
+ The string will be no longer than 32 characters including the null terminator.
+*/
+PaError PaAsio_GetInputChannelName( PaDeviceIndex device, int channelIndex,
+        const char** channelName );
+
+        
+/** Retrieve a pointer to a string containing the name of the specified
+ input channel. The string is valid until Pa_Terminate is called.
+
+ The string will be no longer than 32 characters including the null terminator.
+*/
+PaError PaAsio_GetOutputChannelName( PaDeviceIndex device, int channelIndex,
+        const char** channelName );
+
+
+/** Set the sample rate of an open paASIO stream.
+ 
+ @param stream The stream to operate on.
+ @param sampleRate The new sample rate. 
+
+ Note that this function may fail if the stream is alredy running and the 
+ ASIO driver does not support switching the sample rate of a running stream.
+
+ Returns paIncompatibleStreamHostApi if stream is not a paASIO stream.
+*/
+PaError PaAsio_SetStreamSampleRate( PaStream* stream, double sampleRate );
+
+
+#define paAsioUseChannelSelectors      (0x01)
+
+typedef struct PaAsioStreamInfo{
+    unsigned long size;             /**< sizeof(PaAsioStreamInfo) */
+    PaHostApiTypeId hostApiType;    /**< paASIO */
+    unsigned long version;          /**< 1 */
+
+    unsigned long flags;
+
+    /* Support for opening only specific channels of an ASIO device.
+        If the paAsioUseChannelSelectors flag is set, channelSelectors is a
+        pointer to an array of integers specifying the device channels to use.
+        When used, the length of the channelSelectors array must match the
+        corresponding channelCount parameter to Pa_OpenStream() otherwise a
+        crash may result.
+        The values in the selectors array must specify channels within the
+        range of supported channels for the device or paInvalidChannelCount will
+        result.
+    */
+    int *channelSelectors;
+}PaAsioStreamInfo;
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PA_ASIO_H */

+ 76 - 0
ThirdParty/PortAudio/include/pa_jack.h

@@ -0,0 +1,76 @@
+#ifndef PA_JACK_H
+#define PA_JACK_H
+
+/*
+ * $Id:
+ * PortAudio Portable Real-Time Audio Library
+ * JACK-specific extensions
+ *
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+/** @file
+ *  @ingroup public_header
+ *  @brief JACK-specific PortAudio API extension header file.
+ */
+#include "portaudio.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Set the JACK client name.
+ *
+ * During Pa_Initialize, When PA JACK connects as a client of the JACK server, it requests a certain
+ * name, which is for instance prepended to port names. By default this name is "PortAudio". The
+ * JACK server may append a suffix to the client name, in order to avoid clashes among clients that
+ * try to connect with the same name (e.g., different PA JACK clients).
+ *
+ * This function must be called before Pa_Initialize, otherwise it won't have any effect. Note that
+ * the string is not copied, but instead referenced directly, so it must not be freed for as long as
+ * PA might need it.
+ * @sa PaJack_GetClientName
+ */
+PaError PaJack_SetClientName( const char* name );
+
+/** Get the JACK client name used by PA JACK.
+ *
+ * The caller is responsible for freeing the returned pointer.
+ */
+PaError PaJack_GetClientName(const char** clientName);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 99 - 0
ThirdParty/PortAudio/include/pa_linux_alsa.h

@@ -0,0 +1,99 @@
+#ifndef PA_LINUX_ALSA_H
+#define PA_LINUX_ALSA_H
+
+/*
+ * $Id: pa_linux_alsa.h 1414 2009-05-24 17:02:10Z aknudsen $
+ * PortAudio Portable Real-Time Audio Library
+ * ALSA-specific extensions
+ *
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+/** @file
+ *  @ingroup public_header
+ *  @brief ALSA-specific PortAudio API extension header file.
+ */
+#include "portaudio.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PaAlsaStreamInfo
+{
+    unsigned long size;
+    PaHostApiTypeId hostApiType;
+    unsigned long version;
+
+    const char *deviceString;
+}
+PaAlsaStreamInfo;
+
+/** Initialize host API specific structure, call this before setting relevant attributes. */
+void PaAlsa_InitializeStreamInfo( PaAlsaStreamInfo *info );
+
+/** Instruct whether to enable real-time priority when starting the audio thread.
+ *
+ * If this is turned on by the stream is started, the audio callback thread will be created
+ * with the FIFO scheduling policy, which is suitable for realtime operation.
+ **/
+void PaAlsa_EnableRealtimeScheduling( PaStream *s, int enable );
+
+#if 0
+void PaAlsa_EnableWatchdog( PaStream *s, int enable );
+#endif
+
+/** Get the ALSA-lib card index of this stream's input device. */
+PaError PaAlsa_GetStreamInputCard( PaStream *s, int *card );
+
+/** Get the ALSA-lib card index of this stream's output device. */
+PaError PaAlsa_GetStreamOutputCard( PaStream *s, int *card );
+
+/** Set the number of periods (buffer fragments) to configure devices with.
+ *
+ * By default the number of periods is 4, this is the lowest number of periods that works well on
+ * the author's soundcard.
+ * @param numPeriods The number of periods.
+ */
+PaError PaAlsa_SetNumPeriods( int numPeriods );
+
+/** Set the maximum number of times to retry opening busy device (sleeping for a
+ * short interval inbetween).
+ */
+PaError PaAlsa_SetRetriesBusy( int retries );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 176 - 0
ThirdParty/PortAudio/include/pa_mac_core.h

@@ -0,0 +1,176 @@
+#ifndef PA_MAC_CORE_H
+#define PA_MAC_CORE_H
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * Macintosh Core Audio specific extensions
+ * portaudio.h should be included before this file.
+ *
+ * Copyright (c) 2005-2006 Bjorn Roche
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+/** @file
+ *  @ingroup public_header
+ *  @brief CoreAudio-specific PortAudio API extension header file.
+ */
+
+#include <AudioUnit/AudioUnit.h>
+//#include <AudioToolbox/AudioToolbox.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * A pointer to a paMacCoreStreamInfo may be passed as
+ * the hostApiSpecificStreamInfo in the PaStreamParameters struct
+ * when opening a stream or querying the format. Use NULL, for the
+ * defaults. Note that for duplex streams, flags for input and output
+ * should be the same or behaviour is undefined.
+ */
+typedef struct
+{
+    unsigned long size;           /**size of whole structure including this header */
+    PaHostApiTypeId hostApiType;  /**host API for which this data is intended */
+    unsigned long version;        /**structure version */
+    unsigned long flags;          /* flags to modify behaviour */
+    SInt32 const * channelMap;    /* Channel map for HAL channel mapping , if not needed, use NULL;*/ 
+    unsigned long channelMapSize; /* Channel map size for HAL channel mapping , if not needed, use 0;*/ 
+} PaMacCoreStreamInfo;
+
+/*
+ * Functions
+ */
+
+
+/* Use this function to initialize a paMacCoreStreamInfo struct
+ * using the requested flags. Note that channel mapping is turned
+ * off after a call to this function.
+ * @param data The datastructure to initialize
+ * @param flags The flags to initialize the datastructure with.
+*/
+void PaMacCore_SetupStreamInfo( PaMacCoreStreamInfo *data, unsigned long flags );
+
+/* call this after pa_SetupMacCoreStreamInfo to use channel mapping as described in notes.txt.
+ * @param data The stream info structure to assign a channel mapping to
+ * @param channelMap The channel map array, as described in notes.txt. This array pointer will be used directly (ie the underlying data will not be copied), so the caller should not free the array until after the stream has been opened.
+ * @param channelMapSize The size of the channel map array.
+ */
+void PaMacCore_SetupChannelMap( PaMacCoreStreamInfo *data, const SInt32 * const channelMap, unsigned long channelMapSize );
+
+/*
+ * Retrieve the AudioDeviceID of the input device assigned to an open stream
+ *
+ * @param s The stream to query.
+ *
+ * @return A valid AudioDeviceID, or NULL if an error occurred.
+ */
+AudioDeviceID PaMacCore_GetStreamInputDevice( PaStream* s );
+ 
+/*
+ * Retrieve the AudioDeviceID of the output device assigned to an open stream
+ *
+ * @param s The stream to query.
+ *
+ * @return A valid AudioDeviceID, or NULL if an error occurred.
+ */
+AudioDeviceID PaMacCore_GetStreamOutputDevice( PaStream* s );
+
+/*
+ * Returns a statically allocated string with the device's name
+ * for the given channel. NULL will be returned on failure.
+ *
+ * This function's implemenation is not complete!
+ *
+ * @param device The PortAudio device index.
+ * @param channel The channel number who's name is requested.
+ * @return a statically allocated string with the name of the device.
+ *         Because this string is statically allocated, it must be
+ *         coppied if it is to be saved and used by the user after
+ *         another call to this function.
+ *
+ */
+const char *PaMacCore_GetChannelName( int device, int channelIndex, bool input );
+
+/*
+ * Flags
+ */
+
+/*
+ * The following flags alter the behaviour of PA on the mac platform.
+ * they can be ORed together. These should work both for opening and
+ * checking a device.
+ */
+
+/* Allows PortAudio to change things like the device's frame size,
+ * which allows for much lower latency, but might disrupt the device
+ * if other programs are using it, even when you are just Querying
+ * the device. */
+#define paMacCoreChangeDeviceParameters (0x01)
+
+/* In combination with the above flag,
+ * causes the stream opening to fail, unless the exact sample rates
+ * are supported by the device. */
+#define paMacCoreFailIfConversionRequired (0x02)
+
+/* These flags set the SR conversion quality, if required. The wierd ordering
+ * allows Maximum Quality to be the default.*/
+#define paMacCoreConversionQualityMin    (0x0100)
+#define paMacCoreConversionQualityMedium (0x0200)
+#define paMacCoreConversionQualityLow    (0x0300)
+#define paMacCoreConversionQualityHigh   (0x0400)
+#define paMacCoreConversionQualityMax    (0x0000)
+
+/*
+ * Here are some "preset" combinations of flags (above) to get to some
+ * common configurations. THIS IS OVERKILL, but if more flags are added
+ * it won't be.
+ */
+
+/*This is the default setting: do as much sample rate conversion as possible
+ * and as little mucking with the device as possible. */
+#define paMacCorePlayNice                    (0x00)
+/*This setting is tuned for pro audio apps. It allows SR conversion on input
+  and output, but it tries to set the appropriate SR on the device.*/
+#define paMacCorePro                         (0x01)
+/*This is a setting to minimize CPU usage and still play nice.*/
+#define paMacCoreMinimizeCPUButPlayNice      (0x0100)
+/*This is a setting to minimize CPU usage, even if that means interrupting the device. */
+#define paMacCoreMinimizeCPU                 (0x0101)
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PA_MAC_CORE_H */

+ 101 - 0
ThirdParty/PortAudio/include/pa_win_ds.h

@@ -0,0 +1,101 @@
+#ifndef PA_WIN_DS_H
+#define PA_WIN_DS_H
+/*
+ * $Id:  $
+ * PortAudio Portable Real-Time Audio Library
+ * DirectSound specific extensions
+ *
+ * Copyright (c) 1999-2007 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+/** @file
+ @ingroup public_header
+ @brief DirectSound-specific PortAudio API extension header file.
+*/
+
+
+#include "portaudio.h"
+#include "pa_win_waveformat.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+#define paWinDirectSoundUseLowLevelLatencyParameters            (0x01)
+#define paWinDirectSoundUseChannelMask                          (0x04)
+
+
+typedef struct PaWinDirectSoundStreamInfo{
+    unsigned long size;             /**< sizeof(PaWinDirectSoundStreamInfo) */
+    PaHostApiTypeId hostApiType;    /**< paDirectSound */
+    unsigned long version;          /**< 1 */
+
+    unsigned long flags;
+
+    /* low-level latency setting support
+        TODO ** NOT IMPLEMENTED **
+        These settings control the number and size of host buffers in order
+        to set latency. They will be used instead of the generic parameters
+        to Pa_OpenStream() if flags contains the paWinDirectSoundUseLowLevelLatencyParameters
+        flag.
+
+        If PaWinDirectSoundStreamInfo structures with paWinDirectSoundUseLowLevelLatencyParameters
+        are supplied for both input and output in a full duplex stream, then the
+        input and output framesPerBuffer must be the same, or the larger of the
+        two must be a multiple of the smaller, otherwise a
+        paIncompatibleHostApiSpecificStreamInfo error will be returned from
+        Pa_OpenStream().
+
+    unsigned long framesPerBuffer;
+    */
+
+    /*
+        support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
+        paWinDirectSoundUseChannelMask this allows you to specify which speakers 
+        to address in a multichannel stream. Constants for channelMask
+        are specified in pa_win_waveformat.h
+
+    */
+    PaWinWaveFormatChannelMask channelMask;
+
+}PaWinDirectSoundStreamInfo;
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PA_WIN_DS_H */                                  

+ 391 - 0
ThirdParty/PortAudio/include/pa_win_wasapi.h

@@ -0,0 +1,391 @@
+#ifndef PA_WIN_WASAPI_H
+#define PA_WIN_WASAPI_H
+/*
+ * $Id:  $
+ * PortAudio Portable Real-Time Audio Library
+ * DirectSound specific extensions
+ *
+ * Copyright (c) 1999-2007 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+/** @file
+ @ingroup public_header
+ @brief WASAPI-specific PortAudio API extension header file.
+*/
+
+#include "portaudio.h"
+#include "pa_win_waveformat.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+/* Setup flags */
+typedef enum PaWasapiFlags
+{
+    /* puts WASAPI into exclusive mode */
+    paWinWasapiExclusive                = (1 << 0),
+
+    /* allows to skip internal PA processing completely */
+    paWinWasapiRedirectHostProcessor    = (1 << 1),
+
+    /* assigns custom channel mask */
+    paWinWasapiUseChannelMask           = (1 << 2),
+
+    /* selects non-Event driven method of data read/write
+       Note: WASAPI Event driven core is capable of 2ms latency!!!, but Polling
+             method can only provide 15-20ms latency. */
+    paWinWasapiPolling                  = (1 << 3),
+
+    /* forces custom thread priority setting. must be used if PaWasapiStreamInfo::threadPriority 
+       is set to custom value. */
+    paWinWasapiThreadPriority           = (1 << 4)
+}
+PaWasapiFlags;
+#define paWinWasapiExclusive             (paWinWasapiExclusive)
+#define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor)
+#define paWinWasapiUseChannelMask        (paWinWasapiUseChannelMask)
+#define paWinWasapiPolling               (paWinWasapiPolling)
+#define paWinWasapiThreadPriority        (paWinWasapiThreadPriority)
+
+
+/* Host processor. Allows to skip internal PA processing completely. 
+   You must set paWinWasapiRedirectHostProcessor flag to PaWasapiStreamInfo::flags member
+   in order to have host processor redirected to your callback.
+   Use with caution! inputFrames and outputFrames depend solely on final device setup.
+   To query maximal values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer.
+*/
+typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer,  long inputFrames,
+                                               void *outputBuffer, long outputFrames,
+                                               void *userData);
+
+/* Device role */
+typedef enum PaWasapiDeviceRole
+{
+    eRoleRemoteNetworkDevice = 0,
+    eRoleSpeakers,
+    eRoleLineLevel,
+    eRoleHeadphones,
+    eRoleMicrophone,
+    eRoleHeadset,
+    eRoleHandset,
+    eRoleUnknownDigitalPassthrough,
+    eRoleSPDIF,
+    eRoleHDMI,
+    eRoleUnknownFormFactor
+}
+PaWasapiDeviceRole;
+
+
+/* Jack connection type */
+typedef enum PaWasapiJackConnectionType
+{
+    eJackConnTypeUnknown,
+    eJackConnType3Point5mm,
+    eJackConnTypeQuarter,
+    eJackConnTypeAtapiInternal,
+    eJackConnTypeRCA,
+    eJackConnTypeOptical,
+    eJackConnTypeOtherDigital,
+    eJackConnTypeOtherAnalog,
+    eJackConnTypeMultichannelAnalogDIN,
+    eJackConnTypeXlrProfessional,
+    eJackConnTypeRJ11Modem,
+    eJackConnTypeCombination
+} 
+PaWasapiJackConnectionType;
+
+
+/* Jack geometric location */
+typedef enum PaWasapiJackGeoLocation
+{
+	eJackGeoLocUnk = 0,
+    eJackGeoLocRear = 0x1, /* matches EPcxGeoLocation::eGeoLocRear */
+    eJackGeoLocFront,
+    eJackGeoLocLeft,
+    eJackGeoLocRight,
+    eJackGeoLocTop,
+    eJackGeoLocBottom,
+    eJackGeoLocRearPanel,
+    eJackGeoLocRiser,
+    eJackGeoLocInsideMobileLid,
+    eJackGeoLocDrivebay,
+    eJackGeoLocHDMI,
+    eJackGeoLocOutsideMobileLid,
+    eJackGeoLocATAPI,
+    eJackGeoLocReserved5,
+    eJackGeoLocReserved6,
+} 
+PaWasapiJackGeoLocation;
+
+
+/* Jack general location */
+typedef enum PaWasapiJackGenLocation
+{
+    eJackGenLocPrimaryBox = 0,
+    eJackGenLocInternal,
+    eJackGenLocSeparate,
+    eJackGenLocOther
+} 
+PaWasapiJackGenLocation;
+
+
+/* Jack's type of port */
+typedef enum PaWasapiJackPortConnection
+{
+    eJackPortConnJack = 0,
+    eJackPortConnIntegratedDevice,
+    eJackPortConnBothIntegratedAndJack,
+    eJackPortConnUnknown
+} 
+PaWasapiJackPortConnection;
+
+
+/* Thread priority */
+typedef enum PaWasapiThreadPriority
+{
+    eThreadPriorityNone = 0,
+    eThreadPriorityAudio,            //!< Default for Shared mode.
+    eThreadPriorityCapture,
+    eThreadPriorityDistribution,
+    eThreadPriorityGames,
+    eThreadPriorityPlayback,
+    eThreadPriorityProAudio,        //!< Default for Exclusive mode.
+    eThreadPriorityWindowManager
+}
+PaWasapiThreadPriority;
+
+
+/* Stream descriptor. */
+typedef struct PaWasapiJackDescription 
+{
+    unsigned long              channelMapping;
+    unsigned long              color; /* derived from macro: #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) */
+    PaWasapiJackConnectionType connectionType;
+    PaWasapiJackGeoLocation    geoLocation;
+    PaWasapiJackGenLocation    genLocation;
+    PaWasapiJackPortConnection portConnection;
+    unsigned int               isConnected;
+}
+PaWasapiJackDescription;
+
+
+/* Stream descriptor. */
+typedef struct PaWasapiStreamInfo 
+{
+    unsigned long size;             /**< sizeof(PaWasapiStreamInfo) */
+    PaHostApiTypeId hostApiType;    /**< paWASAPI */
+    unsigned long version;          /**< 1 */
+
+    unsigned long flags;            /**< collection of PaWasapiFlags */
+
+    /* Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
+       paWinWasapiUseChannelMask this allows you to specify which speakers 
+       to address in a multichannel stream. Constants for channelMask
+       are specified in pa_win_waveformat.h. Will be used only if 
+       paWinWasapiUseChannelMask flag is specified.
+    */
+    PaWinWaveFormatChannelMask channelMask;
+
+    /* Delivers raw data to callback obtained from GetBuffer() methods skipping 
+       internal PortAudio processing inventory completely. userData parameter will 
+       be the same that was passed to Pa_OpenStream method. Will be used only if 
+       paWinWasapiRedirectHostProcessor flag is specified.
+    */
+    PaWasapiHostProcessorCallback hostProcessorOutput;
+    PaWasapiHostProcessorCallback hostProcessorInput;
+
+    /* Specifies thread priority explicitly. Will be used only if paWinWasapiThreadPriority flag
+       is specified.
+
+       Please note, if Input/Output streams are opened simultaniously (Full-Duplex mode)
+       you shall specify same value for threadPriority or othervise one of the values will be used
+       to setup thread priority.
+    */
+    PaWasapiThreadPriority threadPriority;
+} 
+PaWasapiStreamInfo;
+
+
+/** Returns default sound format for device. Format is represented by PaWinWaveFormat or 
+    WAVEFORMATEXTENSIBLE structure.
+
+ @param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
+ @param nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
+ @param nDevice Device index.
+
+ @return Non-negative value indicating the number of bytes copied into format decriptor
+         or, a PaErrorCode (which are always negative) if PortAudio is not initialized
+         or an error is encountered.
+*/
+int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice );
+
+
+/** Returns device role (PaWasapiDeviceRole enum).
+
+ @param nDevice device index.
+
+ @return Non-negative value indicating device role or, a PaErrorCode (which are always negative)
+         if PortAudio is not initialized or an error is encountered.
+*/
+int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice );
+
+
+/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread
+    which makes calls to Pa_WriteStream/Pa_ReadStream.
+
+ @param hTask Handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority
+              method to revert thread priority to initial state.
+
+ @param nPriorityClass Id of thread priority of PaWasapiThreadPriority type. Specifying 
+                       eThreadPriorityNone does nothing.
+
+ @return Error code indicating success or failure.
+ @see    PaWasapi_RevertThreadPriority
+*/
+PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPriorityClass );
+
+
+/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread
+    which makes calls to Pa_WriteStream/Pa_ReadStream.
+
+ @param  hTask Task handle obtained by PaWasapi_BoostThreadPriority method.
+ @return Error code indicating success or failure.
+ @see    PaWasapi_BoostThreadPriority
+*/
+PaError PaWasapi_ThreadPriorityRevert( void *hTask );
+
+
+/** Get number of frames per host buffer. This is maximal value of frames of WASAPI buffer which 
+    can be locked for operations. Use this method as helper to findout maximal values of 
+    inputFrames/outputFrames of PaWasapiHostProcessorCallback.
+
+ @param  pStream Pointer to PaStream to query.
+ @param  nInput  Pointer to variable to receive number of input frames. Can be NULL.
+ @param  nOutput Pointer to variable to receive number of output frames. Can be NULL.
+ @return Error code indicating success or failure.
+ @see    PaWasapiHostProcessorCallback
+*/
+PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput );
+
+
+/** Get number of jacks associated with a WASAPI device.  Use this method to determine if
+    there are any jacks associated with the provided WASAPI device.  Not all audio devices
+	will support this capability.  This is valid for both input and output devices.
+ @param  nDevice  device index.
+ @param  jcount   Number of jacks is returned in this variable
+ @return Error code indicating success or failure
+ @see PaWasapi_GetJackDescription
+ */
+PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount);
+
+
+/** Get the jack description associated with a WASAPI device and jack number
+    Before this function is called, use PaWasapi_GetJackCount to determine the
+	number of jacks associated with device.  If jcount is greater than zero, then
+	each jack from 0 to jcount can be queried with this function to get the jack
+	description.
+ @param  nDevice  device index.
+ @param  jindex   Which jack to return information
+ @param  KSJACK_DESCRIPTION This structure filled in on success.
+ @return Error code indicating success or failure
+ @see PaWasapi_GetJackCount
+ */
+PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription);
+
+
+/*
+    IMPORTANT:
+
+    WASAPI is implemented for Callback and Blocking interfaces. It supports Shared and Exclusive
+    share modes. 
+    
+    Exclusive Mode:
+
+        Exclusive mode allows to deliver audio data directly to hardware bypassing
+        software mixing.
+        Exclusive mode is specified by 'paWinWasapiExclusive' flag.
+
+    Callback Interface:
+
+        Provides best audio quality with low latency. Callback interface is implemented in 
+        two versions:
+
+        1) Event-Driven:
+        This is the most powerful WASAPI implementation which provides glitch-free
+        audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is 
+        3 ms for HD Audio class audio chips. For the Shared mode latency can not be 
+		lower than 20 ms.
+
+        2) Poll-Driven:
+        Polling is another 2-nd method to operate with WASAPI. It is less efficient than Event-Driven
+        and provides latency at around 10-13ms. Polling must be used to overcome a system bug
+        under Windows Vista x64 when application is WOW64(32-bit) and Event-Driven method simply 
+        times out (event handle is never signalled on buffer completion). Please note, such WOW64 bug 
+        does not exist in Vista x86 or Windows 7.
+        Polling can be setup by speciying 'paWinWasapiPolling' flag. Our WASAPI implementation detects
+        WOW64 bug and sets 'paWinWasapiPolling' automatically.
+
+    Thread priority:
+
+        Normally thread priority is set automatically and does not require modification. Although
+        if user wants some tweaking thread priority can be modified by setting 'paWinWasapiThreadPriority'
+        flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority 
+        enum.
+
+    Blocking Interface:
+
+        Blocking interface is implemented but due to above described Poll-Driven method can not
+        deliver lowest possible latency. Specifying too low latency in Shared mode will result in 
+        distorted audio although Exclusive mode adds stability.
+
+    Pa_IsFormatSupported:
+
+        To check format with correct Share Mode (Exclusive/Shared) you must supply
+        PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of 
+        PaStreamParameters::hostApiSpecificStreamInfo structure.
+
+    Pa_OpenStream:
+
+        To set desired Share Mode (Exclusive/Shared) you must supply
+        PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of 
+        PaStreamParameters::hostApiSpecificStreamInfo structure.
+*/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PA_WIN_WASAPI_H */                                  

+ 199 - 0
ThirdParty/PortAudio/include/pa_win_waveformat.h

@@ -0,0 +1,199 @@
+#ifndef PA_WIN_WAVEFORMAT_H
+#define PA_WIN_WAVEFORMAT_H
+
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * Windows WAVEFORMAT* data structure utilities
+ * portaudio.h should be included before this file.
+ *
+ * Copyright (c) 2007 Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+/** @file
+ @ingroup public_header
+ @brief Windows specific PortAudio API extension and utilities header file.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+	The following #defines for speaker channel masks are the same
+	as those in ksmedia.h, except with PAWIN_ prepended, KSAUDIO_ removed
+	in some cases, and casts to PaWinWaveFormatChannelMask added.
+*/
+
+typedef unsigned long PaWinWaveFormatChannelMask;
+
+/* Speaker Positions: */
+#define PAWIN_SPEAKER_FRONT_LEFT				((PaWinWaveFormatChannelMask)0x1)
+#define PAWIN_SPEAKER_FRONT_RIGHT				((PaWinWaveFormatChannelMask)0x2)
+#define PAWIN_SPEAKER_FRONT_CENTER				((PaWinWaveFormatChannelMask)0x4)
+#define PAWIN_SPEAKER_LOW_FREQUENCY				((PaWinWaveFormatChannelMask)0x8)
+#define PAWIN_SPEAKER_BACK_LEFT					((PaWinWaveFormatChannelMask)0x10)
+#define PAWIN_SPEAKER_BACK_RIGHT				((PaWinWaveFormatChannelMask)0x20)
+#define PAWIN_SPEAKER_FRONT_LEFT_OF_CENTER		((PaWinWaveFormatChannelMask)0x40)
+#define PAWIN_SPEAKER_FRONT_RIGHT_OF_CENTER		((PaWinWaveFormatChannelMask)0x80)
+#define PAWIN_SPEAKER_BACK_CENTER				((PaWinWaveFormatChannelMask)0x100)
+#define PAWIN_SPEAKER_SIDE_LEFT					((PaWinWaveFormatChannelMask)0x200)
+#define PAWIN_SPEAKER_SIDE_RIGHT				((PaWinWaveFormatChannelMask)0x400)
+#define PAWIN_SPEAKER_TOP_CENTER				((PaWinWaveFormatChannelMask)0x800)
+#define PAWIN_SPEAKER_TOP_FRONT_LEFT			((PaWinWaveFormatChannelMask)0x1000)
+#define PAWIN_SPEAKER_TOP_FRONT_CENTER			((PaWinWaveFormatChannelMask)0x2000)
+#define PAWIN_SPEAKER_TOP_FRONT_RIGHT			((PaWinWaveFormatChannelMask)0x4000)
+#define PAWIN_SPEAKER_TOP_BACK_LEFT				((PaWinWaveFormatChannelMask)0x8000)
+#define PAWIN_SPEAKER_TOP_BACK_CENTER			((PaWinWaveFormatChannelMask)0x10000)
+#define PAWIN_SPEAKER_TOP_BACK_RIGHT			((PaWinWaveFormatChannelMask)0x20000)
+
+/* Bit mask locations reserved for future use */
+#define PAWIN_SPEAKER_RESERVED					((PaWinWaveFormatChannelMask)0x7FFC0000)
+
+/* Used to specify that any possible permutation of speaker configurations */
+#define PAWIN_SPEAKER_ALL						((PaWinWaveFormatChannelMask)0x80000000)
+
+/* DirectSound Speaker Config */
+#define PAWIN_SPEAKER_DIRECTOUT					0
+#define PAWIN_SPEAKER_MONO						(PAWIN_SPEAKER_FRONT_CENTER)
+#define PAWIN_SPEAKER_STEREO					(PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT)
+#define PAWIN_SPEAKER_QUAD						(PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+												PAWIN_SPEAKER_BACK_LEFT  | PAWIN_SPEAKER_BACK_RIGHT)
+#define PAWIN_SPEAKER_SURROUND					(PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+												PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_BACK_CENTER)
+#define PAWIN_SPEAKER_5POINT1					(PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+												PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
+												PAWIN_SPEAKER_BACK_LEFT  | PAWIN_SPEAKER_BACK_RIGHT)
+#define PAWIN_SPEAKER_7POINT1					(PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+												PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
+												PAWIN_SPEAKER_BACK_LEFT | PAWIN_SPEAKER_BACK_RIGHT | \
+												PAWIN_SPEAKER_FRONT_LEFT_OF_CENTER | PAWIN_SPEAKER_FRONT_RIGHT_OF_CENTER)
+#define PAWIN_SPEAKER_5POINT1_SURROUND			(PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+												PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
+												PAWIN_SPEAKER_SIDE_LEFT  | PAWIN_SPEAKER_SIDE_RIGHT)
+#define PAWIN_SPEAKER_7POINT1_SURROUND			(PAWIN_SPEAKER_FRONT_LEFT | PAWIN_SPEAKER_FRONT_RIGHT | \
+												PAWIN_SPEAKER_FRONT_CENTER | PAWIN_SPEAKER_LOW_FREQUENCY | \
+												PAWIN_SPEAKER_BACK_LEFT | PAWIN_SPEAKER_BACK_RIGHT | \
+												PAWIN_SPEAKER_SIDE_LEFT | PAWIN_SPEAKER_SIDE_RIGHT)
+/*
+ According to the Microsoft documentation:
+ The following are obsolete 5.1 and 7.1 settings (they lack side speakers).  Note this means
+ that the default 5.1 and 7.1 settings (KSAUDIO_SPEAKER_5POINT1 and KSAUDIO_SPEAKER_7POINT1 are
+ similarly obsolete but are unchanged for compatibility reasons).
+*/
+#define PAWIN_SPEAKER_5POINT1_BACK				PAWIN_SPEAKER_5POINT1
+#define PAWIN_SPEAKER_7POINT1_WIDE				PAWIN_SPEAKER_7POINT1
+
+/* DVD Speaker Positions */
+#define PAWIN_SPEAKER_GROUND_FRONT_LEFT			PAWIN_SPEAKER_FRONT_LEFT
+#define PAWIN_SPEAKER_GROUND_FRONT_CENTER		PAWIN_SPEAKER_FRONT_CENTER
+#define PAWIN_SPEAKER_GROUND_FRONT_RIGHT		PAWIN_SPEAKER_FRONT_RIGHT
+#define PAWIN_SPEAKER_GROUND_REAR_LEFT			PAWIN_SPEAKER_BACK_LEFT
+#define PAWIN_SPEAKER_GROUND_REAR_RIGHT			PAWIN_SPEAKER_BACK_RIGHT
+#define PAWIN_SPEAKER_TOP_MIDDLE				PAWIN_SPEAKER_TOP_CENTER
+#define PAWIN_SPEAKER_SUPER_WOOFER				PAWIN_SPEAKER_LOW_FREQUENCY
+
+
+/*
+	PaWinWaveFormat is defined here to provide compatibility with
+	compilation environments which don't have headers defining 
+	WAVEFORMATEXTENSIBLE (e.g. older versions of MSVC, Borland C++ etc.
+
+	The fields for WAVEFORMATEX and WAVEFORMATEXTENSIBLE are declared as an
+    unsigned char array here to avoid clients who include this file having 
+    a dependency on windows.h and mmsystem.h, and also to to avoid having
+    to write separate packing pragmas for each compiler.
+*/
+#define PAWIN_SIZEOF_WAVEFORMATEX   18
+#define PAWIN_SIZEOF_WAVEFORMATEXTENSIBLE (PAWIN_SIZEOF_WAVEFORMATEX + 22)
+
+typedef struct{
+    unsigned char fields[ PAWIN_SIZEOF_WAVEFORMATEXTENSIBLE ];
+    unsigned long extraLongForAlignment; /* ensure that compiler aligns struct to DWORD */ 
+} PaWinWaveFormat;
+
+/*
+    WAVEFORMATEXTENSIBLE fields:
+    
+    union  {
+	    WORD  wValidBitsPerSample;    
+	    WORD  wSamplesPerBlock;    
+	    WORD  wReserved;  
+    } Samples;
+    DWORD  dwChannelMask;  
+    GUID  SubFormat;
+*/
+
+#define PAWIN_INDEXOF_WVALIDBITSPERSAMPLE	(PAWIN_SIZEOF_WAVEFORMATEX+0)
+#define PAWIN_INDEXOF_DWCHANNELMASK			(PAWIN_SIZEOF_WAVEFORMATEX+2)
+#define PAWIN_INDEXOF_SUBFORMAT				(PAWIN_SIZEOF_WAVEFORMATEX+6)
+
+
+/*
+    Valid values to pass for the waveFormatTag PaWin_InitializeWaveFormatEx and
+    PaWin_InitializeWaveFormatExtensible functions below. These must match
+    the standard Windows WAVE_FORMAT_* values.
+*/
+#define PAWIN_WAVE_FORMAT_PCM               (1)
+#define PAWIN_WAVE_FORMAT_IEEE_FLOAT        (3)
+#define PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF   (0x0092)
+#define PAWIN_WAVE_FORMAT_WMA_SPDIF         (0x0164)
+
+
+/*
+    returns PAWIN_WAVE_FORMAT_PCM or PAWIN_WAVE_FORMAT_IEEE_FLOAT
+    depending on the sampleFormat parameter.
+*/
+int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat );
+
+/*
+	Use the following two functions to initialize the waveformat structure.
+*/
+
+void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat, 
+		int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate );
+
+
+void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat, 
+		int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate,
+	    PaWinWaveFormatChannelMask channelMask );
+
+
+/* Map a channel count to a speaker channel mask */
+PaWinWaveFormatChannelMask PaWin_DefaultChannelMask( int numChannels );
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PA_WIN_WAVEFORMAT_H */

+ 186 - 0
ThirdParty/PortAudio/include/pa_win_wmme.h

@@ -0,0 +1,186 @@
+#ifndef PA_WIN_WMME_H
+#define PA_WIN_WMME_H
+/*
+ * $Id: pa_win_wmme.h 1405 2009-03-08 08:10:55Z rossb $
+ * PortAudio Portable Real-Time Audio Library
+ * MME specific extensions
+ *
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+/** @file
+ @ingroup public_header
+ @brief WMME-specific PortAudio API extension header file.
+*/
+
+
+#include "portaudio.h"
+#include "pa_win_waveformat.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+/* The following are flags which can be set in 
+  PaWinMmeStreamInfo's flags field.
+*/
+
+#define paWinMmeUseLowLevelLatencyParameters            (0x01)
+#define paWinMmeUseMultipleDevices                      (0x02)  /* use mme specific multiple device feature */
+#define paWinMmeUseChannelMask                          (0x04)
+
+/* By default, the mme implementation drops the processing thread's priority
+    to THREAD_PRIORITY_NORMAL and sleeps the thread if the CPU load exceeds 100%
+    This flag disables any priority throttling. The processing thread will always
+    run at THREAD_PRIORITY_TIME_CRITICAL.
+*/
+#define paWinMmeDontThrottleOverloadedProcessingThread  (0x08)
+
+/*  Flags for non-PCM spdif passthrough.
+*/
+#define paWinMmeWaveFormatDolbyAc3Spdif                 (0x10)
+#define paWinMmeWaveFormatWmaSpdif                      (0x20)
+
+
+typedef struct PaWinMmeDeviceAndChannelCount{
+    PaDeviceIndex device;
+    int channelCount;
+}PaWinMmeDeviceAndChannelCount;
+
+
+typedef struct PaWinMmeStreamInfo{
+    unsigned long size;             /**< sizeof(PaWinMmeStreamInfo) */
+    PaHostApiTypeId hostApiType;    /**< paMME */
+    unsigned long version;          /**< 1 */
+
+    unsigned long flags;
+
+    /* low-level latency setting support
+        These settings control the number and size of host buffers in order
+        to set latency. They will be used instead of the generic parameters
+        to Pa_OpenStream() if flags contains the PaWinMmeUseLowLevelLatencyParameters
+        flag.
+
+        If PaWinMmeStreamInfo structures with PaWinMmeUseLowLevelLatencyParameters
+        are supplied for both input and output in a full duplex stream, then the
+        input and output framesPerBuffer must be the same, or the larger of the
+        two must be a multiple of the smaller, otherwise a
+        paIncompatibleHostApiSpecificStreamInfo error will be returned from
+        Pa_OpenStream().
+    */
+    unsigned long framesPerBuffer;
+    unsigned long bufferCount;  /* formerly numBuffers */ 
+
+    /* multiple devices per direction support
+        If flags contains the PaWinMmeUseMultipleDevices flag,
+        this functionality will be used, otherwise the device parameter to
+        Pa_OpenStream() will be used instead.
+        If devices are specified here, the corresponding device parameter
+        to Pa_OpenStream() should be set to paUseHostApiSpecificDeviceSpecification,
+        otherwise an paInvalidDevice error will result.
+        The total number of channels accross all specified devices
+        must agree with the corresponding channelCount parameter to
+        Pa_OpenStream() otherwise a paInvalidChannelCount error will result.
+    */
+    PaWinMmeDeviceAndChannelCount *devices;
+    unsigned long deviceCount;
+
+    /*
+        support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
+        paWinMmeUseChannelMask this allows you to specify which speakers 
+        to address in a multichannel stream. Constants for channelMask
+        are specified in pa_win_waveformat.h
+
+    */
+    PaWinWaveFormatChannelMask channelMask;
+
+}PaWinMmeStreamInfo;
+
+
+/** Retrieve the number of wave in handles used by a PortAudio WinMME stream.
+ Returns zero if the stream is output only.
+
+ @return A non-negative value indicating the number of wave in handles
+ or, a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+
+ @see PaWinMME_GetStreamInputHandle
+*/
+int PaWinMME_GetStreamInputHandleCount( PaStream* stream );
+
+
+/** Retrieve a wave in handle used by a PortAudio WinMME stream.
+
+ @param stream The stream to query.
+ @param handleIndex The zero based index of the wave in handle to retrieve. This
+    should be in the range [0, PaWinMME_GetStreamInputHandleCount(stream)-1].
+
+ @return A valid wave in handle, or NULL if an error occurred.
+
+ @see PaWinMME_GetStreamInputHandle
+*/
+HWAVEIN PaWinMME_GetStreamInputHandle( PaStream* stream, int handleIndex );
+
+
+/** Retrieve the number of wave out handles used by a PortAudio WinMME stream.
+ Returns zero if the stream is input only.
+ 
+ @return A non-negative value indicating the number of wave out handles
+ or, a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+
+ @see PaWinMME_GetStreamOutputHandle
+*/
+int PaWinMME_GetStreamOutputHandleCount( PaStream* stream );
+
+
+/** Retrieve a wave out handle used by a PortAudio WinMME stream.
+
+ @param stream The stream to query.
+ @param handleIndex The zero based index of the wave out handle to retrieve.
+    This should be in the range [0, PaWinMME_GetStreamOutputHandleCount(stream)-1].
+
+ @return A valid wave out handle, or NULL if an error occurred.
+
+ @see PaWinMME_GetStreamOutputHandleCount
+*/
+HWAVEOUT PaWinMME_GetStreamOutputHandle( PaStream* stream, int handleIndex );
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PA_WIN_WMME_H */                                  

+ 1134 - 0
ThirdParty/PortAudio/include/portaudio.h

@@ -0,0 +1,1134 @@
+#ifndef PORTAUDIO_H
+#define PORTAUDIO_H
+/*
+ * $Id: portaudio.h 1337 2008-02-15 07:32:09Z rossb $
+ * PortAudio Portable Real-Time Audio Library
+ * PortAudio API Header File
+ * Latest version available at: http://www.portaudio.com/
+ *
+ * Copyright (c) 1999-2002 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+/** @file
+ @ingroup public_header
+ @brief The portable PortAudio API.
+*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+ 
+/** Retrieve the release number of the currently running PortAudio build,
+ eg 1900.
+*/
+int Pa_GetVersion( void );
+
+
+/** Retrieve a textual description of the current PortAudio build,
+ eg "PortAudio V19-devel 13 October 2002".
+*/
+const char* Pa_GetVersionText( void );
+
+
+/** Error codes returned by PortAudio functions.
+ Note that with the exception of paNoError, all PaErrorCodes are negative.
+*/
+
+typedef int PaError;
+typedef enum PaErrorCode
+{
+    paNoError = 0,
+
+    paNotInitialized = -10000,
+    paUnanticipatedHostError,
+    paInvalidChannelCount,
+    paInvalidSampleRate,
+    paInvalidDevice,
+    paInvalidFlag,
+    paSampleFormatNotSupported,
+    paBadIODeviceCombination,
+    paInsufficientMemory,
+    paBufferTooBig,
+    paBufferTooSmall,
+    paNullCallback,
+    paBadStreamPtr,
+    paTimedOut,
+    paInternalError,
+    paDeviceUnavailable,
+    paIncompatibleHostApiSpecificStreamInfo,
+    paStreamIsStopped,
+    paStreamIsNotStopped,
+    paInputOverflowed,
+    paOutputUnderflowed,
+    paHostApiNotFound,
+    paInvalidHostApi,
+    paCanNotReadFromACallbackStream,      /**< @todo review error code name */
+    paCanNotWriteToACallbackStream,       /**< @todo review error code name */
+    paCanNotReadFromAnOutputOnlyStream,   /**< @todo review error code name */
+    paCanNotWriteToAnInputOnlyStream,     /**< @todo review error code name */
+    paIncompatibleStreamHostApi,
+    paBadBufferPtr
+} PaErrorCode;
+
+
+/** Translate the supplied PortAudio error code into a human readable
+ message.
+*/
+const char *Pa_GetErrorText( PaError errorCode );
+
+
+/** Library initialization function - call this before using PortAudio.
+ This function initialises internal data structures and prepares underlying
+ host APIs for use.  With the exception of Pa_GetVersion(), Pa_GetVersionText(),
+ and Pa_GetErrorText(), this function MUST be called before using any other
+ PortAudio API functions.
+
+ If Pa_Initialize() is called multiple times, each successful 
+ call must be matched with a corresponding call to Pa_Terminate(). 
+ Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not 
+ required to be fully nested.
+
+ Note that if Pa_Initialize() returns an error code, Pa_Terminate() should
+ NOT be called.
+
+ @return paNoError if successful, otherwise an error code indicating the cause
+ of failure.
+
+ @see Pa_Terminate
+*/
+PaError Pa_Initialize( void );
+
+
+/** Library termination function - call this when finished using PortAudio.
+ This function deallocates all resources allocated by PortAudio since it was
+ initializied by a call to Pa_Initialize(). In cases where Pa_Initialise() has
+ been called multiple times, each call must be matched with a corresponding call
+ to Pa_Terminate(). The final matching call to Pa_Terminate() will automatically
+ close any PortAudio streams that are still open.
+
+ Pa_Terminate() MUST be called before exiting a program which uses PortAudio.
+ Failure to do so may result in serious resource leaks, such as audio devices
+ not being available until the next reboot.
+
+ @return paNoError if successful, otherwise an error code indicating the cause
+ of failure.
+ 
+ @see Pa_Initialize
+*/
+PaError Pa_Terminate( void );
+
+
+
+/** The type used to refer to audio devices. Values of this type usually
+ range from 0 to (Pa_GetDeviceCount()-1), and may also take on the PaNoDevice
+ and paUseHostApiSpecificDeviceSpecification values.
+
+ @see Pa_GetDeviceCount, paNoDevice, paUseHostApiSpecificDeviceSpecification
+*/
+typedef int PaDeviceIndex;
+
+
+/** A special PaDeviceIndex value indicating that no device is available,
+ or should be used.
+
+ @see PaDeviceIndex
+*/
+#define paNoDevice ((PaDeviceIndex)-1)
+
+
+/** A special PaDeviceIndex value indicating that the device(s) to be used
+ are specified in the host api specific stream info structure.
+
+ @see PaDeviceIndex
+*/
+#define paUseHostApiSpecificDeviceSpecification ((PaDeviceIndex)-2)
+
+
+/* Host API enumeration mechanism */
+
+/** The type used to enumerate to host APIs at runtime. Values of this type
+ range from 0 to (Pa_GetHostApiCount()-1).
+
+ @see Pa_GetHostApiCount
+*/
+typedef int PaHostApiIndex;
+
+
+/** Retrieve the number of available host APIs. Even if a host API is
+ available it may have no devices available.
+
+ @return A non-negative value indicating the number of available host APIs
+ or, a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+
+ @see PaHostApiIndex
+*/
+PaHostApiIndex Pa_GetHostApiCount( void );
+
+
+/** Retrieve the index of the default host API. The default host API will be
+ the lowest common denominator host API on the current platform and is
+ unlikely to provide the best performance.
+
+ @return A non-negative value ranging from 0 to (Pa_GetHostApiCount()-1)
+ indicating the default host API index or, a PaErrorCode (which are always
+ negative) if PortAudio is not initialized or an error is encountered.
+*/
+PaHostApiIndex Pa_GetDefaultHostApi( void );
+
+
+/** Unchanging unique identifiers for each supported host API. This type
+ is used in the PaHostApiInfo structure. The values are guaranteed to be
+ unique and to never change, thus allowing code to be written that
+ conditionally uses host API specific extensions.
+
+ New type ids will be allocated when support for a host API reaches
+ "public alpha" status, prior to that developers should use the
+ paInDevelopment type id.
+
+ @see PaHostApiInfo
+*/
+typedef enum PaHostApiTypeId
+{
+    paInDevelopment=0, /* use while developing support for a new host API */
+    paDirectSound=1,
+    paMME=2,
+    paASIO=3,
+    paSoundManager=4,
+    paCoreAudio=5,
+    paOSS=7,
+    paALSA=8,
+    paAL=9,
+    paBeOS=10,
+    paWDMKS=11,
+    paJACK=12,
+    paWASAPI=13,
+    paAudioScienceHPI=14
+} PaHostApiTypeId;
+
+
+/** A structure containing information about a particular host API. */
+
+typedef struct PaHostApiInfo
+{
+    /** this is struct version 1 */
+    int structVersion;
+    /** The well known unique identifier of this host API @see PaHostApiTypeId */
+    PaHostApiTypeId type;
+    /** A textual description of the host API for display on user interfaces. */
+    const char *name;
+
+    /**  The number of devices belonging to this host API. This field may be
+     used in conjunction with Pa_HostApiDeviceIndexToDeviceIndex() to enumerate
+     all devices for this host API.
+     @see Pa_HostApiDeviceIndexToDeviceIndex
+    */
+    int deviceCount;
+
+    /** The default input device for this host API. The value will be a
+     device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice
+     if no default input device is available.
+    */
+    PaDeviceIndex defaultInputDevice;
+
+    /** The default output device for this host API. The value will be a
+     device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice
+     if no default output device is available.
+    */
+    PaDeviceIndex defaultOutputDevice;
+    
+} PaHostApiInfo;
+
+
+/** Retrieve a pointer to a structure containing information about a specific
+ host Api.
+
+ @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1)
+
+ @return A pointer to an immutable PaHostApiInfo structure describing
+ a specific host API. If the hostApi parameter is out of range or an error
+ is encountered, the function returns NULL.
+
+ The returned structure is owned by the PortAudio implementation and must not
+ be manipulated or freed. The pointer is only guaranteed to be valid between
+ calls to Pa_Initialize() and Pa_Terminate().
+*/
+const PaHostApiInfo * Pa_GetHostApiInfo( PaHostApiIndex hostApi );
+
+
+/** Convert a static host API unique identifier, into a runtime
+ host API index.
+
+ @param type A unique host API identifier belonging to the PaHostApiTypeId
+ enumeration.
+
+ @return A valid PaHostApiIndex ranging from 0 to (Pa_GetHostApiCount()-1) or,
+ a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+ 
+ The paHostApiNotFound error code indicates that the host API specified by the
+ type parameter is not available.
+
+ @see PaHostApiTypeId
+*/
+PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type );
+
+
+/** Convert a host-API-specific device index to standard PortAudio device index.
+ This function may be used in conjunction with the deviceCount field of
+ PaHostApiInfo to enumerate all devices for the specified host API.
+
+ @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1)
+
+ @param hostApiDeviceIndex A valid per-host device index in the range
+ 0 to (Pa_GetHostApiInfo(hostApi)->deviceCount-1)
+
+ @return A non-negative PaDeviceIndex ranging from 0 to (Pa_GetDeviceCount()-1)
+ or, a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+
+ A paInvalidHostApi error code indicates that the host API index specified by
+ the hostApi parameter is out of range.
+
+ A paInvalidDevice error code indicates that the hostApiDeviceIndex parameter
+ is out of range.
+ 
+ @see PaHostApiInfo
+*/
+PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi,
+        int hostApiDeviceIndex );
+
+
+
+/** Structure used to return information about a host error condition.
+*/
+typedef struct PaHostErrorInfo{
+    PaHostApiTypeId hostApiType;    /**< the host API which returned the error code */
+    long errorCode;                 /**< the error code returned */
+    const char *errorText;          /**< a textual description of the error if available, otherwise a zero-length string */
+}PaHostErrorInfo;
+
+
+/** Return information about the last host error encountered. The error
+ information returned by Pa_GetLastHostErrorInfo() will never be modified
+ asyncronously by errors occurring in other PortAudio owned threads
+ (such as the thread that manages the stream callback.)
+
+ This function is provided as a last resort, primarily to enhance debugging
+ by providing clients with access to all available error information.
+
+ @return A pointer to an immutable structure constaining information about
+ the host error. The values in this structure will only be valid if a
+ PortAudio function has previously returned the paUnanticipatedHostError
+ error code.
+*/
+const PaHostErrorInfo* Pa_GetLastHostErrorInfo( void );
+
+
+
+/* Device enumeration and capabilities */
+
+/** Retrieve the number of available devices. The number of available devices
+ may be zero.
+
+ @return A non-negative value indicating the number of available devices or,
+ a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+*/
+PaDeviceIndex Pa_GetDeviceCount( void );
+
+
+/** Retrieve the index of the default input device. The result can be
+ used in the inputDevice parameter to Pa_OpenStream().
+
+ @return The default input device index for the default host API, or paNoDevice
+ if no default input device is available or an error was encountered.
+*/
+PaDeviceIndex Pa_GetDefaultInputDevice( void );
+
+
+/** Retrieve the index of the default output device. The result can be
+ used in the outputDevice parameter to Pa_OpenStream().
+
+ @return The default output device index for the defualt host API, or paNoDevice
+ if no default output device is available or an error was encountered.
+
+ @note
+ On the PC, the user can specify a default device by
+ setting an environment variable. For example, to use device #1.
+<pre>
+ set PA_RECOMMENDED_OUTPUT_DEVICE=1
+</pre>
+ The user should first determine the available device ids by using
+ the supplied application "pa_devs".
+*/
+PaDeviceIndex Pa_GetDefaultOutputDevice( void );
+
+
+/** The type used to represent monotonic time in seconds that can be used
+ for syncronisation. The type is used for the outTime argument to the
+ PaStreamCallback and as the result of Pa_GetStreamTime().
+     
+ @see PaStreamCallback, Pa_GetStreamTime
+*/
+typedef double PaTime;
+
+
+/** A type used to specify one or more sample formats. Each value indicates
+ a possible format for sound data passed to and from the stream callback,
+ Pa_ReadStream and Pa_WriteStream.
+
+ The standard formats paFloat32, paInt16, paInt32, paInt24, paInt8
+ and aUInt8 are usually implemented by all implementations.
+
+ The floating point representation (paFloat32) uses +1.0 and -1.0 as the
+ maximum and minimum respectively.
+
+ paUInt8 is an unsigned 8 bit format where 128 is considered "ground"
+
+ The paNonInterleaved flag indicates that a multichannel buffer is passed
+ as a set of non-interleaved pointers.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream, PaDeviceInfo
+ @see paFloat32, paInt16, paInt32, paInt24, paInt8
+ @see paUInt8, paCustomFormat, paNonInterleaved
+*/
+typedef unsigned long PaSampleFormat;
+
+
+#define paFloat32        ((PaSampleFormat) 0x00000001) /**< @see PaSampleFormat */
+#define paInt32          ((PaSampleFormat) 0x00000002) /**< @see PaSampleFormat */
+#define paInt24          ((PaSampleFormat) 0x00000004) /**< Packed 24 bit format. @see PaSampleFormat */
+#define paInt16          ((PaSampleFormat) 0x00000008) /**< @see PaSampleFormat */
+#define paInt8           ((PaSampleFormat) 0x00000010) /**< @see PaSampleFormat */
+#define paUInt8          ((PaSampleFormat) 0x00000020) /**< @see PaSampleFormat */
+#define paCustomFormat   ((PaSampleFormat) 0x00010000)/**< @see PaSampleFormat */
+
+#define paNonInterleaved ((PaSampleFormat) 0x80000000)
+
+/** A structure providing information and capabilities of PortAudio devices.
+ Devices may support input, output or both input and output.
+*/
+typedef struct PaDeviceInfo
+{
+    int structVersion;  /* this is struct version 2 */
+    const char *name;
+    PaHostApiIndex hostApi; /* note this is a host API index, not a type id*/
+    
+    int maxInputChannels;
+    int maxOutputChannels;
+
+    /* Default latency values for interactive performance. */
+    PaTime defaultLowInputLatency;
+    PaTime defaultLowOutputLatency;
+    /* Default latency values for robust non-interactive applications (eg. playing sound files). */
+    PaTime defaultHighInputLatency;
+    PaTime defaultHighOutputLatency;
+
+    double defaultSampleRate;
+} PaDeviceInfo;
+
+
+/** Retrieve a pointer to a PaDeviceInfo structure containing information
+ about the specified device.
+ @return A pointer to an immutable PaDeviceInfo structure. If the device
+ parameter is out of range the function returns NULL.
+
+ @param device A valid device index in the range 0 to (Pa_GetDeviceCount()-1)
+
+ @note PortAudio manages the memory referenced by the returned pointer,
+ the client must not manipulate or free the memory. The pointer is only
+ guaranteed to be valid between calls to Pa_Initialize() and Pa_Terminate().
+
+ @see PaDeviceInfo, PaDeviceIndex
+*/
+const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device );
+
+
+/** Parameters for one direction (input or output) of a stream.
+*/
+typedef struct PaStreamParameters
+{
+    /** A valid device index in the range 0 to (Pa_GetDeviceCount()-1)
+     specifying the device to be used or the special constant
+     paUseHostApiSpecificDeviceSpecification which indicates that the actual
+     device(s) to use are specified in hostApiSpecificStreamInfo.
+     This field must not be set to paNoDevice.
+    */
+    PaDeviceIndex device;
+    
+    /** The number of channels of sound to be delivered to the
+     stream callback or accessed by Pa_ReadStream() or Pa_WriteStream().
+     It can range from 1 to the value of maxInputChannels in the
+     PaDeviceInfo record for the device specified by the device parameter.
+    */
+    int channelCount;
+
+    /** The sample format of the buffer provided to the stream callback,
+     a_ReadStream() or Pa_WriteStream(). It may be any of the formats described
+     by the PaSampleFormat enumeration.
+    */
+    PaSampleFormat sampleFormat;
+
+    /** The desired latency in seconds. Where practical, implementations should
+     configure their latency based on these parameters, otherwise they may
+     choose the closest viable latency instead. Unless the suggested latency
+     is greater than the absolute upper limit for the device implementations
+     should round the suggestedLatency up to the next practial value - ie to
+     provide an equal or higher latency than suggestedLatency wherever possibe.
+     Actual latency values for an open stream may be retrieved using the
+     inputLatency and outputLatency fields of the PaStreamInfo structure
+     returned by Pa_GetStreamInfo().
+     @see default*Latency in PaDeviceInfo, *Latency in PaStreamInfo
+    */
+    PaTime suggestedLatency;
+
+    /** An optional pointer to a host api specific data structure
+     containing additional information for device setup and/or stream processing.
+     hostApiSpecificStreamInfo is never required for correct operation,
+     if not used it should be set to NULL.
+    */
+    void *hostApiSpecificStreamInfo;
+
+} PaStreamParameters;
+
+
+/** Return code for Pa_IsFormatSupported indicating success. */
+#define paFormatIsSupported (0)
+
+/** Determine whether it would be possible to open a stream with the specified
+ parameters.
+
+ @param inputParameters A structure that describes the input parameters used to
+ open a stream. The suggestedLatency field is ignored. See PaStreamParameters
+ for a description of these parameters. inputParameters must be NULL for
+ output-only streams.
+
+ @param outputParameters A structure that describes the output parameters used
+ to open a stream. The suggestedLatency field is ignored. See PaStreamParameters
+ for a description of these parameters. outputParameters must be NULL for
+ input-only streams.
+
+ @param sampleRate The required sampleRate. For full-duplex streams it is the
+ sample rate for both input and output
+
+ @return Returns 0 if the format is supported, and an error code indicating why
+ the format is not supported otherwise. The constant paFormatIsSupported is
+ provided to compare with the return value for success.
+
+ @see paFormatIsSupported, PaStreamParameters
+*/
+PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
+                              const PaStreamParameters *outputParameters,
+                              double sampleRate );
+
+
+
+/* Streaming types and functions */
+
+
+/**
+ A single PaStream can provide multiple channels of real-time
+ streaming audio input and output to a client application. A stream
+ provides access to audio hardware represented by one or more
+ PaDevices. Depending on the underlying Host API, it may be possible 
+ to open multiple streams using the same device, however this behavior 
+ is implementation defined. Portable applications should assume that 
+ a PaDevice may be simultaneously used by at most one PaStream.
+
+ Pointers to PaStream objects are passed between PortAudio functions that
+ operate on streams.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream, Pa_OpenDefaultStream, Pa_CloseStream,
+ Pa_StartStream, Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive,
+ Pa_GetStreamTime, Pa_GetStreamCpuLoad
+
+*/
+typedef void PaStream;
+
+
+/** Can be passed as the framesPerBuffer parameter to Pa_OpenStream()
+ or Pa_OpenDefaultStream() to indicate that the stream callback will
+ accept buffers of any size.
+*/
+#define paFramesPerBufferUnspecified  (0)
+
+
+/** Flags used to control the behavior of a stream. They are passed as
+ parameters to Pa_OpenStream or Pa_OpenDefaultStream. Multiple flags may be
+ ORed together.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream
+ @see paNoFlag, paClipOff, paDitherOff, paNeverDropInput,
+  paPrimeOutputBuffersUsingStreamCallback, paPlatformSpecificFlags
+*/
+typedef unsigned long PaStreamFlags;
+
+/** @see PaStreamFlags */
+#define   paNoFlag          ((PaStreamFlags) 0)
+
+/** Disable default clipping of out of range samples.
+ @see PaStreamFlags
+*/
+#define   paClipOff         ((PaStreamFlags) 0x00000001)
+
+/** Disable default dithering.
+ @see PaStreamFlags
+*/
+#define   paDitherOff       ((PaStreamFlags) 0x00000002)
+
+/** Flag requests that where possible a full duplex stream will not discard
+ overflowed input samples without calling the stream callback. This flag is
+ only valid for full duplex callback streams and only when used in combination
+ with the paFramesPerBufferUnspecified (0) framesPerBuffer parameter. Using
+ this flag incorrectly results in a paInvalidFlag error being returned from
+ Pa_OpenStream and Pa_OpenDefaultStream.
+
+ @see PaStreamFlags, paFramesPerBufferUnspecified
+*/
+#define   paNeverDropInput  ((PaStreamFlags) 0x00000004)
+
+/** Call the stream callback to fill initial output buffers, rather than the
+ default behavior of priming the buffers with zeros (silence). This flag has
+ no effect for input-only and blocking read/write streams.
+ 
+ @see PaStreamFlags
+*/
+#define   paPrimeOutputBuffersUsingStreamCallback ((PaStreamFlags) 0x00000008)
+
+/** A mask specifying the platform specific bits.
+ @see PaStreamFlags
+*/
+#define   paPlatformSpecificFlags ((PaStreamFlags)0xFFFF0000)
+
+/**
+ Timing information for the buffers passed to the stream callback.
+*/
+typedef struct PaStreamCallbackTimeInfo{
+    PaTime inputBufferAdcTime;
+    PaTime currentTime;
+    PaTime outputBufferDacTime;
+} PaStreamCallbackTimeInfo;
+
+
+/**
+ Flag bit constants for the statusFlags to PaStreamCallback.
+
+ @see paInputUnderflow, paInputOverflow, paOutputUnderflow, paOutputOverflow,
+ paPrimingOutput
+*/
+typedef unsigned long PaStreamCallbackFlags;
+
+/** In a stream opened with paFramesPerBufferUnspecified, indicates that
+ input data is all silence (zeros) because no real data is available. In a
+ stream opened without paFramesPerBufferUnspecified, it indicates that one or
+ more zero samples have been inserted into the input buffer to compensate
+ for an input underflow.
+ @see PaStreamCallbackFlags
+*/
+#define paInputUnderflow   ((PaStreamCallbackFlags) 0x00000001)
+
+/** In a stream opened with paFramesPerBufferUnspecified, indicates that data
+ prior to the first sample of the input buffer was discarded due to an
+ overflow, possibly because the stream callback is using too much CPU time.
+ Otherwise indicates that data prior to one or more samples in the
+ input buffer was discarded.
+ @see PaStreamCallbackFlags
+*/
+#define paInputOverflow    ((PaStreamCallbackFlags) 0x00000002)
+
+/** Indicates that output data (or a gap) was inserted, possibly because the
+ stream callback is using too much CPU time.
+ @see PaStreamCallbackFlags
+*/
+#define paOutputUnderflow  ((PaStreamCallbackFlags) 0x00000004)
+
+/** Indicates that output data will be discarded because no room is available.
+ @see PaStreamCallbackFlags
+*/
+#define paOutputOverflow   ((PaStreamCallbackFlags) 0x00000008)
+
+/** Some of all of the output data will be used to prime the stream, input
+ data may be zero.
+ @see PaStreamCallbackFlags
+*/
+#define paPrimingOutput    ((PaStreamCallbackFlags) 0x00000010)
+
+/**
+ Allowable return values for the PaStreamCallback.
+ @see PaStreamCallback
+*/
+typedef enum PaStreamCallbackResult
+{
+    paContinue=0,
+    paComplete=1,
+    paAbort=2
+} PaStreamCallbackResult;
+
+
+/**
+ Functions of type PaStreamCallback are implemented by PortAudio clients.
+ They consume, process or generate audio in response to requests from an
+ active PortAudio stream.
+     
+ @param input and @param output are arrays of interleaved samples,
+ the format, packing and number of channels used by the buffers are
+ determined by parameters to Pa_OpenStream().
+     
+ @param frameCount The number of sample frames to be processed by
+ the stream callback.
+
+ @param timeInfo The time in seconds when the first sample of the input
+ buffer was received at the audio input, the time in seconds when the first
+ sample of the output buffer will begin being played at the audio output, and
+ the time in seconds when the stream callback was called.
+ See also Pa_GetStreamTime()
+
+ @param statusFlags Flags indicating whether input and/or output buffers
+ have been inserted or will be dropped to overcome underflow or overflow
+ conditions.
+
+ @param userData The value of a user supplied pointer passed to
+ Pa_OpenStream() intended for storing synthesis data etc.
+
+ @return
+ The stream callback should return one of the values in the
+ PaStreamCallbackResult enumeration. To ensure that the callback continues
+ to be called, it should return paContinue (0). Either paComplete or paAbort
+ can be returned to finish stream processing, after either of these values is
+ returned the callback will not be called again. If paAbort is returned the
+ stream will finish as soon as possible. If paComplete is returned, the stream
+ will continue until all buffers generated by the callback have been played.
+ This may be useful in applications such as soundfile players where a specific
+ duration of output is required. However, it is not necessary to utilise this
+ mechanism as Pa_StopStream(), Pa_AbortStream() or Pa_CloseStream() can also
+ be used to stop the stream. The callback must always fill the entire output
+ buffer irrespective of its return value.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream
+
+ @note With the exception of Pa_GetStreamCpuLoad() it is not permissable to call
+ PortAudio API functions from within the stream callback.
+*/
+typedef int PaStreamCallback(
+    const void *input, void *output,
+    unsigned long frameCount,
+    const PaStreamCallbackTimeInfo* timeInfo,
+    PaStreamCallbackFlags statusFlags,
+    void *userData );
+
+
+/** Opens a stream for either input, output or both.
+     
+ @param stream The address of a PaStream pointer which will receive
+ a pointer to the newly opened stream.
+     
+ @param inputParameters A structure that describes the input parameters used by
+ the opened stream. See PaStreamParameters for a description of these parameters.
+ inputParameters must be NULL for output-only streams.
+
+ @param outputParameters A structure that describes the output parameters used by
+ the opened stream. See PaStreamParameters for a description of these parameters.
+ outputParameters must be NULL for input-only streams.
+ 
+ @param sampleRate The desired sampleRate. For full-duplex streams it is the
+ sample rate for both input and output
+     
+ @param framesPerBuffer The number of frames passed to the stream callback
+ function, or the preferred block granularity for a blocking read/write stream.
+ The special value paFramesPerBufferUnspecified (0) may be used to request that
+ the stream callback will recieve an optimal (and possibly varying) number of
+ frames based on host requirements and the requested latency settings.
+ Note: With some host APIs, the use of non-zero framesPerBuffer for a callback
+ stream may introduce an additional layer of buffering which could introduce
+ additional latency. PortAudio guarantees that the additional latency
+ will be kept to the theoretical minimum however, it is strongly recommended
+ that a non-zero framesPerBuffer value only be used when your algorithm
+ requires a fixed number of frames per stream callback.
+ 
+ @param streamFlags Flags which modify the behaviour of the streaming process.
+ This parameter may contain a combination of flags ORed together. Some flags may
+ only be relevant to certain buffer formats.
+     
+ @param streamCallback A pointer to a client supplied function that is responsible
+ for processing and filling input and output buffers. If this parameter is NULL
+ the stream will be opened in 'blocking read/write' mode. In blocking mode,
+ the client can receive sample data using Pa_ReadStream and write sample data
+ using Pa_WriteStream, the number of samples that may be read or written
+ without blocking is returned by Pa_GetStreamReadAvailable and
+ Pa_GetStreamWriteAvailable respectively.
+
+ @param userData A client supplied pointer which is passed to the stream callback
+ function. It could for example, contain a pointer to instance data necessary
+ for processing the audio buffers. This parameter is ignored if streamCallback
+ is NULL.
+     
+ @return
+ Upon success Pa_OpenStream() returns paNoError and places a pointer to a
+ valid PaStream in the stream argument. The stream is inactive (stopped).
+ If a call to Pa_OpenStream() fails, a non-zero error code is returned (see
+ PaError for possible error codes) and the value of stream is invalid.
+
+ @see PaStreamParameters, PaStreamCallback, Pa_ReadStream, Pa_WriteStream,
+ Pa_GetStreamReadAvailable, Pa_GetStreamWriteAvailable
+*/
+PaError Pa_OpenStream( PaStream** stream,
+                       const PaStreamParameters *inputParameters,
+                       const PaStreamParameters *outputParameters,
+                       double sampleRate,
+                       unsigned long framesPerBuffer,
+                       PaStreamFlags streamFlags,
+                       PaStreamCallback *streamCallback,
+                       void *userData );
+
+
+/** A simplified version of Pa_OpenStream() that opens the default input
+ and/or output devices.
+
+ @param stream The address of a PaStream pointer which will receive
+ a pointer to the newly opened stream.
+ 
+ @param numInputChannels  The number of channels of sound that will be supplied
+ to the stream callback or returned by Pa_ReadStream. It can range from 1 to
+ the value of maxInputChannels in the PaDeviceInfo record for the default input
+ device. If 0 the stream is opened as an output-only stream.
+
+ @param numOutputChannels The number of channels of sound to be delivered to the
+ stream callback or passed to Pa_WriteStream. It can range from 1 to the value
+ of maxOutputChannels in the PaDeviceInfo record for the default output dvice.
+ If 0 the stream is opened as an output-only stream.
+
+ @param sampleFormat The sample format of both the input and output buffers
+ provided to the callback or passed to and from Pa_ReadStream and Pa_WriteStream.
+ sampleFormat may be any of the formats described by the PaSampleFormat
+ enumeration.
+ 
+ @param sampleRate Same as Pa_OpenStream parameter of the same name.
+ @param framesPerBuffer Same as Pa_OpenStream parameter of the same name.
+ @param streamCallback Same as Pa_OpenStream parameter of the same name.
+ @param userData Same as Pa_OpenStream parameter of the same name.
+
+ @return As for Pa_OpenStream
+
+ @see Pa_OpenStream, PaStreamCallback
+*/
+PaError Pa_OpenDefaultStream( PaStream** stream,
+                              int numInputChannels,
+                              int numOutputChannels,
+                              PaSampleFormat sampleFormat,
+                              double sampleRate,
+                              unsigned long framesPerBuffer,
+                              PaStreamCallback *streamCallback,
+                              void *userData );
+
+
+/** Closes an audio stream. If the audio stream is active it
+ discards any pending buffers as if Pa_AbortStream() had been called.
+*/
+PaError Pa_CloseStream( PaStream *stream );
+
+
+/** Functions of type PaStreamFinishedCallback are implemented by PortAudio 
+ clients. They can be registered with a stream using the Pa_SetStreamFinishedCallback
+ function. Once registered they are called when the stream becomes inactive
+ (ie once a call to Pa_StopStream() will not block).
+ A stream will become inactive after the stream callback returns non-zero,
+ or when Pa_StopStream or Pa_AbortStream is called. For a stream providing audio
+ output, if the stream callback returns paComplete, or Pa_StopStream is called,
+ the stream finished callback will not be called until all generated sample data
+ has been played.
+ 
+ @param userData The userData parameter supplied to Pa_OpenStream()
+
+ @see Pa_SetStreamFinishedCallback
+*/
+typedef void PaStreamFinishedCallback( void *userData );
+
+
+/** Register a stream finished callback function which will be called when the 
+ stream becomes inactive. See the description of PaStreamFinishedCallback for 
+ further details about when the callback will be called.
+
+ @param stream a pointer to a PaStream that is in the stopped state - if the
+ stream is not stopped, the stream's finished callback will remain unchanged 
+ and an error code will be returned.
+
+ @param streamFinishedCallback a pointer to a function with the same signature
+ as PaStreamFinishedCallback, that will be called when the stream becomes
+ inactive. Passing NULL for this parameter will un-register a previously
+ registered stream finished callback function.
+
+ @return on success returns paNoError, otherwise an error code indicating the cause
+ of the error.
+
+ @see PaStreamFinishedCallback
+*/
+PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback ); 
+
+
+/** Commences audio processing.
+*/
+PaError Pa_StartStream( PaStream *stream );
+
+
+/** Terminates audio processing. It waits until all pending
+ audio buffers have been played before it returns.
+*/
+PaError Pa_StopStream( PaStream *stream );
+
+
+/** Terminates audio processing immediately without waiting for pending
+ buffers to complete.
+*/
+PaError Pa_AbortStream( PaStream *stream );
+
+
+/** Determine whether the stream is stopped.
+ A stream is considered to be stopped prior to a successful call to
+ Pa_StartStream and after a successful call to Pa_StopStream or Pa_AbortStream.
+ If a stream callback returns a value other than paContinue the stream is NOT
+ considered to be stopped.
+
+ @return Returns one (1) when the stream is stopped, zero (0) when
+ the stream is running or, a PaErrorCode (which are always negative) if
+ PortAudio is not initialized or an error is encountered.
+
+ @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive
+*/
+PaError Pa_IsStreamStopped( PaStream *stream );
+
+
+/** Determine whether the stream is active.
+ A stream is active after a successful call to Pa_StartStream(), until it
+ becomes inactive either as a result of a call to Pa_StopStream() or
+ Pa_AbortStream(), or as a result of a return value other than paContinue from
+ the stream callback. In the latter case, the stream is considered inactive
+ after the last buffer has finished playing.
+
+ @return Returns one (1) when the stream is active (ie playing or recording
+ audio), zero (0) when not playing or, a PaErrorCode (which are always negative)
+ if PortAudio is not initialized or an error is encountered.
+
+ @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamStopped
+*/
+PaError Pa_IsStreamActive( PaStream *stream );
+
+
+
+/** A structure containing unchanging information about an open stream.
+ @see Pa_GetStreamInfo
+*/
+
+typedef struct PaStreamInfo
+{
+    /** this is struct version 1 */
+    int structVersion;
+
+    /** The input latency of the stream in seconds. This value provides the most
+     accurate estimate of input latency available to the implementation. It may
+     differ significantly from the suggestedLatency value passed to Pa_OpenStream().
+     The value of this field will be zero (0.) for output-only streams.
+     @see PaTime
+    */
+    PaTime inputLatency;
+
+    /** The output latency of the stream in seconds. This value provides the most
+     accurate estimate of output latency available to the implementation. It may
+     differ significantly from the suggestedLatency value passed to Pa_OpenStream().
+     The value of this field will be zero (0.) for input-only streams.
+     @see PaTime
+    */
+    PaTime outputLatency;
+
+    /** The sample rate of the stream in Hertz (samples per second). In cases
+     where the hardware sample rate is inaccurate and PortAudio is aware of it,
+     the value of this field may be different from the sampleRate parameter
+     passed to Pa_OpenStream(). If information about the actual hardware sample
+     rate is not available, this field will have the same value as the sampleRate
+     parameter passed to Pa_OpenStream().
+    */
+    double sampleRate;
+    
+} PaStreamInfo;
+
+
+/** Retrieve a pointer to a PaStreamInfo structure containing information
+ about the specified stream.
+ @return A pointer to an immutable PaStreamInfo structure. If the stream
+ parameter invalid, or an error is encountered, the function returns NULL.
+
+ @param stream A pointer to an open stream previously created with Pa_OpenStream.
+
+ @note PortAudio manages the memory referenced by the returned pointer,
+ the client must not manipulate or free the memory. The pointer is only
+ guaranteed to be valid until the specified stream is closed.
+
+ @see PaStreamInfo
+*/
+const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream );
+
+
+/** Determine the current time for the stream according to the same clock used
+ to generate buffer timestamps. This time may be used for syncronising other
+ events to the audio stream, for example synchronizing audio to MIDI.
+                                        
+ @return The stream's current time in seconds, or 0 if an error occurred.
+
+ @see PaTime, PaStreamCallback
+*/
+PaTime Pa_GetStreamTime( PaStream *stream );
+
+
+/** Retrieve CPU usage information for the specified stream.
+ The "CPU Load" is a fraction of total CPU time consumed by a callback stream's
+ audio processing routines including, but not limited to the client supplied
+ stream callback. This function does not work with blocking read/write streams.
+
+ This function may be called from the stream callback function or the
+ application.
+     
+ @return
+ A floating point value, typically between 0.0 and 1.0, where 1.0 indicates
+ that the stream callback is consuming the maximum number of CPU cycles possible
+ to maintain real-time operation. A value of 0.5 would imply that PortAudio and
+ the stream callback was consuming roughly 50% of the available CPU time. The
+ return value may exceed 1.0. A value of 0.0 will always be returned for a
+ blocking read/write stream, or if an error occurrs.
+*/
+double Pa_GetStreamCpuLoad( PaStream* stream );
+
+
+/** Read samples from an input stream. The function doesn't return until
+ the entire buffer has been filled - this may involve waiting for the operating
+ system to supply the data.
+
+ @param stream A pointer to an open stream previously created with Pa_OpenStream.
+ 
+ @param buffer A pointer to a buffer of sample frames. The buffer contains
+ samples in the format specified by the inputParameters->sampleFormat field
+ used to open the stream, and the number of channels specified by
+ inputParameters->numChannels. If non-interleaved samples were requested,
+ buffer is a pointer to the first element of an array of non-interleaved
+ buffer pointers, one for each channel.
+
+ @param frames The number of frames to be read into buffer. This parameter
+ is not constrained to a specific range, however high performance applications
+ will want to match this parameter to the framesPerBuffer parameter used
+ when opening the stream.
+
+ @return On success PaNoError will be returned, or PaInputOverflowed if input
+ data was discarded by PortAudio after the previous call and before this call.
+*/
+PaError Pa_ReadStream( PaStream* stream,
+                       void *buffer,
+                       unsigned long frames );
+
+
+/** Write samples to an output stream. This function doesn't return until the
+ entire buffer has been consumed - this may involve waiting for the operating
+ system to consume the data.
+
+ @param stream A pointer to an open stream previously created with Pa_OpenStream.
+
+ @param buffer A pointer to a buffer of sample frames. The buffer contains
+ samples in the format specified by the outputParameters->sampleFormat field
+ used to open the stream, and the number of channels specified by
+ outputParameters->numChannels. If non-interleaved samples were requested,
+ buffer is a pointer to the first element of an array of non-interleaved
+ buffer pointers, one for each channel.
+
+ @param frames The number of frames to be written from buffer. This parameter
+ is not constrained to a specific range, however high performance applications
+ will want to match this parameter to the framesPerBuffer parameter used
+ when opening the stream.
+
+ @return On success PaNoError will be returned, or paOutputUnderflowed if
+ additional output data was inserted after the previous call and before this
+ call.
+*/
+PaError Pa_WriteStream( PaStream* stream,
+                        const void *buffer,
+                        unsigned long frames );
+
+
+/** Retrieve the number of frames that can be read from the stream without
+ waiting.
+
+ @return Returns a non-negative value representing the maximum number of frames
+ that can be read from the stream without blocking or busy waiting or, a
+ PaErrorCode (which are always negative) if PortAudio is not initialized or an
+ error is encountered.
+*/
+signed long Pa_GetStreamReadAvailable( PaStream* stream );
+
+
+/** Retrieve the number of frames that can be written to the stream without
+ waiting.
+
+ @return Returns a non-negative value representing the maximum number of frames
+ that can be written to the stream without blocking or busy waiting or, a
+ PaErrorCode (which are always negative) if PortAudio is not initialized or an
+ error is encountered.
+*/
+signed long Pa_GetStreamWriteAvailable( PaStream* stream );
+
+
+/* Miscellaneous utilities */
+
+
+/** Retrieve the size of a given sample format in bytes.
+
+ @return The size in bytes of a single sample in the specified format,
+ or paSampleFormatNotSupported if the format is not supported.
+*/
+PaError Pa_GetSampleSize( PaSampleFormat format );
+
+
+/** Put the caller to sleep for at least 'msec' milliseconds. This function is
+ provided only as a convenience for authors of portable code (such as the tests
+ and examples in the PortAudio distribution.)
+
+ The function may sleep longer than requested so don't rely on this for accurate
+ musical timing.
+*/
+void Pa_Sleep( long msec );
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PORTAUDIO_H */

+ 243 - 0
ThirdParty/PortAudio/src/common/pa_allocation.c

@@ -0,0 +1,243 @@
+/*
+ * $Id: pa_allocation.c 1097 2006-08-26 08:27:53Z rossb $
+ * Portable Audio I/O Library allocation group implementation
+ * memory allocation group for tracking allocation groups
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+/** @file
+ @ingroup common_src
+
+ @brief Allocation Group implementation.
+*/
+
+
+#include "pa_allocation.h"
+#include "pa_util.h"
+
+
+/*
+    Maintain 3 singly linked lists...
+    linkBlocks: the buffers used to allocate the links
+    spareLinks: links available for use in the allocations list
+    allocations: the buffers currently allocated using PaUtil_ContextAllocateMemory()
+
+    Link block size is doubled every time new links are allocated.
+*/
+
+
+#define PA_INITIAL_LINK_COUNT_    16
+
+struct PaUtilAllocationGroupLink
+{
+    struct PaUtilAllocationGroupLink *next;
+    void *buffer;
+};
+
+/*
+    Allocate a block of links. The first link will have it's buffer member
+    pointing to the block, and it's next member set to <nextBlock>. The remaining
+    links will have NULL buffer members, and each link will point to
+    the next link except the last, which will point to <nextSpare>
+*/
+static struct PaUtilAllocationGroupLink *AllocateLinks( long count,
+        struct PaUtilAllocationGroupLink *nextBlock,
+        struct PaUtilAllocationGroupLink *nextSpare )
+{
+    struct PaUtilAllocationGroupLink *result;
+    int i;
+    
+    result = (struct PaUtilAllocationGroupLink *)PaUtil_AllocateMemory(
+            sizeof(struct PaUtilAllocationGroupLink) * count );
+    if( result )
+    {
+        /* the block link */
+        result[0].buffer = result;
+        result[0].next = nextBlock;
+
+        /* the spare links */
+        for( i=1; i<count; ++i )
+        {
+            result[i].buffer = 0;
+            result[i].next = &result[i+1];
+        }
+        result[count-1].next = nextSpare;
+    }
+    
+    return result;
+}
+
+
+PaUtilAllocationGroup* PaUtil_CreateAllocationGroup( void )
+{
+    PaUtilAllocationGroup* result = 0;
+    struct PaUtilAllocationGroupLink *links;
+
+
+    links = AllocateLinks( PA_INITIAL_LINK_COUNT_, 0, 0 );
+    if( links != 0 )
+    {
+        result = (PaUtilAllocationGroup*)PaUtil_AllocateMemory( sizeof(PaUtilAllocationGroup) );
+        if( result )
+        {
+            result->linkCount = PA_INITIAL_LINK_COUNT_;
+            result->linkBlocks = &links[0];
+            result->spareLinks = &links[1];
+            result->allocations = 0;
+        }
+        else
+        {
+            PaUtil_FreeMemory( links );
+        }
+    }
+
+    return result;
+}
+
+
+void PaUtil_DestroyAllocationGroup( PaUtilAllocationGroup* group )
+{
+    struct PaUtilAllocationGroupLink *current = group->linkBlocks;
+    struct PaUtilAllocationGroupLink *next;
+
+    while( current )
+    {
+        next = current->next;
+        PaUtil_FreeMemory( current->buffer );
+        current = next;
+    }
+
+    PaUtil_FreeMemory( group );
+}
+
+
+void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size )
+{
+    struct PaUtilAllocationGroupLink *links, *link;
+    void *result = 0;
+    
+    /* allocate more links if necessary */
+    if( !group->spareLinks )
+    {
+        /* double the link count on each block allocation */
+        links = AllocateLinks( group->linkCount, group->linkBlocks, group->spareLinks );
+        if( links )
+        {
+            group->linkCount += group->linkCount;
+            group->linkBlocks = &links[0];
+            group->spareLinks = &links[1];
+        }
+    }
+
+    if( group->spareLinks )
+    {
+        result = PaUtil_AllocateMemory( size );
+        if( result )
+        {
+            link = group->spareLinks;
+            group->spareLinks = link->next;
+
+            link->buffer = result;
+            link->next = group->allocations;
+
+            group->allocations = link;
+        }
+    }
+
+    return result;    
+}
+
+
+void PaUtil_GroupFreeMemory( PaUtilAllocationGroup* group, void *buffer )
+{
+    struct PaUtilAllocationGroupLink *current = group->allocations;
+    struct PaUtilAllocationGroupLink *previous = 0;
+
+    if( buffer == 0 )
+        return;
+
+    /* find the right link and remove it */
+    while( current )
+    {
+        if( current->buffer == buffer )
+        {
+            if( previous )
+            {
+                previous->next = current->next;
+            }
+            else
+            {
+                group->allocations = current->next;
+            }
+
+            current->buffer = 0;
+            current->next = group->spareLinks;
+            group->spareLinks = current;
+
+            break;
+        }
+        
+        previous = current;
+        current = current->next;
+    }
+
+    PaUtil_FreeMemory( buffer ); /* free the memory whether we found it in the list or not */
+}
+
+
+void PaUtil_FreeAllAllocations( PaUtilAllocationGroup* group )
+{
+    struct PaUtilAllocationGroupLink *current = group->allocations;
+    struct PaUtilAllocationGroupLink *previous = 0;
+
+    /* free all buffers in the allocations list */
+    while( current )
+    {
+        PaUtil_FreeMemory( current->buffer );
+        current->buffer = 0;
+
+        previous = current;
+        current = current->next;
+    }
+
+    /* link the former allocations list onto the front of the spareLinks list */
+    if( previous )
+    {
+        previous->next = group->spareLinks;
+        group->spareLinks = group->allocations;
+        group->allocations = 0;
+    }
+}
+

Some files were not shown because too many files changed in this diff