我正在尝试创建一个程序来跟踪应用程序的聚焦窗口。我遇到了一些部分答案,但我认为它没有用。
这是Qt应用程序的Objective C ++部分,因此它可能与RunLoop有关,但我不确定。
void focusObserverCallback( AXObserverRef observer, AXUIElementRef element,
CFStringRef notificationName, void * contextData )
{
// Never executes.
qInfo("Focus changed.");
}
QString updateActiveWindow (void)
{
NSRunningApplication* app = [[NSWorkspace sharedWorkspace]
frontmostApplication];
pid_t pid = [app processIdentifier];
AXUIElementRef appElem = AXUIElementCreateApplication(pid);
if (!appElem) {
qInfo() << "!appElem";
return nullptr;
}
// Get the accessibility element corresponding to the frontmost window
// of the frontmost application.
CFStringRef appName=nullptr;
AXUIElementRef window = nullptr;
if (AXUIElementCopyAttributeValue (appElem, kAXTitleAttribute, ((CFTypeRef*)&appName)) !=kAXErrorSuccess){
if(appElem)
CFRelease(appElem);
}
focusedAppName=toQString(appName);
if (AXUIElementCopyAttributeValue (appElem, kAXFocusedWindowAttribute, (CFTypeRef*)&window) != kAXErrorSuccess) {
if(appElem)
CFRelease(appElem);
}
AXObserverRef observer = nullptr;
if(AXObserverCreate(pid, focusObserverCallback, &observer) !=kAXErrorSuccess){
qInfo("Failed to register observer");
}
AXObserverAddNotification(observer, window, kAXApplicationActivatedNotification, nullptr);
CFRunLoopAddSource([[NSRunLoop currentRunLoop] getCFRunLoop],
AXObserverGetRunLoopSource(observer),
kCFRunLoopDefaultMode );
// Finally, get the title of the frontmost window.
CFStringRef title = nullptr;
if(AXUIElementCopyAttributeValue(window, kAXTitleAttribute, (CFTypeRef*)&title)!=kAXErrorSuccess){
qInfo("Problem Copying title");
}
focusedAppTitle= toQString(title);
return toQString(title);
}
此代码的作用是,它运行一次即可获取最前面的应用程序最前面的窗口的名称和标题。那部分就像一个魅力。
问题是,它没有注册回调,并且当窗口失去焦点时也不会触发。我对Objective C完全陌生,因此可能还有其他问题(例如垃圾回收)。如果您可以提出一些建议,我将倍感荣幸。
答案 0 :(得分:2)
应用程序被激活后将发送kAXApplicationActivatedNotification
并成为最前面的应用程序。观察应用程序的kAXFocusedWindowChangedNotification
,以观察应用程序的焦点窗口更改。