Mercurial > minori
comparison dep/animone/src/win/quartz.cc @ 271:f01b6e9c8fa2
dep/animone: make OS X code build
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Sun, 14 Apr 2024 22:28:50 -0400 |
| parents | 382b50754fe4 |
| children | 5437009cb10e |
comparison
equal
deleted
inserted
replaced
| 270:0718f538c5f9 | 271:f01b6e9c8fa2 |
|---|---|
| 16 #include <CoreGraphics/CoreGraphics.h> | 16 #include <CoreGraphics/CoreGraphics.h> |
| 17 | 17 |
| 18 namespace animone::internal::quartz { | 18 namespace animone::internal::quartz { |
| 19 | 19 |
| 20 template<typename T> | 20 template<typename T> |
| 21 using CFPtr = std::unique_ptr<T, CFDecontructor<T>>; | 21 struct CFDeconstructor { |
| 22 using pointer = T; | |
| 23 void operator()(pointer t) const { ::CFRelease(t); }; | |
| 24 }; | |
| 25 | |
| 26 template<typename T> | |
| 27 using CFPtr = std::unique_ptr<T, CFDeconstructor<T>>; | |
| 22 | 28 |
| 23 #if __LP64__ | 29 #if __LP64__ |
| 24 typedef long NSInteger; | 30 typedef long NSInteger; |
| 25 #else | 31 #else |
| 26 typedef int NSInteger; | 32 typedef int NSInteger; |
| 98 return false; | 104 return false; |
| 99 | 105 |
| 100 return true; | 106 return true; |
| 101 } | 107 } |
| 102 | 108 |
| 103 template<typename T> | |
| 104 struct CFDeconstructor { | |
| 105 using pointer = T; | |
| 106 void operator()(pointer t) const { ::CFRelease(t); }; | |
| 107 }; | |
| 108 | |
| 109 static bool GetWindowTitleAccessibility(unsigned int wid, pid_t pid, std::string& result) { | 109 static bool GetWindowTitleAccessibility(unsigned int wid, pid_t pid, std::string& result) { |
| 110 CGRect bounds = {0}; | 110 CGRect bounds = {0}; |
| 111 { | 111 { |
| 112 const CGWindowID wids[1] = {wid}; | 112 const CGWindowID wids[1] = {wid}; |
| 113 CFPtr<CFArrayRef> arr(CFArrayCreate(kCFAllocatorDefault, (CFTypeRef*)wids, 1, NULL)); | 113 CFPtr<CFArrayRef> arr(CFArrayCreate(kCFAllocatorDefault, (CFTypeRef*)wids, 1, NULL)); |
| 114 CFPtr<CFArrayRef> dicts(CGWindowListCreateDescriptionFromArray(arr)); | 114 CFPtr<CFArrayRef> dicts(CGWindowListCreateDescriptionFromArray(arr.get())); |
| 115 | 115 |
| 116 if (!dicts.get() || CFArrayGetCount(dicts.get()) < 1) | 116 if (!dicts.get() || CFArrayGetCount(dicts.get()) < 1) |
| 117 return false; | 117 return false; |
| 118 | 118 |
| 119 CFDictionaryRef dict = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(dicts, 0)); | 119 CFDictionaryRef dict = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(dicts.get(), 0)); |
| 120 if (!dict) | 120 if (!dict) |
| 121 return false; | 121 return false; |
| 122 | 122 |
| 123 CFDictionaryRef bounds_dict = nullptr; | 123 CFDictionaryRef bounds_dict = nullptr; |
| 124 if (!CFDictionaryGetValueIfPresent(dict, kCGWindowBounds, reinterpret_cast<CFTypeRef*>(&bounds_dict)) || | 124 if (!CFDictionaryGetValueIfPresent(dict, kCGWindowBounds, reinterpret_cast<CFTypeRef*>(&bounds_dict)) || |
| 149 /* does this leak memory? probably. */ | 149 /* does this leak memory? probably. */ |
| 150 AXValueRef val; | 150 AXValueRef val; |
| 151 if (AXUIElementCopyAttributeValue(window, kAXPositionAttribute, reinterpret_cast<CFTypeRef*>(&val)) == | 151 if (AXUIElementCopyAttributeValue(window, kAXPositionAttribute, reinterpret_cast<CFTypeRef*>(&val)) == |
| 152 kAXErrorSuccess) { | 152 kAXErrorSuccess) { |
| 153 CGPoint point; | 153 CGPoint point; |
| 154 if (!AXValueGetValue(val, kAXValueTypeCGPoint, reinterpret_cast<CFTypeRef>(&point)) || | 154 if (!AXValueGetValue(val, kAXValueCGPointType, reinterpret_cast<void*>(&point)) || |
| 155 (point.x != bounds.origin.x || point.y != bounds.origin.y)) { | 155 (point.x != bounds.origin.x || point.y != bounds.origin.y)) { |
| 156 CFRelease(val); | 156 CFRelease(val); |
| 157 continue; | 157 continue; |
| 158 } | 158 } |
| 159 } else { | 159 } else { |
| 164 CFRelease(val); | 164 CFRelease(val); |
| 165 | 165 |
| 166 if (AXUIElementCopyAttributeValue(window, kAXSizeAttribute, reinterpret_cast<CFTypeRef*>(&val)) == | 166 if (AXUIElementCopyAttributeValue(window, kAXSizeAttribute, reinterpret_cast<CFTypeRef*>(&val)) == |
| 167 kAXErrorSuccess) { | 167 kAXErrorSuccess) { |
| 168 CGSize size; | 168 CGSize size; |
| 169 if (!AXValueGetValue(val, kAXValueTypeCGSize, reinterpret_cast<CFTypeRef>(&size)) || | 169 if (!AXValueGetValue(val, kAXValueCGSizeType, reinterpret_cast<void*>(&size)) || |
| 170 (size.width != bounds.size.width || size.height != bounds.size.height)) { | 170 (size.width != bounds.size.width || size.height != bounds.size.height)) { |
| 171 CFRelease(val); | 171 CFRelease(val); |
| 172 continue; | 172 continue; |
| 173 } | 173 } |
| 174 } else { | 174 } else { |
| 209 } | 209 } |
| 210 | 210 |
| 211 static bool GetProcessBundleIdentifierNew(pid_t pid, std::string& result) { | 211 static bool GetProcessBundleIdentifierNew(pid_t pid, std::string& result) { |
| 212 /* 10.6 and higher */ | 212 /* 10.6 and higher */ |
| 213 const id app = | 213 const id app = |
| 214 cls_send(objc_getClass("NSRunningApplication"), sel_getUid("runningApplicationWithProcessIdentifier:"), pid); | 214 cls_send((Class)objc_getClass("NSRunningApplication"), sel_getUid("runningApplicationWithProcessIdentifier:"), pid); |
| 215 if (!app) | 215 if (!app) |
| 216 return false; | 216 return false; |
| 217 | 217 |
| 218 CFStringRef bundle_id = reinterpret_cast<CFStringRef>(obj_send(app, sel_getUid("bundleIdentifier"))); | 218 CFStringRef bundle_id = reinterpret_cast<CFStringRef>(obj_send(app, sel_getUid("bundleIdentifier"))); |
| 219 if (!bundle_id) | 219 if (!bundle_id) |
| 226 /* OS X 10.2; deprecated in 10.9 */ | 226 /* OS X 10.2; deprecated in 10.9 */ |
| 227 ProcessSerialNumber psn; | 227 ProcessSerialNumber psn; |
| 228 if (GetProcessForPID(pid, &psn)) | 228 if (GetProcessForPID(pid, &psn)) |
| 229 return false; | 229 return false; |
| 230 | 230 |
| 231 CFPtr<CFDictionaryRef> info = ProcessInformationCopyDictionary(psn, kProcessDictionaryIncludeAllInformationMask); | 231 CFPtr<CFDictionaryRef> info(ProcessInformationCopyDictionary(&psn, kProcessDictionaryIncludeAllInformationMask)); |
| 232 if (!info) | 232 if (!info) |
| 233 return false; | 233 return false; |
| 234 | 234 |
| 235 CFStringRef value = reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("CFBundleIdentifier"))); | 235 CFStringRef value = reinterpret_cast<CFStringRef>(CFDictionaryGetValue(info.get(), CFSTR("CFBundleIdentifier"))); |
| 236 if (!value) | 236 if (!value) |
| 237 return false; | 237 return false; |
| 238 | 238 |
| 239 return StringFromCFString(value, result); | 239 return StringFromCFString(value, result); |
| 240 } | 240 } |
| 245 * each program, although it requires an app bundle. | 245 * each program, although it requires an app bundle. |
| 246 */ | 246 */ |
| 247 if (GetProcessBundleIdentifierNew(pid, result)) | 247 if (GetProcessBundleIdentifierNew(pid, result)) |
| 248 return true; | 248 return true; |
| 249 | 249 |
| 250 return GetProcessBundleIdentifierOld(); | 250 return GetProcessBundleIdentifierOld(pid, result); |
| 251 } | 251 } |
| 252 | 252 |
| 253 bool EnumerateWindows(window_proc_t window_proc) { | 253 bool EnumerateWindows(window_proc_t window_proc) { |
| 254 if (!window_proc) | 254 if (!window_proc) |
| 255 return false; | 255 return false; |
