From f504cdf9cf2c703c9f8e0c69165df42985d22d30 Mon Sep 17 00:00:00 2001 From: Timothy Risi Date: Mon, 2 May 2016 17:09:13 -0800 Subject: [PATCH] [Mac] Add support for os x extensions --- .../Tasks/CompileAppManifest.cs | 10 +- msbuild/Xamarin.Mac.Tasks/Tasks/Mmp.cs | 13 +- .../Xamarin.Mac.AppExtension.CSharp.targets | 36 ++++ .../Xamarin.Mac.AppExtension.Common.props | 30 ++++ .../Xamarin.Mac.AppExtension.Common.targets | 67 ++++++++ .../Xamarin.Mac.Common.props | 1 + .../Xamarin.Mac.Common.targets | 158 +++++++++++++++++- .../Xamarin.Mac.Tasks.csproj | 9 + .../Tasks/CodesignTaskBase.cs | 7 + .../Tasks/CompileAppManifestTaskBase.cs | 3 + .../Tasks/IBToolTaskBase.cs | 3 + .../Tasks/CompileAppManifestTaskBase.cs | 3 - runtime/Makefile | 15 ++ runtime/launcher.m | 81 ++++++--- runtime/libxammac.csproj | 1 + runtime/main-internal.h | 5 +- runtime/runtime-internal.h | 1 + runtime/runtime.m | 8 +- src/FinderSync/Enums.cs | 13 ++ src/NotificationCenter/NCEnums.cs | 2 +- src/appkit.cs | 53 +++--- src/findersync.cs | 62 +++++++ src/foundation.cs | 17 +- src/frameworks.sources | 7 + src/notificationcenter.cs | 126 +++++++++++++- tools/mmp/driver.cs | 15 +- 26 files changed, 671 insertions(+), 75 deletions(-) create mode 100644 msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.CSharp.targets create mode 100644 msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.Common.props create mode 100644 msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.Common.targets create mode 100644 src/FinderSync/Enums.cs create mode 100644 src/findersync.cs diff --git a/msbuild/Xamarin.Mac.Tasks/Tasks/CompileAppManifest.cs b/msbuild/Xamarin.Mac.Tasks/Tasks/CompileAppManifest.cs index efdeab801788..e3e87e209466 100644 --- a/msbuild/Xamarin.Mac.Tasks/Tasks/CompileAppManifest.cs +++ b/msbuild/Xamarin.Mac.Tasks/Tasks/CompileAppManifest.cs @@ -29,6 +29,7 @@ public override bool Execute () Log.LogTaskProperty ("Architecture", Architecture); Log.LogTaskProperty ("AssemblyName", AssemblyName); Log.LogTaskProperty ("BundleIdentifier", BundleIdentifier); + Log.LogTaskProperty ("IsAppExtension", IsAppExtension); Log.LogTaskProperty ("PartialAppManifests", PartialAppManifests); try { @@ -38,12 +39,15 @@ public override bool Execute () return false; } + plist[ManifestKeys.CFBundleExecutable] = new PString (AssemblyName); + plist.SetIfNotPresent (ManifestKeys.CFBundleIdentifier, BundleIdentifier); plist.SetIfNotPresent (ManifestKeys.CFBundleInfoDictionaryVersion, "6.0"); - plist.SetIfNotPresent ("MonoBundleExecutable", AssemblyName + ".exe"); + if (!IsAppExtension) + plist.SetIfNotPresent ("MonoBundleExecutable", AssemblyName + ".exe"); plist.SetIfNotPresent (ManifestKeys.CFBundleExecutable, AssemblyName); plist.SetIfNotPresent (ManifestKeys.CFBundleName, AppBundleName); - plist.SetIfNotPresent (ManifestKeys.CFBundlePackageType, "APPL"); + plist.SetIfNotPresent (ManifestKeys.CFBundlePackageType, IsAppExtension ? "XPC!" : "APPL"); plist.SetIfNotPresent (ManifestKeys.CFBundleSignature, "????"); plist.SetIfNotPresent (ManifestKeys.CFBundleVersion, "1.0"); @@ -56,4 +60,4 @@ public override bool Execute () return !Log.HasLoggedErrors; } } -} \ No newline at end of file +} diff --git a/msbuild/Xamarin.Mac.Tasks/Tasks/Mmp.cs b/msbuild/Xamarin.Mac.Tasks/Tasks/Mmp.cs index 8d5de2cc05e3..7c992a2ef0d0 100644 --- a/msbuild/Xamarin.Mac.Tasks/Tasks/Mmp.cs +++ b/msbuild/Xamarin.Mac.Tasks/Tasks/Mmp.cs @@ -53,6 +53,8 @@ protected override string ToolName { [Required] public string SdkVersion { get; set; } + public bool IsAppExtension { get; set; } + public bool UseXamMacFullFramework { get; set; } public string ApplicationName { get; set; } @@ -163,8 +165,9 @@ protected override string GenerateCommandLineCommands () args.AddQuoted ("/assembly:" + Path.GetFullPath (asm)); } - if (!string.IsNullOrEmpty (ApplicationAssembly)) - args.AddQuoted (Path.GetFullPath (ApplicationAssembly)); + if (!string.IsNullOrEmpty (ApplicationAssembly)) { + args.AddQuoted (Path.GetFullPath (ApplicationAssembly + (IsAppExtension ? ".dll" : ".exe"))); + } if (!string.IsNullOrWhiteSpace (ExtraArguments)) args.Add (ExtraArguments); @@ -173,6 +176,9 @@ protected override string GenerateCommandLineCommands () foreach (var nr in NativeReferences) args.AddQuoted ("/native-reference:" + Path.GetFullPath (nr)); } + + if (IsAppExtension) + args.AddQuoted ("/extension"); args.Add ("/sdkroot"); args.AddQuoted (SdkRoot); @@ -190,7 +196,7 @@ protected override string GenerateCommandLineCommands () public override bool Execute () { Log.LogTaskName ("Mmp"); - Log.LogTaskProperty ("ApplicationAssembly", ApplicationAssembly); + Log.LogTaskProperty ("ApplicationAssembly", ApplicationAssembly + (IsAppExtension ? ".dll" : ".exe")); Log.LogTaskProperty ("ApplicationName", ApplicationName); Log.LogTaskProperty ("Architecture", Architecture); Log.LogTaskProperty ("Debug", Debug); @@ -210,6 +216,7 @@ public override bool Execute () Log.LogTaskProperty ("AppManifest", AppManifest); Log.LogTaskProperty ("SdkVersion", SdkVersion); Log.LogTaskProperty ("NativeReferences", NativeReferences); + Log.LogTaskProperty ("IsAppExtension", IsAppExtension); return base.Execute (); } diff --git a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.CSharp.targets b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.CSharp.targets new file mode 100644 index 000000000000..e55fe82ffbb0 --- /dev/null +++ b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.CSharp.targets @@ -0,0 +1,36 @@ + + + + + + + v4.5 + + + /Library/Frameworks/Mono.framework/Commands + mcs + + __UNIFIED__;$(DefineConstants) + + + + + + + diff --git a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.Common.props b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.Common.props new file mode 100644 index 000000000000..99c38b4c2c50 --- /dev/null +++ b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.Common.props @@ -0,0 +1,30 @@ + + + + + + + + + <_XamarinAppExtensionCommonPropsHasBeenImported>true + + + + + diff --git a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.Common.targets b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.Common.targets new file mode 100644 index 000000000000..e434bdd3f8a8 --- /dev/null +++ b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.AppExtension.Common.targets @@ -0,0 +1,67 @@ + + + + + True + + + + + + + + + + + + + + + + true + <_CodeSigningKey Condition="'$(_CodeSigningKey)' == ''">- + Entitlements.plist + + + + + + $(OutputPath)$(DeviceSpecificOutputPath)$(_AppBundleName).appex + <_AppBundlePath>$(AppBundleDir)\ + + <_AppResourcesPath>$(_AppBundlePath)Contents\Resources\ + + + <_AppExtensionBundlePath>$(MSBuildProjectDirectory)\$(AppBundleDir) + + + <_AppExtensionBundlePath Include="$(MSBuildProjectDirectory)\$(AppBundleDir)"> + + $(BuildSessionId) + ..\..\$(BuildAppName)\$(BuildSessionId)\$(AppBundleDir) + + + + + + + + + diff --git a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Common.props b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Common.props index 6de19bd9d316..026d8c89fecd 100644 --- a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Common.props +++ b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Common.props @@ -54,6 +54,7 @@ Copyright (C) 2013-2014 Xamarin. All rights reserved. x86_64 Resources $(MonoMacResourcePrefix) + False + - @@ -39,6 +39,11 @@ Copyright (C) 2014 Xamarin. All rights reserved. + + + + + @@ -50,25 +55,59 @@ Copyright (C) 2014 Xamarin. All rights reserved. /Library/Frameworks/Xamarin.Mac.framework/Versions/Current - + $(XamarinMacFrameworkRoot)/lib/reference/full;$(XamarinMacFrameworkRoot)/lib/mono;$(AssemblySearchPaths) - + $(XamarinMacFrameworkRoot)/lib/mono/4.5;$(AssemblySearchPaths) <_CanOutputAppBundle>False - <_CanOutputAppBundle Condition="'$(OutputType)' == 'Exe'">True + <_CanOutputAppBundle Condition="'$(OutputType)' == 'Exe' Or '$(IsAppExtension)' == 'true'">true <_CanArchive>False - <_CanArchive Condition="'$(OutputType)' == 'Exe'">True + <_CanArchive Condition="'$(OutputType)' == 'Exe'">true <_PreparedResourceRules> <_AppBundleName>$(AssemblyName) + + true + + + _SeparateAppExtensionReferences; + $(ResolveReferencesDependsOn); + ImplicitlyExpandDesignTimeFacades + + + + $(ImplicitlyExpandDesignTimeFacadesDependsOn); + GetReferenceAssemblyPaths + + + + + + <_HasReferenceToSystemRuntime Condition="'%(ReferenceDependencyPaths.Filename)' == 'System.Runtime'">true + + + + <_DesignTimeFacadeAssemblies Include="%(DesignTimeFacadeDirectories.Identity)*.dll"/> + + + false + false + ImplicitlyExpandDesignTimeFacades + + + + + + + _CollectBundleResources; @@ -102,6 +141,7 @@ Copyright (C) 2014 Xamarin. All rights reserved. _CompileAppManifest; _CompileToNative; _CreatePkgInfo; + _CopyAppExtensionsToBundle; @@ -170,6 +210,7 @@ Copyright (C) 2014 Xamarin. All rights reserved. Resource="%(_NativeLibrary.Identity)" SigningKey="$(_CodeSigningKey)" ExtraArgs="$(CodesignExtraArgs)" + IsAppExtension="$(IsAppExtension)" > @@ -191,7 +232,7 @@ Copyright (C) 2014 Xamarin. All rights reserved. BundleIdentifier="$(_BundleIdentifier)" Entitlements="$(CodeSignEntitlements)" CompiledEntitlements="$(IntermediateOutputPath)Entitlements.xcent" - IsAppExtension="false" + IsAppExtension="$(IsAppExtension)" ProvisioningProfile="$(_ProvisioningProfile)" SdkVersion="$(MacOSXSdkVersion)" SdkDevPath="$(_SdkDevPath)" @@ -210,6 +251,7 @@ Copyright (C) 2014 Xamarin. All rights reserved. Resource="$(AppBundleDir)" SigningKey="$(_CodeSigningKey)" ExtraArgs="$(CodesignExtraArgs)" + IsAppExtension="$(IsAppExtension)" > @@ -365,7 +407,11 @@ Copyright (C) 2014 Xamarin. All rights reserved. - + + + <_AppBundleName>$(AssemblyName) + + @@ -413,7 +460,7 @@ Copyright (C) 2014 Xamarin. All rights reserved. FrameworkRoot="$(XamarinMacFrameworkRoot)" OutputPath="$(OutputPath)" ApplicationName="$(_AppBundleName)" - ApplicationAssembly="$(OutputPath)$(AssemblyName).exe" + ApplicationAssembly="$(OutputPath)$(AssemblyName)" TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)" TargetFrameworkVersion="$(TargetFrameworkVersion)" UseXamMacFullFramework="$(UseXamMacFullFramework)" @@ -431,6 +478,7 @@ Copyright (C) 2014 Xamarin. All rights reserved. IntermediateOutputPath="$(IntermediateOutputPath)mmp-cache" AppManifest="$(_AppManifest)" SdkVersion="$(MacOSXSdkVersion)" + IsAppExtension="$(IsAppExtension)" /> @@ -534,8 +582,100 @@ Copyright (C) 2014 Xamarin. All rights reserved. + + + + + + + + + Condition="'$(UseXamMacFullFramework)' == 'true'"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj index ac9adab1f113..09580fee3009 100644 --- a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj +++ b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj @@ -97,5 +97,14 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CodesignTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CodesignTaskBase.cs index 9a7d436b1086..dbd30f49806f 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CodesignTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CodesignTaskBase.cs @@ -28,6 +28,8 @@ public abstract class CodesignTaskBase : ToolTask public string ExtraArgs { get; set; } + public bool IsAppExtension { get; set; } + #endregion protected override string ToolName { @@ -50,6 +52,10 @@ protected override string GenerateCommandLineCommands () args.Add ("-v"); args.Add ("--force"); + + if (IsAppExtension) + args.Add("--deep"); + args.Add ("--sign"); args.AddQuoted (SigningKey); @@ -92,6 +98,7 @@ public override bool Execute () Log.LogTaskProperty ("ResourceRules", ResourceRules); Log.LogTaskProperty ("SigningKey", SigningKey); Log.LogTaskProperty ("ExtraArgs", ExtraArgs); + Log.LogTaskProperty ("IsAppExtension", IsAppExtension); EnvironmentVariables = new string[] { "CODESIGN_ALLOCATE=" + CodesignAllocate diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs index e650bdd952d2..6455e14d4c6e 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs @@ -17,6 +17,9 @@ public abstract class CompileAppManifestTaskBase : Task [Required] public string AppBundleName { get; set; } + [Required] + public bool IsAppExtension { get; set; } + [Required] public string AppBundleDir { get; set; } diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/IBToolTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/IBToolTaskBase.cs index 5996b3bcd84a..d3e03d1ac7fe 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/IBToolTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/IBToolTaskBase.cs @@ -21,6 +21,8 @@ public abstract class IBToolTaskBase : XcodeCompilerToolTask public bool IsWatchApp { get; set; } public bool IsWatch2App { get; set; } + public bool IsAppExtension { get; set; } + public string SdkRoot { get; set; } #endregion @@ -170,6 +172,7 @@ public override bool Execute () Log.LogTaskProperty ("IntermediateOutputPath", IntermediateOutputPath); Log.LogTaskProperty ("IsWatchApp", IsWatchApp); Log.LogTaskProperty ("IsWatch2App", IsWatch2App); + Log.LogTaskProperty ("IsAppExtension", IsAppExtension); Log.LogTaskProperty ("ProjectDir", ProjectDir); Log.LogTaskProperty ("ResourcePrefix", ResourcePrefix); Log.LogTaskProperty ("SdkBinPath", SdkBinPath); diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs index 6816f6b3e227..ac8896b3964e 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs +++ b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs @@ -16,9 +16,6 @@ public abstract class CompileAppManifestTaskBase : Xamarin.MacDev.Tasks.CompileA [Required] public string DefaultSdkVersion { get; set; } - [Required] - public bool IsAppExtension { get; set; } - [Required] public bool IsWatchApp { get; set; } diff --git a/runtime/Makefile b/runtime/Makefile index 8e2c04170a6e..774971f627c2 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -313,6 +313,7 @@ ALLOWED_UNDEFINED_SYMBOLS = _xamarin_enable_debug _xammac_setup MAC_LIBS = \ XamMacLauncher \ + libextension.a \ libxammac.a \ libxammac-debug.a \ libxammac.dylib \ @@ -380,6 +381,20 @@ $(eval $(call ObjTemplate,x86_64,64)) $(eval $(call ObjTemplate,i386,DEBUG32,-debug,-DDEBUG)) $(eval $(call ObjTemplate,x86_64,DEBUG64,-debug,-DDEBUG)) +$(foreach arch,$(MAC_ARCHITECTURES),.libs/mac/extension-main.$(arch).o): EXTRA_DEFINES=-DEXTENSION + +.libs/mac/extension-main.%.o: + $(Q) rm -f $@ + $(call Q_2,CC, [mac]) $(MAC_CLANG) -c -DEXTENSION extension-main.m -arch $* -o $@ + +.libs/mac/libextension.%.a: .libs/mac/extension-main.%.o + $(Q) rm -f $@ + $(call Q_2,AR, [mac]) $(DEVICE_BIN_PATH)/ar cru $@ $^ + +.libs/mac/libextension.a: $(foreach arch,$(MAC_ARCHITECTURES),.libs/mac/libextension.$(arch).a) + $(Q) rm -f $@ + $(call Q_2,LIPO, [mac]) $(DEVICE_BIN_PATH)/lipo $^ -create -output $@ + .libs/mac/libxammac-debug.dylib: .libs/mac/libxammac-debug.x86_64.dylib .libs/mac/libxammac-debug.i386.dylib $(call Q_2,LIPO, [mac]) xcrun lipo -create $^ -o $@ diff --git a/runtime/launcher.m b/runtime/launcher.m index f45c0f71932c..1955a8595522 100644 --- a/runtime/launcher.m +++ b/runtime/launcher.m @@ -9,6 +9,8 @@ #include "xamarin/xamarin.h" #include "xamarin/launch.h" #include "launcher.h" +#include "runtime-internal.h" +#include "main-internal.h" #ifdef DYNAMIC_MONO_RUNTIME #define DEFAULT_MONO_RUNTIME "/Library/Frameworks/Mono.framework/Versions/Current" @@ -353,7 +355,7 @@ } static void -app_initialize (xamarin_initialize_data *data) +app_initialize (xamarin_initialize_data *data, bool is_extension) { // The launch code here is publicly documented in xamarin/launch.h // The numbers in the comments refer to numbers in xamarin/launch.h. @@ -429,28 +431,47 @@ mono_version = mono_get_runtime_build_info (); if (!check_mono_version (mono_version, [minVersion UTF8String])) exit_with_message ([[NSString stringWithFormat:@"This application requires the Mono framework version %@ or newer.", minVersion] UTF8String], data->basename, true); - // 6) Find the executable. The name is: [...] - NSString *exeName = NULL; - NSString *exePath; - if (plist != NULL) - exeName = (NSString *) [plist objectForKey:@"MonoBundleExecutable"]; - else - fprintf (stderr, PRODUCT ": Could not find Info.plist in the bundle.\n"); - - if (exeName == NULL) - exeName = [[NSString stringWithUTF8String: data->basename] stringByAppendingString: @".exe"]; - - if (mkbundle) { - exePath = exeName; - } else { - exePath = [[[NSString stringWithUTF8String: xamarin_get_bundle_path ()] stringByAppendingString: @"/"] stringByAppendingString: exeName]; + if (!is_extension) { + NSString *exeName = NULL; + NSString *exePath; + if (plist != NULL) + exeName = (NSString *) [plist objectForKey:@"MonoBundleExecutable"]; + else + fprintf (stderr, PRODUCT ": Could not find Info.plist in the bundle.\n"); - if (!xamarin_file_exists ([exePath UTF8String])) - exit_with_message ([[NSString stringWithFormat:@"Could not find the executable '%@'\n\nFull path: %@", exeName, exePath] UTF8String], data->basename, false); - } + if (exeName == NULL) + exeName = [[NSString stringWithUTF8String: data->basename] stringByAppendingString: @".exe"]; + + if (mkbundle) { + exePath = exeName; + } else { + exePath = [[[NSString stringWithUTF8String: xamarin_get_bundle_path ()] stringByAppendingString: @"/"] stringByAppendingString: exeName]; + + if (!xamarin_file_exists ([exePath UTF8String])) + exit_with_message ([[NSString stringWithFormat:@"Could not find the executable '%@'\n\nFull path: %@", exeName, exePath] UTF8String], data->basename, false); + } + exe_path = strdup ([exePath UTF8String]); + } else { + + mono_jit_init_version ("EmbeddedXamarinMac", "v4.0.0.0"); + + MonoAssembly *assembly = xamarin_open_assembly ("Xamarin.Mac.dll"); + if (!assembly) + xamarin_assertion_message ("Failed to load %s.", "Xamarin.Mac.dll"); + + MonoImage *image = mono_assembly_get_image (assembly); + + MonoClass *app_class = mono_class_from_name (image, "AppKit", "NSApplication"); + if (!app_class) + xamarin_assertion_message ("Fatal error: failed to load the NSApplication class"); - exe_path = strdup ([exePath UTF8String]); + MonoMethod *initialize = mono_class_get_method_from_name (app_class, "Init", 0); + if (!initialize) + xamarin_assertion_message ("Fatal error: failed to load the NSApplication init method"); + + mono_runtime_invoke (initialize, NULL, NULL, NULL); + } // 7a) [If not embedding] Parse the system Mono's config file ($monodir/etc/mono/config). // 7b) [If embedding] Parse $appdir/Contents/MonoBundle/machine.config and $appdir/Contents/MonoBundle/config @@ -499,7 +520,7 @@ #define __XAMARIN_MAC_RELAUNCH_APP__ "__XAMARIN_MAC_RELAUNCH_APP__" -int main (int argc, char **argv) +int xamarin_main (int argc, char **argv, bool is_extension) { xamarin_initialize_data data = { 0 }; @@ -521,7 +542,7 @@ int main (int argc, char **argv) if (data.is_relaunch) unsetenv (__XAMARIN_MAC_RELAUNCH_APP__); - app_initialize (&data); + app_initialize (&data, is_extension); if (data.exit) return data.exit_code; @@ -559,10 +580,24 @@ int main (int argc, char **argv) *ptr++ = argv [i]; *ptr = NULL; - rv = mono_main (new_argc, new_argv); + if (is_extension) { + rv = NSExtensionMain (new_argc, new_argv); + } else { + rv = mono_main (new_argc, new_argv); + } free (new_argv); } return rv; } + +int main (int argc, char **argv) +{ + return xamarin_main (argc, argv, false); +} + +int xamarin_mac_extension_main (int argc, char **argv) +{ + return xamarin_main (argc, argv, true); +} diff --git a/runtime/libxammac.csproj b/runtime/libxammac.csproj index a557101adbf4..85af8d224300 100644 --- a/runtime/libxammac.csproj +++ b/runtime/libxammac.csproj @@ -74,6 +74,7 @@ + diff --git a/runtime/main-internal.h b/runtime/main-internal.h index 9b58cae41dc3..b5fa37fb06de 100644 --- a/runtime/main-internal.h +++ b/runtime/main-internal.h @@ -6,9 +6,12 @@ extern "C" { #endif -#ifdef EXTENSION +//#ifdef EXTENSION int NSExtensionMain (int argc, char** argv); +#ifdef MONOMAC + int xamarin_mac_extension_main (int argc, char **argv); #endif +//#endif #ifdef WATCH_EXTENSION // WatchKit.framework defines a main function. diff --git a/runtime/runtime-internal.h b/runtime/runtime-internal.h index 1bb3472b580c..91989a1ff799 100644 --- a/runtime/runtime-internal.h +++ b/runtime/runtime-internal.h @@ -25,6 +25,7 @@ #endif void *xamarin_marshal_return_value (MonoType *mtype, const char *type, MonoObject *retval, bool retain, MonoMethod *method); +MonoAssembly * xamarin_open_assembly (const char *name); /* * XamarinGCHandle diff --git a/runtime/runtime.m b/runtime/runtime.m index 5d0559e32b33..6dfe571fc309 100644 --- a/runtime/runtime.m +++ b/runtime/runtime.m @@ -691,8 +691,8 @@ -(void) xamarinSetGCHandle: (int) gc_handle; return stat (path, &buffer) == 0; } -static MonoAssembly * -open_assembly (const char *name) +MonoAssembly * +xamarin_open_assembly (const char *name) { char path [1024]; MonoAssembly *assembly; @@ -761,7 +761,7 @@ -(void) xamarinSetGCHandle: (int) gc_handle; { MonoAssembly *assembly; - assembly = open_assembly (aname); + assembly = xamarin_open_assembly (aname); register_assembly (assembly); @@ -1001,7 +1001,7 @@ -(void) xamarinSetGCHandle: (int) gc_handle; product_dll = xamarin_use_new_assemblies ? PRODUCT_DUAL_ASSEMBLY : PRODUCT_COMPAT_ASSEMBLY; - assembly = open_assembly (product_dll); + assembly = xamarin_open_assembly (product_dll); if (!assembly) xamarin_assertion_message ("Failed to load %s.", product_dll); diff --git a/src/FinderSync/Enums.cs b/src/FinderSync/Enums.cs new file mode 100644 index 000000000000..d131cd0e4b71 --- /dev/null +++ b/src/FinderSync/Enums.cs @@ -0,0 +1,13 @@ +using System; +using XamCore.ObjCRuntime; + +namespace XamCore.FinderSync { + [Native] + public enum FIMenuKind : nuint + { + ContextualMenuForItems = 0, + ContextualMenuForContainer = 1, + ContextualMenuForSidebar = 2, + ToolbarItemMenu = 3 + } +} \ No newline at end of file diff --git a/src/NotificationCenter/NCEnums.cs b/src/NotificationCenter/NCEnums.cs index b08451dae4ec..e1e5048ae754 100644 --- a/src/NotificationCenter/NCEnums.cs +++ b/src/NotificationCenter/NCEnums.cs @@ -10,7 +10,7 @@ namespace XamCore.NotificationCenter { - [iOS (8,0)] + [iOS (8,0)][Mac (10,10)] [Native] public enum NCUpdateResult : nuint { NewData, diff --git a/src/appkit.cs b/src/appkit.cs index 17d3a640218a..458c90ebf764 100644 --- a/src/appkit.cs +++ b/src/appkit.cs @@ -7024,6 +7024,7 @@ public interface NSGestureRecognizerDelegate { } [BaseType (typeof (NSObject))] + [ThreadSafe] // Not documented anywhere, but their Finder extension sample uses it on non-ui thread [Dispose ("__mt_items_var = null;")] public partial interface NSMenu : NSCoding, NSCopying { [Export ("initWithTitle:")] @@ -7220,6 +7221,7 @@ public interface NSMenuDelegate { } [BaseType (typeof (NSObject))] + [ThreadSafe] // Not documented anywhere, but their Finder extension sample uses it on non-ui thread public interface NSMenuItem : NSCoding, NSCopying { [Static] [Export ("separatorItem")] @@ -14631,7 +14633,11 @@ public interface NSViewAnimation { [BaseType (typeof (NSResponder))] - public interface NSViewController : NSUserInterfaceItemIdentification, NSCoding, NSSeguePerforming { + public interface NSViewController : NSUserInterfaceItemIdentification, NSCoding, NSSeguePerforming +#if XAMCORE_2_0 + , NSExtensionRequestHandling +#endif + { [Export ("initWithNibName:bundle:")] IntPtr Constructor ([NullAllowed] string nibNameOrNull, [NullAllowed] NSBundle nibBundleOrNull); @@ -14775,26 +14781,31 @@ public interface NSViewController : NSUserInterfaceItemIdentification, NSCoding, [Export ("storyboard", ArgumentSemantic.Strong)] NSStoryboard Storyboard { get; } -// Needs NSExtensionRequestHandling support -// [Mac (10,10)] -// [Export ("extensionContext", ArgumentSemantic.Strong)] -// NSExtensionContext ExtensionContext { get; } -// -// [Mac (10,10)] -// [Export ("sourceItemView", ArgumentSemantic.Strong)] -// NSView SourceItemView { get; set; } -// -// [Mac (10,10)] -// [Export ("preferredScreenOrigin")] -// CGPoint PreferredScreenOrigin { get; set; } -// -// [Mac (10,10)] -// [Export ("preferredMinimumSize")] -// CGSize PreferredMinimumSize { get; } -// -// [Mac (10,10)] -// [Export ("preferredMaximumSize")] -// CGSize PreferredMaximumSize { get; } + [Mac (10,10)] + [Export ("presentViewControllerInWidget:")] + void PresentViewControllerInWidget (NSViewController viewController); + +#if XAMCORE_2_0 + [Mac (10, 10, onlyOn64: true)] + [NullAllowed, Export ("extensionContext", ArgumentSemantic.Retain)] + NSExtensionContext ExtensionContext { get; } + + [Mac (10, 10, onlyOn64: true)] + [NullAllowed, Export ("sourceItemView", ArgumentSemantic.Strong)] + NSView SourceItemView { get; set; } + + [Mac (10, 10, onlyOn64: true)] + [Export ("preferredScreenOrigin", ArgumentSemantic.Assign)] + CGPoint PreferredScreenOrigin { get; set; } + + [Mac (10, 10, onlyOn64: true)] + [Export ("preferredMinimumSize")] + CGSize PreferredMinimumSize { get; } + + [Mac (10, 10, onlyOn64: true)] + [Export ("preferredMaximumSize")] + CGSize PreferredMaximumSize { get; } +#endif } [Mac (10,10)] diff --git a/src/findersync.cs b/src/findersync.cs new file mode 100644 index 000000000000..49657cc3b34e --- /dev/null +++ b/src/findersync.cs @@ -0,0 +1,62 @@ +using System; +using XamCore.Foundation; +using XamCore.ObjCRuntime; +using XamCore.AppKit; + +#if XAMCORE_2_0 +namespace XamCore.FinderSync { + [Mac (10, 10, onlyOn64: true)] + [BaseType (typeof(NSExtensionContext))] + interface FIFinderSyncController + { + [Static] + [Export("defaultController")] + FIFinderSyncController DefaultController { get; } + + [Export ("directoryURLs", ArgumentSemantic.Copy)] + NSSet DirectoryUrls { get; set; } + + [Export ("setBadgeImage:label:forBadgeIdentifier:")] + void SetBadgeImage (NSImage image, [NullAllowed] string label, string badgeID); + + [Export ("setBadgeIdentifier:forURL:")] + void SetBadgeIdentifier (string badgeID, NSUrl url); + + [NullAllowed, Export ("targetedURL")] + NSUrl TargetedURL { get; } + + [NullAllowed, Export ("selectedItemURLs")] + NSUrl[] SelectedItemURLs { get; } + } + + [Mac (10, 10, onlyOn64: true)] + interface IFIFinderSync { } + + [Mac (10, 10, onlyOn64: true)] + [BaseType (typeof(NSObject))] + interface FIFinderSync : NSExtensionRequestHandling + { + [Export ("menuForMenuKind:")] + [return: NullAllowed] + NSMenu GetMenu (FIMenuKind menuKind); + + [Export ("beginObservingDirectoryAtURL:")] + void BeginObservingDirectory (NSUrl url); + + [Export ("endObservingDirectoryAtURL:")] + void EndObservingDirectory (NSUrl url); + + [Export ("requestBadgeIdentifierForURL:")] + void RequestBadgeIdentifier (NSUrl url); + + [Export ("toolbarItemName")] + string ToolbarItemName { get; } + + [Export ("toolbarItemImage", ArgumentSemantic.Copy)] + NSImage ToolbarItemImage { get; } + + [Export ("toolbarItemToolTip")] + string ToolbarItemToolTip { get; } + } +} +#endif \ No newline at end of file diff --git a/src/foundation.cs b/src/foundation.cs index 390e684d07e7..035d65e74e33 100644 --- a/src/foundation.cs +++ b/src/foundation.cs @@ -11395,7 +11395,21 @@ NSObject PropertyListWithStream (NSInputStream stream, NSPropertyListReadOptions bool IsValidForFormat (NSObject plist, NSPropertyListFormat format); } - [iOS (8,0)][Mac (10,10, onlyOn64 : true)] // Not defined in 32-bit +#if XAMCORE_2_0 || !MONOMAC + public interface INSExtensionRequestHandling { } + + [iOS (8,0)][Mac (10,10)] // Not defined in 32-bit + [Protocol, Model] + [BaseType (typeof (NSObject))] + public interface NSExtensionRequestHandling { + [Abstract] + [Mac (10,10, onlyOn64 : true)] + // @required - (void)beginRequestWithExtensionContext:(NSExtensionContext *)context; + [Export ("beginRequestWithExtensionContext:")] + void BeginRequestWithExtensionContext (NSExtensionContext context); + } +#else + [iOS (8,0)][Mac (10,10, onlyOn64:true)] // Not defined in 32-bit [Protocol, Model] [BaseType (typeof (NSObject))] public interface NSExtensionRequestHandling { @@ -11404,6 +11418,7 @@ public interface NSExtensionRequestHandling { [Export ("beginRequestWithExtensionContext:")] void BeginRequestWithExtensionContext (NSExtensionContext context); } +#endif [Protocol] public interface NSLocking { diff --git a/src/frameworks.sources b/src/frameworks.sources index 6b033b1ddb30..b2c11ebb3bde 100644 --- a/src/frameworks.sources +++ b/src/frameworks.sources @@ -570,6 +570,11 @@ EVENTKITUI_CORE_SOURCES = \ EXTERNALACCESSORY_API_SOURCES = \ ExternalAccessory/EAEnums.cs \ +# FinderSync + +FINDERSYNC_CORE_SOURCES = \ + FinderSync/Enums.cs \ + # Foundation FOUNDATION_CORE_SOURCES = \ @@ -1461,6 +1466,7 @@ MAC_FRAMEWORKS = \ CoreVideo \ CoreWlan \ EventKit \ + FinderSync \ GameController \ GameKit \ GameplayKit \ @@ -1479,6 +1485,7 @@ MAC_FRAMEWORKS = \ ModelIO \ MultipeerConnectivity \ NetworkExtension \ + NotificationCenter \ OpenGL \ PdfKit \ QTKit \ diff --git a/src/notificationcenter.cs b/src/notificationcenter.cs index 331fd5c0b5ca..058cfdbe860f 100644 --- a/src/notificationcenter.cs +++ b/src/notificationcenter.cs @@ -5,11 +5,13 @@ #if !MONOMAC using XamCore.UIKit; +#else +using XamCore.AppKit; #endif namespace XamCore.NotificationCenter { - [iOS (8,0)] + [iOS (8,0)][Mac (10,10)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // not meant to be user created interface NCWidgetController { @@ -22,7 +24,7 @@ interface NCWidgetController { void SetHasContent (bool flag, string bundleID); } - [iOS (8,0)] + [iOS (8,0)][Mac (10,10)] [Protocol, Model] [BaseType (typeof (NSObject))] interface NCWidgetProviding { @@ -31,10 +33,25 @@ interface NCWidgetProviding { void WidgetPerformUpdate(Action completionHandler); [Export ("widgetMarginInsetsForProposedMarginInsets:"), DelegateName ("NCWidgetProvidingMarginInsets"), DefaultValueFromArgument ("defaultMarginInsets")] +#if !MONOMAC UIEdgeInsets GetWidgetMarginInsets (UIEdgeInsets defaultMarginInsets); - } +#else + NSEdgeInsets GetWidgetMarginInsets (NSEdgeInsets defaultMarginInsets); +#endif + +#if MONOMAC + [Export ("widgetAllowsEditing")] + bool WidgetAllowsEditing { get; set; } + + [Export ("widgetDidBeginEditing")] + void WidgetDidBeginEditing (); + [Export ("widgetDidEndEditing")] + void WidgetDidEndEditing (); +#endif + } +#if !MONOMAC [iOS (8,0)] [BaseType (typeof (UIVibrancyEffect))] [Category] @@ -47,6 +64,109 @@ interface UIVibrancyEffect_NotificationCenter { [Static, Export ("notificationCenterVibrancyEffect")] UIVibrancyEffect NotificationCenterVibrancyEffect (); } +#endif + +#if MONOMAC + [Mac (10,10)] + [BaseType (typeof(NSViewController), Delegates=new string [] { "Delegate" }, Events=new Type [] { typeof (NCWidgetListViewDelegate)})] + interface NCWidgetListViewController + { + [Wrap ("WeakDelegate")] + NCWidgetListViewDelegate Delegate { get; set; } + + [NullAllowed, Export ("delegate", ArgumentSemantic.Weak)] + NSObject WeakDelegate { get; set; } + + [Export ("contents", ArgumentSemantic.Copy)] + NSViewController[] Contents { get; set; } + + [Export ("minimumVisibleRowCount", ArgumentSemantic.Assign)] + nuint MinimumVisibleRowCount { get; set; } + [Export ("hasDividerLines")] + bool HasDividerLines { get; set; } + + [Export ("editing")] + bool Editing { get; set; } + + [Export ("showsAddButtonWhenEditing")] + bool ShowsAddButtonWhenEditing { get; set; } + + [Export ("viewControllerAtRow:makeIfNecessary:")] + NSViewController GetViewController (nuint row, bool makeIfNecesary); + + [Export ("rowForViewController:")] + nuint GetRow (NSViewController viewController); + } + public interface INCWidgetListViewDelegate {} + + [Mac (10, 10)] + [Protocol, Model] + [BaseType (typeof(NSObject))] + interface NCWidgetListViewDelegate + { + [Abstract] + [Export ("widgetList:viewControllerForRow:"), DelegateName ("NCWidgetListViewGetController"), DefaultValue (null)] + NSViewController GetViewControllerForRow (NCWidgetListViewController list, nuint row); + + [Export ("widgetListPerformAddAction:"), DelegateName ("NCWidgetListViewController")] + void PerformAddAction (NCWidgetListViewController list); + + [Export ("widgetList:shouldReorderRow:"), DelegateName ("NCWidgetListViewControllerShouldReorderRow"), DefaultValue (false)] + bool ShouldReorderRow (NCWidgetListViewController list, nuint row); + + [Export ("widgetList:didReorderRow:toRow:"), EventArgs ("NCWidgetListViewControllerDidReorder"), DefaultValue (false)] + void DidReorderRow (NCWidgetListViewController list, nuint row, nuint newIndex); + + [Export ("widgetList:shouldRemoveRow:"), DelegateName ("NCWidgetListViewControllerShouldRemoveRow"), DefaultValue (false)] + bool ShouldRemoveRow (NCWidgetListViewController list, nuint row); + + [Export ("widgetList:didRemoveRow:"), EventArgs ("NCWidgetListViewControllerDidRemoveRow"), DefaultValue (false)] + void DidRemoveRow (NCWidgetListViewController list, nuint row); + } + + [Mac (10,10)] + [BaseType (typeof(NSViewController), Delegates=new string [] { "Delegate" }, Events=new Type [] { typeof (NCWidgetSearchViewDelegate)})] + interface NCWidgetSearchViewController + { + [Wrap ("WeakDelegate")] + NCWidgetSearchViewDelegate Delegate { get; set; } + + [NullAllowed, Export ("delegate", ArgumentSemantic.Weak)] + NSObject WeakDelegate { get; set; } + + [Export ("searchResults", ArgumentSemantic.Copy)] + NSObject[] SearchResults { get; set; } + + [Export ("searchDescription")] + string SearchDescription { get; set; } + + [Export ("searchResultsPlaceholderString")] + string SearchResultsPlaceholderString { get; set; } + + [Export ("searchResultKeyPath")] + string SearchResultKeyPath { get; set; } + } + + public interface INCWidgetSearchViewDelegate {} + + [Mac (10,10)] + [Protocol, Model] + [BaseType (typeof(NSObject))] + interface NCWidgetSearchViewDelegate + { + [Abstract] + [Export ("widgetSearch:searchForTerm:maxResults:"), EventArgs ("NSWidgetSearchForTerm"), DefaultValue (false)] + void SearchForTearm (NCWidgetSearchViewController controller, string searchTerm, nuint max); + + [Abstract] + [Export ("widgetSearchTermCleared:"), EventArgs ("NSWidgetSearchViewController"), DefaultValue (false)] + void TermCleared (NCWidgetSearchViewController controller); + + [Abstract] + [Export ("widgetSearch:resultSelected:"), EventArgs ("NSWidgetSearchResultSelected"), DefaultValue (false)] + void ResultSelected (NCWidgetSearchViewController controller, NSObject obj); + } +#endif } diff --git a/tools/mmp/driver.cs b/tools/mmp/driver.cs index 306393d03116..83151f7b7c96 100644 --- a/tools/mmp/driver.cs +++ b/tools/mmp/driver.cs @@ -106,6 +106,8 @@ public static partial class Driver { static int verbose = 0; public static bool Force; + static bool is_extension; + // This must be kept in sync with the system launcher's minimum mono version (in launcher/launcher-system.m) static Version MinimumMonoVersion = new Version (4, 2, 0); const string pkg_config = "/Library/Frameworks/Mono.framework/Commands/pkg-config"; @@ -281,6 +283,7 @@ static void Main2 (string [] args) { "custom_bundle_name=", "Specify a custom name for the MonoBundle folder.", v => custom_bundle_name = v, true }, // Hidden hack for "universal binaries" { "tls-provider=", "Specify the default TLS provider", v => { tls_provider = v; }}, { "http-message-handler=", "Specify the default HTTP Message Handler", v => { http_message_provider = v; }}, + { "extension", "Specifies an app extension", v => is_extension = true }, }; AddSharedOptions (os); @@ -491,7 +494,9 @@ static void Pack (IList unprocessed) if (registrar == RegistrarMode.Default) registrar = RegistrarMode.Dynamic; - + if (is_extension) + registrar = RegistrarMode.Static; + if (no_executable) { if (unprocessed.Count != 0) { var exceptions = new List (); @@ -562,7 +567,7 @@ static void Pack (IList unprocessed) GatherAssemblies (); CheckReferences (); - if (!resolved_assemblies.Exists (f => Path.GetExtension (f).ToLower () == ".exe")) + if (!is_extension && !resolved_assemblies.Exists (f => Path.GetExtension (f).ToLower () == ".exe")) throw new MonoMacException (79, true, "No executable was copied into the app bundle. Please contact 'support@xamarin.com'", ""); // i18n must be dealed outside linking too (e.g. bug 11448) @@ -1031,6 +1036,9 @@ static int Compile (IEnumerable internalSymbols) args.Append (Quote (finalLibPath)).Append (' '); } + if (is_extension) + args.Append ("-e _xamarin_mac_extension_main -framework NotificationCenter").Append(' '); + foreach (var f in BuildTarget.Frameworks) args.Append ("-framework ").Append (f).Append (' '); foreach (var f in BuildTarget.WeakFrameworks) @@ -1413,7 +1421,8 @@ static void CreateSymLink (string directory, string real, string link) /* Currently we clobber any existing files, perhaps we should error and have a -force flag */ static void CreateDirectoriesIfNeeded () { - App.AppDirectory = Path.Combine (output_dir, string.Format ("{0}.app", app_name)); + App.AppDirectory = Path.Combine (output_dir, string.Format("{0}.{1}", app_name, is_extension ? "appex" : "app")); + contents_dir = Path.Combine (App.AppDirectory, "Contents"); macos_dir = Path.Combine (contents_dir, "MacOS"); frameworks_dir = Path.Combine (contents_dir, "Frameworks");