mirror of
https://github.com/glfw/glfw.git
synced 2024-11-22 13:04:35 +00:00
Cocoa: Remove subclassing of NSApplication
This removes the GLFW NSApplication subclass as a step towards better coexistence with other libraries that touch Cocoa. This moves application object creation to platform init to allow event processing before window creation. Related to #1317.
This commit is contained in:
parent
f9923e9095
commit
88c5edb409
@ -27,6 +27,10 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include <sys/param.h> // For MAXPATHLEN
|
#include <sys/param.h> // For MAXPATHLEN
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||||
|
#define NSEventMaskKeyUp NSKeyUpMask
|
||||||
|
#define NSEventModifierFlagCommand NSCommandKeyMask
|
||||||
|
#endif
|
||||||
|
|
||||||
// Change to our application bundle's resources directory, if present
|
// Change to our application bundle's resources directory, if present
|
||||||
//
|
//
|
||||||
@ -271,17 +275,21 @@ static GLFWbool initializeTIS(void)
|
|||||||
return updateUnicodeDataNS();
|
return updateUnicodeDataNS();
|
||||||
}
|
}
|
||||||
|
|
||||||
@interface GLFWLayoutListener : NSObject
|
@interface GLFWHelper : NSObject
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GLFWLayoutListener
|
@implementation GLFWHelper
|
||||||
|
|
||||||
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
|
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
|
||||||
{
|
{
|
||||||
updateUnicodeDataNS();
|
updateUnicodeDataNS();
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
- (void)doNothing:(id)object
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@end // GLFWHelper
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -291,13 +299,31 @@ static GLFWbool initializeTIS(void)
|
|||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||||
|
_glfw.ns.helper = [[GLFWHelper alloc] init];
|
||||||
|
|
||||||
|
[NSThread detachNewThreadSelector:@selector(doNothing:)
|
||||||
|
toTarget:_glfw.ns.helper
|
||||||
|
withObject:nil];
|
||||||
|
|
||||||
|
[NSApplication sharedApplication];
|
||||||
|
|
||||||
|
NSEvent* (^block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
||||||
|
{
|
||||||
|
if ([event modifierFlags] & NSEventModifierFlagCommand)
|
||||||
|
[[NSApp keyWindow] sendEvent:event];
|
||||||
|
|
||||||
|
return event;
|
||||||
|
};
|
||||||
|
|
||||||
|
_glfw.ns.keyUpMonitor =
|
||||||
|
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
|
||||||
|
handler:block];
|
||||||
|
|
||||||
if (_glfw.hints.init.ns.chdir)
|
if (_glfw.hints.init.ns.chdir)
|
||||||
changeToResourcesDirectory();
|
changeToResourcesDirectory();
|
||||||
|
|
||||||
_glfw.ns.listener = [[GLFWLayoutListener alloc] init];
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
addObserver:_glfw.ns.listener
|
addObserver:_glfw.ns.helper
|
||||||
selector:@selector(selectedKeyboardInputSourceChanged:)
|
selector:@selector(selectedKeyboardInputSourceChanged:)
|
||||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
@ -342,18 +368,21 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfw.ns.delegate = nil;
|
_glfw.ns.delegate = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.ns.listener)
|
if (_glfw.ns.helper)
|
||||||
{
|
{
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
removeObserver:_glfw.ns.listener
|
removeObserver:_glfw.ns.helper
|
||||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
removeObserver:_glfw.ns.listener];
|
removeObserver:_glfw.ns.helper];
|
||||||
[_glfw.ns.listener release];
|
[_glfw.ns.helper release];
|
||||||
_glfw.ns.listener = nil;
|
_glfw.ns.helper = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_glfw.ns.keyUpMonitor)
|
||||||
|
[NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
|
||||||
|
|
||||||
free(_glfw.ns.clipboardString);
|
free(_glfw.ns.clipboardString);
|
||||||
|
|
||||||
_glfwTerminateNSGL();
|
_glfwTerminateNSGL();
|
||||||
|
@ -109,7 +109,9 @@ typedef struct _GLFWlibraryNS
|
|||||||
TISInputSourceRef inputSource;
|
TISInputSourceRef inputSource;
|
||||||
IOHIDManagerRef hidManager;
|
IOHIDManagerRef hidManager;
|
||||||
id unicodeData;
|
id unicodeData;
|
||||||
id listener;
|
id helper;
|
||||||
|
id keyUpMonitor;
|
||||||
|
id nibObjects;
|
||||||
|
|
||||||
char keyName[64];
|
char keyName[64];
|
||||||
short int keycodes[256];
|
short int keycodes[256];
|
||||||
|
@ -46,7 +46,6 @@
|
|||||||
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
|
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
|
||||||
#define NSEventMaskAny NSAnyEventMask
|
#define NSEventMaskAny NSAnyEventMask
|
||||||
#define NSEventTypeApplicationDefined NSApplicationDefined
|
#define NSEventTypeApplicationDefined NSApplicationDefined
|
||||||
#define NSEventTypeKeyUp NSKeyUp
|
|
||||||
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -856,52 +855,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// GLFW application class
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@interface GLFWApplication : NSApplication
|
|
||||||
{
|
|
||||||
NSArray* nibObjects;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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] == NSEventTypeKeyUp &&
|
|
||||||
([event modifierFlags] & NSEventModifierFlagCommand))
|
|
||||||
{
|
|
||||||
[[self keyWindow] sendEvent:event];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
[super sendEvent:event];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// No-op thread entry point
|
|
||||||
//
|
|
||||||
- (void)doNothing:(id)object
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)loadMainMenu
|
|
||||||
{
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
|
|
||||||
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
|
|
||||||
owner:NSApp
|
|
||||||
topLevelObjects:&nibObjects];
|
|
||||||
#else
|
|
||||||
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
// Set up the menu bar (manually)
|
// Set up the menu bar (manually)
|
||||||
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
|
// 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
|
// could go away at any moment, lots of stuff that really should be
|
||||||
@ -1011,32 +964,9 @@ static void createMenuBar(void)
|
|||||||
//
|
//
|
||||||
static GLFWbool initializeAppKit(void)
|
static GLFWbool initializeAppKit(void)
|
||||||
{
|
{
|
||||||
if (NSApp)
|
if (_glfw.ns.delegate)
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
|
|
||||||
// Implicitly create shared NSApplication instance
|
|
||||||
[GLFWApplication sharedApplication];
|
|
||||||
|
|
||||||
// Make Cocoa enter multi-threaded mode
|
|
||||||
[NSThread detachNewThreadSelector:@selector(doNothing:)
|
|
||||||
toTarget:NSApp
|
|
||||||
withObject:nil];
|
|
||||||
|
|
||||||
if (_glfw.hints.init.ns.menubar)
|
|
||||||
{
|
|
||||||
// In case we are unbundled, make us a proper UI application
|
|
||||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
|
||||||
|
|
||||||
// Menu bar setup must go between sharedApplication above and
|
|
||||||
// finishLaunching below, in order to properly emulate the behavior
|
|
||||||
// of NSApplicationMain
|
|
||||||
|
|
||||||
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
|
|
||||||
[NSApp loadMainMenu];
|
|
||||||
else
|
|
||||||
createMenuBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
// There can only be one application delegate, but we allocate it the
|
// There can only be one application delegate, but we allocate it the
|
||||||
// first time a window is created to keep all window code in this file
|
// first time a window is created to keep all window code in this file
|
||||||
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
|
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
|
||||||
@ -1048,6 +978,30 @@ static GLFWbool initializeAppKit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NSApp setDelegate:_glfw.ns.delegate];
|
[NSApp setDelegate:_glfw.ns.delegate];
|
||||||
|
|
||||||
|
if (_glfw.hints.init.ns.menubar)
|
||||||
|
{
|
||||||
|
// In case we are unbundled, make us a proper UI application
|
||||||
|
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||||
|
|
||||||
|
// Menu bar setup must go between sharedApplication above and
|
||||||
|
// finishLaunching below, in order to properly emulate the behavior
|
||||||
|
// of NSApplicationMain
|
||||||
|
|
||||||
|
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
|
||||||
|
{
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
|
||||||
|
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
|
||||||
|
owner:NSApp
|
||||||
|
topLevelObjects:&_glfw.ns.nibObjects];
|
||||||
|
#else
|
||||||
|
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
createMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
[NSApp run];
|
[NSApp run];
|
||||||
|
|
||||||
// Press and Hold prevents some keys from emitting repeated characters
|
// Press and Hold prevents some keys from emitting repeated characters
|
||||||
@ -1554,9 +1508,6 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
|||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
{
|
{
|
||||||
if (!initializeAppKit())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||||
@ -1707,9 +1658,6 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
|||||||
NSImage* native;
|
NSImage* native;
|
||||||
NSBitmapImageRep* rep;
|
NSBitmapImageRep* rep;
|
||||||
|
|
||||||
if (!initializeAppKit())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
rep = [[NSBitmapImageRep alloc]
|
rep = [[NSBitmapImageRep alloc]
|
||||||
initWithBitmapDataPlanes:NULL
|
initWithBitmapDataPlanes:NULL
|
||||||
pixelsWide:image->width
|
pixelsWide:image->width
|
||||||
@ -1745,9 +1693,6 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
|||||||
|
|
||||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||||
{
|
{
|
||||||
if (!initializeAppKit())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (shape == GLFW_ARROW_CURSOR)
|
if (shape == GLFW_ARROW_CURSOR)
|
||||||
cursor->ns.object = [NSCursor arrowCursor];
|
cursor->ns.object = [NSCursor arrowCursor];
|
||||||
else if (shape == GLFW_IBEAM_CURSOR)
|
else if (shape == GLFW_IBEAM_CURSOR)
|
||||||
|
Loading…
Reference in New Issue
Block a user