From 62d948da0abb337382b72135cf1fcea4f27697b3 Mon Sep 17 00:00:00 2001 From: decodism Date: Sun, 7 Jul 2024 22:49:16 +0200 Subject: [PATCH] feat: add function key modifier --- Pods/ShortcutRecorder/Library/SRCommon.h | 40 +++++++++++- Pods/ShortcutRecorder/Library/SRCommon.m | 31 +++++++++ .../Library/SRModifierFlagsTransformer.m | 9 +++ .../Library/SRRecorderControl.m | 6 +- Pods/ShortcutRecorder/Library/SRShortcut.h | 2 + Pods/ShortcutRecorder/Library/SRShortcut.m | 63 +++++++++++++++++-- .../Library/SRShortcutAction.m | 2 + .../en.lproj/ShortcutRecorder.strings | 3 + .../CustomRecorderControl.swift | 2 +- 9 files changed, 147 insertions(+), 11 deletions(-) diff --git a/Pods/ShortcutRecorder/Library/SRCommon.h b/Pods/ShortcutRecorder/Library/SRCommon.h index aef1f0951..f98145fea 100644 --- a/Pods/ShortcutRecorder/Library/SRCommon.h +++ b/Pods/ShortcutRecorder/Library/SRCommon.h @@ -10,18 +10,21 @@ NS_ASSUME_NONNULL_BEGIN +static const UInt32 fakeFunctionKey = 1 << 16; + + /*! Mask representing subset of Cocoa modifier flags suitable for shortcuts. */ NS_SWIFT_NAME(CocoaModifierFlagsMask) -static const NSEventModifierFlags SRCocoaModifierFlagsMask = NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagShift | NSEventModifierFlagControl; +static const NSEventModifierFlags SRCocoaModifierFlagsMask = NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagShift | NSEventModifierFlagControl | NSEventModifierFlagFunction; /*! Mask representing subset of Carbon modifier flags suitable for shortcuts. */ NS_SWIFT_NAME(CarbonModifierFlagsMask) -static const UInt32 SRCarbonModifierFlagsMask = cmdKey | optionKey | shiftKey | controlKey; +static const UInt32 SRCarbonModifierFlagsMask = cmdKey | optionKey | shiftKey | controlKey | fakeFunctionKey; /*! @@ -107,7 +110,9 @@ typedef NS_ENUM(unichar, SRModifierFlagGlyph) SRModifierFlagGlyphCommand = kCommandUnicode, // ⌘ SRModifierFlagGlyphOption = kOptionUnicode, // ⌥ SRModifierFlagGlyphShift = kShiftUnicode, // ⇧ - SRModifierFlagGlyphControl = kControlUnicode // ⌃ + SRModifierFlagGlyphControl = kControlUnicode, // ⌃ + SRModifierFlagGlyphFunction1 = 0x0066, // f + SRModifierFlagGlyphFunction2 = 0x006E // n } NS_SWIFT_NAME(ModifierFlagGlyph); @@ -243,6 +248,8 @@ extern SRModifierFlagString const SRModifierFlagStringCommand; extern SRModifierFlagString const SRModifierFlagStringOption; extern SRModifierFlagString const SRModifierFlagStringShift; extern SRModifierFlagString const SRModifierFlagStringControl; +extern SRModifierFlagString const SRModifierFlagStringFunction1; +extern SRModifierFlagString const SRModifierFlagStringFunction2; /*! @@ -274,6 +281,9 @@ NS_INLINE NSEventModifierFlags SRCarbonToCocoaFlags(UInt32 aCarbonFlags) if (aCarbonFlags & shiftKey) cocoaFlags |= NSEventModifierFlagShift; + + if (aCarbonFlags & fakeFunctionKey) + cocoaFlags |= NSEventModifierFlagFunction; return cocoaFlags; } @@ -297,6 +307,9 @@ NS_INLINE UInt32 SRCocoaToCarbonFlags(NSEventModifierFlags aCocoaFlags) if (aCocoaFlags & NSEventModifierFlagShift) carbonFlags |= shiftKey; + + if (aCocoaFlags & NSEventModifierFlagFunction) + carbonFlags |= fakeFunctionKey; return carbonFlags; } @@ -367,4 +380,25 @@ NSImage * _Nullable SRImage(NSString * _Nullable anImageName); @end + +extern CGError CGSSetHotKeyWithExclusion(int cid, void* uid, UInt16 keyEquivalent, UInt16 keyCode, UInt64 keyModifiers, int exclusion); + + +extern OSStatus interposed_RegisterEventHotKey( + UInt32 inHotKeyCode, + UInt32 inHotKeyModifiers, + EventHotKeyID inHotKeyID, + EventTargetRef inTarget, + OptionBits inOptions, + EventHotKeyRef * outRef +); + + +extern CGError interposed_CGSSetHotKeyWithExclusion(int cid, void* uid, UInt16 keyEquivalent, UInt16 keyCode, UInt64 keyModifiers, int exclusion); + + +#define DYLD_INTERPOSE(_replacement,_replacee) \ + __attribute__((used)) static struct{ const void* replacement; const void* replacee; } _interpose_##_replacee \ + __attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacement, (const void*)(unsigned long)&_replacee }; + NS_ASSUME_NONNULL_END diff --git a/Pods/ShortcutRecorder/Library/SRCommon.m b/Pods/ShortcutRecorder/Library/SRCommon.m index 3c6a48724..c92b73eb1 100644 --- a/Pods/ShortcutRecorder/Library/SRCommon.m +++ b/Pods/ShortcutRecorder/Library/SRCommon.m @@ -34,6 +34,8 @@ SRModifierFlagString const SRModifierFlagStringOption = @"⌥"; SRModifierFlagString const SRModifierFlagStringShift = @"⇧"; SRModifierFlagString const SRModifierFlagStringControl = @"⌃"; +SRModifierFlagString const SRModifierFlagStringFunction1 = @"f"; +SRModifierFlagString const SRModifierFlagStringFunction2 = @"n"; NSBundle *SRBundle() @@ -95,3 +97,32 @@ - (BOOL)SR_isEqual:(nullable NSObject *)anObject usingSelector:(SEL)aSelector of } @end + + +static UInt32 cached_inHotKeyModifiers = 0; + + +OSStatus interposed_RegisterEventHotKey( + UInt32 inHotKeyCode, + UInt32 inHotKeyModifiers, + EventHotKeyID inHotKeyID, + EventTargetRef inTarget, + OptionBits inOptions, + EventHotKeyRef * outRef +) { + cached_inHotKeyModifiers = inHotKeyModifiers; + return RegisterEventHotKey(inHotKeyCode, inHotKeyModifiers, inHotKeyID, inTarget, inOptions, outRef); +} + + +CGError interposed_CGSSetHotKeyWithExclusion(int cid, void* uid, UInt16 keyEquivalent, UInt16 keyCode, UInt64 keyModifiers, int exclusion) { + if (cached_inHotKeyModifiers != 0) { + keyModifiers = SRCarbonToCocoaFlags(cached_inHotKeyModifiers); + cached_inHotKeyModifiers = 0; + } + return CGSSetHotKeyWithExclusion(cid, uid, keyEquivalent, keyCode, keyModifiers, exclusion); +} + + +DYLD_INTERPOSE(interposed_RegisterEventHotKey, RegisterEventHotKey) +DYLD_INTERPOSE(interposed_CGSSetHotKeyWithExclusion, CGSSetHotKeyWithExclusion) diff --git a/Pods/ShortcutRecorder/Library/SRModifierFlagsTransformer.m b/Pods/ShortcutRecorder/Library/SRModifierFlagsTransformer.m index 8d84302f8..4ed480e23 100644 --- a/Pods/ShortcutRecorder/Library/SRModifierFlagsTransformer.m +++ b/Pods/ShortcutRecorder/Library/SRModifierFlagsTransformer.m @@ -106,6 +106,9 @@ - (NSString *)transformedValue:(NSNumber *)aValue layoutDirection:(NSUserInterfa if (flags & NSEventModifierFlagCommand) [flagsStringComponents addObject:SRLoc(@"Command")]; + + if (flags & NSEventModifierFlagFunction) + [flagsStringComponents addObject:SRLoc(@"Function")]; if (aDirection == NSUserInterfaceLayoutDirectionRightToLeft) return [[[flagsStringComponents reverseObjectEnumerator] allObjects] componentsJoinedByString:SRLoc(@"-")]; @@ -157,6 +160,9 @@ - (NSString *)transformedValue:(NSNumber *)aValue layoutDirection:(NSUserInterfa if (flags & NSEventModifierFlagCommand) [flagsStringFragments addObject:SRModifierFlagStringCommand]; + + if (flags & NSEventModifierFlagFunction) + [flagsStringFragments addObject:[SRModifierFlagStringFunction1 stringByAppendingString:SRModifierFlagStringFunction2]]; if (aDirection == NSUserInterfaceLayoutDirectionRightToLeft) return [[[flagsStringFragments reverseObjectEnumerator] allObjects] componentsJoinedByString:@""]; @@ -187,6 +193,9 @@ - (NSNumber *)reverseTransformedValue:(NSString *)aValue flags |= NSEventModifierFlagShift; else if ([substring isEqualToString:SRModifierFlagStringCommand] && (flags & NSEventModifierFlagCommand) == 0) flags |= NSEventModifierFlagCommand; + else if ([substring isEqualToString:SRModifierFlagStringFunction1] && (flags & NSEventModifierFlagFunction) == 0) + flags |= NSEventModifierFlagFunction; + else if ([substring isEqualToString:SRModifierFlagStringFunction2] && (flags & NSEventModifierFlagFunction) != 0) {} else { foundInvalidSubstring = YES; diff --git a/Pods/ShortcutRecorder/Library/SRRecorderControl.m b/Pods/ShortcutRecorder/Library/SRRecorderControl.m index 38e634692..2d76b1e13 100644 --- a/Pods/ShortcutRecorder/Library/SRRecorderControl.m +++ b/Pods/ShortcutRecorder/Library/SRRecorderControl.m @@ -1206,7 +1206,7 @@ - (void)prepareForInterfaceBuilder { [super prepareForInterfaceBuilder]; self.objectValue = [SRShortcut shortcutWithCode:0 - modifierFlags:NSEventModifierFlagControl | NSEventModifierFlagOption | NSEventModifierFlagShift | NSEventModifierFlagCommand + modifierFlags:NSEventModifierFlagControl | NSEventModifierFlagOption | NSEventModifierFlagShift | NSEventModifierFlagCommand | NSEventModifierFlagFunction characters:@"" charactersIgnoringModifiers:@"a"]; } @@ -1269,7 +1269,7 @@ - (NSString *)stringValue return SRLoc(@""); __auto_type layoutDirection = self.stringValueRespectsUserInterfaceLayoutDirection ? self.userInterfaceLayoutDirection : NSUserInterfaceLayoutDirectionLeftToRight; - NSString *flags = [SRSymbolicModifierFlagsTransformer.sharedTransformer transformedValue:@(_objectValue.modifierFlags) + NSString *flags = [SRSymbolicModifierFlagsTransformer.sharedTransformer transformedValue:@(_objectValue.displayModifierFlags) layoutDirection:layoutDirection]; SRKeyCodeTransformer *transformer = nil; @@ -1798,6 +1798,8 @@ - (void)flagsChanged:(NSEvent *)anEvent nextModifierFlags ^= NSEventModifierFlagShift; else if ((modifierFlags & NSEventModifierFlagControl) && (keyCode == kVK_Control || keyCode == kVK_RightControl)) nextModifierFlags ^= NSEventModifierFlagControl; + else if ((modifierFlags & NSEventModifierFlagFunction) && keyCode == kVK_Function) + nextModifierFlags ^= NSEventModifierFlagFunction; else if (modifierFlags == 0 && _lastSeenModifierFlags != 0) { SRShortcut *newObjectValue = [SRShortcut shortcutWithCode:SRKeyCodeNone diff --git a/Pods/ShortcutRecorder/Library/SRShortcut.h b/Pods/ShortcutRecorder/Library/SRShortcut.h index c8e6fbfc4..1a7596141 100644 --- a/Pods/ShortcutRecorder/Library/SRShortcut.h +++ b/Pods/ShortcutRecorder/Library/SRShortcut.h @@ -120,6 +120,8 @@ NS_SWIFT_NAME(Shortcut) */ @property (readonly) NSEventModifierFlags modifierFlags; +@property (readonly) NSEventModifierFlags displayModifierFlags; + /*! Representation of the key code with modifier flags. diff --git a/Pods/ShortcutRecorder/Library/SRShortcut.m b/Pods/ShortcutRecorder/Library/SRShortcut.m index 64982a57e..1ffd48dbd 100644 --- a/Pods/ShortcutRecorder/Library/SRShortcut.m +++ b/Pods/ShortcutRecorder/Library/SRShortcut.m @@ -59,6 +59,8 @@ + (instancetype)shortcutWithEvent:(NSEvent *)aKeyboardEvent modifierFlags |= NSEventModifierFlagShift; else if (keyCode == kVK_Control || keyCode == kVK_RightControl) modifierFlags |= NSEventModifierFlagControl; + else if (keyCode == kVK_Function) + modifierFlags |= NSEventModifierFlagFunction; keyCode = SRKeyCodeNone; } @@ -121,11 +123,13 @@ + (instancetype)shortcutWithKeyEquivalent:(NSString *)aKeyEquivalent static NSCharacterSet *PossibleFlags = nil; static dispatch_once_t OnceToken; dispatch_once(&OnceToken, ^{ - PossibleFlags = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:@"%C%C%C%C", + PossibleFlags = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:@"%C%C%C%C%C%C", SRModifierFlagGlyphCommand, SRModifierFlagGlyphOption, SRModifierFlagGlyphShift, - SRModifierFlagGlyphControl]]; + SRModifierFlagGlyphControl, + SRModifierFlagGlyphFunction1, + SRModifierFlagGlyphFunction2]]; }); NSScanner *parser = [NSScanner scannerWithString:aKeyEquivalent]; @@ -203,6 +207,36 @@ - (instancetype)initWithCode:(SRKeyCode)aKeyCode #pragma mark Properties +- (NSEventModifierFlags)displayModifierFlags +{ + switch (self.keyCode) + { + case SRKeyCodeF1: + case SRKeyCodeF2: + case SRKeyCodeF3: + case SRKeyCodeF4: + case SRKeyCodeF5: + case SRKeyCodeF6: + case SRKeyCodeF7: + case SRKeyCodeF8: + case SRKeyCodeF9: + case SRKeyCodeF10: + case SRKeyCodeF11: + case SRKeyCodeF12: + case SRKeyCodeF13: + case SRKeyCodeF14: + case SRKeyCodeF15: + case SRKeyCodeF16: + case SRKeyCodeF17: + case SRKeyCodeF18: + case SRKeyCodeF19: + case SRKeyCodeF20: + return self.modifierFlags & ~NSEventModifierFlagFunction; + default: + return self.modifierFlags; + } +} + - (NSDictionary *)dictionaryRepresentation { NSMutableDictionary *d = [NSMutableDictionary dictionaryWithCapacity:4]; @@ -313,16 +347,33 @@ - (BOOL)isEqualToKeyEquivalent:(NSString *)aKeyEquivalent NSEventModifierFlagCommand, NSEventModifierFlagShift, NSEventModifierFlagOption, + NSEventModifierFlagFunction, NSEventModifierFlagControl | NSEventModifierFlagCommand, NSEventModifierFlagControl | NSEventModifierFlagShift, NSEventModifierFlagControl | NSEventModifierFlagOption, + NSEventModifierFlagControl | NSEventModifierFlagFunction, NSEventModifierFlagCommand | NSEventModifierFlagShift, NSEventModifierFlagCommand | NSEventModifierFlagOption, + NSEventModifierFlagCommand | NSEventModifierFlagFunction, NSEventModifierFlagShift | NSEventModifierFlagOption, + NSEventModifierFlagShift | NSEventModifierFlagFunction, + NSEventModifierFlagOption | NSEventModifierFlagFunction, NSEventModifierFlagControl | NSEventModifierFlagCommand | NSEventModifierFlagShift, NSEventModifierFlagControl | NSEventModifierFlagCommand | NSEventModifierFlagOption, + NSEventModifierFlagControl | NSEventModifierFlagCommand | NSEventModifierFlagFunction, + NSEventModifierFlagControl | NSEventModifierFlagShift | NSEventModifierFlagOption, + NSEventModifierFlagControl | NSEventModifierFlagShift | NSEventModifierFlagFunction, + NSEventModifierFlagControl | NSEventModifierFlagOption | NSEventModifierFlagFunction, NSEventModifierFlagCommand | NSEventModifierFlagShift | NSEventModifierFlagOption, - NSEventModifierFlagControl | NSEventModifierFlagCommand | NSEventModifierFlagShift | NSEventModifierFlagOption + NSEventModifierFlagCommand | NSEventModifierFlagShift | NSEventModifierFlagFunction, + NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagFunction, + NSEventModifierFlagShift | NSEventModifierFlagOption | NSEventModifierFlagFunction, + NSEventModifierFlagControl | NSEventModifierFlagCommand | NSEventModifierFlagShift | NSEventModifierFlagOption, + NSEventModifierFlagControl | NSEventModifierFlagCommand | NSEventModifierFlagShift | NSEventModifierFlagFunction, + NSEventModifierFlagControl | NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagFunction, + NSEventModifierFlagControl | NSEventModifierFlagShift | NSEventModifierFlagOption | NSEventModifierFlagFunction, + NSEventModifierFlagCommand | NSEventModifierFlagShift | NSEventModifierFlagOption | NSEventModifierFlagFunction, + NSEventModifierFlagControl | NSEventModifierFlagCommand | NSEventModifierFlagShift | NSEventModifierFlagOption | NSEventModifierFlagFunction }; static const size_t PossibleFlagsSize = sizeof(PossibleFlags) / sizeof(NSEventModifierFlags); @@ -489,11 +540,12 @@ - (UInt32)carbonModifierFlags if (!c) c = [NSString stringWithFormat:@"<%hu>", aKeyCode]; - return [NSString stringWithFormat:@"%@%@%@%@%@", + return [NSString stringWithFormat:@"%@%@%@%@%@%@", (aModifierFlags & NSEventModifierFlagCommand ? SRLoc(@"Command-") : @""), (aModifierFlags & NSEventModifierFlagOption ? SRLoc(@"Option-") : @""), (aModifierFlags & NSEventModifierFlagControl ? SRLoc(@"Control-") : @""), (aModifierFlags & NSEventModifierFlagShift ? SRLoc(@"Shift-") : @""), + (aModifierFlags & NSEventModifierFlagFunction ? SRLoc(@"Function-") : @""), c]; } @@ -506,11 +558,12 @@ - (UInt32)carbonModifierFlags if (!c) c = [NSString stringWithFormat:@"<%hu>", aKeyCode]; - return [NSString stringWithFormat:@"%@%@%@%@%@", + return [NSString stringWithFormat:@"%@%@%@%@%@%@", (aModifierFlags & NSEventModifierFlagCommand ? SRLoc(@"Command-") : @""), (aModifierFlags & NSEventModifierFlagOption ? SRLoc(@"Option-") : @""), (aModifierFlags & NSEventModifierFlagControl ? SRLoc(@"Control-") : @""), (aModifierFlags & NSEventModifierFlagShift ? SRLoc(@"Shift-") : @""), + (aModifierFlags & NSEventModifierFlagFunction ? SRLoc(@"Function-") : @""), c]; } diff --git a/Pods/ShortcutRecorder/Library/SRShortcutAction.m b/Pods/ShortcutRecorder/Library/SRShortcutAction.m index 44bd1b85b..188189ce5 100644 --- a/Pods/ShortcutRecorder/Library/SRShortcutAction.m +++ b/Pods/ShortcutRecorder/Library/SRShortcutAction.m @@ -391,6 +391,8 @@ - (SRKeyEventType)SR_keyEventType eventType = self.modifierFlags & NSEventModifierFlagShift ? SRKeyEventTypeDown : SRKeyEventTypeUp; else if (keyCode == kVK_Control || keyCode == kVK_RightControl) eventType = self.modifierFlags & NSEventModifierFlagControl ? SRKeyEventTypeDown : SRKeyEventTypeUp; + else if (keyCode == kVK_Function) + eventType = self.modifierFlags & NSEventModifierFlagFunction ? SRKeyEventTypeDown : SRKeyEventTypeUp; else os_trace("#Error Unexpected key code %hu for the FlagsChanged event", keyCode); break; diff --git a/Pods/ShortcutRecorder/Resources/en.lproj/ShortcutRecorder.strings b/Pods/ShortcutRecorder/Resources/en.lproj/ShortcutRecorder.strings index d745f714f..bd2d018f6 100644 --- a/Pods/ShortcutRecorder/Resources/en.lproj/ShortcutRecorder.strings +++ b/Pods/ShortcutRecorder/Resources/en.lproj/ShortcutRecorder.strings @@ -52,5 +52,8 @@ /* VoiceOver name of the Control modifier key */ "Control" = "Control"; +/* VoiceOver name of the Function modifier key */ +"Function" = "Function"; + /* VoiceOver name of the modifier keys delimiter */ "-" = "-"; diff --git a/src/ui/generic-components/CustomRecorderControl.swift b/src/ui/generic-components/CustomRecorderControl.swift index 7128e5b9a..b8dcd169e 100644 --- a/src/ui/generic-components/CustomRecorderControl.swift +++ b/src/ui/generic-components/CustomRecorderControl.swift @@ -1,7 +1,7 @@ import Cocoa import ShortcutRecorder -let allowedModifiers = NSEvent.ModifierFlags(arrayLiteral: [.command, .control, .option, .shift]) +let allowedModifiers = NSEvent.ModifierFlags(arrayLiteral: [.command, .control, .option, .shift, .function]) class CustomRecorderControl: RecorderControl, RecorderControlDelegate { var clearable: Bool!