2013-10-20 58 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

謝謝,還沒有測試過,但會盡快。我剛剛注意到在更新到小牛之後,它實際上已經照顧到了這一點,現在屏幕正在返回到它的原始屏幕。 –