From 2a5375a0c82008d2a6e4b7a5abca4b7086e4d22d Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 13 Apr 2016 22:43:16 +0300 Subject: [PATCH] Configurable keys for the Cocoa port --- Cocoa/AppDelegate.h | 2 + Cocoa/AppDelegate.m | 33 ++++++++++- Cocoa/GBButtons.h | 24 ++++++++ Cocoa/GBButtons.m | 4 ++ Cocoa/GBPreferencesWindow.h | 5 ++ Cocoa/GBPreferencesWindow.m | 60 +++++++++++++++++++ Cocoa/GBView.m | 105 +++++++++++++--------------------- Cocoa/MainMenu.xib | 9 +-- Cocoa/NSKeyboardShortcut.h | 22 +++++++ Cocoa/NSString+StringForKey.h | 5 ++ Cocoa/NSString+StringForKey.m | 12 ++++ Cocoa/Preferences.xib | 97 +++++++++++++++++++++++++++++++ Makefile | 3 +- 13 files changed, 309 insertions(+), 72 deletions(-) create mode 100644 Cocoa/GBButtons.h create mode 100644 Cocoa/GBButtons.m create mode 100644 Cocoa/GBPreferencesWindow.h create mode 100644 Cocoa/GBPreferencesWindow.m create mode 100644 Cocoa/NSKeyboardShortcut.h create mode 100644 Cocoa/NSString+StringForKey.h create mode 100644 Cocoa/NSString+StringForKey.m create mode 100644 Cocoa/Preferences.xib diff --git a/Cocoa/AppDelegate.h b/Cocoa/AppDelegate.h index c38bd96..d4ffe7c 100644 --- a/Cocoa/AppDelegate.h +++ b/Cocoa/AppDelegate.h @@ -2,6 +2,8 @@ @interface AppDelegate : NSObject +@property IBOutlet NSWindow *preferencesWindow; +- (IBAction)showPreferences: (id) sender; - (IBAction)toggleDeveloperMode:(id)sender; @end diff --git a/Cocoa/AppDelegate.m b/Cocoa/AppDelegate.m index 1fe8d99..2b17823 100644 --- a/Cocoa/AppDelegate.m +++ b/Cocoa/AppDelegate.m @@ -5,6 +5,28 @@ @end @implementation AppDelegate +{ + NSWindow *preferences_window; +} + +- (void) applicationDidFinishLaunching:(NSNotification *)notification +{ +#define KEY(x) ({unichar __x = x; [NSString stringWithCharacters:&(__x) length:1];}) + [[NSUserDefaults standardUserDefaults] registerDefaults:@{ + @"GBRight": KEY(NSRightArrowFunctionKey), + @"GBLeft": KEY(NSLeftArrowFunctionKey), + @"GBUp": KEY(NSUpArrowFunctionKey), + @"GBDown": KEY(NSDownArrowFunctionKey), + + @"GBA": @"x", + @"GBB": @"z", + @"GBSelect": @"\x7f", + @"GBStart": @"\r", + + @"GBTurbo": @" ", + }]; +#undef KEY +} - (IBAction)toggleDeveloperMode:(id)sender { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; @@ -15,10 +37,17 @@ { if ([anItem action] == @selector(toggleDeveloperMode:)) { [(NSMenuItem*)anItem setState:[[NSUserDefaults standardUserDefaults] boolForKey:@"DeveloperMode"]]; - return true; } - return false; + return true; } +- (IBAction) showPreferences: (id) sender +{ + NSArray *objects; + if (!_preferencesWindow) { + [[NSBundle mainBundle] loadNibNamed:@"Preferences" owner:self topLevelObjects:&objects]; + } + [_preferencesWindow makeKeyAndOrderFront:self]; +} @end diff --git a/Cocoa/GBButtons.h b/Cocoa/GBButtons.h new file mode 100644 index 0000000..e02440e --- /dev/null +++ b/Cocoa/GBButtons.h @@ -0,0 +1,24 @@ +#ifndef GBButtons_h +#define GBButtons_h + +typedef enum : NSUInteger { + GBRight, + GBLeft, + GBUp, + GBDown, + GBA, + GBB, + GBSelect, + GBStart, + GBTurbo, + GBButtonCount +} GBButton; + +extern NSString const *GBButtonNames[GBButtonCount]; + +static inline NSString *button_to_preference_name(GBButton button) +{ + return [NSString stringWithFormat:@"GB%@", GBButtonNames[button]]; +} + +#endif diff --git a/Cocoa/GBButtons.m b/Cocoa/GBButtons.m new file mode 100644 index 0000000..9784eef --- /dev/null +++ b/Cocoa/GBButtons.m @@ -0,0 +1,4 @@ +#import +#import "GBButtons.h" + +NSString const *GBButtonNames[] = {@"Right", @"Left", @"Up", @"Down", @"A", @"B", @"Select", @"Start", @"Turbo"}; \ No newline at end of file diff --git a/Cocoa/GBPreferencesWindow.h b/Cocoa/GBPreferencesWindow.h new file mode 100644 index 0000000..0d83d5a --- /dev/null +++ b/Cocoa/GBPreferencesWindow.h @@ -0,0 +1,5 @@ +#import + +@interface GBPreferencesWindow : NSWindow +@property IBOutlet NSTableView *controlsTableView; +@end diff --git a/Cocoa/GBPreferencesWindow.m b/Cocoa/GBPreferencesWindow.m new file mode 100644 index 0000000..85d545e --- /dev/null +++ b/Cocoa/GBPreferencesWindow.m @@ -0,0 +1,60 @@ +#import "GBPreferencesWindow.h" +#import "NSString+StringForKey.h" +#import "GBButtons.h" + +@implementation GBPreferencesWindow +{ + bool is_button_being_modified; + NSInteger button_being_modified; +} + +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView +{ + return GBButtonCount; +} + +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row +{ + if ([tableColumn.identifier isEqualToString:@"keyName"]) { + return GBButtonNames[row]; + } + + if (is_button_being_modified && button_being_modified == row) { + return @"Select a new key..."; + } + + return [NSString displayStringForKeyString:[[NSUserDefaults standardUserDefaults] stringForKey: + button_to_preference_name(row)]]; +} + +- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row +{ + dispatch_async(dispatch_get_main_queue(), ^{ + is_button_being_modified = true; + button_being_modified = row; + tableView.enabled = NO; + [tableView reloadData]; + [self makeFirstResponder:self]; + }); + return NO; +} + +-(void)keyDown:(NSEvent *)theEvent +{ + if (!is_button_being_modified) { + if (self.firstResponder != self.controlsTableView) { + [super keyDown:theEvent]; + } + return; + } + + is_button_being_modified = false; + + [[NSUserDefaults standardUserDefaults] setObject:theEvent.charactersIgnoringModifiers + forKey:button_to_preference_name(button_being_modified)]; + self.controlsTableView.enabled = YES; + [self.controlsTableView reloadData]; + [self makeFirstResponder:self.controlsTableView]; +} + +@end diff --git a/Cocoa/GBView.m b/Cocoa/GBView.m index ada01e9..f72e01f 100644 --- a/Cocoa/GBView.m +++ b/Cocoa/GBView.m @@ -1,6 +1,7 @@ -#import #import #import "GBView.h" +#import "GBButtons.h" +#import "NSString+StringForKey.h" @implementation GBView { @@ -76,77 +77,51 @@ -(void)keyDown:(NSEvent *)theEvent { - unsigned short key = theEvent.keyCode; - switch (key) { - case kVK_RightArrow: - _gb->keys[0] = true; - break; - case kVK_LeftArrow: - _gb->keys[1] = true; - break; - case kVK_UpArrow: - _gb->keys[2] = true; - break; - case kVK_DownArrow: - _gb->keys[3] = true; - break; - case kVK_ANSI_X: - _gb->keys[4] = true; - break; - case kVK_ANSI_Z: - _gb->keys[5] = true; - break; - case kVK_Delete: - _gb->keys[6] = true; - break; - case kVK_Return: - _gb->keys[7] = true; - break; - case kVK_Space: - _gb->turbo = true; - break; + bool handled = false; - default: - [super keyDown:theEvent]; - break; + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + for (GBButton i = 0; i < GBButtonCount; i++) { + if ([[defaults stringForKey:button_to_preference_name(i)] isEqualToString:theEvent.charactersIgnoringModifiers]) { + handled = true; + switch (i) { + case GBTurbo: + _gb->turbo = true; + break; + + default: + _gb->keys[i] = true; + break; + } + } + } + + if (!handled) { + [super keyDown:theEvent]; } } -(void)keyUp:(NSEvent *)theEvent { - unsigned short key = theEvent.keyCode; - switch (key) { - case kVK_RightArrow: - _gb->keys[0] = false; - break; - case kVK_LeftArrow: - _gb->keys[1] = false; - break; - case kVK_UpArrow: - _gb->keys[2] = false; - break; - case kVK_DownArrow: - _gb->keys[3] = false; - break; - case kVK_ANSI_X: - _gb->keys[4] = false; - break; - case kVK_ANSI_Z: - _gb->keys[5] = false; - break; - case kVK_Delete: - _gb->keys[6] = false; - break; - case kVK_Return: - _gb->keys[7] = false; - break; - case kVK_Space: - _gb->turbo = false; - break; + bool handled = false; - default: - [super keyUp:theEvent]; - break; + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + for (GBButton i = 0; i < GBButtonCount; i++) { + if ([[defaults stringForKey:button_to_preference_name(i)] isEqualToString:theEvent.charactersIgnoringModifiers]) { + handled = true; + switch (i) { + case GBTurbo: + _gb->turbo = false; + break; + + default: + _gb->keys[i] = false; + break; + } + } + } + + if (!handled) { + [super keyUp:theEvent]; } } diff --git a/Cocoa/MainMenu.xib b/Cocoa/MainMenu.xib index fd5a96d..d3bc791 100644 --- a/Cocoa/MainMenu.xib +++ b/Cocoa/MainMenu.xib @@ -26,7 +26,11 @@ - + + + + + @@ -305,9 +309,6 @@ - - - diff --git a/Cocoa/NSKeyboardShortcut.h b/Cocoa/NSKeyboardShortcut.h new file mode 100644 index 0000000..347fc76 --- /dev/null +++ b/Cocoa/NSKeyboardShortcut.h @@ -0,0 +1,22 @@ +#ifndef NSKeyboardShortcut_h +#define NSKeyboardShortcut_h + +/* This is private API, but it is a very simple and comprehensive way + to convert a key equivalent to its display name. */ + +@interface NSKeyboardShortcut : NSObject + ++ (id)shortcutWithPreferencesEncoding:(NSString *)encoding; ++ (id)shortcutWithKeyEquivalent:(NSString *)key_equivalent modifierMask:(unsigned long long)mask; +- (id)initWithKeyEquivalent:(NSString *)key_equivalent modifierMask:(unsigned long long)mask; + +@property(readonly) unsigned long long modifierMask; +@property(readonly) NSString *keyEquivalent; +@property(readonly) NSString *preferencesEncoding; +@property(readonly) NSString *localizedModifierMaskDisplayName; +@property(readonly) NSString *localizedKeyEquivalentDisplayName; +@property(readonly) NSString *localizedDisplayName; + +@end + +#endif \ No newline at end of file diff --git a/Cocoa/NSString+StringForKey.h b/Cocoa/NSString+StringForKey.h new file mode 100644 index 0000000..d8e872b --- /dev/null +++ b/Cocoa/NSString+StringForKey.h @@ -0,0 +1,5 @@ +#import + +@interface NSString (StringForKey) ++ (NSString *) displayStringForKeyString: (NSString *)key_string; +@end diff --git a/Cocoa/NSString+StringForKey.m b/Cocoa/NSString+StringForKey.m new file mode 100644 index 0000000..fb8fc09 --- /dev/null +++ b/Cocoa/NSString+StringForKey.m @@ -0,0 +1,12 @@ +#import "NSString+StringForKey.h" +#import "NSKeyboardShortcut.h" + +@implementation NSString (StringForKey) + ++ (NSString *) displayStringForKeyString: (NSString *)key_string +{ + + return [[NSKeyboardShortcut shortcutWithKeyEquivalent:key_string modifierMask:0] localizedDisplayName]; +} + +@end diff --git a/Cocoa/Preferences.xib b/Cocoa/Preferences.xib new file mode 100644 index 0000000..2a58475 --- /dev/null +++ b/Cocoa/Preferences.xib @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Makefile b/Makefile index 4ce99d4..4ebbb96 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,8 @@ $(BIN)/Sameboy.app: $(BIN)/Sameboy.app/Contents/MacOS/Sameboy \ $(BIN)/BootROMs/dmg_boot.bin \ $(BIN)/BootROMs/cgb_boot.bin \ $(BIN)/Sameboy.app/Contents/Resources/Base.lproj/Document.nib \ - $(BIN)/Sameboy.app/Contents/Resources/Base.lproj/MainMenu.nib + $(BIN)/Sameboy.app/Contents/Resources/Base.lproj/MainMenu.nib \ + $(BIN)/Sameboy.app/Contents/Resources/Base.lproj/Preferences.nib mkdir -p $(BIN)/Sameboy.app/Contents/Resources cp Cocoa/*.icns $(BIN)/BootROMs/dmg_boot.bin $(BIN)/BootROMs/cgb_boot.bin $(BIN)/Sameboy.app/Contents/Resources/ sed s/@VERSION/$(VERSION)/ < Cocoa/info.plist > $(BIN)/Sameboy.app/Contents/info.plist