From ed7acf358a6837a570cdff4bf25657fb1cb3b8c9 Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Sat, 12 Mar 2022 21:08:01 +0100 Subject: [PATCH] Skip "StatusIndicator" window in Auto-Type window list (#7526) Starting with macOS 12.2, when the audio recording indicator is shown, the "Window Server" process injects a "StatusIndicator" window into the list of active windows, which messes with Auto-Type's window title matching. This window has an Alpha value of 1 (so technically, it is not invisible), and it is always in front of all other windows. Hence, the only way to skip it is by title and owner name. Fixes #7418 --- src/autotype/mac/AutoTypeMac.cpp | 39 ++++++++++++++++++++++---------- src/autotype/mac/AutoTypeMac.h | 2 +- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/autotype/mac/AutoTypeMac.cpp b/src/autotype/mac/AutoTypeMac.cpp index 02cd5957d..015abe670 100644 --- a/src/autotype/mac/AutoTypeMac.cpp +++ b/src/autotype/mac/AutoTypeMac.cpp @@ -23,7 +23,6 @@ #include -#define MAX_WINDOW_TITLE_LENGTH 1024 #define INVALID_KEYCODE 0xFFFF AutoTypePlatformMac::AutoTypePlatformMac() @@ -60,7 +59,15 @@ QStringList AutoTypePlatformMac::windowTitles() continue; } - QString title = windowTitle(window); + QString title = windowStringProperty(window, kCGWindowName); + QString owner = windowStringProperty(window, kCGWindowOwnerName); + + // Audio recording injects a "StatusIndicator" window owned by the "Window Server" process + // into to list in macOS 12.2 (see: https://github.com/keepassxreboot/keepassxc/issues/7418). + if (title == "StatusIndicator" && owner == "Window Server") { + continue; + } + if (!title.isEmpty()) { list.append(title); } @@ -95,8 +102,16 @@ QString AutoTypePlatformMac::activeWindowTitle() for (CFIndex i = 0; i < count; i++) { CFDictionaryRef window = static_cast(::CFArrayGetValueAtIndex(windowList, i)); if (windowLayer(window) == 0) { + title = windowStringProperty(window, kCGWindowName); + QString owner = windowStringProperty(window, kCGWindowOwnerName); + + // Audio recording injects a "StatusIndicator" window owned by the "Window Server" process + // into to list in macOS 12.2 (see: https://github.com/keepassxreboot/keepassxc/issues/7418). + if (title == "StatusIndicator" && owner == "Window Server") { + continue; + } + // First toplevel window in list (front to back order) - title = windowTitle(window); if (!title.isEmpty()) { break; } @@ -190,20 +205,20 @@ int AutoTypePlatformMac::windowLayer(CFDictionaryRef window) } // -// Get window title +// Get window string property // -QString AutoTypePlatformMac::windowTitle(CFDictionaryRef window) +QString AutoTypePlatformMac::windowStringProperty(CFDictionaryRef window, CFStringRef propertyRef) { - char buffer[MAX_WINDOW_TITLE_LENGTH]; - QString title; + char buffer[1024]; + QString value; - CFStringRef titleRef = static_cast(::CFDictionaryGetValue(window, kCGWindowName)); - if (titleRef != nullptr - && ::CFStringGetCString(titleRef, buffer, MAX_WINDOW_TITLE_LENGTH, kCFStringEncodingUTF8)) { - title = QString::fromUtf8(buffer); + CFStringRef valueRef = static_cast(::CFDictionaryGetValue(window, propertyRef)); + if (valueRef != nullptr + && ::CFStringGetCString(valueRef, buffer, 1024, kCFStringEncodingUTF8)) { + value = QString::fromUtf8(buffer); } - return title; + return value; } // diff --git a/src/autotype/mac/AutoTypeMac.h b/src/autotype/mac/AutoTypeMac.h index 008ff9aa1..e12a06ec5 100644 --- a/src/autotype/mac/AutoTypeMac.h +++ b/src/autotype/mac/AutoTypeMac.h @@ -49,7 +49,7 @@ public: private: static int windowLayer(CFDictionaryRef window); - static QString windowTitle(CFDictionaryRef window); + static QString windowStringProperty(CFDictionaryRef window, CFStringRef propertyRef); }; class AutoTypeExecutorMac : public AutoTypeExecutor