From d115e9d080a7113e75a78d340b319b9e2db5e0d6 Mon Sep 17 00:00:00 2001 From: Luke Griffioen Date: Thu, 15 Jan 2026 13:01:22 -0500 Subject: [PATCH 1/2] allow disabling a shortcut recorder control --- SRRecorderControl.h | 2 ++ SRRecorderControl.m | 44 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/SRRecorderControl.h b/SRRecorderControl.h index 1898a4b1..c3e45faf 100755 --- a/SRRecorderControl.h +++ b/SRRecorderControl.h @@ -122,6 +122,8 @@ extern NSString *const SRShortcutCharactersIgnoringModifiers; */ @property BOOL allowsDeleteToClearShortcutAndEndRecording; +@property BOOL isEnabled; + /*! @brief Determines whether recording is in process. */ diff --git a/SRRecorderControl.m b/SRRecorderControl.m index 8d7accb0..7a56f3de 100755 --- a/SRRecorderControl.m +++ b/SRRecorderControl.m @@ -115,6 +115,7 @@ @implementation SRRecorderControl NSMutableDictionary *_bindingInfo; BOOL _shouldDrawBackground; + BOOL _isEnabled; } - (instancetype)initWithFrame:(NSRect)aFrameRect @@ -129,6 +130,7 @@ - (instancetype)initWithFrame:(NSRect)aFrameRect _drawsASCIIEquivalentOfShortcut = YES; _allowsEscapeToCancelRecording = YES; _allowsDeleteToClearShortcutAndEndRecording = YES; + _isEnabled = YES; _mouseTrackingButtonTag = _SRRecorderControlInvalidButtonTag; _snapBackButtonToolTipTag = NSIntegerMax; _bindingInfo = [NSMutableDictionary dictionary]; @@ -210,12 +212,22 @@ - (void)setObjectValue:(NSDictionary *)newObjectValue } } +- (void)setIsEnabled:(BOOL)isEnabled +{ + _isEnabled = isEnabled; + [self setNeedsDisplay:YES]; +} + +-(BOOL)isEnabled +{ + return _isEnabled; +} #pragma mark Methods - (BOOL)beginRecording { - if (self.isRecording) + if (self.isRecording || !self.isEnabled) return YES; [self setNeedsDisplay:YES]; @@ -541,10 +553,12 @@ - (void)drawBackground:(NSRect)aDirtyRect CGFloat corner = frame.size.height / 2; frame = NSInsetRect(frame, 1, 1); + CGFloat opacity = self.isEnabled ? 1 : 0.5; + NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:frame xRadius:corner yRadius:corner]; path.lineWidth = 1; - [[NSColor controlColor] setFill]; - [[NSColor grayColor] setStroke]; + [[[NSColor controlColor] colorWithAlphaComponent:opacity] setFill]; + [[[NSColor grayColor] colorWithAlphaComponent:opacity] setStroke]; [path fill]; [path stroke]; @@ -760,6 +774,11 @@ - (NSString *)accessibilityActionDescription:(NSString *)anAction - (void)accessibilityPerformAction:(NSString *)anAction { + if (!self.isEnabled) + { + return; + } + if ([anAction isEqualToString:NSAccessibilityPressAction]) [self beginRecording]; else if (self.isRecording && [anAction isEqualToString:NSAccessibilityCancelAction]) @@ -898,7 +917,7 @@ - (void)drawRect:(NSRect)aDirtyRect - (void)drawFocusRingMask { - if (self.window.firstResponder == self) + if (self.window.firstResponder == self && self.isEnabled) [self.controlShape fill]; } @@ -1058,6 +1077,11 @@ - (BOOL)needsPanelToBecomeKey - (void)mouseDown:(NSEvent *)anEvent { + if (!self.isEnabled) + { + return; + } + NSPoint locationInView = [self convertPoint:anEvent.locationInWindow fromView:nil]; if (self.isRecording) @@ -1123,6 +1147,11 @@ - (void)mouseUp:(NSEvent *)anEvent - (void)mouseEntered:(NSEvent *)anEvent { + if (!self.isEnabled) + { + return; + } + if (_borderlessButton) { _shouldDrawBackground = YES; @@ -1141,6 +1170,11 @@ - (void)mouseEntered:(NSEvent *)anEvent - (void)mouseExited:(NSEvent *)anEvent { + if (self.isEnabled) + { + return; + } + if (_borderlessButton) { _shouldDrawBackground = NO; @@ -1165,7 +1199,7 @@ - (void)keyDown:(NSEvent *)anEvent - (BOOL)performKeyEquivalent:(NSEvent *)anEvent { - if (self.window.firstResponder != self) + if (self.window.firstResponder != self || !self.isEnabled) return NO; if (_mouseTrackingButtonTag != _SRRecorderControlInvalidButtonTag) From c393a146b11f1b71396ca97c4a3937af8ea13de2 Mon Sep 17 00:00:00 2001 From: Luke Griffioen Date: Thu, 15 Jan 2026 13:09:46 -0500 Subject: [PATCH 2/2] clean up super old os checks --- SRCommon.h | 5 +---- SRRecorderControl.m | 54 +++++++++++---------------------------------- 2 files changed, 14 insertions(+), 45 deletions(-) diff --git a/SRCommon.h b/SRCommon.h index a2919cf2..95a4dd7a 100644 --- a/SRCommon.h +++ b/SRCommon.h @@ -109,10 +109,7 @@ FOUNDATION_STATIC_INLINE NSImage *SRImage(NSString *anImageName) #else NSBundle *b = [NSBundle bundleWithIdentifier:@"com.kulakov.ShortcutRecorder"]; - if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6) - return [[NSImage alloc] initByReferencingURL:[b URLForImageResource:anImageName]]; - else - return [b imageForResource:anImageName]; + return [b imageForResource:anImageName]; #endif } diff --git a/SRRecorderControl.m b/SRRecorderControl.m index 7a56f3de..17de8d6e 100755 --- a/SRRecorderControl.m +++ b/SRRecorderControl.m @@ -136,20 +136,17 @@ - (instancetype)initWithFrame:(NSRect)aFrameRect _bindingInfo = [NSMutableDictionary dictionary]; _fontSize = 12.0; - if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) - { - self.translatesAutoresizingMaskIntoConstraints = NO; - - [self setContentHuggingPriority:NSLayoutPriorityDefaultLow - forOrientation:NSLayoutConstraintOrientationHorizontal]; - [self setContentHuggingPriority:NSLayoutPriorityRequired - forOrientation:NSLayoutConstraintOrientationVertical]; - - [self setContentCompressionResistancePriority:NSLayoutPriorityDefaultLow - forOrientation:NSLayoutConstraintOrientationHorizontal]; - [self setContentCompressionResistancePriority:NSLayoutPriorityRequired - forOrientation:NSLayoutConstraintOrientationVertical]; - } + self.translatesAutoresizingMaskIntoConstraints = NO; + + [self setContentHuggingPriority:NSLayoutPriorityDefaultLow + forOrientation:NSLayoutConstraintOrientationHorizontal]; + [self setContentHuggingPriority:NSLayoutPriorityRequired + forOrientation:NSLayoutConstraintOrientationVertical]; + + [self setContentCompressionResistancePriority:NSLayoutPriorityDefaultLow + forOrientation:NSLayoutConstraintOrientationHorizontal]; + [self setContentCompressionResistancePriority:NSLayoutPriorityRequired + forOrientation:NSLayoutConstraintOrientationVertical]; NSString* sgwaesf = NSLocalizedStringFromTableInBundle(@"+ Shortcut", @"ShortcutRecorder", @@ -842,10 +839,7 @@ - (void)unbind:(NSString *)aBinding if (valueBindingInfo) { - if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6) - [valueBindingInfo[NSObservedObjectKey] removeObserver:self forKeyPath:valueBindingInfo[NSObservedKeyPathKey]]; - else - [valueBindingInfo[NSObservedObjectKey] removeObserver:self forKeyPath:valueBindingInfo[NSObservedKeyPathKey] context:&_SRValueObservationContext]; + [valueBindingInfo[NSObservedObjectKey] removeObserver:self forKeyPath:valueBindingInfo[NSObservedKeyPathKey] context:&_SRValueObservationContext]; [_bindingInfo removeObjectForKey:NSValueBinding]; } @@ -902,17 +896,6 @@ - (void)drawRect:(NSRect)aDirtyRect } [self drawInterior:aDirtyRect]; - - if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6) - { - if (self.window.firstResponder == self) - { - [NSGraphicsContext saveGraphicsState]; - NSSetFocusRingStyle(NSFocusRingOnly); - [self.controlShape fill]; - [NSGraphicsContext restoreGraphicsState]; - } - } } - (void)drawFocusRingMask @@ -931,7 +914,7 @@ - (NSRect)focusRingMaskBounds - (NSEdgeInsets)alignmentRectInsets { - if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6 || self.window == nil) + if (self.window == nil) return NSEdgeInsetsMake(0.0, 0.0, _SRRecorderControlBottomShadowHeightInPixels, 0.0); else return NSEdgeInsetsMake(0.0, 0.0, _SRRecorderControlBottomShadowHeightInPixels / self.window.backingScaleFactor, 0.0); @@ -1040,19 +1023,8 @@ - (BOOL)acceptsFirstResponder return YES; } -- (BOOL)becomeFirstResponder -{ - if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6) - [self setKeyboardFocusRingNeedsDisplayInRect:self.bounds]; - - return [super becomeFirstResponder]; -} - - (BOOL)resignFirstResponder { - if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6) - [self setKeyboardFocusRingNeedsDisplayInRect:self.bounds]; - [self endRecording]; _mouseTrackingButtonTag = _SRRecorderControlInvalidButtonTag; return [super resignFirstResponder];