Last active
November 17, 2017 03:01
-
-
Save MasonRemaley/af5e1d3c538aedbfd6c726762205b1fb to your computer and use it in GitHub Desktop.
Minimal cocoa text entry for OpenGL apps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// *DISCLAIMER IF YOU FOUND THIS VIA GOOGLE: I'm at the time of writing still figuring this out, it | |
// works for me but I don't actually know if it's correct yet* | |
// | |
// This is a minimal example of how one might accept text entry in Cocoa in an OpenGL app or | |
// such. Unlike using `[event characters]`, it ignores unprintable keys such as the arrow keys. It | |
// also allows you to type accents and such, e.g. `alt+e o`. This example contains no error | |
// checking, and the only way to exit it is to kill it from the command line. | |
// | |
// To execute it, run: | |
// `$ gcc minimal_cocoa_gl_text_entry.m -framework Cocoa && ./a.out` | |
#import <Cocoa/Cocoa.h> | |
// We need to create a new subclass of `NsView` that implements the `NSTextInputClient` protocol. | |
// NSView can be replaced with NSOpenGLView or such here if needed. | |
// | |
// It's possible that instead you could just have a separate `NSTextInputClient` object, and send | |
// the `keyDown` events to it from here instead. I haven't yet tried this. | |
@interface MyView : NSView<NSTextInputClient> | |
{ | |
} | |
@end | |
@implementation MyView | |
// Accept first responder so we get events | |
- (BOOL)acceptsFirstResponder { | |
return YES; | |
} | |
// Interpret the key events as text | |
- (void)keyDown:(NSEvent *)event { | |
[self interpretKeyEvents:[NSArray arrayWithObject:event]]; | |
} | |
// Just log the text as we get it to show that it works | |
- (void)insertText:(id)string replacementRange:(NSRange)replacementRange { | |
NSLog(@"%@", string); | |
} | |
// The rest of these are methods I don't yet understand and have just filled in stubs for so it | |
// would compile. | |
- (BOOL)hasMarkedText { | |
return NO; | |
} | |
- (NSRange)markedRange { | |
return NSMakeRange(0, 0); | |
} | |
- (NSRange)selectedRange { | |
return NSMakeRange(0, 0); | |
} | |
- (void)setMarkedText:(id)string | |
selectedRange:(NSRange)selectedRange | |
replacementRange:(NSRange)replacementRange { | |
} | |
- (void)unmarkText { | |
} | |
- (NSArray*)validAttributesForMarkedText { | |
return [NSArray array]; | |
} | |
- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range | |
actualRange:(NSRangePointer)actualRange { | |
return nil; | |
} | |
- (NSUInteger)characterIndexForPoint:(NSPoint)point { | |
return 0; | |
} | |
- (NSRect)firstRectForCharacterRange:(NSRange)range | |
actualRange:(NSRangePointer)actualRange { | |
return NSMakeRect(0, 0, 0, 0); | |
} | |
- (void)doCommandBySelector:(SEL)selector { | |
} | |
@end | |
int main() { | |
@autoreleasepool { | |
NSApplication* app = [NSApplication sharedApplication]; | |
[app setActivationPolicy: NSApplicationActivationPolicyRegular]; | |
NSWindow *window = [[[NSWindow alloc] | |
initWithContentRect: NSMakeRect(0, 0, 200, 200) | |
styleMask: NSWindowStyleMaskTitled | |
backing: NSBackingStoreBuffered | |
defer: NO | |
] autorelease]; | |
[window setContentView: [[MyView alloc] init]]; // Here we're using our custom view | |
[window cascadeTopLeftFromPoint:NSMakePoint(20,20)]; | |
[window makeKeyAndOrderFront:nil]; | |
[NSApp activateIgnoringOtherApps:YES]; | |
[app run]; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment