Уведомление об изменении активного документа в OS X?

Я использую NSWorkspace's NSWorkspaceDidActivateApplicationNotification определить, когда изменяется активное приложение. я получил NSRunningApplication из ключа userInfo уведомления.

Мне нужно получить уведомление при изменении активного документа. Я могу получить активный документ, используя рамки доступности NSAccessibilityDocumentAttribute ключ через AXUIElementCopyAttributeValue(),

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

Мне не нужно использовать рамки доступности. AppleScript (мост сценариев), по-видимому, также может получить документ окна, но инфраструктура доступности, похоже, работает с большим количеством приложений.

Меня волнует только активный документ, активное окно, активное приложение. То, что в данный момент ориентировано на систему.

Я тестировал с такими приложениями, как Sublime Text 2 и Xcode. Sublime возвращает текущую выбранную вкладку, где Xcode возвращает активный проект.

1 ответ

Решение

На самом деле я пытался достичь того же самого, и я думаю, что нашел решение для этого.

То, что я сделал, использовало CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);

Это даст вам список всех активных окон, включая окна, которые вам, вероятно, не нужны.

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

Вот как я это сделал:

    CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
NSMutableArray *data = [(__bridge NSArray *) windowList mutableCopy];

NSMutableArray *filteredData = [[NSMutableArray alloc] initWithCapacity:10];

for (NSMutableDictionary *theDict in data) {
    id layer = [theDict objectForKey:(id)kCGWindowLayer];

    if ([layer intValue] == 0) {
        [filteredData addObject:theDict];
    }
}

NSLog(@"window: %@", filteredData);

Это может быть самым элегантным решением, поэтому, если у кого-то есть идея получше, поделитесь. Также вам стоит взглянуть на демонстрационное приложение Apple Son of Grab.

Другие вопросы по тегам