annotate dep/animone/src/win/quartz.cc @ 310:a4257370de16

dep/animone: prepare for v1.0 release; it should be ready by now
author Paper <paper@paper.us.eu.org>
date Tue, 11 Jun 2024 04:38:51 -0400
parents 246017a7907a
children a7d4e5107531
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
1 /*
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
2 * win/quartz.cc: support for macOS (the Quartz Compositor)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
3 *
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
4 * This file does not require an Objective-C++ compiler,
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
5 * but it *does* require an Objective-C runtime.
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
6 */
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
7 #include "animone/win/quartz.h"
299
246017a7907a dep/animone: clean up OS X code
Paper <paper@paper.us.eu.org>
parents: 272
diff changeset
8 #include "animone/fd.h"
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
9 #include "animone.h"
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
10
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
11 #include <objc/message.h>
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
12 #include <objc/runtime.h>
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
13
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
14 #include <ApplicationServices/ApplicationServices.h>
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
15 #include <CoreFoundation/CoreFoundation.h>
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
16 #include <CoreGraphics/CoreGraphics.h>
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
17
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
18 namespace animone::internal::quartz {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
19
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
20 template<typename T>
271
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
21 struct CFDeconstructor {
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
22 using pointer = T;
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
23 void operator()(pointer t) const { ::CFRelease(t); };
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
24 };
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
25
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
26 template<typename T>
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
27 using CFPtr = std::unique_ptr<T, CFDeconstructor<T>>;
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
28
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
29 #if __LP64__
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
30 typedef long NSInteger;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
31 #else
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
32 typedef int NSInteger;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
33 #endif
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
34 typedef int CGSConnection;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
35
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
36 typedef CGSConnection (*CGSDefaultConnectionForThreadSpec)(void);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
37 typedef CGError (*CGSCopyWindowPropertySpec)(const CGSConnection, NSInteger, CFStringRef, CFStringRef*);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
38
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
39 static CGSDefaultConnectionForThreadSpec CGSDefaultConnectionForThread = nullptr;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
40 static CGSCopyWindowPropertySpec CGSCopyWindowProperty = nullptr;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
41
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
42 static const CFStringRef kCoreGraphicsBundleID = CFSTR("com.apple.CoreGraphics");
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
43
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
44 /* Objective-C */
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
45 typedef id (*object_message_send)(id, SEL, ...);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
46 typedef id (*class_message_send)(Class, SEL, ...);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
47
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
48 static const object_message_send obj_send = reinterpret_cast<object_message_send>(objc_msgSend);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
49 static const class_message_send cls_send = reinterpret_cast<class_message_send>(objc_msgSend);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
50
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
51 static bool GetCoreGraphicsPrivateSymbols() {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
52 CFBundleRef core_graphics_bundle = CFBundleGetBundleWithIdentifier(kCoreGraphicsBundleID);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
53 if (!core_graphics_bundle)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
54 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
55
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
56 CGSDefaultConnectionForThread = (CGSDefaultConnectionForThreadSpec)CFBundleGetFunctionPointerForName(
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
57 core_graphics_bundle, CFSTR("CGSDefaultConnectionForThread"));
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
58 if (!CGSDefaultConnectionForThread)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
59 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
60
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
61 CGSCopyWindowProperty = (CGSCopyWindowPropertySpec)CFBundleGetFunctionPointerForName(
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
62 core_graphics_bundle, CFSTR("CGSCopyWindowProperty"));
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
63 if (!CGSCopyWindowProperty)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
64 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
65
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
66 return true;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
67 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
68
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
69 template<typename T>
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
70 static bool GetCFNumber(CFNumberRef num, T& result) {
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
71 if (!num)
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
72 return false;
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
73
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
74 int64_t res;
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
75 if (!CFNumberGetValue(num, static_cast<CFNumberType>(4), &res))
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
76 return false;
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
77
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
78 result = static_cast<T>(res);
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
79 return true;
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
80 }
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
81
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
82 static bool StringFromCFString(CFStringRef string, std::string& result) {
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
83 if (!string)
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
84 return false;
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
85
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
86 result.resize(CFStringGetMaximumSizeForEncoding(CFStringGetLength(string), kCFStringEncodingUTF8) + 1);
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
87 if (!CFStringGetCString(string, &result.front(), result.length(), kCFStringEncodingUTF8))
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
88 return false;
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
89
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
90 return true;
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
91 }
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
92
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
93 template<typename T>
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
94 static bool CFDictionaryGetValue(CFDictionaryRef thedict, CFStringRef key, T& out) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
95 CFTypeRef data = nullptr;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
96 if (!CFDictionaryGetValueIfPresent(thedict, key, reinterpret_cast<const void**>(&data)) || !data)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
97 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
98
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
99 if constexpr (std::is_arithmetic<T>::value)
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
100 GetCFNumber(reinterpret_cast<CFNumberRef>(data), out);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
101 else if constexpr (std::is_same<T, std::string>::value)
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
102 StringFromCFString(reinterpret_cast<CFStringRef>(data), out);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
103 else
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
104 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
105
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
106 return true;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
107 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
108
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
109 static bool GetWindowTitleAccessibility(unsigned int wid, pid_t pid, std::string& result) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
110 CGRect bounds = {0};
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
111 {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
112 const CGWindowID wids[1] = {wid};
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
113 CFPtr<CFArrayRef> arr(CFArrayCreate(kCFAllocatorDefault, (CFTypeRef*)wids, 1, NULL));
271
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
114 CFPtr<CFArrayRef> dicts(CGWindowListCreateDescriptionFromArray(arr.get()));
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
115
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
116 if (!dicts.get() || CFArrayGetCount(dicts.get()) < 1)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
117 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
118
271
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
119 CFDictionaryRef dict = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(dicts.get(), 0));
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
120 if (!dict)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
121 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
122
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
123 CFDictionaryRef bounds_dict = nullptr;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
124 if (!CFDictionaryGetValueIfPresent(dict, kCGWindowBounds, reinterpret_cast<CFTypeRef*>(&bounds_dict)) ||
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
125 !bounds_dict)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
126 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
127
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
128 if (!CGRectMakeWithDictionaryRepresentation(bounds_dict, &bounds))
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
129 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
130 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
131
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
132 /* now we can actually do stuff */
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
133 AXUIElementRef axapp = AXUIElementCreateApplication(pid);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
134 CFPtr<CFArrayRef> windows;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
135 {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
136 CFArrayRef ref;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
137 if ((AXUIElementCopyAttributeValue(axapp, kAXWindowsAttribute, reinterpret_cast<CFTypeRef*>(&ref)) !=
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
138 kAXErrorSuccess) ||
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
139 !windows)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
140 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
141
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
142 windows.reset(ref);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
143 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
144
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
145 const CFIndex count = CFArrayGetCount(windows.get());
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
146 for (CFIndex i = 0; i < count; i++) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
147 const AXUIElementRef window = reinterpret_cast<AXUIElementRef>(CFArrayGetValueAtIndex(windows.get(), i));
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
148
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
149 /* does this leak memory? probably. */
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
150 AXValueRef val;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
151 if (AXUIElementCopyAttributeValue(window, kAXPositionAttribute, reinterpret_cast<CFTypeRef*>(&val)) ==
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
152 kAXErrorSuccess) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
153 CGPoint point;
272
5437009cb10e dep/animone: get macOS side building
Paper <paper@paper.us.eu.org>
parents: 271
diff changeset
154 if (!AXValueGetValue(val, static_cast<AXValueType>(kAXValueCGPointType), reinterpret_cast<void*>(&point)) ||
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
155 (point.x != bounds.origin.x || point.y != bounds.origin.y)) {
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
156 CFRelease(val);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
157 continue;
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
158 }
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
159 } else {
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
160 CFRelease(val);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
161 continue;
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
162 }
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
163
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
164 CFRelease(val);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
165
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
166 if (AXUIElementCopyAttributeValue(window, kAXSizeAttribute, reinterpret_cast<CFTypeRef*>(&val)) ==
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
167 kAXErrorSuccess) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
168 CGSize size;
272
5437009cb10e dep/animone: get macOS side building
Paper <paper@paper.us.eu.org>
parents: 271
diff changeset
169 if (!AXValueGetValue(val, static_cast<AXValueType>(kAXValueCGSizeType), reinterpret_cast<void*>(&size)) ||
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
170 (size.width != bounds.size.width || size.height != bounds.size.height)) {
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
171 CFRelease(val);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
172 continue;
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
173 }
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
174 } else {
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
175 CFRelease(val);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
176 continue;
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
177 }
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
178
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
179 CFRelease(val);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
180
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
181 CFStringRef title;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
182 if (AXUIElementCopyAttributeValue(window, kAXTitleAttribute, reinterpret_cast<CFTypeRef*>(&title)) ==
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
183 kAXErrorSuccess) {
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
184 bool success = StringFromCFString(title, result);
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
185 CFRelease(title);
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
186 return success;
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
187 }
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
188 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
189
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
190 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
191 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
192
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
193 static bool GetWindowTitle(unsigned int wid, pid_t pid, std::string& result) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
194 /* try using CoreGraphics (only usable on old versions of OS X) */
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
195 if ((CGSDefaultConnectionForThread && CGSCopyWindowProperty) || GetCoreGraphicsPrivateSymbols()) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
196 CFPtr<CFStringRef> title;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
197 {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
198 CFStringRef t = nullptr;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
199 CGSCopyWindowProperty(CGSDefaultConnectionForThread(), wid, CFSTR("kCGSWindowTitle"), &t);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
200 title.reset(t);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
201 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
202
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
203 if (title && CFStringGetLength(title.get()) && StringFromCFString(title.get(), result))
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
204 return true;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
205 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
206
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
207 /* then try linking to a window using the accessibility API */
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
208 return AXIsProcessTrusted() ? GetWindowTitleAccessibility(wid, pid, result) : false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
209 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
210
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
211 static bool GetProcessBundleIdentifierNew(pid_t pid, std::string& result) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
212 /* 10.6 and higher */
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
213 const id app =
271
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
214 cls_send((Class)objc_getClass("NSRunningApplication"), sel_getUid("runningApplicationWithProcessIdentifier:"), pid);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
215 if (!app)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
216 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
217
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
218 CFStringRef bundle_id = reinterpret_cast<CFStringRef>(obj_send(app, sel_getUid("bundleIdentifier")));
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
219 if (!bundle_id)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
220 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
221
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
222 return StringFromCFString(bundle_id, result);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
223 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
224
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
225 static bool GetProcessBundleIdentifierOld(pid_t pid, std::string& result) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
226 /* OS X 10.2; deprecated in 10.9 */
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
227 ProcessSerialNumber psn;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
228 if (GetProcessForPID(pid, &psn))
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
229 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
230
271
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
231 CFPtr<CFDictionaryRef> info(ProcessInformationCopyDictionary(&psn, kProcessDictionaryIncludeAllInformationMask));
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
232 if (!info)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
233 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
234
271
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
235 CFStringRef value = reinterpret_cast<CFStringRef>(CFDictionaryGetValue(info.get(), CFSTR("CFBundleIdentifier")));
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
236 if (!value)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
237 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
238
268
382b50754fe4 dep/animone: make osx code a bit less hacky
Paper <paper@paper.us.eu.org>
parents: 258
diff changeset
239 return StringFromCFString(value, result);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
240 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
241
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
242 static bool GetProcessBundleIdentifier(pid_t pid, std::string& result) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
243 /* The Bundle ID is essentially OS X's solution to Windows'
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
244 * "class name"; theoretically, it should be different for
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
245 * each program, although it requires an app bundle.
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
246 */
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
247 if (GetProcessBundleIdentifierNew(pid, result))
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
248 return true;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
249
271
f01b6e9c8fa2 dep/animone: make OS X code build
Paper <paper@paper.us.eu.org>
parents: 268
diff changeset
250 return GetProcessBundleIdentifierOld(pid, result);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
251 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
252
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
253 bool EnumerateWindows(window_proc_t window_proc) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
254 if (!window_proc)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
255 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
256
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
257 const CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
258 if (!windows)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
259 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
260
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
261 const CFIndex count = CFArrayGetCount(windows);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
262 for (CFIndex i = 0; i < count; i++) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
263 CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windows, i));
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
264 if (!window)
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
265 continue;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
266
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
267 Process proc;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
268 {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
269 CFDictionaryGetValue(window, CFSTR("kCGWindowOwnerPID"), proc.pid);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
270 if (!CFDictionaryGetValue(window, CFSTR("kCGWindowOwnerName"), proc.name))
299
246017a7907a dep/animone: clean up OS X code
Paper <paper@paper.us.eu.org>
parents: 272
diff changeset
271 fd::GetProcessName(proc.pid, proc.name);
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
272 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
273
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
274 Window win;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
275 {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
276 CFDictionaryGetValue(window, CFSTR("kCGWindowNumber"), win.id);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
277
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
278 if (!GetProcessBundleIdentifier(proc.pid, win.class_name))
299
246017a7907a dep/animone: clean up OS X code
Paper <paper@paper.us.eu.org>
parents: 272
diff changeset
279 /* XXX is this right? */
258
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
280 CFDictionaryGetValue(window, CFSTR("kCGWindowName"), win.class_name);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
281
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
282 GetWindowTitle(win.id, proc.pid, win.text);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
283 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
284
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
285 if (!window_proc(proc, win)) {
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
286 CFRelease(windows);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
287 return false;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
288 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
289 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
290
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
291 CFRelease(windows);
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
292
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
293 return true;
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
294 }
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
295
862d0d8619f6 *: HUUUGE changes
Paper <paper@paper.us.eu.org>
parents:
diff changeset
296 } // namespace animone::internal::quartz