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: - 可复用的播放器内容视图(主窗口和全屏共用)
|
// MARK: - 可复用的播放器内容视图(主窗口和全屏共用)
|
||||||
struct PlayerContentView: View {
|
struct PlayerContentView: View {
|
||||||
@ObservedObject var bridge: PlayerBridge
|
@ObservedObject var bridge: PlayerBridge
|
||||||
@ -327,9 +375,9 @@ struct PlayerContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onHover { hovering in
|
.background(MouseTrackingArea(onHoverChange: { hovering in
|
||||||
setWindowTitleBarVisible(hovering)
|
setWindowTitleBarVisible(hovering)
|
||||||
}
|
}))
|
||||||
.onAppear {
|
.onAppear {
|
||||||
// 初始状态:标题栏完全隐藏(含红绿灯按钮)
|
// 初始状态:标题栏完全隐藏(含红绿灯按钮)
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user