Thomas Paltz
Thomas Paltz

Reputation: 55

CGWindowListCreate generates a hugely long list of windows

When I use CGWindowListCreate from quartz window services, it generates a very long array of window id's. I tried to turn on the option to exclude desktop elements, but I get a list of 30-40 windows even if there are only 3 or 4 of what I would call windows open.

Here is how I am doing it:

 CGWindowListOption opt = 1 << 4;
 CFArrayRef windowids =CGWindowListCreate(opt,kCGNullWindowID);

I am wondering what I am doing wrong that is causing this problem, and what I can do to fix it. I simply want the program to list windows created by applications, such as finder windows or browser windows, and not whatever else it is including. Thank you in advance for your help.

Upvotes: 1

Views: 1805

Answers (2)

Chris Miles
Chris Miles

Reputation: 7526

I discovered a solution is to filter the window list to only those windows "below" the Dock (in terms of window layering).

The code below worked well for me. It fetches all on screen windows (excluding desktop elements). It extracts the window ID for the "Dock" window out of the list. Then fetches on screen windows again, filtering to only those windows "below" the Dock window.

// Fetch all on screen windows
CFArrayRef windowListArray = CGWindowListCreate(kCGWindowListOptionOnScreenOnly|kCGWindowListExcludeDesktopElements, kCGNullWindowID);
NSArray *windows = CFBridgingRelease(CGWindowListCreateDescriptionFromArray(windowListArray));

NSLog(@"All on screen windows: %@", windows);

// Find window ID of "Dock" window
NSNumber *dockWindowNumber = nil;
for (NSDictionary *window in windows) {
    if ([(NSString *)window[(__bridge NSString *)kCGWindowName] isEqualToString:@"Dock"]) {
        dockWindowNumber = window[(__bridge NSString *)kCGWindowNumber];
        break;
    }
}

NSLog(@"dockWindowNumber: %@", dockWindowNumber);

CFRelease(windowListArray);

if (dockWindowNumber) {
    // Fetch on screen windows again, filtering to those "below" the Dock window
    // This filters out all but the "standard" application windows
    windowListArray = CGWindowListCreate(kCGWindowListOptionOnScreenBelowWindow|kCGWindowListExcludeDesktopElements, [dockWindowNumber unsignedIntValue]);
    NSArray *windows = CFBridgingRelease(CGWindowListCreateDescriptionFromArray(windowListArray));
    NSLog(@"On screen application windows: %@", windows);
}
else {
    NSLog(@"Could not find Dock window description");
}

Upvotes: 1

borrrden
borrrden

Reputation: 33421

This will return every window whether it is on screen or off screen, you should combine it with the option kCGWindowListOptionOnScreenOnly (and also don't hardcode the one you are using). It will look like this:

CGWindowListOption opt = kCGWindowListOptionOnScreenOnly|kCGWindowListExcludeDesktopElements;
CFArrayRef windowids =CGWindowListCreate(opt,kCGNullWindowID);

That is what I gathered from the docs anyway.

Upvotes: 1

Related Questions