view dep/animia/src/win/quartz.mm @ 187:9613d72b097e

*: multiple performance improvements like marking `static const` when it makes sense... date: change old stupid heap-based method to a structure which should make copying the thing actually make a copy. also many performance-based changes, like removing the std::tie dependency and forward-declaring nlohmann json *: replace every instance of QString::fromUtf8 to Strings::ToQString. the main difference is that our function will always convert exactly what is in the string, while some other times it would only convert up to the nearest NUL byte
author Paper <mrpapersonic@gmail.com>
date Wed, 06 Dec 2023 13:43:54 -0500
parents c413e475f496
children
line wrap: on
line source

/* We actually DON'T need Objective-C for most of this file.
 * GetWindowTitle() is the only function that really needs it.
 * (and even then, we can use the C bindings for it...)
 *
 * However, being able to use the Foundation classes makes things
 * so, so, so much easier, and so I've decided to make this file
 * in Objective-C++.
*/
#include "animia/win/quartz.h"
#include "animia.h"

#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <AppKit/AppKit.h>

namespace animia::internal::quartz {

template<typename T>
static bool IntegerFromNSNumber(NSNumber* num, T& result) {
	if (!num)
		return false;

	result = [num intValue];
	return true;
}

static bool StringFromNSString(NSString* string, std::string& result) {
	if (!string)
		return false;

	result = [string UTF8String];
	return true;
}

/* This is really the only a*/
static bool GetWindowTitle(unsigned int wid, std::string& result) {
	NSWindow* window = [NSApp windowWithWindowNumber: wid];
	if (!window)
		return false;

	return StringFromNSString([window title], result);
}

bool QuartzWinTools::EnumerateWindows(window_proc_t window_proc) {
	if (!window_proc)
		return false;

	NSMutableArray* windows = reinterpret_cast<NSMutableArray*>(CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID));
	if (!windows)
		return false;

	for (NSDictionary* window in windows) {
		if (!window)
			continue;

		Process proc;
		{
			IntegerFromNSNumber([window objectForKey:@"kCGWindowOwnerPID"], proc.pid);
			StringFromNSString([window objectForKey:@"kCGWindowOwnerName"], proc.name);
			if (proc.name.empty())
				osx::util::GetProcessName(proc.pid, proc.name);
		}

		Window win;
		{
			IntegerFromNSNumber([window objectForKey:@"kCGWindowNumber"], win.id);
			StringFromNSString([window objectForKey:@"kCGWindowName"], win.class_name);
			GetWindowTitle(win.id, win.text);
		}

		if (!window_proc(proc, win))
			return false;
	}

	return true;
}

} // namespace animia::win::detail