diff --git a/Sources/tart/Commands/Run.swift b/Sources/tart/Commands/Run.swift index 2dae4769..cebad860 100644 --- a/Sources/tart/Commands/Run.swift +++ b/Sources/tart/Commands/Run.swift @@ -229,7 +229,7 @@ struct Run: AsyncParsableCommand { if suspendable { let config = try VMConfig.init(fromURL: vmDir.configURL) - if (config.platform is Linux) { + if !(config.platform is PlatformSuspendable) { throw ValidationError("You can only suspend macOS VMs") } if dir.count > 0 { diff --git a/Sources/tart/Platform/Darwin.swift b/Sources/tart/Platform/Darwin.swift index 73d24cb0..f765864b 100644 --- a/Sources/tart/Platform/Darwin.swift +++ b/Sources/tart/Platform/Darwin.swift @@ -8,7 +8,7 @@ struct UnsupportedHostOSError: Error, CustomStringConvertible { #if arch(arm64) - struct Darwin: Platform { + struct Darwin: PlatformSuspendable { var ecid: VZMacMachineIdentifier var hardwareModel: VZMacHardwareModel @@ -103,18 +103,32 @@ struct UnsupportedHostOSError: Error, CustomStringConvertible { func keyboards() -> [VZKeyboardConfiguration] { if #available(macOS 14, *) { // Mac keyboard is only supported by guests starting with macOS Ventura - return [VZMacKeyboardConfiguration()] + return [VZUSBKeyboardConfiguration(), VZMacKeyboardConfiguration()] } else { return [VZUSBKeyboardConfiguration()] } } + func keyboardsSuspendable() -> [VZKeyboardConfiguration] { + if #available(macOS 14, *) { + return [VZMacKeyboardConfiguration()] + } else { + // fallback to the regular configuration + return keyboards() + } + } + func pointingDevices() -> [VZPointingDeviceConfiguration] { - if #available(macOS 13, *) { + // Trackpad is only supported by guests starting with macOS Ventura + [VZUSBScreenCoordinatePointingDeviceConfiguration(), VZMacTrackpadConfiguration()] + } + + func pointingDevicesSuspendable() -> [VZPointingDeviceConfiguration] { + if #available(macOS 14, *) { return [VZMacTrackpadConfiguration()] } else { // fallback to the regular configuration - return [VZUSBScreenCoordinatePointingDeviceConfiguration()] + return pointingDevices() } } } diff --git a/Sources/tart/Platform/Platform.swift b/Sources/tart/Platform/Platform.swift index 9b8c04e5..e8627818 100644 --- a/Sources/tart/Platform/Platform.swift +++ b/Sources/tart/Platform/Platform.swift @@ -8,3 +8,8 @@ protocol Platform: Codable { func keyboards() -> [VZKeyboardConfiguration] func pointingDevices() -> [VZPointingDeviceConfiguration] } + +protocol PlatformSuspendable: Platform { + func pointingDevicesSuspendable() -> [VZPointingDeviceConfiguration] + func keyboardsSuspendable() -> [VZKeyboardConfiguration] +} diff --git a/Sources/tart/VM.swift b/Sources/tart/VM.swift index cf62fb16..ba3e8fac 100644 --- a/Sources/tart/VM.swift +++ b/Sources/tart/VM.swift @@ -329,8 +329,13 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject { configuration.audioDevices = [soundDeviceConfiguration] // Keyboard and mouse - configuration.keyboards = vmConfig.platform.keyboards() - configuration.pointingDevices = vmConfig.platform.pointingDevices() + if suspendable, let platformSuspendable = vmConfig.platform.self as? PlatformSuspendable { + configuration.keyboards = platformSuspendable.keyboardsSuspendable() + configuration.pointingDevices = platformSuspendable.pointingDevicesSuspendable() + } else { + configuration.keyboards = vmConfig.platform.keyboards() + configuration.pointingDevices = vmConfig.platform.pointingDevices() + } // Networking configuration.networkDevices = network.attachments().map {