annotate dep/animia/src/win/quartz.cc @ 198:bc1ae1810855

dep/animia: switch from using classes to global functions the old idea was ok, but sort of hackish; this method doesn't use classes at all, and this way (especially important!) we can do wayland stuff AND x11 at the same time, which wasn't really possible without stupid workarounds in the other method
author Paper <mrpapersonic@gmail.com>
date Sun, 24 Dec 2023 02:59:42 -0500
parents c4ca035c565d
children a7d0d543b334
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,
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
5 * but it *does* require an Objective-C runtime and linking
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
6 * with AppKit in order to receive proper window titles.
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
7 */
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
8 #include "animia/win/quartz.h"
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
9 #include "animia/util/osx.h"
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
10 #include "animia.h"
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
11
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
12 #include <objc/runtime.h>
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
13 #include <objc/message.h>
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
14
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
15 #include <CoreFoundation/CoreFoundation.h>
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
16 #include <CoreGraphics/CoreGraphics.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
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
20 typedef id (*object_message_send)(id, SEL, ...);
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
21 typedef id (*class_message_send)(Class, SEL, ...);
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
22
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
23 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
24 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
25
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
26 static bool GetWindowTitle(unsigned int wid, std::string& result) {
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
27 // NSApplication* app = [NSApplication sharedApplication];
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
28 const id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication"));
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
29
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
30 // NSWindow* window = [app windowWithWindowNumber: wid];
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
31 const id window = obj_send(app, sel_getUid("windowWithWindowNumber:"), wid);
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
32 if (!window)
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
33 return false;
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
34
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
35 // NSString* title = [window title];
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
36 const CFStringRef title = reinterpret_cast<CFStringRef>(obj_send(window, sel_getUid("title")));
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
37 if (!title)
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
38 return false;
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
39
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
40 // return [title UTF8String];
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
41 return osx::util::StringFromCFString(title, result);
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
42 }
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
43
192
50108040d792 dep/animia/quartz: GetWindowBundleIdentifier -> GetProcessBundleIdentifier
Paper <mrpapersonic@gmail.com>
parents: 191
diff changeset
44 static bool GetProcessBundleIdentifier(pid_t pid, std::string& result) {
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
45 /* The Bundle ID is essentially OS X's solution to Windows'
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
46 * "class name"; theoretically, it should be different for
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
47 * each program, although it requires an app bundle.
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
48 */
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
49
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
50 // NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier: pid];
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
51 const id app = cls_send(objc_getClass("NSRunningApplication"), sel_getUid("runningApplicationWithProcessIdentifier:"), pid);
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
52 if (!app)
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
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
55 // NSString* bundle_id = [app bundleIdentifier];
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
56 const CFStringRef bundle_id = reinterpret_cast<CFStringRef>(obj_send(app, sel_getUid("bundleIdentifier")));
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
57 if (!bundle_id)
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
58 return false;
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
59
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
60 // return [bundle_id UTF8String];
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
61 return osx::util::StringFromCFString(bundle_id, result);
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
62 }
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
63
197
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
64 template<typename T>
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
65 static bool CFDictionaryGetValue(CFDictionaryRef thedict, CFStringRef key, T& out) {
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
66 CFTypeRef data = nullptr;
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
67 if (!CFDictionaryGetValueIfPresent(thedict, key, reinterpret_cast<const void**>(&data)) || !data)
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
68 return false;
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
69
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
70 if constexpr (std::is_arithmetic<T>::value)
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
71 osx::util::GetCFNumber(reinterpret_cast<CFNumberRef>(data), out);
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
72 else if constexpr (std::is_same<T, std::string>::value)
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
73 osx::util::StringFromCFString(reinterpret_cast<CFStringRef>(data), out);
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
74 else
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
75 return false;
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
76
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
77 return true;
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
78 }
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
79
198
bc1ae1810855 dep/animia: switch from using classes to global functions
Paper <mrpapersonic@gmail.com>
parents: 197
diff changeset
80 bool EnumerateWindows(window_proc_t window_proc) {
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
81 if (!window_proc)
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
82 return false;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
83
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
84 const CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
85 if (!windows)
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
86 return false;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
87
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
88 const CFIndex count = CFArrayGetCount(windows);
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
89 for (CFIndex i = 0; i < count; i++) {
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
90 CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windows, i));
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
91 if (!window)
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
92 continue;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
93
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
94 Process proc;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
95 {
197
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
96 CFDictionaryGetValue(window, CFSTR("kCGWindowOwnerPID"), proc.pid);
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
97 if (!CFDictionaryGetValue(window, CFSTR("kCGWindowOwnerName"), proc.name))
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
98 osx::util::GetProcessName(proc.pid, proc.name);
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
99 }
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
100
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
101 Window win;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
102 {
197
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
103 CFDictionaryGetValue(window, CFSTR("kCGWindowNumber"), win.id);
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
104
192
50108040d792 dep/animia/quartz: GetWindowBundleIdentifier -> GetProcessBundleIdentifier
Paper <mrpapersonic@gmail.com>
parents: 191
diff changeset
105 if (!GetProcessBundleIdentifier(proc.pid, win.class_name)) {
191
0fc126d52de4 animia: multiple stylistic choices
Paper <mrpapersonic@gmail.com>
parents: 190
diff changeset
106 // 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
107 // *could* be.
197
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
108 CFDictionaryGetValue(window, CFSTR("kCGWindowName"), win.class_name);
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
109 }
197
c4ca035c565d *: misc. patches
Paper <mrpapersonic@gmail.com>
parents: 192
diff changeset
110
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
111 GetWindowTitle(win.id, win.text);
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
112 }
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
113
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
114 if (!window_proc(proc, win)) {
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
115 CFRelease(windows);
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
116 return false;
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
117 }
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
118 }
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
119
190
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
120 CFRelease(windows);
2d5823df870f dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents: 189
diff changeset
121
189
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
122 return true;
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
123 }
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
124
649786bae914 *: etc. code cleanup
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
125 } // namespace animia::win::detail