From ac54d5b7ec21cdc06e33b4d01d21c94bb40533f4 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 6 Dec 2024 23:59:00 +0200 Subject: [PATCH] Update Quick Look to support macOS 15 --- Makefile | 70 +++++++++++++++++++++++---------- QuickLook/GBPreviewProvider.h | 6 +++ QuickLook/GBPreviewProvider.m | 20 ++++++++++ QuickLook/GBThumbnailProvider.h | 5 +++ QuickLook/GBThumbnailProvider.m | 27 +++++++++++++ QuickLook/Info.plist | 4 +- QuickLook/Previewer.plist | 45 +++++++++++++++++++++ QuickLook/Thumbnailer.plist | 45 +++++++++++++++++++++ QuickLook/generator.m | 14 ++++--- QuickLook/plugin.entitlements | 10 +++++ 10 files changed, 217 insertions(+), 29 deletions(-) create mode 100644 QuickLook/GBPreviewProvider.h create mode 100644 QuickLook/GBPreviewProvider.m create mode 100644 QuickLook/GBThumbnailProvider.h create mode 100644 QuickLook/GBThumbnailProvider.m create mode 100644 QuickLook/Previewer.plist create mode 100644 QuickLook/Thumbnailer.plist create mode 100644 QuickLook/plugin.entitlements diff --git a/Makefile b/Makefile index de01cfb..7265676 100644 --- a/Makefile +++ b/Makefile @@ -342,12 +342,6 @@ LDFLAGS += -mno-outline endif STRIP := strip -CODESIGN := true -ifeq ($(PLATFORM),Darwin) -LDFLAGS += -Wl,-exported_symbols_list,$(NULL) -STRIP := strip -x -CODESIGN := codesign -fs - -endif LDFLAGS += -flto CFLAGS += -flto LDFLAGS += -Wno-lto-type-mismatch # For GCC's LTO @@ -356,6 +350,13 @@ else $(error Invalid value for CONF: $(CONF). Use "debug", "release" or "native_release") endif +CODESIGN := true +ifeq ($(PLATFORM),Darwin) +LDFLAGS += -Wl,-exported_symbols_list,$(NULL) +STRIP := strip -x +CODESIGN := codesign -fs - +endif + ifeq ($(PLATFORM),windows32) LDFLAGS += -fuse-ld=lld endif @@ -540,7 +541,9 @@ $(BIN)/SameBoy.app: $(BIN)/SameBoy.app/Contents/MacOS/SameBoy \ $(BIN)/SameBoy.app/Contents/Resources/sgb_boot.bin \ $(BIN)/SameBoy.app/Contents/Resources/sgb2_boot.bin \ $(patsubst %.xib,%.nib,$(addprefix $(BIN)/SameBoy.app/Contents/Resources/,$(shell cd Cocoa;ls *.xib))) \ - $(BIN)/SameBoy.qlgenerator \ + $(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator \ + $(BIN)/SameBoy.app/Contents/PlugIns/Thumbnailer.appex \ + $(BIN)/SameBoy.app/Contents/PlugIns/Previewer.appex \ Shaders $(MKDIR) -p $(BIN)/SameBoy.app/Contents/Resources cp Cocoa/*.icns Cocoa/*.png Misc/registers.sym $(BIN)/SameBoy.app/Contents/Resources/ @@ -549,20 +552,19 @@ $(BIN)/SameBoy.app: $(BIN)/SameBoy.app/Contents/MacOS/SameBoy \ $(MKDIR) -p $(BIN)/SameBoy.app/Contents/Resources/Shaders cp Shaders/*.fsh Shaders/*.metal $(BIN)/SameBoy.app/Contents/Resources/Shaders $(MKDIR) -p $(BIN)/SameBoy.app/Contents/Library/QuickLook/ - cp -rf $(BIN)/SameBoy.qlgenerator $(BIN)/SameBoy.app/Contents/Library/QuickLook/ ifeq ($(CONF), release) $(CODESIGN) $@ endif # We place the dylib inside the Quick Look plugin, because Quick Look plugins run in a very strict sandbox -$(BIN)/SameBoy.app/Contents/MacOS/SameBoy: $(BIN)/SameBoy.qlgenerator/Contents/MacOS/SameBoy.dylib +$(BIN)/SameBoy.app/Contents/MacOS/SameBoy: $(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/MacOS/SameBoy.dylib -@$(MKDIR) -p $(dir $@) $(CC) $^ -o $@ $(LDFLAGS) $(FAT_FLAGS) -rpath @executable_path/../Library/QuickLook/SameBoy.qlgenerator/ -Wl,-reexport_library,$^ -$(BIN)/SameBoy.qlgenerator/Contents/MacOS/SameBoy.dylib: $(COCOA_OBJECTS) $(CORE_OBJECTS) $(QUICKLOOK_OBJECTS) +$(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/MacOS/SameBoy.dylib: $(COCOA_OBJECTS) $(CORE_OBJECTS) $(QUICKLOOK_OBJECTS) -@$(MKDIR) -p $(dir $@) - $(CC) $^ -o $@ $(LDFLAGS) $(FAT_FLAGS) -shared -install_name @rpath/Contents/MacOS/SameBoy.dylib -framework OpenGL -framework AudioUnit -framework AVFoundation -framework CoreVideo -framework CoreMedia -framework IOKit -framework PreferencePanes -framework Carbon -framework QuartzCore -framework Security -framework WebKit -weak_framework Metal -weak_framework MetalKit -framework Quicklook -framework AppKit -Wl,-exported_symbols_list,QuickLook/exports.sym -Wl,-exported_symbol,_main + $(CC) $^ -o $@ $(LDFLAGS) $(FAT_FLAGS) -shared -install_name @rpath/Contents/MacOS/SameBoy.dylib -framework OpenGL -framework AudioUnit -framework AVFoundation -framework CoreVideo -framework CoreMedia -framework IOKit -framework PreferencePanes -framework Carbon -framework QuartzCore -framework Security -framework WebKit -weak_framework Metal -weak_framework MetalKit -weak_framework QuickLookThumbnailing -weak_framework QuickLookUI -framework Quicklook -framework AppKit -Wl,-exported_symbols_list,QuickLook/exports.sym -Wl,-exported_symbol,_main ifeq ($(CONF), release) $(STRIP) $@ $(CODESIGN) $@ @@ -574,29 +576,55 @@ $(BIN)/SameBoy.app/Contents/Resources/%.nib: Cocoa/%.xib $(BIN)/SameBoy-iOS.app/%.storyboardc: iOS/%.storyboard ibtool --target-device iphone --target-device ipad --minimum-deployment-target $(IOS_MIN) --compile $@ $^ 2>&1 | cat - -# Quick Look generator +# Quick Look generators -$(BIN)/SameBoy.qlgenerator: $(BIN)/SameBoy.qlgenerator/Contents/MacOS/SameBoyQL \ - $(shell ls QuickLook/*.png) \ - QuickLook/Info.plist \ - $(BIN)/SameBoy.qlgenerator/Contents/Resources/cgb_boot_fast.bin - $(MKDIR) -p $(BIN)/SameBoy.qlgenerator/Contents/Resources - cp QuickLook/*.png $(BIN)/SameBoy.qlgenerator/Contents/Resources/ - sed "s/@VERSION/$(VERSION)/;s/@COPYRIGHT_YEAR/$(COPYRIGHT_YEAR)/" < QuickLook/Info.plist > $(BIN)/SameBoy.qlgenerator/Contents/Info.plist +$(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator: $(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/MacOS/SameBoyQL \ + $(shell ls QuickLook/*.png) \ + QuickLook/Info.plist \ + $(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/Resources/cgb_boot_fast.bin + $(MKDIR) -p $(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/Resources + cp QuickLook/*.png $(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/Resources/ + sed "s/@VERSION/$(VERSION)/;s/@COPYRIGHT_YEAR/$(COPYRIGHT_YEAR)/" < QuickLook/Info.plist > $(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/Info.plist ifeq ($(CONF), release) $(CODESIGN) $@ endif -$(BIN)/SameBoy.qlgenerator/Contents/MacOS/SameBoyQL: $(BIN)/SameBoy.qlgenerator/Contents/MacOS/SameBoy.dylib +$(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/MacOS/SameBoyQL: $(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/MacOS/SameBoy.dylib -@$(MKDIR) -p $(dir $@) $(CC) -o $@ $(LDFLAGS) $(FAT_FLAGS) -bundle -Wl,-reexport_library,$^ -rpath @loader_path/../../ ifeq ($(CONF), release) $(STRIP) $@ endif +$(BIN)/SameBoy.app/Contents/PlugIns/Thumbnailer.appex: $(BIN)/SameBoy.app/Contents/PlugIns/Thumbnailer.appex/Contents/MacOS/Thumbnailer \ + QuickLook/Thumbnailer.plist \ + QuickLook/plugin.entitlements + sed "s/@VERSION/$(VERSION)/;s/@COPYRIGHT_YEAR/$(COPYRIGHT_YEAR)/" < QuickLook/Thumbnailer.plist > $(BIN)/SameBoy.app/Contents/PlugIns/Thumbnailer.appex/Contents/Info.plist + $(CODESIGN) --entitlements QuickLook/plugin.entitlements $@ + +$(BIN)/SameBoy.app/Contents/PlugIns/Thumbnailer.appex/Contents/MacOS/Thumbnailer: $(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/MacOS/SameBoy.dylib + -@$(MKDIR) -p $(dir $@) + $(CC) -o $@ $(LDFLAGS) $(FAT_FLAGS) -e _NSExtensionMain -framework Foundation -Wl,-reexport_library,$^ -rpath @loader_path/../../../../Library/QuickLook/SameBoy.qlgenerator/ +ifeq ($(CONF), release) + $(STRIP) $@ +endif + +$(BIN)/SameBoy.app/Contents/PlugIns/Previewer.appex: $(BIN)/SameBoy.app/Contents/PlugIns/Previewer.appex/Contents/MacOS/Previewer \ + QuickLook/Previewer.plist \ + QuickLook/plugin.entitlements + sed "s/@VERSION/$(VERSION)/;s/@COPYRIGHT_YEAR/$(COPYRIGHT_YEAR)/" < QuickLook/Previewer.plist > $(BIN)/SameBoy.app/Contents/PlugIns/Previewer.appex/Contents/Info.plist + $(CODESIGN) --entitlements QuickLook/plugin.entitlements $@ + +$(BIN)/SameBoy.app/Contents/PlugIns/Previewer.appex/Contents/MacOS/Previewer: $(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/MacOS/SameBoy.dylib + -@$(MKDIR) -p $(dir $@) + $(CC) -o $@ $(LDFLAGS) $(FAT_FLAGS) -e _NSExtensionMain -framework Foundation -Wl,-reexport_library,$^ -rpath @loader_path/../../../../Library/QuickLook/SameBoy.qlgenerator/ +ifeq ($(CONF), release) + $(STRIP) $@ +endif + # cgb_boot_fast.bin is not a standard boot ROM, we don't expect it to exist in the user-provided # boot ROM directory. -$(BIN)/SameBoy.qlgenerator/Contents/Resources/cgb_boot_fast.bin: $(BIN)/BootROMs/cgb_boot_fast.bin +$(BIN)/SameBoy.app/Contents/Library/QuickLook/SameBoy.qlgenerator/Contents/Resources/cgb_boot_fast.bin: $(BIN)/BootROMs/cgb_boot_fast.bin -@$(MKDIR) -p $(dir $@) cp -f $^ $@ diff --git a/QuickLook/GBPreviewProvider.h b/QuickLook/GBPreviewProvider.h new file mode 100644 index 0000000..ae0dfd2 --- /dev/null +++ b/QuickLook/GBPreviewProvider.h @@ -0,0 +1,6 @@ +#import +#import + +API_AVAILABLE(macos(12.0)) +@interface GBPreviewProvider : QLPreviewProvider +@end diff --git a/QuickLook/GBPreviewProvider.m b/QuickLook/GBPreviewProvider.m new file mode 100644 index 0000000..dd48db6 --- /dev/null +++ b/QuickLook/GBPreviewProvider.m @@ -0,0 +1,20 @@ +#import "GBPreviewProvider.h" + +extern OSStatus GBQuickLookRender(CGContextRef cgContext, CFURLRef url, bool showBorder); + +@implementation GBPreviewProvider + +- (void)providePreviewForFileRequest:(QLFilePreviewRequest *)request completionHandler:(void (^)(QLPreviewReply *reply, NSError *error))handler +{ + QLPreviewReply* reply = [[QLPreviewReply alloc] initWithContextSize:CGSizeMake(640, 576) + isBitmap:true + drawingBlock:^BOOL (CGContextRef context, QLPreviewReply *reply, NSError **error) { + return !GBQuickLookRender(context, (__bridge CFURLRef)request.fileURL, false); + + }]; + + handler(reply, nil); +} + +@end + diff --git a/QuickLook/GBThumbnailProvider.h b/QuickLook/GBThumbnailProvider.h new file mode 100644 index 0000000..4a8268f --- /dev/null +++ b/QuickLook/GBThumbnailProvider.h @@ -0,0 +1,5 @@ +#import + +API_AVAILABLE(macos(10.15)) +@interface GBThumbnailProvider : QLThumbnailProvider +@end diff --git a/QuickLook/GBThumbnailProvider.m b/QuickLook/GBThumbnailProvider.m new file mode 100644 index 0000000..49a0db6 --- /dev/null +++ b/QuickLook/GBThumbnailProvider.m @@ -0,0 +1,27 @@ +#import "GBThumbnailProvider.h" + +extern OSStatus GBQuickLookRender(CGContextRef cgContext, CFURLRef url, bool showBorder); + +@interface QLThumbnailReply (private) +@property unsigned iconFlavor; +@end + +@implementation GBThumbnailProvider + +- (void)provideThumbnailForFileRequest:(QLFileThumbnailRequest *)request completionHandler:(void (^)(QLThumbnailReply *, NSError *))handler +{ + CGSize size = {64, 64}; + CGSize maximumSize = request.maximumSize; + while (size.width < maximumSize.width / 2 && + size.width < maximumSize.height / 2) { + size.width *= 2; + } + size.height = size.width; + QLThumbnailReply *reply = [QLThumbnailReply replyWithContextSize:size drawingBlock: ^BOOL(CGContextRef context) { + return !GBQuickLookRender(context, (__bridge CFURLRef)request.fileURL, true); + }]; + reply.iconFlavor = 0; + handler(reply, nil); +} + +@end diff --git a/QuickLook/Info.plist b/QuickLook/Info.plist index f98dfb2..924f9f5 100644 --- a/QuickLook/Info.plist +++ b/QuickLook/Info.plist @@ -14,7 +14,7 @@ com.github.liji32.sameboy.gb com.github.liji32.sameboy.gbc com.github.liji32.sameboy.isx - public.gbrom + public.gbrom @@ -27,7 +27,7 @@ CFBundleName SameBoy CFBundleShortVersionString - Version @VERSION + @VERSION CFBundleSignature ???? CFPlugInDynamicRegisterFunction diff --git a/QuickLook/Previewer.plist b/QuickLook/Previewer.plist new file mode 100644 index 0000000..c35a483 --- /dev/null +++ b/QuickLook/Previewer.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDisplayName + Previewer + CFBundleExecutable + Previewer + CFBundleIdentifier + com.github.liji32.sameboy.ios.Previewer + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Previewer + CFBundlePackageType + XPC! + CFBundleShortVersionString + @VERSION + CFBundleSupportedPlatforms + + MacOSX + + LSMinimumSystemVersion + 12.0 + NSExtension + + NSExtensionAttributes + + QLSupportedContentTypes + + com.github.liji32.sameboy.gb + com.github.liji32.sameboy.gbc + com.github.liji32.sameboy.isx + public.gbrom + + QLIsDataBasedPreview + + + NSExtensionPointIdentifier + com.apple.quicklook.preview + NSExtensionPrincipalClass + GBPreviewProvider + + + diff --git a/QuickLook/Thumbnailer.plist b/QuickLook/Thumbnailer.plist new file mode 100644 index 0000000..6e18029 --- /dev/null +++ b/QuickLook/Thumbnailer.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDisplayName + Thumbnailer + CFBundleExecutable + Thumbnailer + CFBundleIdentifier + com.github.liji32.sameboy.ios.Thumbnailer + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Thumbnailer + CFBundlePackageType + XPC! + CFBundleShortVersionString + @VERSION + CFBundleSupportedPlatforms + + MacOSX + + LSMinimumSystemVersion + 12.0 + NSExtension + + NSExtensionAttributes + + QLSupportedContentTypes + + com.github.liji32.sameboy.gb + com.github.liji32.sameboy.gbc + com.github.liji32.sameboy.isx + public.gbrom + + QLThumbnailMinimumDimension + 64 + + NSExtensionPointIdentifier + com.apple.quicklook.thumbnail + NSExtensionPrincipalClass + GBThumbnailProvider + + + diff --git a/QuickLook/generator.m b/QuickLook/generator.m index 536f754..225ddc7 100644 --- a/QuickLook/generator.m +++ b/QuickLook/generator.m @@ -2,7 +2,7 @@ #include #include "get_image_for_rom.h" -static OSStatus render(CGContextRef cgContext, CFURLRef url, bool showBorder) +OSStatus GBQuickLookRender(CGContextRef cgContext, CFURLRef url, bool showBorder) { /* Load the template NSImages when generating the first thumbnail */ static NSImage *template = nil; @@ -11,7 +11,7 @@ static OSStatus render(CGContextRef cgContext, CFURLRef url, bool showBorder) static NSBundle *bundle = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - bundle = [NSBundle bundleWithIdentifier:@"com.github.liji32.sameboy.previewer"]; + bundle = [NSBundle bundleForClass:NSClassFromString(@"GBPanel")]; }); if (showBorder) { static dispatch_once_t onceToken; @@ -53,11 +53,13 @@ static OSStatus render(CGContextRef cgContext, CFURLRef url, bool showBorder) [NSGraphicsContext setCurrentContext:context]; + double ratio = CGBitmapContextGetWidth(cgContext) / 1024.0; + /* Convert the screenshot to a magnified NSImage */ NSImage *screenshot = [[NSImage alloc] initWithCGImage:iref size:NSMakeSize(160, 144)]; /* Draw the screenshot */ if (showBorder) { - [screenshot drawInRect:NSMakeRect(192, 150, 640, 576)]; + [screenshot drawInRect:NSMakeRect(192 * ratio, 150 * ratio, 640 * ratio, 576 * ratio)]; } else { [screenshot drawInRect:NSMakeRect(0, 0, 640, 576)]; @@ -82,7 +84,7 @@ static OSStatus render(CGContextRef cgContext, CFURLRef url, bool showBorder) } /* Mask it with the template (The middle part of the template image is transparent) */ - [effectiveTemplate drawInRect:(NSRect){{0, 0}, template.size}]; + [effectiveTemplate drawInRect:(NSRect){{0, 0}, {CGBitmapContextGetWidth(cgContext), CGBitmapContextGetHeight(cgContext)}}]; } CGColorSpaceRelease(colorSpaceRef); @@ -96,7 +98,7 @@ OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, { @autoreleasepool { CGContextRef cgContext = QLPreviewRequestCreateContext(preview, ((NSSize){640, 576}), true, nil); - if (render(cgContext, url, false) == noErr) { + if (GBQuickLookRender(cgContext, url, false) == noErr) { QLPreviewRequestFlushContext(preview, cgContext); CGContextRelease(cgContext); return noErr; @@ -111,7 +113,7 @@ OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thum extern NSString *kQLThumbnailPropertyIconFlavorKey; @autoreleasepool { CGContextRef cgContext = QLThumbnailRequestCreateContext(thumbnail, ((NSSize){1024, 1024}), true, (__bridge CFDictionaryRef)(@{kQLThumbnailPropertyIconFlavorKey : @(0)})); - if (render(cgContext, url, true) == noErr) { + if (GBQuickLookRender(cgContext, url, true) == noErr) { QLThumbnailRequestFlushContext(thumbnail, cgContext); CGContextRelease(cgContext); return noErr; diff --git a/QuickLook/plugin.entitlements b/QuickLook/plugin.entitlements new file mode 100644 index 0000000..f2ef3ae --- /dev/null +++ b/QuickLook/plugin.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + +