macOS/QuickLook: support rich thumbnail #107072

Open
Ankit Meel wants to merge 10 commits from ankitm/blender:ankitm/2ql into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 219 additions and 2 deletions
Showing only changes of commit 96acded5e8 - Show all commits

View File

@ -38,8 +38,9 @@ if(WIN32)
target_link_libraries(BlendThumb bf_blenlib dbghelp.lib Version.lib)
set_target_properties(BlendThumb PROPERTIES LINK_FLAGS_DEBUG "/NODEFAULTLIB:msvcrt")
endif()
else()
if(UNIX AND NOT APPLE)
ankitm marked this conversation as resolved Outdated

Code is more clearly mutually exclusive if you use:

if(WIN32)
..
elseif(APPLE)
...
elseif(UNIX)
...
endif()
Code is more clearly mutually exclusive if you use: ``` if(WIN32) .. elseif(APPLE) ... elseif(UNIX) ... endif() ```
# -----------------------------------------------------------------------------
# Build `blender-thumbnailer` executable
@ -54,3 +55,32 @@ else()
target_link_libraries(blender-thumbnailer ${PTHREADS_LIBRARIES})
endif()
endif()
if(APPLE)
set(SRC
src/ThumbnailProvider.mm
src/ThumbnailProvider.h
src/Info.plist
)
add_executable(blender-thumbnailer MACOSX_BUNDLE ${SRC})
set_target_properties(blender-thumbnailer PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/src/Info.plist
MACOSX_FRAMEWORK_IDENTIFIER org.blenderfoundation.blender.thumbnailer
)
set_target_properties(blender-thumbnailer PROPERTIES
BUNDLE_EXTENSION appex
BL_CODESIGN_ENTITLEMENTS_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/src/ThumbnailExtensionMacOS.entitlements.Debug
ankitm marked this conversation as resolved Outdated

This is never defined on macOS, not needed.

This is never defined on macOS, not needed.
BL_CODESIGN_ENTITLEMENTS_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/src/ThumbnailExtensionMacOS.entitlements.Release
)
setup_platform_linker_flags(blender-thumbnailer)
target_link_libraries(blender-thumbnailer
bf_blenlib
# For main function
"-e _NSExtensionMain"
"-framework QuickLookThumbnailing"
)
if(DEFINED PTHREADS_LIBRARIES)
target_link_libraries(blender-thumbnailer ${PTHREADS_LIBRARIES})
endif()
endif()

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>blender_thumbnailer</string>
<key>CFBundleExecutable</key>
<string>blender-thumbnailer</string>
<key>CFBundleIdentifier</key>
<string>org.blenderfoundation.blender.thumbnailer</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>blender-thumbnailer</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<!-- TODO automate -->
<string>3.6.0</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<!-- TODO automate -->
<string>3.6.0 2023-04-18</string>
<key>LSMinimumSystemVersion</key>
<!-- TODO automate -->
<string>10.15</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>QLSupportedContentTypes</key>
<array>
<string>org.blenderfoundation.blender.file</string>
</array>
<key>QLThumbnailMinimumDimension</key>
<integer>10</integer>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.quicklook.thumbnail</string>
<key>NSExtensionPrincipalClass</key>
<string>ThumbnailProvider</string>
<key>com.apple.showsInExtensionsManager</key>
<true/>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.get-task-allow</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
ankitm marked this conversation as resolved Outdated

This file should be in release/darwin too.

Personally I'm also fine with not having the debugging entitlement at all, I just disable system integrity protection to be able to debug any application.

This file should be in `release/darwin` too. Personally I'm also fine with not having the debugging entitlement at all, I just disable system integrity protection to be able to debug any application.

I'll remove it.. debugging is only print debugging anyway.

I just disable system integrity protection to be able to debug any application.

Whoa

I'll remove it.. debugging is only print debugging anyway. > I just disable system integrity protection to be able to debug any application. Whoa
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
ankitm marked this conversation as resolved Outdated

Inconsistent indentation.

Inconsistent indentation.
</dict>
</plist>

View File

@ -0,0 +1,13 @@
#pragma once
ankitm marked this conversation as resolved Outdated

snake_case for filenames

snake_case for filenames
#include <Foundation/Foundation.h>
#import <QuickLookThumbnailing/QuickLookThumbnailing.h>
NS_ASSUME_NONNULL_BEGIN
@interface ThumbnailProvider : QLThumbnailProvider
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,82 @@
ankitm marked this conversation as resolved Outdated

snake_case for filenames

