home(iOS): support multiple sessions
This commit is contained in:
parent
8c88fd9aa7
commit
689367a9c3
|
@ -75,24 +75,6 @@ public extension VMDisplayViewController {
|
|||
func enterLive() {
|
||||
UIApplication.shared.isIdleTimerDisabled = disableIdleTimer
|
||||
}
|
||||
|
||||
private func suspend() {
|
||||
// dummy function for selector
|
||||
}
|
||||
|
||||
func terminateApplication() {
|
||||
DispatchQueue.main.async { [self] in
|
||||
// animate to home screen
|
||||
let app = UIApplication.shared
|
||||
app.performSelector(onMainThread: #selector(suspend), with: nil, waitUntilDone: true)
|
||||
|
||||
// wait 2 seconds while app is going background
|
||||
Thread.sleep(forTimeInterval: 2)
|
||||
|
||||
// exit app when app is in background
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Toolbar hiding
|
||||
|
|
|
@ -19,15 +19,23 @@ import SwiftUI
|
|||
|
||||
extension UTMData {
|
||||
func run(vm: VMData, options: UTMVirtualMachineStartOptions = []) {
|
||||
#if WITH_SOLO_VM
|
||||
guard VMSessionState.allActiveSessions.count == 0 else {
|
||||
logger.error("Session already started")
|
||||
return
|
||||
}
|
||||
#endif
|
||||
guard let wrapped = vm.wrapped else {
|
||||
return
|
||||
}
|
||||
let session = VMSessionState(for: wrapped as! (any UTMSpiceVirtualMachine))
|
||||
session.start()
|
||||
if let session = VMSessionState.allActiveSessions.values.first(where: { $0.vm.id == wrapped.id }) {
|
||||
session.showWindow()
|
||||
} else if vm.state == .stopped {
|
||||
let session = VMSessionState(for: wrapped as! (any UTMSpiceVirtualMachine))
|
||||
session.start()
|
||||
} else {
|
||||
showErrorAlert(message: NSLocalizedString("This virtual machine is already running. In order to run it from this device, you must stop it first.", comment: "UTMDataExtension"))
|
||||
}
|
||||
}
|
||||
|
||||
func stop(vm: VMData) {
|
||||
|
@ -37,6 +45,7 @@ extension UTMData {
|
|||
if wrapped.registryEntry.isSuspended {
|
||||
wrapped.requestVmDeleteState()
|
||||
}
|
||||
wrapped.requestVmStop()
|
||||
}
|
||||
|
||||
func close(vm: VMData) {
|
||||
|
|
|
@ -425,10 +425,14 @@ extension VMSessionState {
|
|||
logger.warning("Error starting audio session: \(error.localizedDescription)")
|
||||
}
|
||||
Self.allActiveSessions[id] = self
|
||||
NotificationCenter.default.post(name: .vmSessionCreated, object: nil, userInfo: ["Session": self])
|
||||
showWindow()
|
||||
vm.requestVmStart(options: options)
|
||||
}
|
||||
|
||||
|
||||
func showWindow() {
|
||||
NotificationCenter.default.post(name: .vmSessionCreated, object: nil, userInfo: ["Session": self])
|
||||
}
|
||||
|
||||
@objc private func suspend() {
|
||||
// dummy function for selector
|
||||
}
|
||||
|
@ -442,7 +446,9 @@ extension VMSessionState {
|
|||
}
|
||||
// tell other screens to shut down
|
||||
Self.allActiveSessions.removeValue(forKey: id)
|
||||
NotificationCenter.default.post(name: .vmSessionEnded, object: nil, userInfo: ["Session": self])
|
||||
closeWindows()
|
||||
|
||||
#if WITH_SOLO_VM
|
||||
// animate to home screen
|
||||
let app = UIApplication.shared
|
||||
app.performSelector(onMainThread: #selector(suspend), with: nil, waitUntilDone: true)
|
||||
|
@ -452,8 +458,13 @@ extension VMSessionState {
|
|||
|
||||
// exit app when app is in background
|
||||
exit(0)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
func closeWindows() {
|
||||
NotificationCenter.default.post(name: .vmSessionEnded, object: nil, userInfo: ["Session": self])
|
||||
}
|
||||
|
||||
func powerDown() {
|
||||
Task {
|
||||
try? await vm.deleteSnapshot(name: nil)
|
||||
|
|
|
@ -43,7 +43,11 @@ struct UTMApp: App {
|
|||
.environmentObject(data)
|
||||
.onReceive(vmSessionCreatedNotification) { output in
|
||||
let newSession = output.userInfo!["Session"] as! VMSessionState
|
||||
openWindow(value: newSession.newWindow())
|
||||
if let window = newSession.windows.first {
|
||||
openWindow(value: window)
|
||||
} else {
|
||||
openWindow(value: newSession.newWindow())
|
||||
}
|
||||
}
|
||||
.onReceive(vmSessionEndedNotification) { output in
|
||||
let endedSession = output.userInfo!["Session"] as! VMSessionState
|
||||
|
@ -58,10 +62,12 @@ struct UTMApp: App {
|
|||
WindowGroup(for: VMSessionState.GlobalWindowID.self) { $globalID in
|
||||
if let globalID = globalID, let session = VMSessionState.allActiveSessions[globalID.sessionID] {
|
||||
VMWindowView(id: globalID.windowID).environmentObject(session)
|
||||
#if WITH_SOLO_VM
|
||||
.onAppear {
|
||||
// currently we only support one session, so close the home window
|
||||
dismissWindow(id: "home")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
.windowResizability(.contentMinSize)
|
||||
|
|
|
@ -91,6 +91,9 @@ final class UTMRemoteSpiceVirtualMachine: UTMSpiceVirtualMachine {
|
|||
}
|
||||
|
||||
didSet {
|
||||
if state == .stopped {
|
||||
virtualMachineDidStop()
|
||||
}
|
||||
delegate?.virtualMachine(self, didTransitionToState: state)
|
||||
}
|
||||
}
|
||||
|
@ -278,6 +281,10 @@ extension UTMRemoteSpiceVirtualMachine {
|
|||
try? await server.sendPackageFile(for: id, relativePathComponents: [kUTMBundleScreenshotFilename], data: data)
|
||||
}
|
||||
}
|
||||
|
||||
private func virtualMachineDidStop() {
|
||||
ioService = nil
|
||||
}
|
||||
}
|
||||
|
||||
extension UTMRemoteSpiceVirtualMachine {
|
||||
|
|
|
@ -4406,6 +4406,7 @@
|
|||
ENABLE_PREVIEWS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"WITH_JIT=1",
|
||||
"WITH_SOLO_VM=1",
|
||||
"WITH_USB=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
|
@ -4420,7 +4421,7 @@
|
|||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "WITH_JIT WITH_USB $(inherited)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "WITH_JIT WITH_SOLO_VM WITH_USB $(inherited)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Services/Swift-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
@ -4440,6 +4441,7 @@
|
|||
ENABLE_PREVIEWS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"WITH_JIT=1",
|
||||
"WITH_SOLO_VM=1",
|
||||
"WITH_USB=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
|
@ -4454,7 +4456,7 @@
|
|||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "WITH_JIT WITH_USB $(inherited)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "WITH_JIT WITH_SOLO_VM WITH_USB $(inherited)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Services/Swift-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
|
@ -4761,6 +4763,7 @@
|
|||
ENABLE_PREVIEWS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"WITH_QEMU_TCI=1",
|
||||
"WITH_SOLO_VM=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = Platform/iOS/Info.plist;
|
||||
|
@ -4776,7 +4779,7 @@
|
|||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "WITH_QEMU_TCI $(inherited)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "WITH_QEMU_TCI WITH_SOLO_VM $(inherited)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Services/Swift-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
@ -4796,6 +4799,7 @@
|
|||
ENABLE_PREVIEWS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"WITH_QEMU_TCI=1",
|
||||
"WITH_SOLO_VM=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = Platform/iOS/Info.plist;
|
||||
|
@ -4811,7 +4815,7 @@
|
|||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "WITH_QEMU_TCI $(inherited)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "WITH_QEMU_TCI WITH_SOLO_VM $(inherited)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Services/Swift-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||
|
|
Loading…
Reference in New Issue