changeset 162:61b76c7b656a

dep/animia: add os x launchservices method
author Paper <mrpapersonic@gmail.com>
date Fri, 17 Nov 2023 16:49:57 -0500
parents 71752dcbb49f
children 44c5e6dd9488
files dep/animia/CMakeLists.txt dep/animia/include/animia/util/osx.h dep/animia/src/animia.cc dep/animia/src/fd/xnu.cc dep/animia/src/util/osx.cc
diffstat 5 files changed, 131 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/dep/animia/CMakeLists.txt	Fri Nov 17 13:09:20 2023 -0500
+++ b/dep/animia/CMakeLists.txt	Fri Nov 17 16:49:57 2023 -0500
@@ -10,6 +10,8 @@
 	src/win.cc
 )
 
+include(CheckLanguage)
+
 set(LIBRARIES)
 set(INCLUDE_DIRS)
 set(DEFINES)
@@ -20,6 +22,14 @@
 		# xnu stuff
 		src/fd/xnu.cc
 	)
+
+	include(CheckIncludeFile)
+	check_include_file("CoreFoundation/CoreFoundation.h" HAVE_COREFOUNDATION)
+	if (HAVE_COREFOUNDATION)
+		list(APPEND DEFINES HAVE_COREFOUNDATION)
+		list(APPEND SRC_FILES src/util/osx.cc)
+	endif()
+
 	check_language(OBJCXX)
 	if(CMAKE_OBJCXX_COMPILER)
 		enable_language(OBJCXX)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dep/animia/include/animia/util/osx.h	Fri Nov 17 16:49:57 2023 -0500
