| 
189
 | 
     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"
 | 
| 
 | 
    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>
 | 
| 
 | 
    17 #include <Carbon/Carbon.h>
 | 
| 
 | 
    18 
 | 
| 
 | 
    19 namespace animia::internal::quartz {
 | 
| 
 | 
    20 
 | 
| 
 | 
    21 static bool GetWindowTitle(unsigned int wid, std::string& result) {
 | 
| 
 | 
    22 	// id app = [NSApplication sharedApplication];
 | 
| 
 | 
    23 	id app = cls_msg(cls("NSApplication"), sel("sharedApplication"));
 | 
| 
 | 
    24 
 | 
| 
 | 
    25 	// id window = [app windowWithWindowNumber: wid];
 | 
| 
 | 
    26 	id window = msg(app, sel("windowWithWindowNumber:"), wid);
 | 
| 
 | 
    27 
 | 
| 
 | 
    28 	// return [[window title] UTF8String];
 | 
| 
 | 
    29 	return StringFromCFString(reinterpret_cast<CFStringRef>(msg(window, "title")), result);
 | 
| 
 | 
    30 }
 | 
| 
 | 
    31 
 | 
| 
 | 
    32 bool QuartzWinTools::EnumerateWindows(window_proc_t window_proc) {
 | 
| 
 | 
    33 	if (!window_proc)
 | 
| 
 | 
    34 		return false;
 | 
| 
 | 
    35 
 | 
| 
 | 
    36 	CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
 | 
| 
 | 
    37 	if (!windows)
 | 
| 
 | 
    38 		return false;
 | 
| 
 | 
    39 
 | 
| 
 | 
    40 	CFIndex i = 0; count = CFArrayGetCount(windows);
 | 
| 
 | 
    41 	for (; i < count; i++) {
 | 
| 
 | 
    42 		CFDictionaryRef window = CFArrayGetValueAtIndex(windows, i);
 | 
| 
 | 
    43 		if (!window)
 | 
| 
 | 
    44 			continue;
 | 
| 
 | 
    45 
 | 
| 
 | 
    46 		Process proc;
 | 
| 
 | 
    47 		{
 | 
| 
 | 
    48 			{
 | 
| 
 | 
    49 				CFNumber num;
 | 
| 
 | 
    50 				CFDictionaryGetValueIfPresent(window, "kCGWindowOwnerPID", &num);
 | 
| 
 | 
    51 				osx::util::GetCFNumber(num, proc.pid);
 | 
| 
 | 
    52 			}
 | 
| 
 | 
    53 			{
 | 
| 
 | 
    54 				CFStringRef str;
 | 
| 
 | 
    55 				CFDictionaryGetValueIfPresent(window, "kCGWindowOwnerName", &str);
 | 
| 
 | 
    56 				osx::util::StringFromCFString(str, proc.name);
 | 
| 
 | 
    57 			}
 | 
| 
 | 
    58 			if (proc.name.empty())
 | 
| 
 | 
    59 				osx::util::GetProcessName(proc.pid, proc.name);
 | 
| 
 | 
    60 		}
 | 
| 
 | 
    61 
 | 
| 
 | 
    62 		Window win;
 | 
| 
 | 
    63 		{
 | 
| 
 | 
    64 			{
 | 
| 
 | 
    65 				CFNumber num;
 | 
| 
 | 
    66 				CFDictionaryGetValueIfPresent(window, "kCGWindowNumber", &num);
 | 
| 
 | 
    67 				osx::util::GetCFNumber(num, win.id);
 | 
| 
 | 
    68 			}
 | 
| 
 | 
    69 			{
 | 
| 
 | 
    70 				CFStringRef str;
 | 
| 
 | 
    71 				CFDictionaryGetValueIfPresent(window, "kCGWindowName", &str);
 | 
| 
 | 
    72 				osx::util::GetCFNumber(str, win.class_name);
 | 
| 
 | 
    73 			}
 | 
| 
 | 
    74 			GetWindowTitle(win.id, win.text);
 | 
| 
 | 
    75 		}
 | 
| 
 | 
    76 
 | 
| 
 | 
    77 		if (!window_proc(proc, win))
 | 
| 
 | 
    78 			return false;
 | 
| 
 | 
    79 	}
 | 
| 
 | 
    80 
 | 
| 
 | 
    81 	return true;
 | 
| 
 | 
    82 }
 | 
| 
 | 
    83 
 | 
| 
 | 
    84 } // namespace animia::win::detail
 |