fix: restore window and keyboard interactions with queue

This commit is contained in:
2026-10-18 01:51:51 +02:00
parent afb0c30e09
commit 07243f0ed7
6 changed files with 279 additions and 39 deletions
+49 -33
View File
@@ -1809,14 +1809,6 @@ private struct PlaybackSlider: NSViewRepresentable {
func castVolumeSliderFeedbackCheck() -> Bool { PlaybackSlider.Slider.feedbackCheck() }
#endif
@MainActor
private struct VideoSurface: NSViewRepresentable {
let view: NSView
func makeNSView(context: Context) -> NSView { view }
func updateNSView(_ nsView: NSView, context: Context) {}
}
@MainActor
private struct CaptionSelector: NSViewRepresentable {
let model: PlayerModel
@@ -1888,22 +1880,46 @@ private struct CaptionSelector: NSViewRepresentable {
}
@MainActor
private struct CompactDragSurface: NSViewRepresentable {
struct PlaybackSurface: NSViewRepresentable {
let model: PlayerModel
func makeNSView(context: Context) -> DragView { DragView(model: model) }
func updateNSView(_ view: DragView, context: Context) {}
func updateNSView(_ view: DragView, context: Context) { view.updateVideo() }
final class DragView: NSView {
private let model: PlayerModel
private var hoverTracking: NSTrackingArea?
private var mouseDownEvent: NSEvent?
init(model: PlayerModel) {
self.model = model
super.init(frame: .zero)
identifier = NSUserInterfaceItemIdentifier("PlaybackSurface")
if let video = model.videoView {
video.frame = bounds
video.autoresizingMask = [.width, .height]
addSubview(video)
}
updateVideo()
}
required init?(coder: NSCoder) { nil }
func updateVideo() {
model.videoView?.isHidden = model.fileName == nil || model.castDevice != nil
}
override var mouseDownCanMoveWindow: Bool { false }
override func hitTest(_ point: NSPoint) -> NSView? {
guard super.hitTest(point) != nil else { return nil }
// Leave the outer native resize border alone, not the internal queue boundary.
if let content = window?.contentView,
!content.bounds.insetBy(dx: 5, dy: 5).contains(content.convert(point, from: superview)) {
return nil
}
return self
}
override func updateTrackingAreas() {
super.updateTrackingAreas()
if let hoverTracking { removeTrackingArea(hoverTracking) }
@@ -1916,18 +1932,33 @@ private struct CompactDragSurface: NSViewRepresentable {
override func mouseEntered(with event: NSEvent) { model.revealControls() }
override func mouseMoved(with event: NSEvent) { model.revealControls() }
override func mouseExited(with event: NSEvent) { model.hideControls(hideCursor: false) }
override func mouseExited(with event: NSEvent) {
if model.isCompact { model.hideControls(hideCursor: false) }
}
override func mouseDown(with event: NSEvent) {
mouseDownEvent = nil
if event.clickCount == 2 {
model.toggleCompact()
return
if model.isCompact { model.toggleCompact() } else { model.toggleFullScreen() }
} else {
mouseDownEvent = event
}
}
override func mouseDragged(with event: NSEvent) {
guard let down = mouseDownEvent, let window else { return }
mouseDownEvent = nil
model.setControlsDragging(true)
window?.performDrag(with: event)
model.compactWindow.snapAfterDrag()
window.performDrag(with: down)
if model.isCompact { model.compactWindow.snapAfterDrag() }
model.setControlsDragging(false)
}
override func mouseUp(with event: NSEvent) {
guard mouseDownEvent != nil else { return }
mouseDownEvent = nil
if !model.isCompact { model.hideControls() }
}
}
}
@@ -2350,18 +2381,8 @@ private struct PlayerContent: View {
} else {
Color.black
}
if let view = model.videoView {
VideoSurface(view: view)
.accessibilityLabel("Video")
.opacity(model.fileName == nil || model.castDevice != nil ? 0 : 1)
.gesture(
TapGesture(count: 2).onEnded { model.toggleFullScreen() }
.exclusively(before: TapGesture().onEnded { model.hideControls() })
)
}
if model.isCompact {
CompactDragSurface(model: model).accessibilityHidden(true)
}
PlaybackSurface(model: model)
.accessibilityLabel("Video")
if !model.subtitleText.isEmpty {
Text(model.subtitleText)
.font(.system(size: max(16, min(28, geometry.size.width / 32)), weight: .semibold))
@@ -2703,12 +2724,7 @@ private struct WindowChrome: NSViewRepresentable {
}
}
override func mouseDown(with event: NSEvent) {
model.setControlsDragging(true)
window?.performDrag(with: event)
model.compactWindow.snapAfterDrag()
model.setControlsDragging(false)
}
override func hitTest(_ point: NSPoint) -> NSView? { nil }
func detach() {
if let monitor { NSEvent.removeMonitor(monitor) }