The current multi-window support for iOS uses UIWindowSceneDelegate and
requestSceneSessionActivation() to activate. For visionOS, we can use the
newer SwiftUI APIs with WindowGroups and openWindow(). While this can also
work on newer versions of iOS, for consistency we only use the new APIs on
visionOS.
Using the new APIs allow better handling of window states in visionOS.
Specifically, when we dynamically resize the VM window, the size does not
get saved and restored as the main window size on next launch.
In preparation for multiple-display support, the existing view controller is
decoupled from UTMVirtualMachine and UTMSpiceIO and now interfaces solely
with VMDisplayViewControllerDelegate. This allows us to then wrap the VC into
a UIViewControllerRepresentable and isolate much of the state into
VMWindowState (a single window) and VMSessionState (entire VM). Finally, the
loading screens are re-implemented in SwiftUI.