annotate dep/animia/src/win/quartz.cc @ 237:a7d0d543b334

*: make OS X builds succeed new script: deploy_build.sh, creates the app bundle
author Paper <paper@paper.us.eu.org>
date Fri, 19 Jan 2024 11:14:44 -0500
parents bc1ae1810855
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
1 /*
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
2 * win/quartz.cc: support for macOS (the Quartz Compositor)
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
3 *
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
4 * This file does not require an Objective-C++ compiler,
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
5 * but it *does* require an Objective-C runtime.
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
6 */
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
7 #include "animia/win/quartz.h"
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
8 #include "animia/util/osx.h"
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
9 #include "animia.h"
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
10
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
11 #include <objc/runtime.h>
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
12 #include <objc/message.h>
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
13
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
14 #include <CoreFoundation/CoreFoundation.h>
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
15 #include <CoreGraphics/CoreGraphics.h>
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
16 #include <ApplicationServices/ApplicationServices.h>
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
17
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
18 namespace animia::internal::quartz {
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
19
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
20 /* all of these LaunchServices things use *internal functions* that are subject
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
21 * to change. Granted, it's not very likely that these will change very much
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
22 * because I'm fairly sure Apple uses them lots in their own internal code.
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
23 */
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
24 #if __LP64__
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
25 typedef long NSInteger;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
26 #else
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
27 typedef int NSInteger;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
28 #endif
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
29 typedef int CGSConnection;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
30
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
31 typedef CGSConnection (*CGSDefaultConnectionForThreadSpec)(void);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
32 typedef CGError (*CGSCopyWindowPropertySpec)(const CGSConnection, NSInteger, CFStringRef, CFStringRef*);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
33
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
34 static CGSDefaultConnectionForThreadSpec CGSDefaultConnectionForThread = nullptr;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
35 static CGSCopyWindowPropertySpec CGSCopyWindowProperty = nullptr;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
36
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
37 static const CFStringRef kCoreGraphicsBundleID = CFSTR("com.apple.CoreGraphics");
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
38
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
39 /* Objective-C */
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
40 typedef id (*object_message_send)(id, SEL, ...);
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
41 typedef id (*class_message_send)(Class, SEL, ...);
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
42
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
43 static const object_message_send obj_send = reinterpret_cast<object_message_send>(objc_msgSend);
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
44 static const class_message_send cls_send = reinterpret_cast<class_message_send>(objc_msgSend);
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
45
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
46 static bool GetCoreGraphicsPrivateSymbols() {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
47 CFBundleRef core_graphics_bundle = CFBundleGetBundleWithIdentifier(kCoreGraphicsBundleID);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
48 if (!core_graphics_bundle)
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
49 return false;
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
50
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
51 CGSDefaultConnectionForThread = (CGSDefaultConnectionForThreadSpec)CFBundleGetFunctionPointerForName(core_graphics_bundle, CFSTR("CGSDefaultConnectionForThread"));
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
52 if (!CGSDefaultConnectionForThread)
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
53 return false;
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
54
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
55 CGSCopyWindowProperty = (CGSCopyWindowPropertySpec)CFBundleGetFunctionPointerForName(core_graphics_bundle, CFSTR("CGSCopyWindowProperty"));
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
56 if (!CGSCopyWindowProperty)
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
57 return false;
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
58
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
59 return true;
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
60 }
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
61
197
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
62 template<typename T>
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
63 static bool CFDictionaryGetValue(CFDictionaryRef thedict, CFStringRef key, T& out) {
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
64 CFTypeRef data = nullptr;
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
65 if (!CFDictionaryGetValueIfPresent(thedict, key, reinterpret_cast<const void**>(&data)) || !data)
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
66 return false;
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
67
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
68 if constexpr (std::is_arithmetic<T>::value)
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
69 osx::util::GetCFNumber(reinterpret_cast<CFNumberRef>(data), out);
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
70 else if constexpr (std::is_same<T, std::string>::value)
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
71 osx::util::StringFromCFString(reinterpret_cast<CFStringRef>(data), out);
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
72 else
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
73 return false;
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
74
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
75 return true;
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
76 }
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
77
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
78 static bool GetWindowTitleAccessibility(unsigned int wid, pid_t pid, std::string& result) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
79 CGRect bounds = {0};
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
80 {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
81 const CGWindowID wids[1] = {wid};
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
82 CFArrayRef arr = CFArrayCreate(kCFAllocatorDefault, (CFTypeRef*)wids, 1, NULL);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
83
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
84 CFArrayRef dicts = CGWindowListCreateDescriptionFromArray(arr);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
85
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
86 CFRelease(arr);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
87
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
88 if (!dicts || CFArrayGetCount(dicts) < 1)
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
89 return false;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
90
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
91 CFDictionaryRef dict = (CFDictionaryRef)CFArrayGetValueAtIndex(dicts, 0);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
92 if (!dict) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
93 CFRelease(dicts);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
94 return false;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
95 }
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
96
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
97 CFDictionaryRef bounds_dict = nullptr;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
98 if (!CFDictionaryGetValueIfPresent(dict, kCGWindowBounds, reinterpret_cast<CFTypeRef*>(&bounds_dict)) || !bounds_dict) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
99 CFRelease(dicts);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
100 return false;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
101 }
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
102
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
103 if (!CGRectMakeWithDictionaryRepresentation(bounds_dict, &bounds)) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
104 CFRelease(dicts);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
105 return false;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
106 }
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
107
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
108 CFRelease(dicts);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
109 }
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
110
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
111 /* now we can actually do stuff */
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
112 AXUIElementRef axapp = AXUIElementCreateApplication(pid);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
113 CFArrayRef windows;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
114 if ((AXUIElementCopyAttributeValue(axapp, kAXWindowsAttribute, (CFTypeRef*)&windows) != kAXErrorSuccess) || !windows)
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
115 return false;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
116
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
117 const CFIndex count = CFArrayGetCount(windows);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
118 for (CFIndex i = 0; i < count; i++) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
119 const AXUIElementRef window = (AXUIElementRef)CFArrayGetValueAtIndex(windows, i);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
120
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
121 AXValueRef val;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
122 if (AXUIElementCopyAttributeValue(window, kAXPositionAttribute, (CFTypeRef*)&val) == kAXErrorSuccess) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
123 CGPoint point;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
124 if (!AXValueGetValue(val, kAXValueTypeCGPoint, (void*)&point) || (point.x != bounds.origin.x || point.y != bounds.origin.y))
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
125 continue;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
126 } else continue;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
127
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
128 if (AXUIElementCopyAttributeValue(window, kAXSizeAttribute, (CFTypeRef*)&val) == kAXErrorSuccess) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
129 CGSize size;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
130 if (!AXValueGetValue(val, kAXValueTypeCGSize, (void*)&size) || (size.width != bounds.size.width || size.height != bounds.size.height))
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
131 continue;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
132 } else continue;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
133
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
134 CFStringRef title;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
135 if (AXUIElementCopyAttributeValue(window, kAXTitleAttribute, (CFTypeRef*)&title) == kAXErrorSuccess) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
136 CFRelease(windows);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
137 return osx::util::StringFromCFString(title, result);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
138 }
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
139 }
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
140
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
141 CFRelease(windows);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
142
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
143 return false;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
144 }
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
145
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
146 static bool GetWindowTitle(unsigned int wid, pid_t pid, std::string& result) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
147 /* private internal OS X functions */
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
148 if ((CGSDefaultConnectionForThread && CGSCopyWindowProperty) || GetCoreGraphicsPrivateSymbols()) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
149 CFStringRef title = nullptr;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
150
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
151 CGSCopyWindowProperty(CGSDefaultConnectionForThread(), wid, CFSTR("kCGSWindowTitle"), &title);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
152 if (title && CFStringGetLength(title) && osx::util::StringFromCFString(title, result))
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
153 return true;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
154 }
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
155
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
156 /* don't attempt to use accessibility if we aren't trusted */
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
157 return AXIsProcessTrusted() ? GetWindowTitleAccessibility(wid, pid, result) : false;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
158 }
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
159
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
160 static bool GetProcessBundleIdentifier(pid_t pid, std::string& result) {
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
161 /* The Bundle ID is essentially OS X's solution to Windows'
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
162 * "class name"; theoretically, it should be different for
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
163 * each program, although it requires an app bundle.
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
164 */
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
165 const id app = cls_send(objc_getClass("NSRunningApplication"), sel_getUid("runningApplicationWithProcessIdentifier:"), pid);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
166 if (!app)
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
167 return false;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
168
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
169 CFStringRef bundle_id = reinterpret_cast<CFStringRef>(obj_send(app, sel_getUid("bundleIdentifier")));
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
170 if (!bundle_id)
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
171 return false;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
172
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
173 result = osx::util::StringFromCFString(bundle_id, result);
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
174 return true;
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
175 }
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
176
198
bc1ae1810855 dep/animia: switch from using classes to global functions
Paper <mrpapersonic@gmail.com>
parents: 197
diff changeset
177 bool EnumerateWindows(window_proc_t window_proc) {
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
178 if (!window_proc)
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
179 return false;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
180
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
181 const CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
182 if (!windows)
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
183 return false;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
184
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
185 const CFIndex count = CFArrayGetCount(windows);
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
186 for (CFIndex i = 0; i < count; i++) {
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
187 CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windows, i));
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
188 if (!window)
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
189 continue;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
190
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
191 Process proc;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
192 {
197
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
193 CFDictionaryGetValue(window, CFSTR("kCGWindowOwnerPID"), proc.pid);
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
194 if (!CFDictionaryGetValue(window, CFSTR("kCGWindowOwnerName"), proc.name))
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
195 osx::util::GetProcessName(proc.pid, proc.name);
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
196 }
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
197
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
198 Window win;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
199 {
197
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
200 CFDictionaryGetValue(window, CFSTR("kCGWindowNumber"), win.id);
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
201
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
202 if (!GetProcessBundleIdentifier(proc.pid, win.class_name))
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
203 // Fallback to the Quartz window name, which is unlikely to be filled, but it
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
204 // *could* be.
197
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
205 CFDictionaryGetValue(window, CFSTR("kCGWindowName"), win.class_name);
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
206
237
a7d0d543b334 *: make OS X builds succeed
Paper <paper@paper.us.eu.org>
parents: 198
diff changeset
207 GetWindowTitle(win.id, proc.pid, win.text);
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
208 }
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
209
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
210 if (!window_proc(proc, win)) {
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
211 CFRelease(windows);
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
212 return false;
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
213 }
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
214 }
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
215
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
216 CFRelease(windows);
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
217
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
218 return true;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
219 }
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
220
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
221 } // namespace animia::win::detail