Mercurial > minori
diff dep/animia/src/win/quartz.cc @ 191:0fc126d52de4
animia: multiple stylistic choices
win.class_name is now used to store bundle IDs on OS X,
add some little explanations here and there for dumb stuff
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Thu, 07 Dec 2023 01:48:04 -0500 |
parents | 2d5823df870f |
children | 50108040d792 |
line wrap: on
line diff
--- a/dep/animia/src/win/quartz.cc Wed Dec 06 21:26:13 2023 -0500 +++ b/dep/animia/src/win/quartz.cc Thu Dec 07 01:48:04 2023 -0500 @@ -1,3 +1,10 @@ +/* + * win/quartz.cc: support for macOS (the Quartz Compositor) + * + * This file does not require an Objective-C++ compiler, + * but it *does* require an Objective-C runtime and linking + * with AppKit in order to receive proper window titles. +*/ #include "animia/win/quartz.h" #include "animia/util/osx.h" #include "animia.h" @@ -8,8 +15,6 @@ #include <CoreFoundation/CoreFoundation.h> #include <CoreGraphics/CoreGraphics.h> -#include <iostream> - namespace animia::internal::quartz { typedef id (*object_message_send)(id, SEL, ...); @@ -20,16 +25,15 @@ static bool GetWindowTitle(unsigned int wid, std::string& result) { // NSApplication* app = [NSApplication sharedApplication]; - id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication")); + const id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication")); // NSWindow* window = [app windowWithWindowNumber: wid]; - id window = obj_send(app, sel_getUid("windowWithWindowNumber:"), wid); + const id window = obj_send(app, sel_getUid("windowWithWindowNumber:"), wid); if (!window) return false; // NSString* title = [window title]; - // does this have to be freed? - CFStringRef title = reinterpret_cast<CFStringRef>(obj_send(window, sel_getUid("title"))); + const CFStringRef title = reinterpret_cast<CFStringRef>(obj_send(window, sel_getUid("title"))); if (!title) return false; @@ -37,6 +41,26 @@ return osx::util::StringFromCFString(title, result); } +static bool GetWindowBundleIdentifier(pid_t pid, std::string& result) { + /* The Bundle ID is essentially OS X's solution to Windows' + * "class name"; theoretically, it should be different for + * each program, although it requires an app bundle. + */ + + // NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier: pid]; + const id app = cls_send(objc_getClass("NSRunningApplication"), sel_getUid("runningApplicationWithProcessIdentifier:"), pid); + if (!app) + return false; + + // NSString* bundle_id = [app bundleIdentifier]; + const CFStringRef bundle_id = reinterpret_cast<CFStringRef>(obj_send(app, sel_getUid("bundleIdentifier"))); + if (!bundle_id) + return false; + + // return [bundle_id UTF8String]; + return osx::util::StringFromCFString(bundle_id, result); +} + bool QuartzWinTools::EnumerateWindows(window_proc_t window_proc) { if (!window_proc) return false; @@ -74,7 +98,9 @@ if (CFDictionaryGetValueIfPresent(window, CFSTR("kCGWindowNumber"), reinterpret_cast<const void**>(&num)) && num) osx::util::GetCFNumber(num, win.id); } - { + if (!GetWindowBundleIdentifier(proc.pid, win.class_name)) { + // Fallback to the Quartz window name, which is unlikely to be filled, but it + // *could* be. CFStringRef str = nullptr; if (CFDictionaryGetValueIfPresent(window, CFSTR("kCGWindowName"), reinterpret_cast<const void**>(&str)) && str) osx::util::StringFromCFString(str, win.class_name);