Как определить, изменилось ли активное окно в Mac OS X - PullRequest
0 голосов
/ 07 ноября 2018

Я пытаюсь создать программу, которая отслеживает сфокусированное окно приложения. Я встретил несколько частичных ответов, но я не думаю, что это работает.

Это часть Objective C ++ приложения Qt, так что это может быть связано с 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, поэтому могут быть другие проблемы (например, сборка мусора). Если вы можете предложить некоторые изменения, я был бы вдвойне благодарен.

1 Ответ

0 голосов
/ 07 ноября 2018

Приложение отправляет kAXApplicationActivatedNotification, когда приложение активировано и становится самым передним приложением. Наблюдайте за приложением kAXFocusedWindowChangedNotification, чтобы наблюдать фокусированные изменения окна приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...