mirror of
https://github.com/utmapp/UTM.git
synced 2026-10-12 02:24:01 +00:00
vm(iOS): confirm before closing the window of a running VM
On iPad, closing the last window quits the app: the system ends the process about 100 ms after the scene disconnects, so a running VM was lost without any warning. macOS already asks through windowShouldClose. iOS 27 lets a scene ask for confirmation first, so do that for the last interactive window unless the VM is stopped or paused with its state saved. Stop replaces the Close button. There is no Suspend button because the process does not live long enough after the window closes to save the state; a button that started the save was tried and the state was never written. Not available on visionOS, and not needed for UTM Remote where the VM keeps running on the server. Assisted-by: Claude:claude-fable-5-1
This commit is contained in:
@@ -107,6 +107,7 @@ struct VMWindowView: View {
|
||||
#endif
|
||||
}
|
||||
.modifier(VMToolbarOrnamentModifier(state: $state))
|
||||
.modifier(VMWindowCloseConfirmationModifier(isInteractive: isInteractive))
|
||||
.statusBarHidden(true)
|
||||
.alert(item: $state.alert, content: { type in
|
||||
switch type {
|
||||
@@ -319,3 +320,36 @@ private extension View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Asks before the system closes the last window of a running VM, which would end it without saving.
|
||||
private struct VMWindowCloseConfirmationModifier: ViewModifier {
|
||||
let isInteractive: Bool
|
||||
|
||||
@EnvironmentObject private var session: VMSessionState
|
||||
|
||||
private var isLastWindowOfRunningVM: Bool {
|
||||
let externalWindows = session.externalWindowBinding == nil ? 0 : 1
|
||||
// a VM that is still pausing or saving would lose its state as well
|
||||
let isSafeToClose = session.vmState == .stopped || (session.vmState == .paused && session.vm.registryEntry.isSuspended)
|
||||
return isInteractive && !isSafeToClose && session.windows.count - externalWindows <= 1
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
#if os(visionOS) || WITH_REMOTE
|
||||
content
|
||||
#else
|
||||
if #available(iOS 27, *) {
|
||||
content.dismissalConfirmationDialog("This virtual machine is still running.", shouldPresent: isLastWindowOfRunningVM) {
|
||||
Button("Stop", role: .destructive) {
|
||||
session.powerDown()
|
||||
}
|
||||
} message: {
|
||||
Text("Closing the window stops the virtual machine. Any unsaved changes will be lost.")
|
||||
}
|
||||
} else {
|
||||
content
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user