From 9b9e2d2c4243732aca63aff6227e76305849926c Mon Sep 17 00:00:00 2001 From: Dzmitry Neviadomski Date: Fri, 8 Jan 2021 00:22:01 +0300 Subject: [PATCH] Show Volume slider in NSPopover instead of CGWindow. Also perform Haptic feedback when volume slider is at 100%. --- Window/VolumeButton.h | 6 ++++-- Window/VolumeButton.m | 42 +++++++++++++++++++++++++++++------------- Window/VolumeSlider.m | 18 +++++++++++++++++- 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/Window/VolumeButton.h b/Window/VolumeButton.h index d4354fc95..6eba6cc8e 100644 --- a/Window/VolumeButton.h +++ b/Window/VolumeButton.h @@ -6,9 +6,11 @@ // Copyright 2009 __MyCompanyName__. All rights reserved. // -#import "PopupButton.h" +#import +#import "VolumeSlider.h" -@interface VolumeButton : PopupButton { +@interface VolumeButton : NSButton { + IBOutlet VolumeSlider *_popView; } @end diff --git a/Window/VolumeButton.m b/Window/VolumeButton.m index 79a0d15e5..9faa93c23 100644 --- a/Window/VolumeButton.m +++ b/Window/VolumeButton.m @@ -7,29 +7,45 @@ // #import "VolumeButton.h" -#import "VolumeSlider.h" #import "PlaybackController.h" -@implementation VolumeButton +@implementation VolumeButton { + NSPopover *popover; +} + +- (void)awakeFromNib +{ + popover = [[NSPopover alloc] init]; + + NSViewController * viewController = [[NSViewController alloc] init]; + viewController.view = _popView; + popover.contentViewController = viewController; + popover.behavior = NSPopoverBehaviorTransient; + [popover setContentSize:_popView.bounds.size]; +} - (void)scrollWheel:(NSEvent *)theEvent { - double change = [theEvent deltaY]; - - [(VolumeSlider *)_popView setDoubleValue:[(VolumeSlider *)_popView doubleValue] + change]; - - [[(VolumeSlider *)_popView target] changeVolume:_popView]; - - [(VolumeSlider *)_popView showToolTipForView:self closeAfter:1.0]; + if ([popover isShown]) { + [_popView scrollWheel:theEvent]; + return; + } + + double change = [theEvent deltaY]; + + [_popView setDoubleValue:[_popView doubleValue] + change]; + + [[_popView target] changeVolume:_popView]; + + [_popView showToolTipForView:self closeAfter:1.0]; } - (void)mouseDown:(NSEvent *)theEvent { - [(VolumeSlider *)_popView hideToolTip]; - - [super mouseDown:theEvent]; + [_popView hideToolTip]; + [popover showRelativeToRect:self.bounds ofView:self preferredEdge:NSRectEdgeMaxY]; - [(VolumeSlider *)_popView hideToolTip]; + [super mouseDown:theEvent]; } diff --git a/Window/VolumeSlider.m b/Window/VolumeSlider.m index 8523eed9b..b7d9f26aa 100644 --- a/Window/VolumeSlider.m +++ b/Window/VolumeSlider.m @@ -12,6 +12,7 @@ @implementation VolumeSlider { NSTimer *currentTimer; + BOOL wasInsideSnapRange; } - (id)initWithFrame:(NSRect)frame @@ -27,6 +28,7 @@ } - (void) awakeFromNib { + wasInsideSnapRange = NO; textView = [[NSText alloc] init]; [textView setFrame:NSMakeRect(0, 0, 50, 20)]; textView.drawsBackground = NO; @@ -39,7 +41,7 @@ popover = [[NSPopover alloc] init]; popover.contentViewController = viewController; // Don't hide the popover automatically. - popover.behavior = NSPopoverBehaviorApplicationDefined; + popover.behavior = NSPopoverBehaviorTransient; popover.animates = NO; [popover setContentSize:textView.bounds.size]; } @@ -111,9 +113,23 @@ // Snap to 100% if value is close double snapTarget = logarithmicToLinear(100.0); double snapProgress = ([self doubleValue] - snapTarget) / (self.maxValue - self.minValue); + if (fabs(snapProgress) < 0.005) { [self setDoubleValue:snapTarget]; + if (!wasInsideSnapRange) + { + if (@available(macOS 10.11, *)) + { + [[NSHapticFeedbackManager defaultPerformer] performFeedbackPattern:NSHapticFeedbackPatternGeneric + performanceTime:NSHapticFeedbackPerformanceTimeDefault]; + } + } + wasInsideSnapRange = YES; + } + else + { + wasInsideSnapRange = NO; } [self showToolTip];