Skip to content

Instantly share code, notes, and snippets.

@MasonRemaley
Last active November 17, 2017 03:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MasonRemaley/af5e1d3c538aedbfd6c726762205b1fb to your computer and use it in GitHub Desktop.
Save MasonRemaley/af5e1d3c538aedbfd6c726762205b1fb to your computer and use it in GitHub Desktop.
Minimal cocoa text entry for OpenGL apps
// *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