Fix file associations in macOS.

This commit is contained in:
Martín Lucas Golini
2026-09-18 20:47:22 -03:00
parent b838a42fee
commit cdde2ec49e
4 changed files with 64 additions and 10 deletions

View File

@@ -593,6 +593,10 @@ function build_link_configuration( package_name, use_ee_icon )
end
end
if os.is_real("macosx") then
linkoptions { "-weak_framework UniformTypeIdentifiers" }
end
if _OPTIONS["with-mold-linker"] then
if _OPTIONS.platform == "clang" or _OPTIONS.platform == "clang-analyzer" then
linkoptions { "-fuse-ld=mold" }
@@ -1644,7 +1648,8 @@ solution "eepp"
set_targetdir("libs/" .. os.get_real() .. "/")
includedirs { "include", "src" }
files { "src/eepp/ui/platform/macos/macosmenubar.mm",
"src/eepp/window/platform/macos/platformhelper.mm" }
"src/eepp/window/platform/macos/platformhelper.mm",
"src/eepp/system/fileassociation_macos.mm" }
buildoptions { "-x objective-c++" }
if not is_vs() then
buildoptions{ "-std=c++20" }

View File

@@ -538,6 +538,9 @@ function build_link_configuration( package_name, use_ee_icon )
linkoptions { "-Wl,-rpath,'$$ORIGIN'" }
end
filter "system:macosx"
linkoptions { "-weak_framework UniformTypeIdentifiers" }
filter { "system:bsd" }
if package_name ~= "eepp" and package_name ~= "eepp-static" then
if type(userelativelinks) == "function" then
@@ -1675,7 +1678,8 @@ workspace "eepp"
cppdialect "C++20"
incdirs { "include", "src" }
files { "src/eepp/ui/platform/macos/macosmenubar.mm",
"src/eepp/window/platform/macos/platformhelper.mm" }
"src/eepp/window/platform/macos/platformhelper.mm",
"src/eepp/system/fileassociation_macos.mm" }
buildoptions { "-x objective-c++" }
build_base_cpp_configuration( "eepp-macos-helper" )
target_dir_lib( "" )

View File

@@ -21,6 +21,10 @@
#include <CoreServices/CoreServices.h>
#endif
#if EE_PLATFORM == EE_PLATFORM_MACOS
extern "C" CFStringRef eeppFileAssociationTypeIdentifierForExtension( const char* extension );
#endif
namespace EE::System {
namespace {
@@ -557,11 +561,19 @@ static CFStringRef cfString( const std::string& value ) {
}
static CFStringRef typeForExtension( const std::string& extension ) {
CFRef extensionString( cfString( extension ) );
if ( !extensionString.get() )
return nullptr;
return UTTypeCreatePreferredIdentifierForTag(
kUTTagClassFilenameExtension, static_cast<CFStringRef>( extensionString.get() ), nullptr );
return eeppFileAssociationTypeIdentifierForExtension( extension.c_str() );
}
static CFStringRef applicationIdentifier( const FileAssociationApplication& application ) {
/* Launch Services uses the bundle identifier from the registered bundle. The cross-platform
* application id is not necessarily that identifier (ecode, for example, uses ensoft.dev in
* its macOS Info.plist). Prefer the bundle metadata when this process is running from a bundle,
* and retain the supplied id as a fallback for non-bundled callers. */
if ( auto* bundle = CFBundleGetMainBundle() ) {
if ( auto identifier = CFBundleGetIdentifier( bundle ) )
return static_cast<CFStringRef>( CFRetain( identifier ) );
}
return cfString( application.id );
}
#endif
@@ -621,7 +633,7 @@ std::vector<std::string> FileAssociation::getRegisteredExtensions(
registered.emplace_back( extension );
}
#elif EE_PLATFORM == EE_PLATFORM_MACOS
CFRef applicationId( cfString( mApplication.id ) );
CFRef applicationId( applicationIdentifier( mApplication ) );
if ( !applicationId.get() ) {
mLastError = "The application identifier is not valid UTF-8.";
return {};
@@ -656,7 +668,7 @@ bool FileAssociation::setRegisteredExtensions( const std::vector<std::string>& r
const auto supported = normalizeExtensions( supportedExtensions );
const auto requested = normalizeExtensions( registeredExtensions );
std::vector<std::string> selected;
selected.reserve( (std::min)( requested.size(), supported.size() ) );
selected.reserve( ( std::min )( requested.size(), supported.size() ) );
std::set_intersection( requested.begin(), requested.end(), supported.begin(), supported.end(),
std::back_inserter( selected ) );
#if EE_PLATFORM == EE_PLATFORM_LINUX || EE_PLATFORM == EE_PLATFORM_BSD
@@ -712,7 +724,7 @@ bool FileAssociation::setRegisteredExtensions( const std::vector<std::string>& r
mLastError = "Launch Services could not register the application bundle.";
return false;
}
CFRef applicationId( cfString( mApplication.id ) );
CFRef applicationId( applicationIdentifier( mApplication ) );
if ( !applicationId.get() ) {
mLastError = "The application identifier is not valid UTF-8.";
return false;

View File

@@ -0,0 +1,33 @@
#include <eepp/config.hpp>
#if EE_PLATFORM == EE_PLATFORM_MACOS
#import <CoreServices/CoreServices.h>
#import <Foundation/Foundation.h>
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
extern "C" CFStringRef eeppFileAssociationTypeIdentifierForExtension( const char* extension ) {
if ( extension == nullptr )
return nullptr;
NSString* extensionString = [NSString stringWithUTF8String:extension];
if ( extensionString == nil )
return nullptr;
if ( @available( macOS 11.0, * ) ) {
UTType* type = [UTType typeWithFilenameExtension:extensionString];
if ( type == nil || type.identifier == nil )
return nullptr;
return CFStringCreateWithCString( kCFAllocatorDefault, type.identifier.UTF8String,
kCFStringEncodingUTF8 );
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
CFStringRef type = UTTypeCreatePreferredIdentifierForTag(
kUTTagClassFilenameExtension, static_cast<CFStringRef>( extensionString ), nullptr );
#pragma clang diagnostic pop
return type;
}
#endif