diff dep/animia/src/win/quartz.cc @ 189:649786bae914

*: etc. code cleanup I've removed most macros and stuff dep/animia: [UNTESTED] use raw C++ instead of Objective-C++
author Paper <mrpapersonic@gmail.com>
date Wed, 06 Dec 2023 19:42:33 -0500
parents
children 2d5823df870f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dep/animia/src/win/quartz.cc	Wed Dec 06 19:42:33 2023 -0500
@@ -0,0 +1,84 @@
+/* We actually DON'T need Objective-C for most of this file.
+ * GetWindowTitle() is the only function that really needs it.
+ * (and even then, we can use the C bindings for it...)
+ *
+ * However, being able to use the Foundation classes makes things
+ * so, so, so much easier, and so I've decided to make this file
+ * in Objective-C++.
+*/
+#include "animia/win/quartz.h"
+#include "animia.h"
+
+#include <objc/runtime.h>
+#include <objc/message.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreGraphics/CoreGraphics.h>
+#include <Carbon/Carbon.h>
+
+namespace animia::internal::quartz {
+
+static bool GetWindowTitle(unsigned int wid, std::string& result) {
+	// id app = [NSApplication sharedApplication];
+	id app = cls_msg(cls("NSApplication"), sel("sharedApplication"));
+
+	// id window = [app windowWithWindowNumber: wid];
+	id window = msg(app, sel("windowWithWindowNumber:"), wid);
+
+	// return [[window title] UTF8String];
+	return StringFromCFString(reinterpret_cast<CFStringRef>(msg(window, "title")), result);
+}
+
+bool QuartzWinTools::EnumerateWindows(window_proc_t window_proc) {
+	if (!window_proc)
+		return false;
+
+	CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
+	if (!windows)
+		return false;
+
+	CFIndex i = 0; count = CFArrayGetCount(windows);
+	for (; i < count; i++) {
+		CFDictionaryRef window = CFArrayGetValueAtIndex(windows, i);
+		if (!window)
+			continue;
+
+		Process proc;
+		{
+			{
+				CFNumber num;
+				CFDictionaryGetValueIfPresent(window, "kCGWindowOwnerPID", &num);
+				osx::util::GetCFNumber(num, proc.pid);
+			}
+			{
+				CFStringRef str;
+				CFDictionaryGetValueIfPresent(window, "kCGWindowOwnerName", &str);
+				osx::util::StringFromCFString(str, proc.name);
+			}
+			if (proc.name.empty())
+				osx::util::GetProcessName(proc.pid, proc.name);
+		}
+
+		Window win;
+		{
+			{
+				CFNumber num;
+				CFDictionaryGetValueIfPresent(window, "kCGWindowNumber", &num);
+				osx::util::GetCFNumber(num, win.id);
+			}
+			{
+				CFStringRef str;
+				CFDictionaryGetValueIfPresent(window, "kCGWindowName", &str);
+				osx::util::GetCFNumber(str, win.class_name);
+			}
+			GetWindowTitle(win.id, win.text);
+		}
+
+		if (!window_proc(proc, win))
+			return false;
+	}
+
+	return true;
+}
+
+} // namespace animia::win::detail