2
0
Эх сурвалжийг харах

vm(apple): support taking screenshots

osy 3 жил өмнө
parent
commit
15aa37a17d

+ 10 - 0
Managers/UTMAppleVirtualMachine.swift

@@ -70,6 +70,8 @@ import Virtualization
     
     
     private var sharedDirectoriesChanged: AnyCancellable?
     private var sharedDirectoriesChanged: AnyCancellable?
     
     
+    weak var screenshotDelegate: UTMScreenshotProvider?
+    
     override static func isAppleVM(forPath path: URL) -> Bool {
     override static func isAppleVM(forPath path: URL) -> Bool {
         do {
         do {
             _ = try UTMAppleConfiguration.load(from: path)
             _ = try UTMAppleConfiguration.load(from: path)
@@ -201,6 +203,10 @@ import Virtualization
         }
         }
         changeState(.vmPausing)
         changeState(.vmPausing)
         vmQueue.async {
         vmQueue.async {
+            DispatchQueue.main.sync {
+                self.screenshot = self.screenshotDelegate?.screenshot
+            }
+            self.saveScreenshot()
             self.apple.pause { result in
             self.apple.pause { result in
                 switch result {
                 switch result {
                 case .failure(let error):
                 case .failure(let error):
@@ -376,3 +382,7 @@ extension UTMAppleVirtualMachine: VZVirtualMachineDelegate {
         errorTriggered(error.localizedDescription)
         errorTriggered(error.localizedDescription)
     }
     }
 }
 }
+
+protocol UTMScreenshotProvider: AnyObject {
+    var screenshot: CSScreenshot? { get }
+}

+ 0 - 3
Managers/UTMVirtualMachine-Private.h

@@ -37,9 +37,6 @@ NS_ASSUME_NONNULL_BEGIN
 - (void)restoreViewState;
 - (void)restoreViewState;
 - (void)loadViewState;
 - (void)loadViewState;
 - (void)saveViewState;
 - (void)saveViewState;
-- (void)loadScreenshot;
-- (void)saveScreenshot;
-- (void)deleteScreenshot;
 
 
 @end
 @end
 
 

+ 4 - 0
Managers/UTMVirtualMachine-Protected.h

@@ -45,6 +45,10 @@ extern NSString *const kUTMBundleConfigFilename;
 
 
 - (BOOL)loadConfigurationWithReload:(BOOL)reload error:(NSError * _Nullable __autoreleasing *)err;
 - (BOOL)loadConfigurationWithReload:(BOOL)reload error:(NSError * _Nullable __autoreleasing *)err;
 
 
+- (void)loadScreenshot;
+- (void)saveScreenshot;
+- (void)deleteScreenshot;
+
 @end
 @end
 
 
 NS_ASSUME_NONNULL_END
 NS_ASSUME_NONNULL_END

+ 24 - 0
Platform/macOS/Display/VMDisplayAppleWindowController.swift

@@ -65,6 +65,7 @@ class VMDisplayAppleWindowController: VMDisplayWindowController {
         mainView!.translatesAutoresizingMaskIntoConstraints = false
         mainView!.translatesAutoresizingMaskIntoConstraints = false
         displayView.addSubview(mainView!)
         displayView.addSubview(mainView!)
         NSLayoutConstraint.activate(mainView!.constraintsForAnchoringTo(boundsOf: displayView))
         NSLayoutConstraint.activate(mainView!.constraintsForAnchoringTo(boundsOf: displayView))
+        appleVM.screenshotDelegate = self
         window!.recalculateKeyViewLoop()
         window!.recalculateKeyViewLoop()
         if #available(macOS 12, *) {
         if #available(macOS 12, *) {
             shouldAutoStartVM = appleConfig.macRecoveryIpswURL == nil
             shouldAutoStartVM = appleConfig.macRecoveryIpswURL == nil
@@ -342,6 +343,17 @@ extension VMDisplayAppleWindowController: TerminalViewDelegate, UTMSerialPortDel
     }
     }
 }
 }
 
 
+@available(macOS 11, *)
+extension VMDisplayAppleWindowController: UTMScreenshotProvider {
+    var screenshot: CSScreenshot? {
+        if let image = mainView?.image() {
+            return CSScreenshot(image: image)
+        } else {
+            return nil
+        }
+    }
+}
+
 // https://www.avanderlee.com/swift/auto-layout-programmatically/
 // https://www.avanderlee.com/swift/auto-layout-programmatically/
 fileprivate extension NSView {
 fileprivate extension NSView {
     /// Returns a collection of constraints to anchor the bounds of the current view to the given view.
     /// Returns a collection of constraints to anchor the bounds of the current view to the given view.
@@ -357,3 +369,15 @@ fileprivate extension NSView {
         ]
         ]
     }
     }
 }
 }
+
+// https://stackoverflow.com/a/41387514/13914748
+fileprivate extension NSView {
+    /// Get `NSImage` representation of the view.
+    ///
+    /// - Returns: `NSImage` of view
+    func image() -> NSImage {
+        let imageRepresentation = bitmapImageRepForCachingDisplay(in: bounds)!
+        cacheDisplay(in: bounds, to: imageRepresentation)
+        return NSImage(cgImage: imageRepresentation.cgImage!, size: bounds.size)
+    }
+}