@@ -0,0 +1,13 @@
+#ifndef __animia__animia__util__osx_h
+#define __animia__animia__util__osx_h
+
+#include "animia/types.h"
+#include <string>
+
+namespace animia::internal::osx::util {
+
+bool LaunchServicesGetProcessName(pid_t pid, std::string& result);
+
+}
+
+#endif // __animia__animia__util__osx_h
--- a/dep/animia/src/animia.cc	Fri Nov 17 13:09:20 2023 -0500
+++ b/dep/animia/src/animia.cc	Fri Nov 17 16:49:57 2023 -0500
@@ -72,11 +72,6 @@
 	         We should set the PID of the process if we can get it, but that'll be for when
 	         I can actually be arsed to implement the X11 backend. */
 	auto window_proc = [&](const Process& process, const Window& window) -> bool {
-		std::cout << "Window ID: " << window.id << "\n"
-			<< "\tClass name: " << window.class_name << "\n"
-			<< "\tTitle text: " << window.text << "\n"
-			<< "\tProcess info: " << "\n"
-			<< "\t\tPID: " << process.pid << "\n";
 		for (const auto& player : players) {
 			if (!internal::PlayerHasStrategy(player, Strategy::WindowTitle))
 				continue;
--- a/dep/animia/src/fd/xnu.cc	Fri Nov 17 13:09:20 2023 -0500
+++ b/dep/animia/src/fd/xnu.cc	Fri Nov 17 16:49:57 2023 -0500
@@ -1,8 +1,11 @@
 /*
-** fd/xnu.cpp
+** fd/xnu.cc
 **  - provides support for XNU (part of Darwin)
 */
 #include "animia/fd/xnu.h"
+#ifdef HAVE_COREFOUNDATION
+#	include "animia/util/osx.h"
+#endif
 #include "animia.h"
 
 #include <cassert>
@@ -28,18 +31,22 @@
 
 	/* Get the initial size of the array */
 	size_t size;
-	int ret = sysctl((int*)mib, mib_size, nullptr, &size, nullptr, 0);
-	if (ret)
-		return false;
+	{
+		int ret = sysctl((int*)mib, mib_size, nullptr, &size, nullptr, 0);
+		if (ret)
+			return false;
+	}
 
 	/* Reserve the space for it in a std::string */
 	std::string args;
 	args.resize(size);
 
 	/* Get the contents of argc and argv */
-	ret = sysctl((int*)mib, mib_size, &args.front(), &size, NULL, 0);
-	if (ret)
-		return false;
+	{
+		int ret = sysctl((int*)mib, mib_size, &args.front(), &size, NULL, 0);
+		if (ret)
+			return false;
+	}
 
 	/* Is the size big enough to hold at least argc? */
 	if (size < sizeof(int))
@@ -51,8 +58,7 @@
 	int argc;
 	memcpy(&argc, &args.front(), sizeof(argc));
 
-	/* Check for a condition that, realistically, would never happen,
-	   but better to be safe than sorry */
+	/* Do we even have argv[0]? */
 	if (argc < 1)
 		return false;
 
@@ -81,7 +87,13 @@
 }
 
 static bool GetProcessName(pid_t pid, std::string& result) {
-	/* First try parsing the arguments, this prevents the process name being
+	/* Use LaunchServices */
+#ifdef HAVE_COREFOUNDATION
+	if (osx::util::LaunchServicesGetProcessName(pid, result))
+		return true;
+#endif
+
+	/* Try parsing the arguments, this prevents the process name being
 	   cut off to 2*MAXCOMLEN (32 chars) */
 	if (GetProcessNameFromArgs(pid, result))
 		return true;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dep/animia/src/util/osx.cc	Fri Nov 17 16:49:57 2023 -0500
@@ -0,0 +1,86 @@
+/* A wrapper around multiple LaunchServices things */
+
+#include "animia/util/osx.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <iostream>
+
+namespace animia::internal::osx::util {
+
+#define RDSymbolNameStr(symbol) (CFSTR("_"#symbol))
+
+static constexpr int kLaunchServicesMagicConstant = -2; // or -1, dunno the difference
+
+typedef CFTypeRef (*LSASNCreateWithPidSpec)(CFAllocatorRef, pid_t);
+typedef CFDictionaryRef (*LSCopyApplicationInformationSpec)(int, CFTypeRef, CFArrayRef);
+
+static LSCopyApplicationInformationSpec LSCopyApplicationInformation = nullptr;
+static LSASNCreateWithPidSpec LSASNCreateWithPid = nullptr;
+
+static CFStringRef (kLSDisplayNameKey) = nullptr;
+static CFStringRef (kLSPIDKey) = nullptr;
+
+static CFStringRef (kLaunchServicesBundleID) = CFSTR("com.apple.LaunchServices");
+
+static bool FindLaunchServicesPrivateSymbols() {
+	CFBundleRef launch_services_bundle = CFBundleGetBundleWithIdentifier(kLaunchServicesBundleID);
+	if (!launch_services_bundle)
+		return false;
+
+	LSCopyApplicationInformation = (LSCopyApplicationInformationSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, RDSymbolNameStr(LSCopyApplicationInformation));
+	if (!LSCopyApplicationInformation)
+		return false;
+
+	LSASNCreateWithPid = (LSASNCreateWithPidSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, RDSymbolNameStr(LSASNCreateWithPid));
+	if (!LSASNCreateWithPid)
+		return false;
+
+	kLSDisplayNameKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, RDSymbolNameStr(kLSDisplayNameKey));
+	if (!kLSDisplayNameKey)
+		return false;
+
+	kLSPIDKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, RDSymbolNameStr(kLSPIDKey));
+	if (!kLSPIDKey)
+		return false;
+
+	return true;
+}
+
+bool LaunchServicesGetProcessName(pid_t pid, std::string& result) {
+	if (!LSCopyApplicationInformation || !LSASNCreateWithPid)
+		if (!FindLaunchServicesPrivateSymbols())
+			return false;
+
+	CFTypeRef asn = LSASNCreateWithPid(kCFAllocatorDefault, pid);
+
+	CFArrayRef request_array = CFArrayCreate(NULL, (const void **)kLSDisplayNameKey, 1, NULL);
+
+	CFDictionaryRef dictionary = LSCopyApplicationInformation(kLaunchServicesMagicConstant, asn, request_array);
+
+	CFRelease(request_array);
+	if (!dictionary)
+		return false;
+
+	CFStringRef str;
+	if (!CFDictionaryGetValueIfPresent(dictionary, kLSDisplayNameKey, (CFTypeRef*)&str) || !str) {
+		CFRelease(dictionary);
+		return false;
+	}
+	CFRetain(str);
+
+	CFRelease(dictionary);
+
+	result.reserve(CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1);
+
+	if (!CFStringGetCString(str, &result.front(), result.length(), result.length())) {
+		CFRelease(str);
+		return false;
+	}
+
+	CFRelease(str);
+
+	return true;
+}
+
+}