comparison dep/animia/src/win/quartz.cc @ 190:2d5823df870f

dep/animia: finalize de-objc-ifying quartz this also fixes up some... rather dumb mistakes in window.cc :) HG Enter commit message. Lines beginning with 'HG:' are removed.
author Paper <mrpapersonic@gmail.com>
date Wed, 06 Dec 2023 21:26:13 -0500
parents 649786bae914
children 0fc126d52de4
comparison
equal deleted inserted replaced
189:649786bae914 190:2d5823df870f
1 /* We actually DON'T need Objective-C for most of this file.
2 * GetWindowTitle() is the only function that really needs it.
3 * (and even then, we can use the C bindings for it...)
4 *
5 * However, being able to use the Foundation classes makes things
6 * so, so, so much easier, and so I've decided to make this file
7 * in Objective-C++.
8 */
9 #include "animia/win/quartz.h" 1 #include "animia/win/quartz.h"
2 #include "animia/util/osx.h"
10 #include "animia.h" 3 #include "animia.h"
11 4
12 #include <objc/runtime.h> 5 #include <objc/runtime.h>
13 #include <objc/message.h> 6 #include <objc/message.h>
14 7
15 #include <CoreFoundation/CoreFoundation.h> 8 #include <CoreFoundation/CoreFoundation.h>
16 #include <CoreGraphics/CoreGraphics.h> 9 #include <CoreGraphics/CoreGraphics.h>
17 #include <Carbon/Carbon.h> 10
11 #include <iostream>
18 12
19 namespace animia::internal::quartz { 13 namespace animia::internal::quartz {
20 14
15 typedef id (*object_message_send)(id, SEL, ...);
16 typedef id (*class_message_send)(Class, SEL, ...);
17
18 static const object_message_send obj_send = reinterpret_cast<object_message_send>(objc_msgSend);
19 static const class_message_send cls_send = reinterpret_cast<class_message_send>(objc_msgSend);
20
21 static bool GetWindowTitle(unsigned int wid, std::string& result) { 21 static bool GetWindowTitle(unsigned int wid, std::string& result) {
22 // id app = [NSApplication sharedApplication]; 22 // NSApplication* app = [NSApplication sharedApplication];
23 id app = cls_msg(cls("NSApplication"), sel("sharedApplication")); 23 id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication"));
24 24
25 // id window = [app windowWithWindowNumber: wid]; 25 // NSWindow* window = [app windowWithWindowNumber: wid];
26 id window = msg(app, sel("windowWithWindowNumber:"), wid); 26 id window = obj_send(app, sel_getUid("windowWithWindowNumber:"), wid);
27 if (!window)
28 return false;
27 29
28 // return [[window title] UTF8String]; 30 // NSString* title = [window title];
29 return StringFromCFString(reinterpret_cast<CFStringRef>(msg(window, "title")), result); 31 // does this have to be freed?
32 CFStringRef title = reinterpret_cast<CFStringRef>(obj_send(window, sel_getUid("title")));
33 if (!title)
34 return false;
35
36 // return [title UTF8String];
37 return osx::util::StringFromCFString(title, result);
30 } 38 }
31 39
32 bool QuartzWinTools::EnumerateWindows(window_proc_t window_proc) { 40 bool QuartzWinTools::EnumerateWindows(window_proc_t window_proc) {
33 if (!window_proc) 41 if (!window_proc)
34 return false; 42 return false;
35 43
36 CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID); 44 const CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
37 if (!windows) 45 if (!windows)
38 return false; 46 return false;
39 47
40 CFIndex i = 0; count = CFArrayGetCount(windows); 48 const CFIndex count = CFArrayGetCount(windows);
41 for (; i < count; i++) { 49 for (CFIndex i = 0; i < count; i++) {
42 CFDictionaryRef window = CFArrayGetValueAtIndex(windows, i); 50 CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windows, i));
43 if (!window) 51 if (!window)
44 continue; 52 continue;
45 53
46 Process proc; 54 Process proc;
47 { 55 {
48 { 56 {
49 CFNumber num; 57 CFNumberRef num = nullptr;
50 CFDictionaryGetValueIfPresent(window, "kCGWindowOwnerPID", &num); 58 if (CFDictionaryGetValueIfPresent(window, CFSTR("kCGWindowOwnerPID"), reinterpret_cast<const void**>(&num)) && num)
51 osx::util::GetCFNumber(num, proc.pid); 59 osx::util::GetCFNumber(num, proc.pid);
52 } 60 }
53 { 61 {
54 CFStringRef str; 62 CFStringRef str = nullptr;
55 CFDictionaryGetValueIfPresent(window, "kCGWindowOwnerName", &str); 63 if (CFDictionaryGetValueIfPresent(window, CFSTR("kCGWindowOwnerName"), reinterpret_cast<const void**>(&str)) && str)
56 osx::util::StringFromCFString(str, proc.name); 64 osx::util::StringFromCFString(str, proc.name);
57 } 65 }
58 if (proc.name.empty()) 66 if (proc.name.empty())
59 osx::util::GetProcessName(proc.pid, proc.name); 67 osx::util::GetProcessName(proc.pid, proc.name);
60 } 68 }
61 69
62 Window win; 70 Window win;
63 { 71 {
64 { 72 {
65 CFNumber num; 73 CFNumberRef num = nullptr;
66 CFDictionaryGetValueIfPresent(window, "kCGWindowNumber", &num); 74 if (CFDictionaryGetValueIfPresent(window, CFSTR("kCGWindowNumber"), reinterpret_cast<const void**>(&num)) && num)
67 osx::util::GetCFNumber(num, win.id); 75 osx::util::GetCFNumber(num, win.id);
68 } 76 }
69 { 77 {
70 CFStringRef str; 78 CFStringRef str = nullptr;
71 CFDictionaryGetValueIfPresent(window, "kCGWindowName", &str); 79 if (CFDictionaryGetValueIfPresent(window, CFSTR("kCGWindowName"), reinterpret_cast<const void**>(&str)) && str)
72 osx::util::GetCFNumber(str, win.class_name); 80 osx::util::StringFromCFString(str, win.class_name);
73 } 81 }
74 GetWindowTitle(win.id, win.text); 82 GetWindowTitle(win.id, win.text);
75 } 83 }
76 84
77 if (!window_proc(proc, win)) 85 if (!window_proc(proc, win)) {
86 CFRelease(windows);
78 return false; 87 return false;
88 }
79 } 89 }
90
91 CFRelease(windows);
80 92
81 return true; 93 return true;
82 } 94 }
83 95
84 } // namespace animia::win::detail 96 } // namespace animia::win::detail