forked from MonitorControl/MonitorControl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_osd.swift
More file actions
116 lines (101 loc) · 3.82 KB
/
test_osd.swift
File metadata and controls
116 lines (101 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env swift
import Cocoa
// Standalone test — matches the exact rendering from TahoeOSDWindow
let app = NSApplication.shared
app.setActivationPolicy(.accessory)
let w: CGFloat = 36
let h: CGFloat = 200
let cornerRadius: CGFloat = 18
let iconSize: CGFloat = 16
let iconBottomPadding: CGFloat = 10
class FillView: NSView {
override func draw(_ dirtyRect: NSRect) {
NSColor.white.withAlphaComponent(0.8).setFill()
bounds.fill()
}
}
let panel = NSPanel(
contentRect: NSRect(x: 0, y: 0, width: w, height: h),
styleMask: [.borderless, .nonactivatingPanel],
backing: .buffered,
defer: false
)
panel.isOpaque = false
panel.backgroundColor = .clear
panel.level = NSWindow.Level(rawValue: Int(CGShieldingWindowLevel()) + 1)
panel.collectionBehavior = [.canJoinAllSpaces, .stationary, .ignoresCycle]
panel.ignoresMouseEvents = true
panel.hasShadow = true
panel.isReleasedWhenClosed = false
// Container clips everything to pill shape
let containerView = NSView(frame: NSRect(x: 0, y: 0, width: w, height: h))
containerView.wantsLayer = true
containerView.layer?.cornerRadius = cornerRadius
containerView.layer?.masksToBounds = true
containerView.layer?.cornerCurve = .continuous
panel.contentView = containerView
// Background blur
let effectView = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: w, height: h))
effectView.material = .hudWindow
effectView.blendingMode = .behindWindow
effectView.state = .active
effectView.appearance = NSAppearance(named: .darkAqua)
containerView.addSubview(effectView)
// Fill at 60%
let fillView = FillView(frame: NSRect(x: 0, y: 0, width: w, height: h * 0.6))
containerView.addSubview(fillView)
// Icon
let iconView = NSImageView(frame: NSRect(
x: (w - iconSize) / 2,
y: iconBottomPadding,
width: iconSize,
height: iconSize
))
iconView.imageScaling = .scaleProportionallyUpOrDown
iconView.image = NSImage(systemSymbolName: "sun.max.fill", accessibilityDescription: nil)
iconView.contentTintColor = NSColor(white: 0.1, alpha: 0.9)
containerView.addSubview(iconView)
// Position on main screen
if let screen = NSScreen.main {
let vis = screen.visibleFrame
panel.setFrame(NSRect(x: vis.origin.x + 16, y: vis.origin.y + (vis.height - h) / 2, width: w, height: h), display: true)
}
panel.orderFrontRegardless()
panel.alphaValue = 1
print("OSD visible — left side of screen. Watch for 8 seconds.")
// Step through several fill levels
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
print("→ Fill 90%, speaker icon")
NSAnimationContext.runAnimationGroup { ctx in
ctx.duration = 0.3; ctx.allowsImplicitAnimation = true
fillView.animator().frame = NSRect(x: 0, y: 0, width: w, height: h * 0.9)
}
fillView.needsDisplay = true
iconView.image = NSImage(systemSymbolName: "speaker.wave.3.fill", accessibilityDescription: nil)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 4.0) {
print("→ Fill 20%, speaker low icon")
NSAnimationContext.runAnimationGroup { ctx in
ctx.duration = 0.3; ctx.allowsImplicitAnimation = true
fillView.animator().frame = NSRect(x: 0, y: 0, width: w, height: h * 0.2)
}
fillView.needsDisplay = true
iconView.image = NSImage(systemSymbolName: "speaker.wave.1.fill", accessibilityDescription: nil)
iconView.contentTintColor = .white
}
DispatchQueue.main.asyncAfter(deadline: .now() + 6.0) {
print("→ Fill 0%, muted icon")
NSAnimationContext.runAnimationGroup { ctx in
ctx.duration = 0.3; ctx.allowsImplicitAnimation = true
fillView.animator().frame = NSRect(x: 0, y: 0, width: w, height: 0)
}
iconView.image = NSImage(systemSymbolName: "speaker.slash.fill", accessibilityDescription: nil)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 8.0) {
print("→ Fading out")
NSAnimationContext.runAnimationGroup({ ctx in
ctx.duration = 0.35
panel.animator().alphaValue = 0
}, completionHandler: { app.terminate(nil) })
}
app.run()