6

Is there a way to get the NSScreen for a window of another process assuming that I have the window id?

I got pretty close with the following code, but the info dictionary doesn't say which screen the window is on.

CFArrayRef windowArray = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSArray*  windowList = (NSArray*)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSUInteger count = [windowList count];
for (NSUInteger i = 0; i < count; i++)
{
    NSDictionary*   nswindowsdescription = [windowList objectAtIndex:i];
    NSNumber* windowid = (NSNumber*)[nswindowsdescription objectForKey:@"kCGWindowNumber"];
    if(windowid)
    {
        if ([windowid integerValue] == appWeAreLookingForWindowId)
        {
            Warning(@"Found it: %@", nswindowsdescription);
        }
    }
}
CFRelease(windowArray);

From: CGWindowListCopyWindowInfo, kCGWindowLayer and window level

Here the output:

kCGWindowAlpha = 1;
kCGWindowBounds =     {
    Height = 1010;
    Width = 1600;
    X = 284;
    Y = 43;
};
kCGWindowIsOnscreen = 1; // This is not the screen id, by the way
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 7709736;
kCGWindowName = "osx - CGWindowListCopyWindowInfo, kCGWindowLayer and window level - Stack Overflow";
kCGWindowNumber = 4000;
kCGWindowOwnerName = Safari;
kCGWindowOwnerPID = 240;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 1;

I could try to calculate the screen from the window bounds, but I'm wondering if there's a better way.

Community
  • 1
  • 1
Mark
  • 6,647
  • 1
  • 45
  • 88

1 Answers1

4

The reason this information is not available is probably because a window can be on more than one screen at once. If the user has dragged the window so that a portion of it is in one window and the rest in another, there is no such thing as the current screen.

Your window bounds estimation method is probably the best option.

Rob Keniger
  • 45,830
  • 6
  • 101
  • 134
  • 3
    I ended up calculating the intersection of the window's bounds with each screen choosing the screen with the largest one. – Mark Oct 23 '11 at 09:51
  • There are cases where this isn't possible. For example, I have two monitors each connected to the built-in DisplayPort and through a DisplayLink USB adapter, and a window can't be stretched to appear on both screens; whichever screen a window is "mostly" on is the one it will be displayed on. – chrstphrchvz Mar 02 '19 at 07:14
  • A window can be temporarily displayed on two displays, by dragging and holding the window in that way. But once you release the click, the drag, the window will belong to one or other display. It will never appear on both. – StefanS Apr 07 '22 at 10:56