Mercurial > minori
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 |
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 | 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 | 10 #include "animia.h" |
11 | |
12 #include <objc/runtime.h> | |
13 #include <objc/message.h> | |
14 | |
15 #include <CoreFoundation/CoreFoundation.h> | |
16 #include <CoreGraphics/CoreGraphics.h> | |
190
2d5823df870f
dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents:
189
diff
changeset
|
17 |
189 | 18 namespace animia::internal::quartz { |
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 | 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 | 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 | 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 | 42 } |
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 | 64 template<typename T> |
65 static bool CFDictionaryGetValue(CFDictionaryRef thedict, CFStringRef key, T& out) { | |
66 CFTypeRef data = nullptr; | |
67 if (!CFDictionaryGetValueIfPresent(thedict, key, reinterpret_cast<const void**>(&data)) || !data) | |
68 return false; | |
69 | |
70 if constexpr (std::is_arithmetic<T>::value) | |
71 osx::util::GetCFNumber(reinterpret_cast<CFNumberRef>(data), out); | |
72 else if constexpr (std::is_same<T, std::string>::value) | |
73 osx::util::StringFromCFString(reinterpret_cast<CFStringRef>(data), out); | |
74 else | |
75 return false; | |
76 | |
77 return true; | |
78 } | |
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 | 81 if (!window_proc) |
82 return false; | |
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 | 85 if (!windows) |
86 return false; | |
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 | 91 if (!window) |
92 continue; | |
93 | |
94 Process proc; | |
95 { | |
197 | 96 CFDictionaryGetValue(window, CFSTR("kCGWindowOwnerPID"), proc.pid); |
97 if (!CFDictionaryGetValue(window, CFSTR("kCGWindowOwnerName"), proc.name)) | |
189 | 98 osx::util::GetProcessName(proc.pid, proc.name); |
99 } | |
100 | |
101 Window win; | |
102 { | |
197 | 103 CFDictionaryGetValue(window, CFSTR("kCGWindowNumber"), win.id); |
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 | 108 CFDictionaryGetValue(window, CFSTR("kCGWindowName"), win.class_name); |
189 | 109 } |
197 | 110 |
189 | 111 GetWindowTitle(win.id, win.text); |
112 } | |
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 | 116 return false; |
190
2d5823df870f
dep/animia: finalize de-objc-ifying quartz
Paper <mrpapersonic@gmail.com>
parents:
189
diff
changeset
|
117 } |
189 | 118 } |
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 | 122 return true; |
123 } | |
124 | |
125 } // namespace animia::win::detail |