Mercurial > minori
diff dep/animone/src/win/quartz.cc @ 268:382b50754fe4
dep/animone: make osx code a bit less hacky
it would be nice if macos actually provided a real API for getting
window titles (outside of the accessibility api). the accessibility
API is a real mess to work with; the user has to give permission to
access it under newer versions.
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Fri, 12 Apr 2024 05:21:45 -0400 |
parents | 862d0d8619f6 |
children | f01b6e9c8fa2 |
line wrap: on
line diff
--- a/dep/animone/src/win/quartz.cc Thu Apr 11 22:05:41 2024 -0400 +++ b/dep/animone/src/win/quartz.cc Fri Apr 12 05:21:45 2024 -0400 @@ -17,6 +17,9 @@ namespace animone::internal::quartz { +template<typename T> +using CFPtr = std::unique_ptr<T, CFDecontructor<T>>; + #if __LP64__ typedef long NSInteger; #else @@ -58,21 +61,51 @@ } template<typename T> +static bool GetCFNumber(CFNumberRef num, T& result) { + if (!num) + return false; + + int64_t res; + if (!CFNumberGetValue(num, static_cast<CFNumberType>(4), &res)) + return false; + + result = static_cast<T>(res); + return true; +} + +static bool StringFromCFString(CFStringRef string, std::string& result) { + if (!string) + return false; + + result.resize(CFStringGetMaximumSizeForEncoding(CFStringGetLength(string), kCFStringEncodingUTF8) + 1); + if (!CFStringGetCString(string, &result.front(), result.length(), kCFStringEncodingUTF8)) + return false; + + return true; +} + +template<typename T> static bool CFDictionaryGetValue(CFDictionaryRef thedict, CFStringRef key, T& out) { CFTypeRef data = nullptr; if (!CFDictionaryGetValueIfPresent(thedict, key, reinterpret_cast<const void**>(&data)) || !data) return false; if constexpr (std::is_arithmetic<T>::value) - osx::util::GetCFNumber(reinterpret_cast<CFNumberRef>(data), out); + GetCFNumber(reinterpret_cast<CFNumberRef>(data), out); else if constexpr (std::is_same<T, std::string>::value) - osx::util::StringFromCFString(reinterpret_cast<CFStringRef>(data), out); + StringFromCFString(reinterpret_cast<CFStringRef>(data), out); else return false; return true; } +template<typename T> +struct CFDeconstructor { + using pointer = T; + void operator()(pointer t) const { ::CFRelease(t); }; +}; + static bool GetWindowTitleAccessibility(unsigned int wid, pid_t pid, std::string& result) { CGRect bounds = {0}; { @@ -119,24 +152,39 @@ kAXErrorSuccess) { CGPoint point; if (!AXValueGetValue(val, kAXValueTypeCGPoint, reinterpret_cast<CFTypeRef>(&point)) || - (point.x != bounds.origin.x || point.y != bounds.origin.y)) + (point.x != bounds.origin.x || point.y != bounds.origin.y)) { + CFRelease(val); continue; - } else + } + } else { + CFRelease(val); continue; + } + + CFRelease(val); if (AXUIElementCopyAttributeValue(window, kAXSizeAttribute, reinterpret_cast<CFTypeRef*>(&val)) == kAXErrorSuccess) { CGSize size; if (!AXValueGetValue(val, kAXValueTypeCGSize, reinterpret_cast<CFTypeRef>(&size)) || - (size.width != bounds.size.width || size.height != bounds.size.height)) + (size.width != bounds.size.width || size.height != bounds.size.height)) { + CFRelease(val); continue; - } else + } + } else { + CFRelease(val); continue; + } + + CFRelease(val); CFStringRef title; if (AXUIElementCopyAttributeValue(window, kAXTitleAttribute, reinterpret_cast<CFTypeRef*>(&title)) == - kAXErrorSuccess) - return osx::util::StringFromCFString(title, result); + kAXErrorSuccess) { + bool success = StringFromCFString(title, result); + CFRelease(title); + return success; + } } return false; @@ -152,7 +200,7 @@ title.reset(t); } - if (title && CFStringGetLength(title.get()) && osx::util::StringFromCFString(title.get(), result)) + if (title && CFStringGetLength(title.get()) && StringFromCFString(title.get(), result)) return true; } @@ -171,8 +219,7 @@ if (!bundle_id) return false; - result = osx::util::StringFromCFString(bundle_id, result); - return true; + return StringFromCFString(bundle_id, result); } static bool GetProcessBundleIdentifierOld(pid_t pid, std::string& result) { @@ -189,8 +236,7 @@ if (!value) return false; - result = osx::util::StringFromCFString(value, result); - return true; + return StringFromCFString(value, result); } static bool GetProcessBundleIdentifier(pid_t pid, std::string& result) {