diff --git a/readme.html b/readme.html
index 19e4285d..5ab86c64 100644
--- a/readme.html
+++ b/readme.html
@@ -310,9 +310,11 @@ version of GLFW.
Bugfix: The FSAA test did not check for the availability of GL_ARB_multisample
[Cocoa] Added support for OpenGL 3.2 core profile in 10.7 Lion and above
[Cocoa] Added support for joysticks
+ [Cocoa] Postponed menu creation to first window creation
[Cocoa] Replaced NSDate
time source with mach_absolute_time
[Cocoa] Bugfix: The loop condition for saving video modes used the wrong index variable
[Cocoa] Bugfix: The OpenGL framework was not retrieved, making glfwGetProcAddress crash
+ [Cocoa] Bugfix: glfwInit
changed the current directory for unbundled executables
[X11] Added support for the GLX_EXT_swap_control
extension as an alternative to GLX_SGI_swap_control
[X11] Added the POSIX CLOCK_MONOTONIC
time source as the preferred method
[X11] Added dependency on libm, where present
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 31cd9fd9..b5569c40 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -19,9 +19,9 @@ set(common_SOURCES error.c fullscreen.c gamma.c init.c input.c
joystick.c opengl.c time.c window.c)
if(_GLFW_COCOA_NSGL)
- set(libglfw_SOURCES ${common_SOURCES} cocoa_fullscreen.m cocoa_gamma.m
+ set(libglfw_SOURCES ${common_SOURCES} cocoa_fullscreen.m cocoa_gamma.c
cocoa_init.m cocoa_input.m cocoa_joystick.m
- cocoa_opengl.m cocoa_time.m cocoa_window.m)
+ cocoa_opengl.m cocoa_time.c cocoa_window.m)
# For some reason, CMake doesn't know about .m
set_source_files_properties(${libglfw_SOURCES} PROPERTIES LANGUAGE C)
diff --git a/src/cocoa_gamma.m b/src/cocoa_gamma.c
similarity index 98%
rename from src/cocoa_gamma.m
rename to src/cocoa_gamma.c
index eb291082..53c47a89 100644
--- a/src/cocoa_gamma.m
+++ b/src/cocoa_gamma.c
@@ -32,6 +32,8 @@
#include
#include
+#include
+
//************************************************************************
//**** GLFW internal functions ****
diff --git a/src/cocoa_init.m b/src/cocoa_init.m
index 2c747515..16ea6e68 100644
--- a/src/cocoa_init.m
+++ b/src/cocoa_init.m
@@ -27,162 +27,44 @@
//
//========================================================================
-// Needed for _NSGetProgname
-#include
-
#include "internal.h"
//========================================================================
-// GLFW application class
+// Change to our application bundle's resources directory, if present
//========================================================================
-
-@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
+static void changeToResourcesDirectory(void)
{
- if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask))
- [[self keyWindow] sendEvent:event];
- else
- [super sendEvent:event];
-}
+ char resourcesPath[MAXPATHLEN];
-@end
+ CFBundleRef bundle = CFBundleGetMainBundle();
+ if (!bundle)
+ return;
+ CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
-// 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)
-{
- unsigned int i;
- NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
-
- for (i = 0; i < sizeof(GLFWNameKeys) / sizeof(GLFWNameKeys[0]); i++)
+ CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
+ if (CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo)
{
- id name = [infoDictionary objectForKey:GLFWNameKeys[i]];
- if (name &&
- [name isKindOfClass:[NSString class]] &&
- ![@"" isEqualToString:name])
- {
- return name;
- }
+ CFRelease(last);
+ CFRelease(resourcesURL);
+ return;
}
- // If we get here, we're unbundled
- if (!_glfwLibrary.NS.unbundled)
+ CFRelease(last);
+
+ if (!CFURLGetFileSystemRepresentation(resourcesURL,
+ true,
+ (UInt8*) resourcesPath,
+ MAXPATHLEN))
{
- // 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.NS.unbundled = GL_TRUE;
+ CFRelease(resourcesURL);
+ return;
}
- char** progname = _NSGetProgname();
- if (progname && *progname)
- {
- // TODO: UTF-8?
- return [NSString stringWithUTF8String:*progname];
- }
+ CFRelease(resourcesURL);
- // 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];
+ chdir(resourcesPath);
}
@@ -196,11 +78,6 @@ static void setUpMenuBar(void)
int _glfwPlatformInit(void)
{
- _glfwLibrary.NS.autoreleasePool = [[NSAutoreleasePool alloc] init];
-
- // Implicitly create shared NSApplication instance
- [GLFWApplication sharedApplication];
-
_glfwLibrary.NS.OpenGLFramework =
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
if (_glfwLibrary.NS.OpenGLFramework == NULL)
@@ -210,17 +87,7 @@ int _glfwPlatformInit(void)
return GL_FALSE;
}
- 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];
-
- _glfwPlatformSetTime(0.0);
+ changeToResourcesDirectory();
_glfwLibrary.NS.desktopMode =
(NSDictionary*) CGDisplayCurrentMode(CGMainDisplayID());
diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h
index 93492dbb..1a90af01 100644
--- a/src/cocoa_platform.h
+++ b/src/cocoa_platform.h
@@ -91,7 +91,6 @@ typedef struct _GLFWlibraryNS
// dlopen handle for dynamically loading OpenGL extension entry points
void* OpenGLFramework;
- GLboolean unbundled;
id desktopMode;
id delegate;
id autoreleasePool;
diff --git a/src/cocoa_time.m b/src/cocoa_time.c
similarity index 100%
rename from src/cocoa_time.m
rename to src/cocoa_time.c
diff --git a/src/cocoa_window.m b/src/cocoa_window.m
index b5dfb436..221dcc5e 100644
--- a/src/cocoa_window.m
+++ b/src/cocoa_window.m
@@ -29,6 +29,9 @@
#include "internal.h"
+// Needed for _NSGetProgname
+#include
+
//========================================================================
// Delegate for window related notifications
@@ -443,6 +446,175 @@ static int convertMacKeyCode(unsigned int macKeyCode)
@end
+//========================================================================
+// GLFW application class
+//========================================================================
+
+@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
+
+//========================================================================
+// Try to figure out what the calling application is called
+//========================================================================
+
+static NSString* findAppName(void)
+{
+ unsigned int i;
+ NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
+
+ // Keys to search for as potential application names
+ NSString* GLFWNameKeys[] =
+ {
+ @"CFBundleDisplayName",
+ @"CFBundleName",
+ @"CFBundleExecutable",
+ };
+
+ 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
+ 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);
+
+ char** progname = _NSGetProgname();
+ if (progname && *progname)
+ {
+ // TODO: UTF-8?
+ 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 the Cocoa Application Kit
+//========================================================================
+static GLboolean initializeCocoa(void)
+{
+ if (NSApp)
+ return GL_TRUE;
+
+ _glfwLibrary.NS.autoreleasePool = [[NSAutoreleasePool alloc] init];
+
+ // Implicitly create shared NSApplication instance
+ [GLFWApplication sharedApplication];
+
+ // Setting up the menu bar must go between sharedApplication
+ // above and finishLaunching below, in order to properly emulate the
+ // behavior of NSApplicationMain
+ setUpMenuBar();
+
+ [NSApp finishLaunching];
+
+ return GL_TRUE;
+}
+
//========================================================================
// Create the Cocoa window
//========================================================================
@@ -641,6 +813,9 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWfbconfig* fbconfig)
{
+ if (!initializeCocoa())
+ return GL_FALSE;
+
// We can only have one application delegate, but we only allocate it the
// first time we create a window to keep all window code in this file
if (_glfwLibrary.NS.delegate == nil)
diff --git a/tests/iconify.c b/tests/iconify.c
index 6d001ea5..dbc4d9cf 100644
--- a/tests/iconify.c
+++ b/tests/iconify.c
@@ -62,6 +62,8 @@ static void key_callback(GLFWwindow window, int key, int action)
static void size_callback(GLFWwindow window, int width, int height)
{
+ printf("%0.2f Size %ix%i\n", glfwGetTime(), width, height);
+
glViewport(0, 0, width, height);
}