Skip "StatusIndicator" window in Auto-Type window list (#7527)

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
This commit is contained in:
Janek Bevendorff 2022-03-12 21:07:36 +01:00 committed by GitHub
parent 4bc32d37ac
commit e07d143c9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 13 deletions

View File

@ -23,7 +23,6 @@
#include <ApplicationServices/ApplicationServices.h>
#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<CFDictionaryRef>(::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<CFStringRef>(::CFDictionaryGetValue(window, kCGWindowName));
if (titleRef != nullptr
&& ::CFStringGetCString(titleRef, buffer, MAX_WINDOW_TITLE_LENGTH, kCFStringEncodingUTF8)) {
title = QString::fromUtf8(buffer);
CFStringRef valueRef = static_cast<CFStringRef>(::CFDictionaryGetValue(window, propertyRef));
if (valueRef != nullptr
&& ::CFStringGetCString(valueRef, buffer, 1024, kCFStringEncodingUTF8)) {
value = QString::fromUtf8(buffer);
}
return title;
return value;
}
//

View File

@ -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