| index 5ce2c9c..add0cb4 100644 |
| --- a/native/apple/Sources/CallsInterop/CallSnapshots.swift |
| +++ b/native/apple/Sources/CallsInterop/CallSnapshots.swift |
| @@ -52,4 +52,83 @@ import SwiftUI |
| try await shot("contrast-busy-hidden", .focus, shown: false, backdrop: .busy) |
| } |
| } |
| + |
| + /// The glass and the glow as the window server draws them (0.3.7). An |
| + /// off-screen bitmap has no Liquid Glass and no backdrop to blur, so |
| + /// these are real windows, parked below the desktop where nobody sees |
| + /// them, and captured by `screencapture -l`: the control bar over black, |
| + /// white and a busy frame, in glass and in the material older systems |
| + /// draw; the Devices panel; the names glowing at four levels; the tab. |
| + static func saveGlass(to folder: URL) async throws { |
| + NSApplication.shared.setActivationPolicy(.prohibited) |
| + try FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true) |
| + let size = CGSize(width: 1000, height: 640) |
| + func shot( |
| + _ name: String, _ fixture: CallFixture, grid: Bool = false, devices: Bool = false, |
| + glass: Bool = true, backdrop: FixtureBackdrop? = nil, me: FixtureSelf? = nil, |
| + speaking: FixtureSpeaking? = nil |
| + ) async throws { |
| + let call = Call(playAudio: false) |
| + fixture.apply(to: call) |
| + me?.apply(to: call) |
| + speaking?.apply(to: call) |
| + try await renderLive( |
| + MacCallView( |
| + call: call, grid: grid, showingDevices: devices, style: .fullWindow, |
| + controlsShown: true, leave: {}, rejoin: {} |
| + ) |
| + .tint(CallsAppearance.accent) |
| + .environment(\.fixtureBackdrop, backdrop) |
| + .environment(\.callOverlayGlass, glass), |
| + size: size, to: folder.appendingPathComponent("mac-\(name).png")) |
| + } |
| + for glass in [true, false] { |
| + let kind = glass ? "glass" : "fallback" |
| + for backdrop in FixtureBackdrop.allCases { |
| + try await shot("bar-\(kind)-\(backdrop.rawValue)", .focus, glass: glass, backdrop: backdrop) |
| + } |
| + try await shot("bar-\(kind)-busy-muted", .focus, glass: glass, backdrop: .busy, me: .muted) |
| + try await shot("bar-\(kind)-busy-sharing", .focus, glass: glass, backdrop: .busy, me: .sharing) |
| + try await shot("devices-\(kind)", .focus, devices: true, glass: glass, backdrop: .busy) |
| + } |
| + for level in FixtureSpeaking.allCases { |
| + try await shot("glow-\(level.rawValue)", .grid, grid: true, speaking: level) |
| + try await shot("glow-focus-\(level.rawValue)", .focus, speaking: level) |
| + } |
| + for level in [FixtureSpeaking.silent, .high] { |
| + let call = Call(playAudio: false) |
| + CallFixture.focus.apply(to: call) |
| + level.apply(to: call) |
| + try await renderLive( |
| + ZStack { |
| + FixtureBackdrop.busy.view |
| + MiniWindowSnapshot.tab(call: call) |
| + }, |
| + size: CGSize(width: MiniWindowTab.size.width + 40, height: MiniWindowTab.size.height + 40), |
| + to: folder.appendingPathComponent("mac-tab-\(level.rawValue).png")) |
| + } |
| + } |
| + |
| + /// A real window below the desktop, captured by the window server. |
| + static func renderLive(_ content: some View, size: CGSize, to file: URL) async throws { |
| + let view = NSHostingView(rootView: content.environment(\.colorScheme, .dark)) |
| + view.frame.size = size |
| + let window = NSWindow( |
| + contentRect: NSRect(origin: CGPoint(x: 0, y: 0), size: size), |
| + styleMask: [.borderless], backing: .buffered, defer: false) |
| + window.isReleasedWhenClosed = false |
| + window.level = NSWindow.Level(rawValue: Int(CGWindowLevelForKey(.desktopWindow)) - 1) |
| + window.appearance = NSAppearance(named: .darkAqua) |
| + window.contentView = view |
| + window.orderBack(nil) |
| + try await Task.sleep(for: .milliseconds(600)) |
| + view.layoutSubtreeIfNeeded() |
| + let capture = Process() |
| + capture.executableURL = URL(fileURLWithPath: "/usr/sbin/screencapture") |
| + capture.arguments = ["-x", "-o", "-l", String(window.windowNumber), file.path] |
| + try capture.run() |
| + capture.waitUntilExit() |
| + window.close() |
| + guard capture.terminationStatus == 0 else { throw CocoaError(.fileWriteUnknown) } |
| + } |
| } |