70 lines
1.9 KiB
Swift
70 lines
1.9 KiB
Swift
import LumaCore
|
|
import SwiftUI
|
|
|
|
#if canImport(Virtualization)
|
|
import Virtualization
|
|
|
|
#if canImport(AppKit)
|
|
#endif
|
|
|
|
/// Whichever way a machine offers its display: pixels the host draws, or a
|
|
/// layer the host adopts.
|
|
struct VirtualMachineDisplayView: View {
|
|
let display: VirtualMachineDisplay
|
|
var capturing: PointerCapturePolicy = .onClick
|
|
var dismissal: String? = nil
|
|
|
|
var body: some View {
|
|
screen
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var screen: some View {
|
|
switch display {
|
|
case .frames(let source):
|
|
VirtualMachineScreen(source: source, capturing: capturing, dismissal: dismissal)
|
|
.aspectRatio(source.aspectRatio, contentMode: .fit)
|
|
|
|
case .hostedWindow(let source):
|
|
hosted(source)
|
|
|
|
#if canImport(Virtualization)
|
|
case .virtualizationGuest(let guest):
|
|
VirtualizationScreen(guest: guest)
|
|
.aspectRatio(16.0 / 10.0, contentMode: .fit)
|
|
#endif
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private func hosted(_ source: any VirtualMachineWindowSource) -> some View {
|
|
#if canImport(AppKit)
|
|
VirtualMachineWindowPlacement(source: source)
|
|
.aspectRatio(CGFloat(source.pixelWidth) / CGFloat(source.pixelHeight), contentMode: .fit)
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
#if canImport(Virtualization) && canImport(AppKit)
|
|
/// Virtualization.framework draws its own guest, and takes the keyboard and
|
|
/// pointer with it, so the host only has to give it somewhere to appear.
|
|
@available(macOS 13, *)
|
|
struct VirtualizationScreen: PlatformViewRepresentable {
|
|
let guest: VZVirtualMachine
|
|
|
|
func makeNSView(context: Context) -> VZVirtualMachineView {
|
|
let view = VZVirtualMachineView()
|
|
view.capturesSystemKeys = true
|
|
view.virtualMachine = guest
|
|
return view
|
|
}
|
|
|
|
func updateNSView(_ view: VZVirtualMachineView, context: Context) {
|
|
view.virtualMachine = guest
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#endif
|