Mercurial > minori
changeset 191:0fc126d52de4
animia: multiple stylistic choices
win.class_name is now used to store bundle IDs on OS X,
add some little explanations here and there for dumb stuff
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Thu, 07 Dec 2023 01:48:04 -0500 |
parents | 2d5823df870f |
children | 50108040d792 |
files | dep/animia/CMakeLists.txt dep/animia/README.md dep/animia/include/animia/util/osx.h dep/animia/src/animia.cc dep/animia/src/win/quartz.cc dep/animia/src/win/win32.cc dep/animia/src/win/x11.cc |
diffstat | 7 files changed, 68 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/dep/animia/CMakeLists.txt Wed Dec 06 21:26:13 2023 -0500 +++ b/dep/animia/CMakeLists.txt Thu Dec 07 01:48:04 2023 -0500 @@ -32,7 +32,7 @@ list(APPEND DEFINES HAVE_COREFOUNDATION) list(APPEND SRC_FILES src/win/quartz.cc) - find_library(FOUNDATION_LIBRARY Foundation) + find_library(FOUNDATION_LIBRARY Foundation) find_library(COREGRAPHICS_LIBRARY CoreGraphics) find_library(APPKIT_LIBRARY AppKit) list(APPEND LIBRARIES ${FOUNDATION_LIBRARY} ${COREGRAPHICS_LIBRARY} ${APPKIT_LIBRARY})
--- a/dep/animia/README.md Wed Dec 06 21:26:13 2023 -0500 +++ b/dep/animia/README.md Thu Dec 07 01:48:04 2023 -0500 @@ -4,5 +4,24 @@ Most (if not all) Anisthesia configs should also work in this library as well (at least on Windows). ## Support -Animia supports Windows, macOS, and Linux when dealing with file descriptors. When enumerating windows, it supports Windows, macOS (Quartz), X11. I'd love to be able to support Wayland, but there's nothing I can do to provide an API that literally does not exist. +Animia supports Windows, macOS, and Linux when dealing with file descriptors. When enumerating +windows, it supports Windows, macOS (Quartz), and X11. I'd love to be able to support Wayland, but +there's nothing I can do to provide an API that literally does not exist. + +Unlike Anisthesia, Animia currently does not support UI automation, i.e., some web browsers will not +work properly, if at all. + +## Platform-specific quirks +### macOS +The code to executable names on macOS uses internal functions. However, if these functions +cannot be found for whatever reason, it falls back to parsing the arguments, and then to calling +the kernel. + +macOS doesn't have the concept of "class names", rather, it has bundle identifiers, which are +a suitable replacement for most use cases. + +### X11 +X11 has no idea what PID started your window. As a result, we can't provide it. Eventually, +there'll be support for the XRes extension which provides this possibility. For now, PIDs are +received using the untrustworthy `_NET_WM_PID` resource.
--- a/dep/animia/include/animia/util/osx.h Wed Dec 06 21:26:13 2023 -0500 +++ b/dep/animia/include/animia/util/osx.h Thu Dec 07 01:48:04 2023 -0500 @@ -19,8 +19,8 @@ return false; int64_t res; - if (CFNumberGetValue(num, static_cast<CFNumberType>(4), &res)) - return true; + if (!CFNumberGetValue(num, static_cast<CFNumberType>(4), &res)) + return false; result = static_cast<T>(res); return true;
--- a/dep/animia/src/animia.cc Wed Dec 06 21:26:13 2023 -0500 +++ b/dep/animia/src/animia.cc Thu Dec 07 01:48:04 2023 -0500 @@ -9,8 +9,6 @@ #include <string> #include <vector> -#include <iostream> - namespace animia { namespace internal { @@ -72,7 +70,6 @@ We should set the PID of the process if we can get it, but that'll be for when I can actually be arsed to implement the X11 backend. */ auto window_proc = [&](const Process& process, const Window& window) -> bool { - std::cout << process.name << std::endl; for (const auto& player : players) { if (!internal::PlayerHasStrategy(player, Strategy::WindowTitle)) continue;
--- a/dep/animia/src/win/quartz.cc Wed Dec 06 21:26:13 2023 -0500 +++ b/dep/animia/src/win/quartz.cc Thu Dec 07 01:48:04 2023 -0500 @@ -1,3 +1,10 @@ +/* + * win/quartz.cc: support for macOS (the Quartz Compositor) + * + * This file does not require an Objective-C++ compiler, + * but it *does* require an Objective-C runtime and linking + * with AppKit in order to receive proper window titles. +*/ #include "animia/win/quartz.h" #include "animia/util/osx.h" #include "animia.h" @@ -8,8 +15,6 @@ #include <CoreFoundation/CoreFoundation.h> #include <CoreGraphics/CoreGraphics.h> -#include <iostream> - namespace animia::internal::quartz { typedef id (*object_message_send)(id, SEL, ...); @@ -20,16 +25,15 @@ static bool GetWindowTitle(unsigned int wid, std::string& result) { // NSApplication* app = [NSApplication sharedApplication]; - id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication")); + const id app = cls_send(objc_getClass("NSApplication"), sel_getUid("sharedApplication")); // NSWindow* window = [app windowWithWindowNumber: wid]; - id window = obj_send(app, sel_getUid("windowWithWindowNumber:"), wid); + const id window = obj_send(app, sel_getUid("windowWithWindowNumber:"), wid); if (!window) return false; // NSString* title = [window title]; - // does this have to be freed? - CFStringRef title = reinterpret_cast<CFStringRef>(obj_send(window, sel_getUid("title"))); + const CFStringRef title = reinterpret_cast<CFStringRef>(obj_send(window, sel_getUid("title"))); if (!title) return false; @@ -37,6 +41,26 @@ return osx::util::StringFromCFString(title, result); } +static bool GetWindowBundleIdentifier(pid_t pid, std::string& result) { + /* The Bundle ID is essentially OS X's solution to Windows' + * "class name"; theoretically, it should be different for + * each program, although it requires an app bundle. + */ + + // NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier: pid]; + const id app = cls_send(objc_getClass("NSRunningApplication"), sel_getUid("runningApplicationWithProcessIdentifier:"), pid); + if (!app) + return false; + + // NSString* bundle_id = [app bundleIdentifier]; + const CFStringRef bundle_id = reinterpret_cast<CFStringRef>(obj_send(app, sel_getUid("bundleIdentifier"))); + if (!bundle_id) + return false; + + // return [bundle_id UTF8String]; + return osx::util::StringFromCFString(bundle_id, result); +} + bool QuartzWinTools::EnumerateWindows(window_proc_t window_proc) { if (!window_proc) return false; @@ -74,7 +98,9 @@ if (CFDictionaryGetValueIfPresent(window, CFSTR("kCGWindowNumber"), reinterpret_cast<const void**>(&num)) && num) osx::util::GetCFNumber(num, win.id); } - { + if (!GetWindowBundleIdentifier(proc.pid, win.class_name)) { + // Fallback to the Quartz window name, which is unlikely to be filled, but it + // *could* be. CFStringRef str = nullptr; if (CFDictionaryGetValueIfPresent(window, CFSTR("kCGWindowName"), reinterpret_cast<const void**>(&str)) && str) osx::util::StringFromCFString(str, win.class_name);
--- a/dep/animia/src/win/win32.cc Wed Dec 06 21:26:13 2023 -0500 +++ b/dep/animia/src/win/win32.cc Thu Dec 07 01:48:04 2023 -0500 @@ -1,3 +1,10 @@ +/* + * win/win32.cc: support for Windows + * + * Surprisingly, this is the one time where Microsoft actually + * does it fairly OK. Everything has a pretty simple API, despite + * the stupid wide string stuff. +*/ #include "animia/win/win32.h" #include "animia.h" #include "animia/util/win32.h" @@ -24,9 +31,9 @@ } static std::wstring GetWindowText(HWND hwnd) { - const int estimated_size = ::GetWindowTextLengthW(hwnd); + const auto estimated_size = ::GetWindowTextLengthW(hwnd); + std::wstring buffer(estimated_size + 1, L'\0'); - std::wstring buffer(estimated_size + 1, L'\0'); const auto size = ::GetWindowTextW(hwnd, &buffer.front(), buffer.length()); /* GetWindowTextLength docs: "Under certain conditions, the GetWindowTextLength function may return a value
--- a/dep/animia/src/win/x11.cc Wed Dec 06 21:26:13 2023 -0500 +++ b/dep/animia/src/win/x11.cc Thu Dec 07 01:48:04 2023 -0500 @@ -93,6 +93,9 @@ } static bool WalkWindows(::Display* display, std::set<::Window>& children, const std::set<::Window>& windows) { + /* This sucks. It takes waaaay too long to finish. + * TODO: Look at the code for xwininfo to see what they do. + */ if (windows.empty()) return false;