2011-09-14 34 views
26

我試圖修補an application,它使用可訪問性API調整窗口大小。唯一標識OS X上的活動窗口

我需要維護與以前的窗口大小的字典。關鍵需要識別當前活動的窗口。目前,在按下熱鍵時,通過NSAccessibilityFocusedWindowAttribute檢索該活動窗口。

但是,每次調用此方法時,標識窗口的返回AXUIElementRef都是不同的!這當然意味着我不能將它用作字典鍵 - 字典不會找到相應的條目。

下面的代碼重新問題:

-(IBAction)testWindowIdentification:(id)sender{ 
    AXUIElementRef focusedApp; 
    AXUIElementRef focusedWindow; 

    AXUIElementCopyAttributeValue(_systemWideElement, 
            (CFStringRef) kAXFocusedApplicationAttribute, 
            (CFTypeRef*) &focusedApp); 
    AXUIElementCopyAttributeValue((AXUIElementRef) focusedApp, 
            (CFStringRef) NSAccessibilityFocusedWindowAttribute, 
            (CFTypeRef*) &focusedWindow); 
    CFShow(focusedWindow); 
} 

_systemWideElement已經在init方法使用呼叫被初始化爲AXUIElementCreateSystemWide()

CFShow聲明清楚地顯示不同的ID每一個方法被調用時(即使在同一窗口被激活),這是無用的我:

<AXUIElement 0x47e850> {pid=42463} 
<AXUIElement 0x47e890> {pid=42463} 
<AXUIElement 0x47e2c0> {pid=42463} 
… 

documentation on AXUIElement顯示沒有方法來檢索獨特的屬性爲UI元素,並且that of the NSAccessibility protocol也沒有。 對於我來說,唯一的PID是而不是,因爲一個進程可以有多個窗口。

如何檢索可可中活動窗口的一些唯一標識符?

(順便說一下,真正的代碼是檢查在上面的調用返回代碼;沒有錯誤,則調用成功。)

+1

@JeremyBanks最初的回答者在這裏有正確的想法。如果[這個答案](http://stackoverflow.com/a/312099/517815)被認爲是可信的,那麼確定焦點窗口後,確實可以使用Quartz來獲取'CGWindowID'。這個_應該給你唯一的窗口標識符,你可以在當前應用程序的上下文中逍遙法外。請讓我知道你是否希望將這個更完整的版本作爲實際答案。 – MrGomez

+0

@MrGomez當然,這樣的答案會很棒。 :) –

+0

@JeremyBanks會做。今天我有點超負荷,但我會盡量在今晚晚些時候(PST)得到答案。 :) – MrGomez

回答

16

Rob Keniger擁有正確的策略his answer here。此答案中缺少的唯一東西(實際上是賞金放置的原因)是一個可行的實現,它將當前活動窗口轉換爲適用於當前工作應用程序上下文中的索引的唯一鍵。

Rob的解決方案通過使用在Quartz Window Services環境中給出的CGWindowID來描述這一點。當然,強烈暗示這個窗口參考是only useful for your current application

獲取此窗口引用非常棘手,因爲在Accessibility API和Quartz Window Services之間沒有強有力的保證。但是,您可以解決此在以下幾個方面:

  1. 使用extern "C" AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out);,爲documented here。這不是保證能夠正常工作,但它可用作底層測試,以便在您的OSX版本中可以正常工作。使用例如HIWindowGetCGWindowID()直接獲取CGWindowID。有關選擇活動窗口和提取ID的更多詳細信息,請參見the reference manual for the Carbon Window Manager(警告:大型PDF)。

  2. 使用類似CGWindowListCreateDescriptionFromArray的設置您的CGWindowID,完全符合Rob的建議。這裏的目標是找到一些橋接Accessibility API和Quartz的方案,但這是可以想象的,例如利用綁定到當前活動窗口上下文的回調。然而,我誠實地不知道這個的最佳示例,但它適合未來的驗證

的選項,我建議用2.去您目前的需求,如果你無法創造出一些其他的裝飾爲您的Windows唯一識別它們。它目前在遺留代碼庫中定義,但它會做你想要的。

祝您的應用程序好運。

+0

如何檢測沒有選擇窗口或所有窗口都不活動(即控制在桌面上)? –

+0

請問,如何使用「extern」C「AXError _AXUIElementGetWindow(AXUIElementRef,CGWindowID * out);」在Swift中? – allenlinli

8

我想你可能能夠使用石英窗服務功能,特別是CGWindowListCreateDescriptionFromArray來枚舉特定應用程序中當前活動的窗口。

此調用的級別低於AppKit,並且不會告訴您哪個是活動窗口,但它會爲您提供當前用戶會話唯一的窗口ID。這不是一個好的解決方案,但是您可以將窗口邊界信息與您從可訪問性API中收到的信息進行比較,以將窗口與其真實ID相關聯。