I have been trying to create an app for Cocoa without a nib/xib (No, I don't want to use a nib/xib. I want to be in full control programatically) and I can't seem to be able to catch the Events such as keystrokes and mouse clicks. Here is the code I have so far:
Main.m
#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
@autoreleasepool {
NSApplication *app = [NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[app setDelegate:appDelegate];
[app activateIgnoringOtherApps:YES];
[app run];
}
return EXIT_SUCCESS;
}
AppDelegate.h/m
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
NSWindow *window;
}
@end
#import "AppDelegate.h"
#import "GLView.h"
@implementation AppDelegate
- (id)init{
self = [super init];
if (!self) {
return nil;
}
NSRect bounds = [[NSScreen mainScreen] frame];
GLView *view = [[GLView alloc]initWithFrame:bounds];
window = [[NSWindow alloc] initWithContentRect:bounds
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[window setReleasedWhenClosed:YES];
[window setAcceptsMouseMovedEvents:YES];
[window setContentView:view];
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[window makeKeyAndOrderFront:self];
}
@end
GLView.h/m
#import <Cocoa/Cocoa.h>
@interface GLView : NSView
@end
#import "GLView.h"
@implementation GLView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
// Drawing code here.
}
- (BOOL)canBecomeKeyView
{
return YES;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (BOOL)becomeFirstResponder
{
return YES;
}
- (BOOL)resignFirstResponder
{
return YES;
}
- (void)keyDown:(NSEvent *)theEvent
{
NSString* const character = [theEvent charactersIgnoringModifiers];
unichar const code = [character characterAtIndex:0];
NSLog(@"Key Down: %hu", code);
switch (code)
{
case 27:
{
EXIT_SUCCESS;
break;
}
}
}
- (void)keyUp:(NSEvent *)theEvent
{
}
@end
Nothing I have tried for it has worked. I thought that by setting the view as the first responder I would be able to get the events. So far... Not working. Any ideas on how I can fix this? Remember, NO NIB.
Thanks, Tyler
First, you need to make sure that your window can actually become key, by subclassing and returning YES
from canBecomeKeyWindow
, because windows without title bars cannot become key by default.
Next, your build target needs to be an application. I would guess that you're starting from the Command-Line Tool template in Xcode. This is fine, but you need to produce an application bundle in order for your app to recieve key events. Create a new target in your project that will build a Cocoa Application. It needs to have an Info.plist file (from which you'll want to delete the "Main nib file base class" entry) and have a "Copy Bundle Resources" Build Phase.
I can't quite figure out what all the other differences are in the build process, but starting from your code, I got the window to accept key events with these two steps.