snake_case for filenames
#include "ThumbnailProvider.h"
/**
* This section intends to list the important steps for creating a thumbnail extension.
* qlgenerator has been deprecated. App extensions are the way forward.
* Process goes something like this:
* 1. If an app is launched, or is registered with lsregister, its plugins also get registered.
* 2. When a file thumbnail in Finder or QuickLook is requested, the system looks for a plugin
* that supports the file type UTI.
* 3. The plugin is launched in a sandboxed environment and should call the handler with a reply.
ankitm marked this conversation as resolved Outdated

Add newline before this.

Add newline before this.
*
* # Plugin Info.plist
* The Info.plist file should contain the following keys:
* <dict>
* <key>NSExtensionAttributes</key>
* <dict>
* <key>QLSupportedContentTypes</key>
* <array>
* <!-- Exactly the file UTIs to be supported. Not inherited from parent bundle. -->
* <string>org.blenderfoundation.blender.file</string>
* </array>
* <key>QLThumbnailMinimumDimension</key>
* <!-- To be explored the impact of. -->
* <integer>10</integer>
* </dict>
* <key>NSExtensionPointIdentifier</key>
* <!--com.apple.quicklook.thumbnail for preview extensions -->
* <string>com.apple.quicklook.thumbnail</string>
* <key>NSExtensionPrincipalClass</key>
* <!-- Must be the same as in the code. -->
* <string>ThumbnailProvider</string>
* <!-- Shows checkbox in System Preferences. -->
* <key>com.apple.showsInExtensionsManager</key>
* <true/>
* </dict>
*
* # Codesigning
* - The plugin should be codesigned with entitlements at least for sandbox and read-only/
* read-write (for access to the given file).
* - com.apple.security.get-task-allow is required for debugging.
*
* # Registering the plugin
* The plugin should be registered with lsregister. Either by calling lsregister or by launching
* the parent app.
*
* # Debugging
* Since read-only entitlement is there, creating files to log is not possible. So NSLOG and
* viewing it in Console.app (after triggering a thumbnail) is the
* way to go. Interesting processes are: qlmanage, quicklookd, kernel,
* blender-thumbnailer, secinitd, com.apple.quicklook.ThumbnailsAgent
*
* LLDB/ Xcode, Other debugging tools can be used to debug the plugin. /usr/bin/qlmanage
* is the target. Other args follow.
*
* # Troubleshooting
* - Sometimes blender-thumbnailer running in background can be killed.
* - qlmanage -r && killall Finder
*
* # Triggering a thumbnail
* - qlmanage -t /path/to/file.blend
* - qlmanage -t -s 512 -o /tmp/ /path/to/file.blend
*
*/
@implementation ThumbnailProvider
- (void)provideThumbnailForFileRequest:(QLFileThumbnailRequest *)request
completionHandler:(void (^)(QLThumbnailReply *_Nullable reply,
NSError *_Nullable error))handler
{
NSLog(@"hello world from blender");
NSURL *foo = [[NSURL alloc] initFileURLWithFileSystemRepresentation:""
isDirectory:NO
relativeToURL:nil];
QLThumbnailReply *reply = [QLThumbnailReply replyWithImageFileURL:foo];
handler(reply, nil);
}
@end

View File

@ -1352,7 +1352,16 @@ elseif(APPLE)
if(WITH_BLENDER_THUMBNAILER)
install(
TARGETS blender-thumbnailer
DESTINATION Blender.app/Contents/MacOS/
DESTINATION Blender.app/Contents/Plugins
)
get_target_property(BL_CODESIGN_ENTITLEMENTS_DEBUG blender-thumbnailer BL_CODESIGN_ENTITLEMENTS_DEBUG)
get_target_property(BL_CODESIGN_ENTITLEMENTS_RELEASE blender-thumbnailer BL_CODESIGN_ENTITLEMENTS_RELEASE)
set(BL_CODESIGN_ENTITLEMENTS "$<IF:$<CONFIG:Debug>,${BL_CODESIGN_ENTITLEMENTS_DEBUG},${BL_CODESIGN_ENTITLEMENTS_RELEASE}>")
install(CODE
"execute_process(COMMAND codesign
--deep --force --sign - --entitlements \"${BL_CODESIGN_ENTITLEMENTS}\" --timestamp=none
\"${EXECUTABLE_OUTPUT_PATH}/Blender.app/Contents/Plugins/blender-thumbnailer.appex\"
)"
)
endif()
ankitm marked this conversation as resolved Outdated

Not using relative path is more clear I think, their relative location has no particular importance: ${CMAKE_SOURCE_DIR}/release/darwin/thumbnail_entitlements.plist.

Don't invent new BL_ prefix for variable names, suggest to use THUMBNAIL_ENTITLEMENTS

Not using relative path is more clear I think, their relative location has no particular importance: `${CMAKE_SOURCE_DIR}/release/darwin/thumbnail_entitlements.plist`. Don't invent new `BL_` prefix for variable names, suggest to use `THUMBNAIL_ENTITLEMENTS`
@ -1686,6 +1695,16 @@ execute_process(\
endif()
endif()
if(APPLE)
# Register with lsregister
install(
CODE "
execute_process(COMMAND /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister
-f -R -trusted
\"${EXECUTABLE_OUTPUT_PATH}/Blender.app\"
)"
)
endif()
# -----------------------------------------------------------------------------
# Post-install script