Получение позиции иконки моего приложения с помощью API доступа Cocoa - PullRequest
5 голосов
/ 13 июля 2011

Как я могу получить положение значка дока моего приложения, используя Accessibility API?

Ответы [ 2 ]

6 голосов
/ 13 июля 2011

Нашли это! Используя это сообщение на форуме в качестве ссылки, я смог сформировать данный пример кода так, как мне нужно:

- (NSArray *)subelementsFromElement:(AXUIElementRef)element forAttribute:(NSString *)attribute
{
    NSArray *subElements = nil;
    CFIndex count = 0;
    AXError result;

    result = AXUIElementGetAttributeValueCount(element, (CFStringRef)attribute, &count);
    if (result != kAXErrorSuccess) return nil;
    result = AXUIElementCopyAttributeValues(element, (CFStringRef)attribute, 0, count, (CFArrayRef *)&subElements);
    if (result != kAXErrorSuccess) return nil;

    return [subElements autorelease];
}

- (AXUIElementRef)appDockIconByName:(NSString *)appName
{
    AXUIElementRef appElement = NULL;

    appElement = AXUIElementCreateApplication([[[NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"] lastObject] processIdentifier]);
    if (appElement != NULL)
    {
        AXUIElementRef firstChild = (__bridge AXUIElementRef)[[self subelementsFromElement:appElement forAttribute:@"AXChildren"] objectAtIndex:0];
        NSArray *children = [self subelementsFromElement:firstChild forAttribute:@"AXChildren"];
        NSEnumerator *e = [children objectEnumerator];
        AXUIElementRef axElement;
        while (axElement = (__bridge AXUIElementRef)[e nextObject])
        {
            CFTypeRef value;
            id titleValue;
            AXError result = AXUIElementCopyAttributeValue(axElement, kAXTitleAttribute, &value);
            if (result == kAXErrorSuccess)
            {
                if (AXValueGetType(value) != kAXValueIllegalType)
                    titleValue = [NSValue valueWithPointer:value];
                else
                    titleValue = (__bridge id)value; // assume toll-free bridging
                if ([titleValue isEqual:appName]) {
                    return axElement;
                }
            }
        }
    }

    return nil;
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    AXUIElementRef dockIcon = [self appDockIconByName:@"MYAPPNAME"];
    if (dockIcon) {
        CFTypeRef value;
        CGPoint iconPosition;
        AXError result = AXUIElementCopyAttributeValue(dockIcon, kAXPositionAttribute, &value);
        if (result == kAXErrorSuccess)
        {
            if (AXValueGetValue(value, kAXValueCGPointType, &iconPosition)) {
                NSLog(@"position: (%f, %f)", iconPosition.x, iconPosition.y);
            }
        }
    }
}
1 голос
/ 18 февраля 2016

Что касается Mac OS El Capitan, похоже, что вы не должны получать положение значка с помощью API-интерфейса Accessibility. Дело в том, что значок не находится в иерархии объектов специальных возможностей приложения - его можно найти в иерархии системного приложения Dock. Приложение в песочнице не должно обращаться к объектам специальных возможностей других приложений.

Код в утвержденном ответе не выдает никаких предупреждений о демоне sandboxd в консоли, похоже, он не нарушает никаких правил. Создает объект доступности верхнего уровня с функцией AXUIElementCreateApplication. В документации говорится, что это:

Creates and returns the top-level accessibility object for the
application with the specified process ID.

К сожалению, этот объект верхнего уровня не является предком иконки Dock. Я попытался запустить код, и он вычисляет позицию пункта главного меню первого приложения (который имеет тот же заголовок, что и само приложение). Сравнение происходит в этой строке:

if ([titleValue isEqual:appName]) {

Таким образом, вывод всегда был одинаковым для моего приложения:

position: (45.000000, 0.000000)

Попытка получить доступ к объекту доступности другого приложения вызвала предупреждение в консоли. Я предполагаю, что нужно найти другой способ вычисления положения иконки.

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