From 7f241ea02d1fcd4b257bc028d8f02403cdd03e1e Mon Sep 17 00:00:00 2001 From: Sharker <1548742234@qq.com> Date: Tue, 26 Dec 2023 21:43:08 +0800 Subject: [PATCH] feat: add double click modifier as shortcut --- Podfile | 4 +- Podfile.lock | 17 +++- Pods/Local Podspecs/MASShortcut.podspec.json | 32 +++++++ .../MASShortcut/Framework/Model/MASShortcut.h | 3 + .../MASShortcut/Framework/Model/MASShortcut.m | 24 ++++- .../Framework/Monitoring/MASShortcutMonitor.m | 89 ++++++++++++++++++- .../Framework/UI/MASShortcutView.m | 15 +++- Pods/Manifest.lock | 17 +++- 8 files changed, 184 insertions(+), 17 deletions(-) create mode 100644 Pods/Local Podspecs/MASShortcut.podspec.json diff --git a/Podfile b/Podfile index f91b37ba0..d2d99968b 100644 --- a/Podfile +++ b/Podfile @@ -10,7 +10,7 @@ target 'Easydict' do pod 'MJExtension', '~> 3.2.1' pod 'Masonry', '~> 1.1.0' pod 'ReactiveObjC', '~> 3.1.1' - pod 'MASShortcut', '~> 2.4.0' + pod 'MASShortcut', :git => 'git@github.com:AkaShark/MASShortcut.git', :branch => 'double_click_modifier' pod 'MASPreferences', '~> 1.4.1' pod 'CocoaLumberjack/Swift', '~> 3.6.0' pod 'SSZipArchive', '~> 2.2.2' @@ -34,7 +34,7 @@ target 'EasydictTests' do pod 'MJExtension', '~> 3.2.1' pod 'Masonry', '~> 1.1.0' pod 'ReactiveObjC', '~> 3.1.1' - pod 'MASShortcut', '~> 2.4.0' + pod 'MASShortcut', :git => 'git@github.com:AkaShark/MASShortcut.git', :branch => 'double_click_modifier' pod 'MASPreferences', '~> 1.4.1' pod 'CocoaLumberjack/Swift', '~> 3.6.0' pod 'SSZipArchive', '~> 2.2.2' diff --git a/Podfile.lock b/Podfile.lock index c5d605edf..55028505a 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -117,7 +117,7 @@ DEPENDENCIES: - KVOController (~> 1.2.0) - Masonry (~> 1.1.0) - MASPreferences (~> 1.4.1) - - MASShortcut (~> 2.4.0) + - "MASShortcut (from `git@github.com:AkaShark/MASShortcut.git`, branch `double_click_modifier`)" - MJExtension (~> 3.2.1) - ReactiveObjC (~> 3.1.1) - Sparkle (~> 2.5.1) @@ -139,7 +139,6 @@ SPEC REPOS: - KVOController - Masonry - MASPreferences - - MASShortcut - MJExtension - nanopb - PromisesObjC @@ -148,6 +147,16 @@ SPEC REPOS: - SSZipArchive - SwiftFormat +EXTERNAL SOURCES: + MASShortcut: + :branch: double_click_modifier + :git: "git@github.com:AkaShark/MASShortcut.git" + +CHECKOUT OPTIONS: + MASShortcut: + :commit: 694922e088bc91eb70eff42ddaf7602c5b87f1f1 + :git: "git@github.com:AkaShark/MASShortcut.git" + SPEC CHECKSUMS: AFNetworking: cb604b1c2bded0871f5f61f5d53653739e841d6b AppCenter: 85c92db0759d2792a65eb61d6842d2e86611a49a @@ -171,6 +180,6 @@ SPEC CHECKSUMS: SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9 SwiftFormat: 2ca3d0b75754193f0f3ba532291f25ae08dd1e42 -PODFILE CHECKSUM: a35287f08d36ebe90dd9f3362e15bf7aaeeaf0f5 +PODFILE CHECKSUM: 597cd2d7aa9ead11dfe63d03ada0bdffc6ee7ad8 -COCOAPODS: 1.14.2 +COCOAPODS: 1.13.0 diff --git a/Pods/Local Podspecs/MASShortcut.podspec.json b/Pods/Local Podspecs/MASShortcut.podspec.json new file mode 100644 index 000000000..f0f1aa602 --- /dev/null +++ b/Pods/Local Podspecs/MASShortcut.podspec.json @@ -0,0 +1,32 @@ +{ + "name": "MASShortcut", + "version": "2.4.0", + "summary": "Modern framework for managing global keyboard shortcuts compatible with Mac App Store", + "homepage": "https://github.com/shpakovski/MASShortcut", + "license": "BSD 2-clause", + "authors": { + "Vadim Shpakovski": "vadim@shpakovski.com", + "Tomáš Znamenáček": "tomas.znamenacek@gmail.com" + }, + "platforms": { + "osx": "10.10" + }, + "source": { + "git": "https://github.com/shpakovski/MASShortcut.git", + "tag": "2.4.0" + }, + "source_files": "Framework/**/*.{h,m}", + "exclude_files": "Framework/**/*Tests.m", + "osx": { + "frameworks": [ + "Carbon", + "AppKit" + ], + "resource_bundles": { + "MASShortcut": [ + "Resources/*.lproj" + ] + } + }, + "requires_arc": true +} diff --git a/Pods/MASShortcut/Framework/Model/MASShortcut.h b/Pods/MASShortcut/Framework/Model/MASShortcut.h index 1b7d76bed..e750d56dd 100644 --- a/Pods/MASShortcut/Framework/Model/MASShortcut.h +++ b/Pods/MASShortcut/Framework/Model/MASShortcut.h @@ -71,6 +71,9 @@ - (instancetype)initWithKeyCode:(NSInteger)code modifierFlags:(NSEventModifierFlags)flags; + (instancetype)shortcutWithKeyCode:(NSInteger)code modifierFlags:(NSEventModifierFlags)flags; +- (nonnull instancetype)initDoubleModifierKeyWithCode:(NSInteger)code modifierFlags:(NSEventModifierFlags)flags; ++ (nonnull instancetype)shortcutDoubleModifierKeyWithCode:(NSInteger)code modifierFlags:(NSEventModifierFlags)flags; + /** Creates a new shortcut from an `NSEvent` object. diff --git a/Pods/MASShortcut/Framework/Model/MASShortcut.m b/Pods/MASShortcut/Framework/Model/MASShortcut.m index 1a029a90b..536eda2a7 100644 --- a/Pods/MASShortcut/Framework/Model/MASShortcut.m +++ b/Pods/MASShortcut/Framework/Model/MASShortcut.m @@ -3,7 +3,7 @@ static NSString *const MASShortcutKeyCode = @"KeyCode"; static NSString *const MASShortcutModifierFlags = @"ModifierFlags"; - +static NSUInteger MAShortcutDoubleModifierCode = 100000; @implementation MASShortcut #pragma mark Initialization @@ -23,6 +23,19 @@ + (instancetype)shortcutWithKeyCode:(NSInteger)code modifierFlags:(NSEventModifi return [[self alloc] initWithKeyCode:code modifierFlags:flags]; } +- (nonnull instancetype)initDoubleModifierKeyWithCode:(NSInteger)code modifierFlags:(NSEventModifierFlags)flags { + if (self = [super init]) { + // hard code special key + _keyCode = 100000; + _modifierFlags = MASPickCocoaModifiers(flags); + } + return self; +} + ++ (nonnull instancetype)shortcutDoubleModifierKeyWithCode:(NSInteger)code modifierFlags:(NSEventModifierFlags)flags { + return [[self alloc] initDoubleModifierKeyWithCode:code modifierFlags:flags]; +} + + (instancetype)shortcutWithEvent:(NSEvent *)event { return [[self alloc] initWithKeyCode:event.keyCode modifierFlags:event.modifierFlags]; @@ -32,6 +45,9 @@ + (instancetype)shortcutWithEvent:(NSEvent *)event - (UInt32)carbonKeyCode { + if (self.keyCode == MAShortcutDoubleModifierCode) { + return (UInt32)MAShortcutDoubleModifierCode; + } return (self.keyCode == NSNotFound ? 0 : (UInt32)self.keyCode); } @@ -80,6 +96,9 @@ - (NSString *)keyCodeStringForKeyEquivalent - (NSString *)keyCodeString { + if (self.keyCode == MAShortcutDoubleModifierCode) { + return self.modifierFlagsString; + } // Some key codes don't have an equivalent switch (self.keyCode) { case NSNotFound: return @""; @@ -202,8 +221,7 @@ - (BOOL) isEqual: (MASShortcut*) object && (object.modifierFlags == self.modifierFlags); } -- (NSUInteger) hash -{ +- (NSUInteger) hash { return self.keyCode + self.modifierFlags; } diff --git a/Pods/MASShortcut/Framework/Monitoring/MASShortcutMonitor.m b/Pods/MASShortcut/Framework/Monitoring/MASShortcutMonitor.m index fce802265..7aa7d8506 100644 --- a/Pods/MASShortcut/Framework/Monitoring/MASShortcutMonitor.m +++ b/Pods/MASShortcut/Framework/Monitoring/MASShortcutMonitor.m @@ -7,7 +7,7 @@ @interface MASShortcutMonitor () @end static OSStatus MASCarbonEventCallback(EventHandlerCallRef, EventRef, void*); - +static NSUInteger MAShortcutDoubleModifierCode = 100000; @implementation MASShortcutMonitor #pragma mark Initialization @@ -22,6 +22,8 @@ - (instancetype) init if (status != noErr) { return nil; } + + [self addModifierDoubleClickListener]; return self; } @@ -74,10 +76,91 @@ - (BOOL) isShortcutRegistered: (MASShortcut*) shortcut return !![_hotKeys objectForKey:shortcut]; } +- (void)addModifierDoubleClickListener { + __block NSUInteger preFlag = -1; + __weak typeof(self) weakSelf = self; + // event Monitor + [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskFlagsChanged handler:^NSEvent * _Nullable(NSEvent * event) { + __strong typeof(weakSelf) strongSelf = weakSelf; + NSUInteger flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; + if (flags == NSEventModifierFlagCommand || + flags == NSEventModifierFlagOption || + flags == NSEventModifierFlagShift || + flags == NSEventModifierFlagControl) { + if (preFlag != -1 && flags == preFlag) { + NSUInteger modifierFlag = MASPickCocoaModifiers(flags); +// NSString *eventKey = [strongSelf modifierFlagsString:modifierFlag]; + [strongSelf doubleClickHandleEventWithModifier:modifierFlag]; + preFlag = -1; + } else { + preFlag = flags; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + preFlag = -1; + }); + } + } + return event; + }]; + + [NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskFlagsChanged handler:^(NSEvent *event) { + __strong typeof(weakSelf) strongSelf = weakSelf; + NSUInteger flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; + if (flags == NSEventModifierFlagCommand || + flags == NSEventModifierFlagOption || + flags == NSEventModifierFlagShift || + flags == NSEventModifierFlagControl) { + if (preFlag != -1 && flags == preFlag) { + NSUInteger modifierFlag = MASPickCocoaModifiers(flags); +// NSString *eventKey = [strongSelf modifierFlagsString:modifierFlag]; + [strongSelf doubleClickHandleEventWithModifier:modifierFlag]; + preFlag = -1; + + } else { + preFlag = flags; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + preFlag = -1; + }); + } + } + }]; + +} + #pragma mark Event Handling +- (void)doubleClickHandleEventWithModifier:(NSUInteger)modifierFlag { + __block BOOL flag = NO; + [_hotKeys enumerateKeysAndObjectsUsingBlock:^(MASShortcut *shortcut, MASHotKey *hotKey, BOOL *stop) { + if (shortcut.modifierFlags == modifierFlag && shortcut.keyCode == MAShortcutDoubleModifierCode) { + flag = YES; + *stop = YES; + } else if (shortcut.modifierFlags == modifierFlag && shortcut.keyCode == MAShortcutDoubleModifierCode) { + flag = YES; + *stop = YES; + } else if (shortcut.modifierFlags == modifierFlag && shortcut.keyCode == MAShortcutDoubleModifierCode) { + flag = YES; + *stop = YES; + } else if (shortcut.modifierFlags == modifierFlag && shortcut.keyCode == MAShortcutDoubleModifierCode) { + flag = YES; + *stop = YES; + } + if (flag && [hotKey action]) { + dispatch_async(dispatch_get_main_queue(), [hotKey action]); + } + }]; +} -- (void) handleEvent: (EventRef) event -{ +- (NSString *)modifierFlagsString:(NSUInteger)modifierFlags { + unichar chars[4]; + NSUInteger count = 0; + // These are in the same order as the menu manager shows them + if (modifierFlags & NSEventModifierFlagControl) chars[count++] = kControlUnicode; + if (modifierFlags & NSEventModifierFlagOption) chars[count++] = kOptionUnicode; + if (modifierFlags & NSEventModifierFlagShift) chars[count++] = kShiftUnicode; + if (modifierFlags & NSEventModifierFlagCommand) chars[count++] = kCommandUnicode; + return (count ? [NSString stringWithCharacters:chars length:count] : @""); +} + +- (void) handleEvent: (EventRef) event { if (GetEventClass(event) != kEventClassKeyboard) { return; } diff --git a/Pods/MASShortcut/Framework/UI/MASShortcutView.m b/Pods/MASShortcut/Framework/UI/MASShortcutView.m index 3a44df42e..b91bc6df6 100644 --- a/Pods/MASShortcut/Framework/UI/MASShortcutView.m +++ b/Pods/MASShortcut/Framework/UI/MASShortcutView.m @@ -430,7 +430,7 @@ - (void)activateEventMonitoring:(BOOL)shouldActivate static BOOL isActive = NO; if (isActive == shouldActivate) return; isActive = shouldActivate; - + __block MASShortcut *preModifierFlags; static id eventMonitor = nil; if (shouldActivate) { __unsafe_unretained MASShortcutView *weakSelf = self; @@ -462,6 +462,16 @@ - (void)activateEventMonitoring:(BOOL)shouldActivate else if ((shortcut.modifierFlags == NSCommandKeyMask) && (shortcut.keyCode == kVK_ANSI_W || shortcut.keyCode == kVK_ANSI_Q)) { weakSelf.recording = NO; } + else if ((shortcut.modifierFlags == NSEventModifierFlagCommand || + shortcut.modifierFlags == NSEventModifierFlagOption || + shortcut.modifierFlags == NSEventModifierFlagControl || + shortcut.modifierFlags == NSEventModifierFlagShift) && + preModifierFlags.keyCode == shortcut.keyCode) { + weakSelf.shortcutPlaceholder = shortcut.modifierFlagsString; + MASShortcut *doubleModifierKey = [MASShortcut shortcutDoubleModifierKeyWithCode:shortcut.keyCode modifierFlags:shortcut.modifierFlags]; + weakSelf.shortcutValue = doubleModifierKey; + weakSelf.recording = NO; + } else { // Verify possible shortcut @@ -499,6 +509,9 @@ - (void)activateEventMonitoring:(BOOL)shouldActivate else { // User is playing with modifier keys weakSelf.shortcutPlaceholder = shortcut.modifierFlagsString; + if (shortcut.modifierFlags != 0) { + preModifierFlags = shortcut; + } } event = nil; } diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock index c5d605edf..55028505a 100644 --- a/Pods/Manifest.lock +++ b/Pods/Manifest.lock @@ -117,7 +117,7 @@ DEPENDENCIES: - KVOController (~> 1.2.0) - Masonry (~> 1.1.0) - MASPreferences (~> 1.4.1) - - MASShortcut (~> 2.4.0) + - "MASShortcut (from `git@github.com:AkaShark/MASShortcut.git`, branch `double_click_modifier`)" - MJExtension (~> 3.2.1) - ReactiveObjC (~> 3.1.1) - Sparkle (~> 2.5.1) @@ -139,7 +139,6 @@ SPEC REPOS: - KVOController - Masonry - MASPreferences - - MASShortcut - MJExtension - nanopb - PromisesObjC @@ -148,6 +147,16 @@ SPEC REPOS: - SSZipArchive - SwiftFormat +EXTERNAL SOURCES: + MASShortcut: + :branch: double_click_modifier + :git: "git@github.com:AkaShark/MASShortcut.git" + +CHECKOUT OPTIONS: + MASShortcut: + :commit: 694922e088bc91eb70eff42ddaf7602c5b87f1f1 + :git: "git@github.com:AkaShark/MASShortcut.git" + SPEC CHECKSUMS: AFNetworking: cb604b1c2bded0871f5f61f5d53653739e841d6b AppCenter: 85c92db0759d2792a65eb61d6842d2e86611a49a @@ -171,6 +180,6 @@ SPEC CHECKSUMS: SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9 SwiftFormat: 2ca3d0b75754193f0f3ba532291f25ae08dd1e42 -PODFILE CHECKSUM: a35287f08d36ebe90dd9f3362e15bf7aaeeaf0f5 +PODFILE CHECKSUM: 597cd2d7aa9ead11dfe63d03ada0bdffc6ee7ad8 -COCOAPODS: 1.14.2 +COCOAPODS: 1.13.0