diff --git a/GLFW-b.cabal b/GLFW-b.cabal
--- a/GLFW-b.cabal
+++ b/GLFW-b.cabal
@@ -1,5 +1,5 @@
 name:         GLFW-b
-version:      0.0.2.1
+version:      0.0.2.2
 
 category:     Graphics
 
@@ -8,7 +8,8 @@
               creating OpenGL contexts and managing input, including keyboard,
               mouse, joystick and time.
               .
-              /GLFW-b does not currently work on Mac OS X./ Sorry.
+              GLFW-b works on Windows, Mac OS X, and many Unix-like operating
+              systems.
               .
               Please see README.md
               (<http://github.com/bsl/GLFW-b/blob/master/README.md>) for
@@ -27,12 +28,14 @@
 -- -- -- -- -- -- -- -- -- --
 
 cabal-version: >= 1.6
-build-type:    Simple
+build-type:    Custom 
 
 -- -- -- -- -- -- -- -- -- --
 
 extra-source-files:
+  Makefile
   README.md
+  ./build/glfw/lib/cocoa/.build-tag
   glfw/include/GL/glfw.h
   glfw/lib/internal.h
   glfw/lib/cocoa/platform.h
@@ -90,7 +93,6 @@
 --    -D_GLFW_HAS_DLOPEN
 --    -D_GLFW_HAS_SYSCONF
 --    -pthread
-      -O2
     extra-libraries:
       GL
       GLU
@@ -100,21 +102,12 @@
     if os(darwin)
       include-dirs:
         glfw/lib/cocoa
-      c-sources:
-        glfw/lib/cocoa/cocoa_enable.m
-        glfw/lib/cocoa/cocoa_fullscreen.m
-        glfw/lib/cocoa/cocoa_glext.m
-        glfw/lib/cocoa/cocoa_init.m
-        glfw/lib/cocoa/cocoa_joystick.m
-        glfw/lib/cocoa/cocoa_thread.c
-        glfw/lib/cocoa/cocoa_time.m
-        glfw/lib/cocoa/cocoa_window.m
-      cc-options:
-        -O2
       frameworks:
         AGL
         Cocoa
         OpenGL
+      extra-libraries: glfw
+      extra-lib-dirs: build
     else
       if os(mingw32)
         include-dirs:
@@ -129,8 +122,6 @@
           glfw/lib/win32/win32_thread.c
           glfw/lib/win32/win32_time.c
           glfw/lib/win32/win32_window.c
-        cc-options:
-          -O2
         extra-libraries:
           opengl32
 
diff --git a/Makefile b/Makefile
new file mode 100644
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,33 @@
+FRAMEWORK = -framework AGL -framework Cocoa -framework OpenGL
+CFLAGS    = -O2 -Iglfw/include -Iglfw/lib -Iglfw/lib/cocoa
+SRC_DIR   = glfw/lib/cocoa
+BUILD_DIR = build
+
+OBJ_C_SRC = $(shell find $(SRC_DIR) -name "*.m")
+C_SRC     = $(shell find $(SRC_DIR) -name "*.c")
+GLFW_SRC  = $(shell find glfw/lib -depth 1 -name "*.c")
+SRC       = $(OBJ_C_SRC) $(C_SRC)
+OBJS      = $(addprefix $(BUILD_DIR)/, $(OBJ_C_SRC:.m=.o) $(C_SRC:.c=.o))
+
+all: $(BUILD_DIR)/libglfw.a $(BUILD_DIR)/libglfw.dylib
+
+$(BUILD_DIR)/libglfw.dylib: $(OBJS)
+	$(CC) -dynamiclib $(CFLAGS) -o $@ $(OBJS) $(GLFW_SRC) $(FRAMEWORK)
+
+$(BUILD_DIR)/libglfw.a: $(OBJS)
+	ar -r -s $@ $(OBJS)
+
+$(BUILD_DIR)/$(SRC_DIR)/.build-tag:
+	mkdir -p $(BUILD_DIR)/$(SRC_DIR)
+	touch $@
+
+$(OBJS): $(BUILD_DIR)/$(SRC_DIR)/.build-tag
+
+$(BUILD_DIR)/%.o : %.c
+	$(CC) -c $(CFLAGS) $< -o $@
+$(BUILD_DIR)/%.o : %.m
+	$(CC) -c $(CFLAGS) $< -o $@
+
+.PHONY: clean
+clean:
+	$(RM) -rf $(BUILD_DIR)
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,9 +1,7 @@
-Differences between GLFW and GLFW-b 2010.01
+Differences between GLFW and GLFW-b 2011.03
 ===========================================
 
-* GLFW binds to version 2.6 of the GLFW C library. GLFW-b binds to 2.7. GLFW
-  2.7 is partially written in Objective C. This is a problem for Cabal, so
-  _GLFW-b does not currently work on Mac OS X._
+* GLFW binds to version 2.6 of the GLFW C library. GLFW-b binds to 2.7.
 
 * Some GLFW functions return OpenGL {Gettable,Settable}StateVars. I don't like
   this because it adds an extra step to extract a value and causes GLFW to be
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,6 +1,105 @@
 module Main (main) where
 
-import Distribution.Simple (defaultMain)
+import Distribution.System ( buildOS, OS(..) )
+import Distribution.Simple.InstallDirs ( libdir )
+import Distribution.Simple.Setup ( ConfigFlags, fromFlag, configVerbosity
+                                 , InstallFlags, defaultCopyFlags
+                                 , installDistPref, CleanFlags
+                                 , toFlag, CopyDest(NoCopyDest)
+                                 , installVerbosity, cleanVerbosity
+                                 , CopyFlags(..)
+                                 , configProgramArgs )
+import Distribution.Simple.Utils ( rawSystemExit, installOrdinaryFile )
+import Distribution.Verbosity ( verbose )
+import Distribution.Simple ( defaultMainWithHooks
+                           , simpleUserHooks
+                           , buildHook, Args, confHook
+                           , UserHooks(preConf, preClean,
+                                       postCopy, postInst) )
+import Distribution.Simple.LocalBuildInfo ( absoluteInstallDirs
+                                          , LocalBuildInfo(..) )
+import Distribution.PackageDescription ( emptyBuildInfo
+                                       , updatePackageDescription
+                                       , HookedBuildInfo
+                                       , BuildInfo(..)
+                                       , PackageDescription )
+import System.FilePath ( (</>) )
 
+extraLibDir :: FilePath
+extraLibDir = "build"
+
 main :: IO ()
-main = defaultMain
+main = defaultMainWithHooks simpleUserHooks
+  { preConf   = \a f -> makeGlfw a f >> preConf simpleUserHooks a f
+  , confHook  = \a cfs -> do
+      let pkgForce = [("ghc-pkg",["--force"]) | buildOS == OSX ]
+          cfs' = cfs { configProgramArgs = configProgramArgs cfs ++ pkgForce }
+      confHook simpleUserHooks a cfs'
+  , preClean  = \a f -> makeClean a f >> preClean simpleUserHooks a f
+  , buildHook = \pkgDesc lbi h f ->
+      buildHook simpleUserHooks (glfwPkgDesc pkgDesc) lbi h f
+  , postCopy  = postCopyGlfw
+  , postInst  = postInstGlfw
+  }
+
+makeGlfw :: Args -> ConfigFlags -> IO ()
+makeGlfw _ flags = do
+  let verbosity = fromFlag $ configVerbosity flags
+  case buildOS of
+    OSX -> do
+      let make = rawSystemExit verbosity "env" $
+           "make" : (if verbosity >= verbose then [] else ["--quiet"])
+      make
+    _ -> return ()
+
+makeClean :: Args -> CleanFlags -> IO ()
+makeClean _ flags = do
+  let verbosity = fromFlag $ cleanVerbosity flags
+  case buildOS of
+    OSX -> do
+      let make = rawSystemExit verbosity "env" $
+           ["make"] ++ (if verbosity >= verbose then [] else ["--quiet"])
+            ++ ["clean"]
+      make
+    _ -> return ()
+
+glfwPkgDesc :: PackageDescription -> PackageDescription
+glfwPkgDesc pkgDesc =
+  case buildOS of
+    OSX -> updatePackageDescription libDirGlfw pkgDesc
+    _   -> pkgDesc
+
+libDirGlfw :: HookedBuildInfo
+libDirGlfw = (Just buildinfo, [])
+  where buildinfo = emptyBuildInfo { extraLibDirs = [ extraLibDir ] }
+
+postInstGlfw :: Args -> InstallFlags -> PackageDescription
+             -> LocalBuildInfo -> IO ()
+postInstGlfw _ flags pkgDesc lbi =
+  case buildOS of
+    OSX -> do
+      let copyflags = defaultCopyFlags
+                    { copyDistPref  = installDistPref flags
+                    , copyDest      = toFlag NoCopyDest
+                    , copyVerbosity = installVerbosity flags
+                    }
+      postCopyGlfw undefined copyflags pkgDesc lbi
+    _ -> return ()
+
+postCopyGlfw :: Args -> CopyFlags -> PackageDescription
+             -> LocalBuildInfo -> IO ()
+postCopyGlfw _ flags pkgDesc lbi =
+  case buildOS of
+    OSX -> do
+      let installDirs = absoluteInstallDirs pkgDesc lbi
+            . fromFlag . copyDest $ flags
+          libPref = libdir installDirs
+          verbosity = fromFlag $ copyVerbosity flags
+          copy dest f = installOrdinaryFile verbosity (extraLibDir</>f) (dest</>f)
+      maybe (return ()) (copy libPref) (Just libName)
+      maybe (return ()) (copy libPref) (Just sharedName)
+    _ -> return ()
+
+libName, sharedName :: FilePath
+libName = "libglfw.a"
+sharedName = "libglfw.dylib"
diff --git a/build/glfw/lib/cocoa/.build-tag b/build/glfw/lib/cocoa/.build-tag
new file mode 100644
--- /dev/null
+++ b/build/glfw/lib/cocoa/.build-tag
diff --git a/glfw/lib/cocoa/cocoa_enable.m b/glfw/lib/cocoa/cocoa_enable.m
deleted file mode 100644
--- a/glfw/lib/cocoa/cocoa_enable.m
+++ /dev/null
@@ -1,52 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL framework
-// File:        macosx_enable.m
-// Platform:    Mac OS X
-// API Version: 2.7
-// WWW:         http://glfw.sourceforge.net
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Camilla Berglund
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-//************************************************************************
-//****               Platform implementation functions                ****
-//************************************************************************
-
-//========================================================================
-// 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.
-}
-
diff --git a/glfw/lib/cocoa/cocoa_fullscreen.m b/glfw/lib/cocoa/cocoa_fullscreen.m
deleted file mode 100644
--- a/glfw/lib/cocoa/cocoa_fullscreen.m
+++ /dev/null
@@ -1,103 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL framework
-// File:        macosx_fullscreen.m
-// Platform:    Mac OS X
-// API Version: 2.7
-// WWW:         http://glfw.sourceforge.net
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Camilla Berglund
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-//========================================================================
-// 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 );
-}
-
diff --git a/glfw/lib/cocoa/cocoa_glext.m b/glfw/lib/cocoa/cocoa_glext.m
deleted file mode 100644
--- a/glfw/lib/cocoa/cocoa_glext.m
+++ /dev/null
@@ -1,64 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL framework
-// File:        macosx_glext.m
-// Platform:    Mac OS X
-// API Version: 2.7
-// WWW:         http://glfw.sourceforge.net
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Camilla Berglund
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-//************************************************************************
-//****               Platform implementation functions                ****
-//************************************************************************
-
-//========================================================================
-// Check if an OpenGL extension is available at runtime
-//========================================================================
-
-int _glfwPlatformExtensionSupported( const char *extension )
-{
-    // 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;
-}
-
diff --git a/glfw/lib/cocoa/cocoa_init.m b/glfw/lib/cocoa/cocoa_init.m
deleted file mode 100644
--- a/glfw/lib/cocoa/cocoa_init.m
+++ /dev/null
@@ -1,241 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL framework
-// File:        macosx_init.m
-// Platform:    Mac OS X
-// API Version: 2.7
-// WWW:         http://glfw.sourceforge.net
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Camilla Berglund
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-// Needed for _NSGetProgname
-#include <crt_externs.h>
-
-#include "internal.h"
-
-// 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];
-    }
-}
-
-//========================================================================
-// 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
-    [NSApplication 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];
-
-    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;
-}
-
diff --git a/glfw/lib/cocoa/cocoa_joystick.m b/glfw/lib/cocoa/cocoa_joystick.m
deleted file mode 100644
--- a/glfw/lib/cocoa/cocoa_joystick.m
+++ /dev/null
@@ -1,66 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL framework
-// File:        macosx_joystick.m
-// Platform:    Mac OS X
-// API Version: 2.7
-// WWW:         http://glfw.sourceforge.net
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Camilla Berglund
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-//************************************************************************
-//****               Platform implementation functions                ****
-//************************************************************************
-
-//========================================================================
-// 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;
-}
-
diff --git a/glfw/lib/cocoa/cocoa_thread.c b/glfw/lib/cocoa/cocoa_thread.c
deleted file mode 100644
--- a/glfw/lib/cocoa/cocoa_thread.c
+++ /dev/null
@@ -1,416 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL framework
-// File:        macosx_thread.c
-// Platform:    Mac OS X
-// API Version: 2.7
-// WWW:         http://glfw.sourceforge.net
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Camilla Berglund
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-#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;
-}
-
diff --git a/glfw/lib/cocoa/cocoa_time.m b/glfw/lib/cocoa/cocoa_time.m
deleted file mode 100644
--- a/glfw/lib/cocoa/cocoa_time.m
+++ /dev/null
@@ -1,106 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL framework
-// File:        macosx_time.m
-// Platform:    Mac OS X
-// API Version: 2.7
-// WWW:         http://glfw.sourceforge.net
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Camilla Berglund
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-#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 );
-}
-
diff --git a/glfw/lib/cocoa/cocoa_window.m b/glfw/lib/cocoa/cocoa_window.m
deleted file mode 100644
--- a/glfw/lib/cocoa/cocoa_window.m
+++ /dev/null
@@ -1,880 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL framework
-// File:        macosx_window.m
-// Platform:    Mac OS X
-// API Version: 2.7
-// WWW:         http://glfw.sourceforge.net
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Camilla Berglund
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-//========================================================================
-// 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 */ GLFW_KEY_KP_EQUAL,
-    /* 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,
-    /* 40 */ -1,
-    /* 41 */ GLFW_KEY_KP_DECIMAL,
-    /* 42 */ -1,
-    /* 43 */ GLFW_KEY_KP_MULTIPLY,
-    /* 44 */ -1,
-    /* 45 */ GLFW_KEY_KP_ADD,
-    /* 46 */ -1,
-    /* 47 */ -1,
-    /* 48 */ -1,
-    /* 49 */ -1,
-    /* 4a */ -1,
-    /* 4b */ GLFW_KEY_KP_DIVIDE,
-    /* 4c */ GLFW_KEY_KP_ENTER,
-    /* 4d */ -1,
-    /* 4e */ GLFW_KEY_KP_SUBTRACT,
-    /* 4f */ -1,
-    /* 50 */ -1,
-    /* 51 */ -1,
-    /* 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 */ -1,
-    /* 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 */ -1,
-    /* 66 */ -1,
-    /* 67 */ -1,
-    /* 68 */ -1,
-    /* 69 */ GLFW_KEY_F13,
-    /* 6a */ GLFW_KEY_F16,
-    /* 6b */ -1,
-    /* 6c */ -1,
-    /* 6d */ -1,
-    /* 6e */ -1,
-    /* 6f */ -1,
-    /* 70 */ -1,
-    /* 71 */ -1,
-    /* 72 */ GLFW_KEY_INSERT,
-    /* 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 );
-}
-
-- (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];
-    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;
-
-    _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)
-        {
-            [NSApp sendEvent:event];
-        }
-    }
-    while (event);
-
-    [_glfwLibrary.AutoreleasePool drain];
-    _glfwLibrary.AutoreleasePool = [[NSAutoreleasePool alloc] init];
-}
-
-//========================================================================
-// 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 );
-}
-
