@@ -15,18 +15,17 @@ enum ScreenCaptureBackend: String, Equatable, CustomStringConvertible {
1515 }
1616}
1717
18+ struct ScreenCaptureCLIArguments {
19+ static func selectionArguments( outputURL: URL ) -> [ String ] {
20+ [ " -i " , " -s " , " -x " , " -t " , " png " , outputURL. path]
21+ }
22+ }
23+
1824struct ScreenCaptureStrategy {
1925 static func preferred(
2026 for version: OperatingSystemVersion = ProcessInfo . processInfo. operatingSystemVersion
2127 ) -> ScreenCaptureBackend {
22- if version. majorVersion > 15 {
23- return . nativeRegionSelection
24- }
25-
26- if version. majorVersion == 15 && version. minorVersion >= 2 {
27- return . nativeRegionSelection
28- }
29-
28+ _ = version
3029 return . legacyScreencaptureCLI
3130 }
3231}
@@ -37,17 +36,7 @@ final class ScreenCaptureService {
3736 private let selector = ScreenRegionSelector ( )
3837
3938 func captureSelectionImage( ) async -> NSImage ? {
40- switch ScreenCaptureStrategy . preferred ( ) {
41- case . nativeRegionSelection:
42- if #available( macOS 15 . 2 , * ) {
43- return await captureWithNativeRegionSelection ( )
44- }
45-
46- Logger . log ( . error, " Native region capture was selected on an unsupported macOS version " )
47- return await captureWithLegacyCLI ( )
48- case . legacyScreencaptureCLI:
49- return await captureWithLegacyCLI ( )
50- }
39+ return await captureWithLegacyCLI ( )
5140 }
5241
5342 @available ( macOS 15 . 2 , * )
@@ -72,28 +61,39 @@ final class ScreenCaptureService {
7261 }
7362
7463 private func captureWithLegacyCLI( ) async -> NSImage ? {
75- let initialChangeCount = NSPasteboard . general. changeCount
64+ let outputURL = FileManager . default. temporaryDirectory
65+ . appendingPathComponent ( " screenscribe- \( UUID ( ) . uuidString) " )
66+ . appendingPathExtension ( " png " )
7667
7768 return await withCheckedContinuation { ( continuation: CheckedContinuation < NSImage ? , Never > ) in
7869 let task = Process ( )
7970 task. executableURL = URL ( fileURLWithPath: " /usr/sbin/screencapture " )
80- task. arguments = [ " -i " , " -c " , " -x " ]
81- task. terminationHandler = { _ in
71+ task. arguments = ScreenCaptureCLIArguments . selectionArguments ( outputURL : outputURL )
72+ task. terminationHandler = { process in
8273 DispatchQueue . main. async {
83- let pasteboard = NSPasteboard . general
84- guard pasteboard. changeCount != initialChangeCount else {
74+ defer {
75+ try ? FileManager . default. removeItem ( at: outputURL)
76+ }
77+
78+ guard process. terminationStatus == 0 else {
79+ continuation. resume ( returning: nil )
80+ return
81+ }
82+
83+ guard let data = try ? Data ( contentsOf: outputURL) else {
8584 continuation. resume ( returning: nil )
8685 return
8786 }
8887
89- continuation. resume ( returning: Self . pasteboardImage ( from : pasteboard ) )
88+ continuation. resume ( returning: NSImage ( data : data ) )
9089 }
9190 }
9291
9392 do {
9493 try task. run ( )
9594 } catch {
9695 Logger . log ( . error, " Legacy screencapture launch failed: \( error. localizedDescription) " )
96+ try ? FileManager . default. removeItem ( at: outputURL)
9797 continuation. resume ( returning: nil )
9898 }
9999 }
@@ -118,19 +118,6 @@ final class ScreenCaptureService {
118118 }
119119 }
120120
121- private static func pasteboardImage( from pasteboard: NSPasteboard ) -> NSImage ? {
122- if let data = pasteboard. data ( forType: . fileURL) ,
123- let string = String ( data: data, encoding: . utf8) ,
124- let url = URL ( string: string) {
125- return NSImage ( contentsOf: url)
126- }
127-
128- if let data = pasteboard. data ( forType: . tiff) ?? pasteboard. data ( forType: . png) {
129- return NSImage ( data: data)
130- }
131-
132- return ( pasteboard. readObjects ( forClasses: [ NSImage . self] ) as? [ NSImage ] ) ? . first
133- }
134121}
135122
136123private enum ScreenCaptureServiceError : LocalizedError {
0 commit comments