fix: 用 NSTrackingArea 替代 .onHover 解决标题栏闪烁和红绿灯丢失问题
.onHover 在 macOS 上不可靠,鼠标离开后会误触发 true 导致标题栏短暂回来但没有红绿灯按钮。 改用 NSTrackingArea 的 mouseEntered/mouseExited 做可靠的鼠标追踪。
This commit is contained in:
parent
ec8c3bd51c
commit
fde83a87bc
@ -223,6 +223,54 @@ class PlayerLayerHostView: NSView {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 可靠的鼠标追踪(替代 SwiftUI .onHover 的不可靠行为)
|
||||
struct MouseTrackingArea: NSViewRepresentable {
|
||||
let onHoverChange: @MainActor (Bool) -> Void
|
||||
|
||||
func makeNSView(context: Context) -> MouseTrackingNSView {
|
||||
let view = MouseTrackingNSView()
|
||||
view.onHoverChange = onHoverChange
|
||||
return view
|
||||
}
|
||||
|
||||
func updateNSView(_ nsView: MouseTrackingNSView, context: Context) {
|
||||
nsView.onHoverChange = onHoverChange
|
||||
}
|
||||
}
|
||||
|
||||
class MouseTrackingNSView: NSView {
|
||||
var onHoverChange: (@MainActor (Bool) -> Void)?
|
||||
private var trackingArea: NSTrackingArea?
|
||||
private var isHovering = false
|
||||
|
||||
override func updateTrackingAreas() {
|
||||
super.updateTrackingAreas()
|
||||
if let existing = trackingArea {
|
||||
removeTrackingArea(existing)
|
||||
}
|
||||
let area = NSTrackingArea(
|
||||
rect: .zero,
|
||||
options: [.mouseEnteredAndExited, .activeInKeyWindow, .inVisibleRect],
|
||||
owner: self,
|
||||
userInfo: nil
|
||||
)
|
||||
addTrackingArea(area)
|
||||
trackingArea = area
|
||||
}
|
||||
|
||||
override func mouseEntered(with event: NSEvent) {
|
||||
guard !isHovering else { return }
|
||||
isHovering = true
|
||||
onHoverChange?(true)
|
||||
}
|
||||
|
||||
override func mouseExited(with event: NSEvent) {
|
||||
guard isHovering else { return }
|
||||
isHovering = false
|
||||
onHoverChange?(false)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 可复用的播放器内容视图(主窗口和全屏共用)
|
||||
struct PlayerContentView: View {
|
||||
@ObservedObject var bridge: PlayerBridge
|
||||
@ -327,9 +375,9 @@ struct PlayerContentView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.onHover { hovering in
|
||||
.background(MouseTrackingArea(onHoverChange: { hovering in
|
||||
setWindowTitleBarVisible(hovering)
|
||||
}
|
||||
}))
|
||||
.onAppear {
|
||||
// 初始状态:标题栏完全隐藏(含红绿灯按钮)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user