Dave-C
Dave-C

Reputation: 21

Why would AXUIElementCopyAttributeValue() return kAXErrorAttributeUnsupported for every window on screen in this function?

I am trying to get the on screen position of every visible window on os x. In my function get_position(), AXUIElementCopyAttributeValue() returns kAXErrorAttributeUnsupported for every window on screen except for the finder window. Why is this the case? and What am I doing wrong?

int get_position()
{
    CFArrayRef a = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
    NSArray * arr = CFBridgingRelease(a);
    pid_t window_pid = 0;
    unsigned long count = [ arr count];
    NSMutableDictionary* entry;

    for ( unsigned long i = 0; i < count; i++)
    {
        //CFTypeRef position;
        AXValueRef temp;
        CGPoint current_point;
        entry = arr[i];
        window_pid = [[entry objectForKey:(id)kCGWindowOwnerPID] intValue];
        NSString * temp_ns_string = [entry objectForKey:(id)kCGWindowName ];
        const char *window_name =[temp_ns_string UTF8String];
        printf("%s - ", window_name);
        printf("Pid: %i\n", window_pid);

        AXUIElementRef window_ref = AXUIElementCreateApplication(window_pid);
        AXError error = AXUIElementCopyAttributeValue(window_ref, kAXPositionAttribute, (CFTypeRef *)&temp);

        if ((AXValueGetValue(temp, kAXValueCGPointType, &current_point) ))
        {
            printf("%s - ", window_name);
            printf("Pid: %i - ", window_pid);
            printf(" %f,%f\n", current_point.x, current_point.y);
        }
        else
        {
            printf("%s - ", window_name);
            printf("Pid: %i\n", window_pid);
        }

    }
    return 0;
}

Upvotes: 2

Views: 1523

Answers (2)

Jian Zhong
Jian Zhong

Reputation: 501

On MacOS, each app may have more than one window, different windows use the same pid.

AXUIElementRef app = AXUIElementCreateApplication(pid)

So you can get the 1 focus window by give kAXFocusedWindowAttribute

AXUIElementRef window;
AXUIElementCopyAttributeValue(app, kAXFocusedWindowAttribute, &window)

Or you can get multi windows by give kAXWindowsAttribute

NSArray *windows;
AXUIElementCopyAttributeValues(app, kAXWindowsAttribute,
                           0,
                           99999,
                           (CFArrayRef *) &result
                           );

then get position or size from window

AXValueRef pos;
AXValueRef size;

AXUIElementCopyAttributeValue(window, kAXPositionAttribute, (CFTypeRef *)&pos)
AXUIElementCopyAttributeValue(window, kAXSizeAttribute, (CFTypeRef *)&size)

now, convert the position into actual CGPoint or CGSize

CGPoint cpoint = CGPointMake(0, 0);
CGSize csize = CGSizeMake(0, 0);

AXValueGetValue(pos, kAXValueCGPointType, &cpoint);
AXValueGetValue(size, kAXValueCGSizeType, &csize);

I think above should help.

Upvotes: 5

Willeke
Willeke

Reputation: 15598

AXUIElementRef window_ref = AXUIElementCreateApplication(window_pid);

AXUIElementCreateApplication returns an application object. Most applications don't have a position. Some applications return a position but this isn't the position of the window. The position of the window is in the dictionary with key kCGWindowBounds.

Upvotes: 0

Related Questions