Mercurial > minori
annotate dep/animia/src/win/quartz.cc @ 199:9f3534f6b8c4
dep/animia: initial Wayland support, drop non-working kvm fd plugin
| author | Paper <mrpapersonic@gmail.com> |
|---|---|
| date | Tue, 02 Jan 2024 02:34:27 -0500 |
| parents | bc1ae1810855 |
| 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 |
