From f7659a8910dd1fc685f7ea180bdf9ea22719e905 Mon Sep 17 00:00:00 2001 From: Iulian Onofrei Date: Mon, 12 Aug 2019 22:33:24 +0300 Subject: [PATCH] Add keyboard shortcuts support when using UIKit for Mac (Project Catalyst) Fixes #297. --- Classes/FLEXManager.h | 7 + Classes/Manager/FLEXManager.m | 15 ++- .../Utility/FLEXKeyboardHelpViewController.m | 2 +- Classes/Utility/FLEXKeyboardShortcutManager.h | 8 +- Classes/Utility/FLEXKeyboardShortcutManager.m | 126 +++++++++++++++++- 5 files changed, 152 insertions(+), 6 deletions(-) diff --git a/Classes/FLEXManager.h b/Classes/FLEXManager.h index 3a542e230d..12dbc9c917 100644 --- a/Classes/FLEXManager.h +++ b/Classes/FLEXManager.h @@ -88,4 +88,11 @@ typedef UIViewController *(^FLEXCustomContentViewerFuture)(NSData *data); - (void)setCustomViewerForContentType:(NSString *)contentType viewControllerFutureBlock:(FLEXCustomContentViewerFuture)viewControllerFutureBlock; +#if TARGET_OS_MACCATALYST + +/// Gets the default and custom keyboard shortcuts commands. +- (NSArray *)getKeyCommands; + +#endif + @end diff --git a/Classes/Manager/FLEXManager.m b/Classes/Manager/FLEXManager.m index 1e8bfc00f8..12e778efb8 100644 --- a/Classes/Manager/FLEXManager.m +++ b/Classes/Manager/FLEXManager.m @@ -153,21 +153,21 @@ - (void)explorerViewControllerDidFinish:(FLEXExplorerViewController *)explorerVi - (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description { -# if TARGET_OS_SIMULATOR +# if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST [[FLEXKeyboardShortcutManager sharedManager] registerSimulatorShortcutWithKey:key modifiers:modifiers action:action description:description]; #endif } - (void)setSimulatorShortcutsEnabled:(BOOL)simulatorShortcutsEnabled { -# if TARGET_OS_SIMULATOR +# if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST [[FLEXKeyboardShortcutManager sharedManager] setEnabled:simulatorShortcutsEnabled]; #endif } - (BOOL)simulatorShortcutsEnabled { -# if TARGET_OS_SIMULATOR +# if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST return [[FLEXKeyboardShortcutManager sharedManager] isEnabled]; #else return NO; @@ -378,4 +378,13 @@ - (void)showExplorerIfNeeded } } +#if TARGET_OS_MACCATALYST + +- (NSArray *)getKeyCommands { + + return [[FLEXKeyboardShortcutManager sharedManager] getKeyCommands]; +} + +#endif + @end diff --git a/Classes/Utility/FLEXKeyboardHelpViewController.m b/Classes/Utility/FLEXKeyboardHelpViewController.m index e0e8c1a853..1ba52df3cc 100644 --- a/Classes/Utility/FLEXKeyboardHelpViewController.m +++ b/Classes/Utility/FLEXKeyboardHelpViewController.m @@ -24,7 +24,7 @@ - (void)viewDidLoad self.textView = [[UITextView alloc] initWithFrame:self.view.bounds]; self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; [self.view addSubview:self.textView]; -#if TARGET_OS_SIMULATOR +#if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST self.textView.text = [[FLEXKeyboardShortcutManager sharedManager] keyboardShortcutsDescription]; #endif self.textView.backgroundColor = [UIColor blackColor]; diff --git a/Classes/Utility/FLEXKeyboardShortcutManager.h b/Classes/Utility/FLEXKeyboardShortcutManager.h index 732a8cbf5b..0062db27be 100644 --- a/Classes/Utility/FLEXKeyboardShortcutManager.h +++ b/Classes/Utility/FLEXKeyboardShortcutManager.h @@ -8,7 +8,7 @@ #import -#if TARGET_OS_SIMULATOR +#if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST @interface FLEXKeyboardShortcutManager : NSObject @@ -19,6 +19,12 @@ @property (nonatomic, assign, getter=isEnabled) BOOL enabled; +#if TARGET_OS_MACCATALYST + +- (NSArray *)getKeyCommands; + +#endif + @end #endif diff --git a/Classes/Utility/FLEXKeyboardShortcutManager.m b/Classes/Utility/FLEXKeyboardShortcutManager.m index 551d944956..f21d88860f 100644 --- a/Classes/Utility/FLEXKeyboardShortcutManager.m +++ b/Classes/Utility/FLEXKeyboardShortcutManager.m @@ -11,7 +11,7 @@ #import #import -#if TARGET_OS_SIMULATOR +#if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST @interface UIEvent (UIPhysicalKeyboardEvent) @@ -23,21 +23,109 @@ @interface UIEvent (UIPhysicalKeyboardEvent) @end +#if TARGET_OS_MACCATALYST + +@interface FLEXKeyInput : UIKeyCommand + +@end + +@interface UIKeyCommand (FLEX) + +@property (nonatomic, assign, readonly) BOOL isCreatedByFLEX; + +#else + @interface FLEXKeyInput : NSObject +#endif + @property (nonatomic, copy, readonly) NSString *key; @property (nonatomic, assign, readonly) UIKeyModifierFlags flags; @property (nonatomic, copy, readonly) NSString *helpDescription; @end +#if TARGET_OS_MACCATALYST + +@implementation FLEXKeyInput + +@end + +@implementation UIKeyCommand (FLEX) + +- (NSString *)key { + + return objc_getAssociatedObject(self, @selector(key)); +} + +- (void)setKey:(NSString *)key { + + objc_setAssociatedObject(self, @selector(key), key, OBJC_ASSOCIATION_COPY_NONATOMIC); +} + +- (UIKeyModifierFlags)flags { + + UIKeyModifierFlags (^block)() = objc_getAssociatedObject(self, @selector(flags)); + + return (block ? block() : kNilOptions); +} + +- (void)setFlags:(UIKeyModifierFlags)flags { + + UIKeyModifierFlags (^block)() = ^{ + return flags; + }; + + objc_setAssociatedObject(self, @selector(flags), block, OBJC_ASSOCIATION_COPY); +} + +- (NSString *)helpDescription { + + return objc_getAssociatedObject(self, @selector(helpDescription)); +} + +- (void)setHelpDescription:(NSString *)helpDescription { + + objc_setAssociatedObject(self, @selector(helpDescription), helpDescription, OBJC_ASSOCIATION_COPY_NONATOMIC); +} + +- (BOOL)isCreatedByFLEX { + + BOOL (^block)() = objc_getAssociatedObject(self, @selector(isCreatedByFLEX)); + + return (block ? block() : NO); +} + +- (void)setIsCreatedByFLEX:(BOOL)isCreatedByFLEX { + + BOOL (^block)() = ^{ + return isCreatedByFLEX; + }; + + objc_setAssociatedObject(self, @selector(isCreatedByFLEX), block, OBJC_ASSOCIATION_COPY); +} + +#else + @implementation FLEXKeyInput +#endif + - (BOOL)isEqual:(id)object { BOOL isEqual = NO; +#if TARGET_OS_MACCATALYST + if ([object isKindOfClass:[UIKeyCommand class]]) { + UIKeyCommand *keyCommand = (UIKeyCommand *)object; + if (!keyCommand.isCreatedByFLEX) { + // Not FLEX's business anymore. + + return [super isEqual:object]; + } +#else if ([object isKindOfClass:[FLEXKeyInput class]]) { FLEXKeyInput *keyCommand = (FLEXKeyInput *)object; +#endif BOOL equalKeys = self.key == keyCommand.key || [self.key isEqual:keyCommand.key]; BOOL equalFlags = self.flags == keyCommand.flags; isEqual = equalKeys && equalFlags; @@ -98,6 +186,23 @@ + (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags return [self keyInputForKey:key flags:flags helpDescription:nil]; } +#if TARGET_OS_MACCATALYST + ++ (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags helpDescription:(NSString *)helpDescription +{ + FLEXKeyInput *keyInput = [UIKeyCommand keyCommandWithInput:key modifierFlags:flags action:nil]; + if (keyInput) { + [keyInput setKey:key]; + [keyInput setFlags:flags]; + [keyInput setHelpDescription:helpDescription]; + + [keyInput setIsCreatedByFLEX:YES]; + } + return keyInput; +} + +#else + + (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags helpDescription:(NSString *)helpDescription { FLEXKeyInput *keyInput = [[self alloc] init]; @@ -109,12 +214,22 @@ + (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags h return keyInput; } +#endif + @end @interface FLEXKeyboardShortcutManager () +#if TARGET_OS_MACCATALYST + +@property (nonatomic, strong) NSMutableDictionary *actionsForKeyInputs; + +#else + @property (nonatomic, strong) NSMutableDictionary *actionsForKeyInputs; +#endif + @property (nonatomic, assign, getter=isPressingShift) BOOL pressingShift; @property (nonatomic, assign, getter=isPressingCommand) BOOL pressingCommand; @property (nonatomic, assign, getter=isPressingControl) BOOL pressingControl; @@ -305,6 +420,15 @@ - (NSString *)keyboardShortcutsDescription return [description copy]; } +#if TARGET_OS_MACCATALYST + +- (NSArray *)getKeyCommands { + + return self.actionsForKeyInputs.allKeys; +} + +#endif + @end #endif