Skip to content

Commit

Permalink
Skip "StatusIndicator" window in Auto-Type window list (keepassxreboo…
Browse files Browse the repository at this point in the history
…t#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 keepassxreboot#7418
  • Loading branch information
phoerious authored Mar 12, 2022
1 parent e6a6ba7 commit ed7acf3
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 13 deletions.
39 changes: 27 additions & 12 deletions src/autotype/mac/AutoTypeMac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

#include <ApplicationServices/ApplicationServices.h>

#define MAX_WINDOW_TITLE_LENGTH 1024
#define INVALID_KEYCODE 0xFFFF

AutoTypePlatformMac::AutoTypePlatformMac()
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}

//
Expand Down
2 changes: 1 addition & 1 deletion src/autotype/mac/AutoTypeMac.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class AutoTypePlatformMac : public QObject, public AutoTypePlatformInterface

private:
static int windowLayer(CFDictionaryRef window);
static QString windowTitle(CFDictionaryRef window);
static QString windowStringProperty(CFDictionaryRef window, CFStringRef propertyRef);
};

class AutoTypeExecutorMac : public AutoTypeExecutor
Expand Down

0 comments on commit ed7acf3

Please sign in to comment.