fix: match progress slider dragging to visible thumb

The 3-point progress thumb was drawn inside larger native knob bounds. Override those bounds for progress only so adjacent clicks seek; retain native volume geometry and tracking. Native click regression reproduced before the fix and passes afterward.
This commit is contained in:
2026-10-22 12:12:22 +02:00
parent 80c5f36479
commit dea8880b9b
3 changed files with 43 additions and 4 deletions
+40 -3
View File
@@ -2005,6 +2005,11 @@ private struct PlaybackSlider: NSViewRepresentable {
var volume = false
var bufferedRange: ClosedRange<Double>?
var intervals: [MiruroInterval] = []
override func knobRect(flipped: Bool) -> NSRect {
let rect = super.knobRect(flipped: flipped)
guard !volume else { return rect }
return NSRect(x: rect.midX - 1.5, y: rect.midY - 7.5, width: 3, height: 15)
}
override func drawBar(inside rect: NSRect, flipped: Bool) {
let bar = NSRect(x: rect.minX + knobThickness / 2, y: rect.midY - 1.5,
width: max(0, rect.width - knobThickness), height: 3)
@@ -2046,9 +2051,9 @@ private struct PlaybackSlider: NSViewRepresentable {
}
}
override func drawKnob(_ rect: NSRect) {
let width: CGFloat = volume ? 16 : 3
let height: CGFloat = volume ? 12 : 15
let knob = NSRect(x: rect.midX - width / 2, y: rect.midY - height / 2, width: width, height: height)
let knob = volume
? NSRect(x: rect.midX - 8, y: rect.midY - 6, width: 16, height: 12)
: rect
let color = isEnabled ? (volume ? SunsetPalette.text : SunsetPalette.secondaryText)
: SunsetPalette.disabledThumb
color.setFill()
@@ -2060,6 +2065,38 @@ private struct PlaybackSlider: NSViewRepresentable {
#if PLAYER_CHECK
@MainActor
func castVolumeSliderFeedbackCheck() -> Bool { PlaybackSlider.Slider.feedbackCheck() }
@MainActor
func playbackSliderHitCheck() -> Bool {
let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 320, height: 80),
styleMask: [.borderless], backing: .buffered, defer: false)
let slider = PlaybackSlider.Slider(frame: NSRect(x: 20, y: 20, width: 280, height: 24))
slider.cell = PlaybackSlider.Cell()
slider.minValue = 0
slider.maxValue = 100
slider.isContinuous = true
window.contentView!.addSubview(slider)
window.display()
for offset: CGFloat in [-4, -2, -1, 0, 1, 2, 4] {
slider.doubleValue = 50
let cell = slider.cell as! NSSliderCell
let knob = cell.knobRect(flipped: slider.isFlipped)
let point = slider.convert(NSPoint(x: knob.midX + offset, y: knob.midY), to: nil)
let up = NSEvent.mouseEvent(with: .leftMouseUp, location: point, modifierFlags: [],
timestamp: 0, windowNumber: window.windowNumber, context: nil,
eventNumber: 1, clickCount: 1, pressure: 0)!
let down = NSEvent.mouseEvent(with: .leftMouseDown, location: point, modifierFlags: [],
timestamp: 0, windowNumber: window.windowNumber, context: nil,
eventNumber: 0, clickCount: 1, pressure: 1)!
NSApp.postEvent(up, atStart: true)
slider.mouseDown(with: down)
if abs(offset) <= 1 {
guard slider.doubleValue == 50 else { return false }
} else {
guard (slider.doubleValue - 50) * offset > 0 else { return false }
}
}
return true
}
#endif
@MainActor