Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Bockover <abock@microsoft.com>2019-10-30 23:12:54 +0300
committermonojenkins <jo.shields+jenkins@xamarin.com>2019-11-05 03:19:57 +0300
commitdec980560eac3ca0d870a47cd61410b227498bb8 (patch)
tree8bdb594c3a1ab5d2f4a0c173fb3c24c8f0eb5926
parenteb93b60a5eae416d0c0cbfc37c27892b8710e2c1 (diff)
MacIdeAppleEvents: add an apple event for getting current solution pathbackport-pr-9172-to-release-8.4
-rw-r--r--main/src/addins/MacPlatform/MacIdeAppleEvents.cs86
-rw-r--r--main/src/addins/MacPlatform/MacPlatform.cs4
-rw-r--r--main/src/addins/MacPlatform/MacPlatform.csproj4
-rw-r--r--main/src/addins/MacPlatform/query-vsmac.mm204
4 files changed, 298 insertions, 0 deletions
diff --git a/main/src/addins/MacPlatform/MacIdeAppleEvents.cs b/main/src/addins/MacPlatform/MacIdeAppleEvents.cs
new file mode 100644
index 0000000000..2fecf12ecd
--- /dev/null
+++ b/main/src/addins/MacPlatform/MacIdeAppleEvents.cs
@@ -0,0 +1,86 @@
+//
+// Copyright (c) Microsoft Corp. (https://www.microsoft.com)
+//
+// Authors:
+// Aaron Bockover <abock@microsoft.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using Foundation;
+using ObjCRuntime;
+
+using MonoDevelop.Core;
+using MonoDevelop.Ide;
+
+namespace MacPlatform
+{
+ sealed class MacIdeAppleEvents : NSObject
+ {
+ // From AE.framework AppleEvents.h
+ const uint keyDirectObject = 757935405; // '----'
+ const uint keyErrorNumber = 1701999214; // 'errn'
+ const uint keyErrorString = 1701999219; // 'errs'
+
+ // Our own private event FourCCs; note that all-lowercase FourCCs are reserved by Apple;
+ // any FourCC that has at least one capital letter is considered private to the application.
+ const AEEventClass WorkspaceEventClass = (AEEventClass)1448302419; // 'VSWS' FourCC
+ const AEEventID CurrentSelectedSolutionPathEventID = (AEEventID)1129534288; // 'CSSP' FourCC
+
+ public MacIdeAppleEvents ()
+ {
+ NSAppleEventManager.SharedAppleEventManager.SetEventHandler (
+ this,
+ sel_getCurrentSelectedSolutionPath_withReply_,
+ WorkspaceEventClass,
+ CurrentSelectedSolutionPathEventID);
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ if (disposing) {
+ NSAppleEventManager.SharedAppleEventManager.RemoveEventHandler (
+ WorkspaceEventClass,
+ CurrentSelectedSolutionPathEventID);
+ }
+
+ base.Dispose (disposing);
+ }
+
+ const string getCurrentSelectedSolutionPath_withReply_
+ = "getCurrentSelectedSolutionPath:withReply:";
+
+ static readonly Selector sel_getCurrentSelectedSolutionPath_withReply_
+ = new Selector (getCurrentSelectedSolutionPath_withReply_);
+
+ [Export (getCurrentSelectedSolutionPath_withReply_)]
+ void GetCurrentSelectedSolutionPath (NSAppleEventDescriptor @event, NSAppleEventDescriptor reply)
+ {
+ LoggingService.LogInfo ($"{nameof (GetCurrentSelectedSolutionPath)}: received AppleEvent {@event}");
+
+ var solutionPath = IdeApp.Workspace.CurrentSelectedSolution?.FileName.FullPath.ToString ();
+ if (!string.IsNullOrEmpty (solutionPath)) {
+ reply.SetParamDescriptorforKeyword (
+ NSAppleEventDescriptor.DescriptorWithString (solutionPath),
+ keyDirectObject);
+
+ LoggingService.LogInfo ($"{nameof (GetCurrentSelectedSolutionPath)}: replying to AppleEvent {@event} with {solutionPath}");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MacPlatform/MacPlatform.cs b/main/src/addins/MacPlatform/MacPlatform.cs
index 85e3d11f50..0034752c0e 100644
--- a/main/src/addins/MacPlatform/MacPlatform.cs
+++ b/main/src/addins/MacPlatform/MacPlatform.cs
@@ -139,6 +139,8 @@ namespace MonoDevelop.MacIntegration
AccessibilityInUse = val.BoolValue;
}
+ MacIdeAppleEvents ideAppleEvents;
+
public MacPlatformService ()
{
if (initedGlobal)
@@ -349,6 +351,8 @@ namespace MonoDevelop.MacIntegration
IdeApp.LaunchReason = IdeApp.LaunchType.Normal;
}
+ ideAppleEvents = new MacIdeAppleEvents ();
+
return loaded;
}
diff --git a/main/src/addins/MacPlatform/MacPlatform.csproj b/main/src/addins/MacPlatform/MacPlatform.csproj
index 7f051bd92d..403ddb6edb 100644
--- a/main/src/addins/MacPlatform/MacPlatform.csproj
+++ b/main/src/addins/MacPlatform/MacPlatform.csproj
@@ -116,6 +116,7 @@
<Compile Include="MacHttpMessageHandlerProvider.cs" />
<Compile Include="NSUrlSessionCredentialsHandler.cs" />
<Compile Include="BasicAuthenticationHandler.cs" />
+ <Compile Include="MacIdeAppleEvents.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MacPlatform.addin.xml" />
@@ -157,6 +158,9 @@
<ItemGroup>
<LibXammac Include="..\..\..\external\libxammac.dylib" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="query-vsmac.mm" />
+ </ItemGroup>
<Target Name="AfterBuild">
<Copy SourceFiles="@(LibXammac)" DestinationFiles="$(OutputPath)\libxammac.dylib" SkipUnchangedFiles="true" />
</Target>
diff --git a/main/src/addins/MacPlatform/query-vsmac.mm b/main/src/addins/MacPlatform/query-vsmac.mm
new file mode 100644
index 0000000000..88a8a7dac6
--- /dev/null
+++ b/main/src/addins/MacPlatform/query-vsmac.mm
@@ -0,0 +1,204 @@
+//
+// Copyright (c) Microsoft Corp. (https://www.microsoft.com)
+//
+// Authors:
+// Aaron Bockover <abock@microsoft.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// % clang++ -o query-vsmac -ObjC -fcxx-modules -fmodules -Werror -Wall -Wpedantic query-vsmac.mm
+
+@import AppKit;
+@import CoreServices;
+
+#ifdef __cplusplus
+#define VS_EXTERN extern "C"
+#else
+#define VS_EXTERN extern
+#endif
+
+VS_EXTERN NSRunningApplication **
+VSQueryRunningInstances()
+{
+ NSArray<NSRunningApplication *> *allApps = NSWorkspace.sharedWorkspace.runningApplications;
+ if (!allApps)
+ return nil;
+
+ NSRunningApplication **instances = (NSRunningApplication **)calloc(
+ [allApps count] + 1,
+ sizeof(NSRunningApplication *));
+ if (!instances)
+ goto ret;
+
+ int i = 0;
+
+ for (NSRunningApplication *runningApp in NSWorkspace.sharedWorkspace.runningApplications) {
+ if ([runningApp.bundleIdentifier isEqual: @"com.microsoft.visual-studio"] ||
+ [runningApp.bundleIdentifier isEqual: @"com.xamarin.monodevelop"])
+ instances[i++] = [runningApp retain];
+ }
+
+ret:
+ [allApps release];
+ return instances;
+}
+
+VS_EXTERN void
+VSFreeRunningInstances(NSRunningApplication **instances)
+{
+ if (!instances)
+ return;
+
+ for (int i = 0; instances && instances[i]; i++)
+ [instances[i] release];
+
+ free(instances);
+}
+
+static char *
+NSStringToUTF8Dup(NSString *str)
+{
+ if (str) {
+ const char *utf8str = [str UTF8String];
+ if (utf8str)
+ return strdup(utf8str);
+ }
+
+ return NULL;
+}
+
+VS_EXTERN char *
+VSQueryInstanceCurrentSelectedSolutionPath(NSRunningApplication *runningApplication)
+{
+ NSAppleEventDescriptor *targetDescriptor = [NSAppleEventDescriptor
+ descriptorWithProcessIdentifier: runningApplication.processIdentifier];
+
+ NSAppleEventDescriptor* appleEvent = [NSAppleEventDescriptor
+ appleEventWithEventClass: 1448302419
+ eventID: 1129534288
+ targetDescriptor: targetDescriptor
+ returnID: kAutoGenerateReturnID
+ transactionID: kAnyTransactionID];
+
+ AEDesc aeReply = { 0, };
+
+ OSErr sendResult = AESendMessage(
+ [appleEvent aeDesc],
+ &aeReply,
+ kAEWaitReply | kAENeverInteract,
+ kAEDefaultTimeout);
+
+ [targetDescriptor release];
+ [appleEvent release];
+
+ if (sendResult != noErr) {
+ return NULL;
+ }
+
+ NSAppleEventDescriptor *reply = [[NSAppleEventDescriptor alloc] initWithAEDescNoCopy: &aeReply];
+ NSString *path = [[reply descriptorForKeyword: keyDirectObject] stringValue];
+ [reply release];
+
+ return NSStringToUTF8Dup(path);
+}
+
+VS_EXTERN pid_t
+VSGetInstanceProcessIdentifier(NSRunningApplication *instance)
+{
+ if (!instance)
+ return -1;
+
+ return instance.processIdentifier;
+}
+
+VS_EXTERN char *
+VSGetInstanceBundlePath(NSRunningApplication *instance)
+{
+ if (!instance || !instance.bundleURL)
+ return NULL;
+
+ return NSStringToUTF8Dup(instance.bundleURL.path);
+}
+
+VS_EXTERN char *
+VSGetInstanceExecutablePath(NSRunningApplication *instance)
+{
+ if (!instance || !instance.executableURL)
+ return NULL;
+
+ return NSStringToUTF8Dup(instance.executableURL.path);
+}
+
+VS_EXTERN char *
+VSGetInstanceLocalizedName(NSRunningApplication *instance)
+{
+ if (!instance)
+ return NULL;
+
+ return NSStringToUTF8Dup(instance.localizedName);
+}
+
+VS_EXTERN char *
+VSGetInstanceVersion(NSRunningApplication *instance)
+{
+ if (!instance || !instance.bundleURL)
+ return NULL;
+
+ NSBundle *bundle = [NSBundle bundleWithURL: instance.bundleURL];
+ if (!bundle)
+ return NULL;
+
+ id versionValue = [bundle objectForInfoDictionaryKey: @"CFBundleVersion"];
+ if (versionValue && [versionValue isKindOfClass: [NSString class]])
+ return NSStringToUTF8Dup((NSString *)versionValue);
+
+ return NULL;
+}
+
+int main(int argc, char **argv)
+{
+ NSRunningApplication **instances = VSQueryRunningInstances();
+
+ for (int i = 0; instances && instances[i]; i++) {
+ NSRunningApplication *instance = instances[i];
+
+ pid_t pid = VSGetInstanceProcessIdentifier(instance);
+ char *name = VSGetInstanceLocalizedName(instance);
+ char *version = VSGetInstanceVersion(instance);
+ char *bunPath = VSGetInstanceBundlePath(instance);
+ char *exePath = VSGetInstanceExecutablePath(instance);
+ char *slnPath = VSQueryInstanceCurrentSelectedSolutionPath(instance);
+
+ printf("%s %s\n", name, version);
+ printf(" pid: %u\n", pid);
+ printf(" bun: %s\n", bunPath);
+ printf(" exe: %s\n", exePath);
+ printf(" sln: %s\n", slnPath);
+
+ free(name);
+ free(version);
+ free(bunPath);
+ free(exePath);
+ free(slnPath);
+ }
+
+ VSFreeRunningInstances(instances);
+
+ return 0;
+}