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;