From: Tim Clem tclem@codeweavers.com
The CG methods for capturing screen contents are deprecated and trigger a permissions prompt in Sequoia. ScreenCaptureKit's shareable content APIs are the replacement, and particularly -getCurrentProcessShareableContentWithCompletionHandler: does not require any permissions for capturing images within the same app.
See 496b001ae0b for why we have to do this manually in the first place. --- configure.ac | 4 ++ dlls/winemac.drv/Makefile.in | 3 +- dlls/winemac.drv/cocoa_window.m | 94 ++++++++++++++++++++++++++++++--- 3 files changed, 93 insertions(+), 8 deletions(-)
diff --git a/configure.ac b/configure.ac index 7fe5477daf7..75d5f937acf 100644 --- a/configure.ac +++ b/configure.ac @@ -633,6 +633,10 @@ case $host_os in AC_SUBST(APPKIT_LIBS,"-framework AppKit") AC_SUBST(SECURITY_LIBS,"-framework Security -framework CoreFoundation") AC_SUBST(SYSTEMCONFIGURATION_LIBS,"-framework SystemConfiguration") + AC_LANG_PUSH([Objective C]) + AC_CHECK_HEADER([ScreenCaptureKit/ScreenCaptureKit.h], + [AC_SUBST(SCREENCAPTUREKIT_LIBS,"-framework ScreenCaptureKit")]) + AC_LANG_POP([Objective C])
WINELOADER_LDFLAGS="-Wl,-segalign,0x1000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist"
diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in index e3e71c5f4cc..5680dc7c50e 100644 --- a/dlls/winemac.drv/Makefile.in +++ b/dlls/winemac.drv/Makefile.in @@ -12,7 +12,8 @@ UNIX_LIBS = \ -framework OpenGL \ -framework QuartzCore \ -framework Security \ - $(METAL_LIBS) + $(METAL_LIBS) \ + $(SCREENCAPTUREKIT_LIBS)
SOURCES = \ clipboard.c \ diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 89844dac173..9ab3b317530 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -25,6 +25,9 @@ #import <CoreVideo/CoreVideo.h> #import <Metal/Metal.h> #import <QuartzCore/QuartzCore.h> +#ifdef MAC_OS_VERSION_14_4 +#import <ScreenCaptureKit/ScreenCaptureKit.h> +#endif
#import "cocoa_window.h"
@@ -2334,6 +2337,69 @@ - (CGImageRef) windowListSnapshotForWindow:(WineWindow *)window return windowImage; }
+#ifdef MAC_OS_VERSION_14_4 + /* Create an image of the given window using the ScreenCaptureKit shareable + content APIs. The completion handler block is called on the main thread. + The image passed to the block must be released by the caller. In the case + of an error, the block is called with NULL. */ + - (void) shareableContentSnapshotForWindow:(WineWindow *)window + withCompletionHandler:(void (^)(CGImageRef image))completion + { + [SCShareableContent getCurrentProcessShareableContentWithCompletionHandler:^(SCShareableContent *shareableContent, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + SCWindow *scWindow; + SCContentFilter *filter; + SCStreamConfiguration *streamConfig; + + if (!shareableContent) + { + completion(NULL); + return; + } + + for (SCWindow *scw in shareableContent.windows) + { + if (scw.windowID == window.windowNumber) + { + scWindow = scw; + break; + } + } + + if (!scWindow) + { + completion(NULL); + return; + } + + filter = [[SCContentFilter alloc] initWithDesktopIndependentWindow:scWindow]; + + streamConfig = [[SCStreamConfiguration alloc] init]; + streamConfig.width = NSWidth(window.frame); + streamConfig.height = NSHeight(window.frame); + streamConfig.scalesToFit = YES; + streamConfig.showsCursor = NO; + streamConfig.ignoreShadowsSingleWindow = YES; + streamConfig.ignoreGlobalClipSingleWindow = YES; + streamConfig.includeChildWindows = NO; + + [SCScreenshotManager captureImageWithFilter:filter configuration:streamConfig completionHandler:^(CGImageRef sampleBuffer, NSError *error) { + [filter release]; + [streamConfig release]; + + /* We do *not* own the returned image. */ + if (sampleBuffer) + CGImageRetain(sampleBuffer); + + dispatch_async(dispatch_get_main_queue(), ^{ + completion(sampleBuffer); + }); + }]; + }); + }]; + } +#endif + - (void) drawDockTileWithImage:(CGImageRef)windowImage { NSImage* appImage = [NSApp applicationIconImage]; @@ -2382,8 +2448,6 @@ - (void) drawDockTileWithImage:(CGImageRef)windowImage
- (void) grabDockIconSnapshotFromWindow:(WineWindow*)window force:(BOOL)force { - CGImageRef windowImage; - if (![self isEmptyShaped]) return;
@@ -2417,12 +2481,28 @@ - (void) grabDockIconSnapshotFromWindow:(WineWindow*)window force:(BOOL)force return; }
- windowImage = [self windowListSnapshotForWindow:window]; - if (windowImage) +#ifdef MAC_OS_VERSION_14_4 + if ([SCShareableContent respondsToSelector:@selector(getCurrentProcessShareableContentWithCompletionHandler:)]) { - [self drawDockTileWithImage:windowImage]; - CGImageRelease(windowImage); - lastDockIconSnapshot = now; + [self shareableContentSnapshotForWindow:window withCompletionHandler:^(CGImageRef windowImage) { + if (windowImage) + { + [self drawDockTileWithImage:windowImage]; + CGImageRelease(windowImage); + lastDockIconSnapshot = now; + } + }]; + } + else +#endif + { + CGImageRef windowImage = [self windowListSnapshotForWindow:window]; + if (windowImage) + { + [self drawDockTileWithImage:windowImage]; + CGImageRelease(windowImage); + lastDockIconSnapshot = now; + } } }