diff --git a/MonitorControl/Info.plist b/MonitorControl/Info.plist index e06e3af..11fd03d 100644 --- a/MonitorControl/Info.plist +++ b/MonitorControl/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 7176 + 7182 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/MonitorControl/Support/MenuHandler.swift b/MonitorControl/Support/MenuHandler.swift index baebdc1..27a5728 100644 --- a/MonitorControl/Support/MenuHandler.swift +++ b/MonitorControl/Support/MenuHandler.swift @@ -103,19 +103,54 @@ class MenuHandler: NSMenu, NSMenuDelegate { func addDisplayMenuBlock(addedSliderHandlers: [SliderHandler], blockName: String, monitorSubMenu: NSMenu, numOfDisplays: Int, asSubMenu: Bool) { if numOfDisplays > 1, prefs.integer(forKey: PrefKey.multiSliders.rawValue) != MultiSliders.relevant.rawValue, !DEBUG_MACOS10, #available(macOS 11.0, *) { + /// Draws the original soft outer rings + inner edge; layered on top of `NSVisualEffectView` (which does not reliably call `draw(_:)`). + class BlockBorderOverlayView: NSView { + override var isOpaque: Bool { false } + + override func viewDidChangeEffectiveAppearance() { + super.viewDidChangeEffectiveAppearance() + self.needsDisplay = true + } + + override func draw(_ dirtyRect: NSRect) { + let radius = prefs.bool(forKey: PrefKey.showTickMarks.rawValue) ? CGFloat(4) : CGFloat(11) + let outerMargin = CGFloat(15) + let blockRect = self.bounds.insetBy(dx: outerMargin, dy: outerMargin / 2 + 2).offsetBy(dx: 0, dy: outerMargin / 2 * -1 + 7) + for i in 1 ... 5 { + let blockPath = NSBezierPath(roundedRect: blockRect.insetBy(dx: CGFloat(i) * -1, dy: CGFloat(i) * -1), xRadius: radius + CGFloat(i) * 0.5, yRadius: radius + CGFloat(i) * 0.5) + NSColor.black.withAlphaComponent(0.1 / CGFloat(i)).setStroke() + blockPath.lineWidth = 1 + blockPath.stroke() + } + let blockPath = NSBezierPath(roundedRect: blockRect, xRadius: radius, yRadius: radius) + if [NSAppearance.Name.darkAqua, NSAppearance.Name.vibrantDark].contains(self.effectiveAppearance.name) { + NSColor.systemGray.withAlphaComponent(0.3).setStroke() + blockPath.lineWidth = 1 + blockPath.stroke() + } else { + // With `NSVisualEffectView` behind, skip the old semi-opaque white fill so the material shows; keep a clear inner edge. + NSColor.separatorColor.withAlphaComponent(0.45).setStroke() + blockPath.lineWidth = 1 + blockPath.stroke() + } + } + } + class BlockView: NSVisualEffectView { override init(frame frameRect: NSRect) { super.init(frame: frameRect) - self.material = .popover - self.blendingMode = .behindWindow + // Match the surrounding NSMenu chrome (display name row above, etc.); `.popover` reads as a different panel. + self.material = .menu + self.blendingMode = .withinWindow self.state = .active self.isEmphasized = false self.wantsLayer = true let tickMarks = prefs.bool(forKey: PrefKey.showTickMarks.rawValue) self.layer?.cornerRadius = tickMarks ? CGFloat(10) : CGFloat(14) self.layer?.masksToBounds = true - self.layer?.borderWidth = 0.5 - self.layer?.borderColor = NSColor.separatorColor.withAlphaComponent(0.45).cgColor + let borderOverlay = BlockBorderOverlayView(frame: self.bounds) + borderOverlay.autoresizingMask = [.width, .height] + self.addSubview(borderOverlay) } @available(*, unavailable) diff --git a/MonitorControlHelper/Info.plist b/MonitorControlHelper/Info.plist index 1c04b68..5af0012 100644 --- a/MonitorControlHelper/Info.plist +++ b/MonitorControlHelper/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 7176 + 7182 LSApplicationCategoryType public.app-category.utilities LSBackgroundOnly