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");