2013-10-20 126 views
3

我正在研究一个简单的Mac应用程序,该应用程序可以检测外部屏幕何时拔出,保存所有窗口的位置,并且一旦外部屏幕再次插入,将所有窗口恢复为其原始位置。 (我知道有应用程序在那里了,我只是好奇,如何做到这一点)CGWindowListCopyWindowInfo:多个屏幕和更改属性

很多搜​​索之后,我终于用

NSArray *openWindows = [[NSWorkspace sharedWorkspace] runningApplications]; 
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); 

这将让屏幕上的所有窗口返回类似

{ 
    kCGWindowAlpha = 1; 
    kCGWindowBounds =   { 
     Height = 22; 
     Width = 279; 
     X = 1559; 
     Y = 0; 
    }; 
    kCGWindowIsOnscreen = 1; 
    kCGWindowLayer = 25; 
    kCGWindowMemoryUsage = 13596; 
    kCGWindowName = ""; 
    kCGWindowNumber = 18; 
    kCGWindowOwnerName = SystemUIServer; 
    kCGWindowOwnerPID = 260; 
    kCGWindowSharingState = 1; 
    kCGWindowStoreType = 2; 
}, 
    { 
    kCGWindowAlpha = 0; 
    kCGWindowBounds =   { 
     Height = 22; 
     Width = 1920; 
     X = 0; 
     Y = 0; 
    }; 
    kCGWindowIsOnscreen = 1; 
    kCGWindowLayer = 25; 
    kCGWindowMemoryUsage = 5404; 
    kCGWindowNumber = 19; 
    kCGWindowOwnerName = SystemUIServer; 
    kCGWindowOwnerPID = 260; 
    kCGWindowSharingState = 1; 
    kCGWindowStoreType = 2; 
}, 

,那么我会遍历数组,并期待在每个单独的窗口

for (int i = 0; i < CFArrayGetCount(windowList); i++) { 
    CFDictionaryRef ref = CFArrayGetValueAtIndex(windowList, i); 

    NSLog(@"%@", CFDictionaryGetValue(ref, kCGWindowBounds)); 
} 

但是,这是我被困住的地方,我怎么能首先知道在多屏幕工作时窗口在哪个屏幕上。 其次,以后如何调整窗口边界?每个应用程序都有自己的ID吗?或者有另一种方法可以使用?

回答

1

由于CGWindowList API不暴露屏幕ID,你必须检查窗口边界对屏幕边界:如果一个窗口

NSArray* windowList = (__bridge NSArray*)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); 
uint32_t maxDisplayCount = 10; 
CGDirectDisplayID onlineDisplayIDs[maxDisplayCount]; 
uint32_t displayCount; 
CGGetOnlineDisplayList(maxDisplayCount, (CGDirectDisplayID*)&onlineDisplayIDs, &displayCount); 
for(uint32_t i = 0; i < displayCount; ++i) 
{ 
    CGRect dspyRect = CGDisplayBounds(onlineDisplayIDs[i]); 
    for(NSDictionary* windowDict in windowList) 
    { 
     CGRect windowRect; 
     CGRectMakeWithDictionaryRepresentation((__bridge CFDictionaryRef)(windowDict[(id)kCGWindowBounds]), &windowRect); 
     if(CGRectContainsRect(dspyRect, windowRect)) 
     { 
      NSLog(@"window %@ is on screen with ID:%d", windowDict[(id)kCGWindowName], onlineDisplayIDs[i]); 
     } 
    } 
} 

上面的代码执行天真检查,即检查在整个特定屏幕上。
如果窗口的某个部分覆盖该屏幕,OS X会考虑属于屏幕的窗口。 (这种行为在OS X版本之间也略有改变)

要移动窗口,您可以使用Apple EventsCocoa Accessibility APIs
请注意,Cocoa Accessibility需要您的使用才能在系统偏好设置中启用“为辅助设备启用访问”。
这两种技术在启用App Sandboxing时都可能会遇到问题。

+0

谢谢,还没有测试过,但会尽快。我刚刚注意到在更新到小牛之后,它实际上已经照顾到了这一点,现在屏幕正在返回到它的原始屏幕。 –