Как я могу использовать API Доступности Какао, чтобы обнаружить, что окно выведено на передний план? - PullRequest
13 голосов
/ 07 декабря 2008

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

Как мое приложение может определить, когда другое приложение выводит окно на передний план, не делая его ключевым?

Я надеюсь найти решение, которое работает на OS X 10.4 и 10.5

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

AXObserverAddNotification(observer, element, kAXMainWindowChangedNotification, 0);
AXObserverAddNotification(observer, element, kAXFocusedWindowChangedNotification, 0);

Ответы [ 4 ]

8 голосов
/ 09 марта 2009

Мне не удалось подписаться на текущие изменения окна, но вы можете запросить API-интерфейс для текущего приложения и большинства приоритетных окон текущего приложения.

Представьте, что у вас есть класс CurrentAppData со следующими данными:

@interface CurrentAppData : NSObject {
    NSString* _title;
    AXUIElementRef _systemWide;
    AXUIElementRef _app;
    AXUIElementRef _window;
}

Код для поиска текущего приложения выглядит примерно так:

-(void) updateCurrentApplication {
   // get the currently active application  
   _app = (AXUIElementRef)[CurrentAppData
                           valueOfExistingAttribute:kAXFocusedApplicationAttribute 
                                        ofUIElement:_systemWide];

   // Get the window that has focus for this application
   _window = (AXUIElementRef)[CurrentAppData 
                              valueOfExistingAttribute:kAXFocusedWindowAttribute 
                                           ofUIElement:_app];

   NSString* appName = [CurrentAppData descriptionOfValue:_window
                                             beingVerbose:TRUE];    

   [self setTitle:appName];
}

В этом примере переменная _systemWide инициализируется в функции init классов следующим образом: _system = AXUIElementCreateSystemWide ();

Функция класса valueOfExistingAttribute выглядит следующим образом:

// -------------------------------------------------------------------------------
//  valueOfExistingAttribute:attribute:element
//
//  Given a uiElement and its attribute, return the value of an accessibility
//  object's attribute.
// -------------------------------------------------------------------------------
+ (id)valueOfExistingAttribute:(CFStringRef)attribute ofUIElement:(AXUIElementRef)element
{
    id result = nil;
    NSArray *attrNames;

    if (AXUIElementCopyAttributeNames(element, (CFArrayRef *)&attrNames) == kAXErrorSuccess) 
    {
        if ( [attrNames indexOfObject:(NSString *)attribute] != NSNotFound
                &&
            AXUIElementCopyAttributeValue(element, attribute, (CFTypeRef *)&result) == kAXErrorSuccess
        ) 
        {
            [result autorelease];
        }
        [attrNames release];
    }
    return result;
}

Предыдущая функция была взята из примера Apple UIElementInspector , который также является отличным источником для изучения API доступа.

5 голосов
/ 09 марта 2009

В Mac OS X приложения и окна - это совершенно разные вещи, с приложениями, содержащими окна; раньше они не были такими же, как в Microsoft Windows. Вам необходимо обнаружить активацию и деактивацию каждого приложения.

Вы сделаете это, наблюдая за kAXApplicationActivatedNotification и kAXApplicationDeactivatedNotification. Объектом этих уведомлений является приложение, которое активируется и деактивируется. Вам также нужно будет обнаружить запуск приложений и выход из них; Вы можете сделать это с помощью диспетчера процессов или NSWorkspace. Оба этих API могут дать вам идентификатор процесса, который вы можете использовать для создания объекта AXApplication.

3 голосов
/ 16 февраля 2011

Посмотрите на пример iChatStatusFromApplication в документации для разработчиков. Это именно то, что вам нужно :)

2 голосов
/ 15 марта 2009
...